Logo ROOT   6.19/01
Reference Guide
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 <stdlib.h>
13 #include <string.h>
14 #include <stdio.h>
15 #include <ctype.h>
16 
17 #include "Riostream.h"
18 #include "TROOT.h"
19 #include "TClass.h"
20 #include "TSystem.h"
21 #include "THistPainter.h"
22 #include "TH2.h"
23 #include "TH2Poly.h"
24 #include "TH3.h"
25 #include "TProfile.h"
26 #include "TProfile2D.h"
27 #include "THStack.h"
28 #include "TF2.h"
29 #include "TF3.h"
30 #include "TCutG.h"
31 #include "TMatrixDBase.h"
32 #include "TMatrixFBase.h"
33 #include "TVectorD.h"
34 #include "TVectorF.h"
35 #include "TCanvas.h"
36 #include "TPad.h"
37 #include "TPaveStats.h"
38 #include "TFrame.h"
39 #include "TLatex.h"
40 #include "TLine.h"
41 #include "TPolyLine.h"
42 #include "TPoints.h"
43 #include "TStyle.h"
44 #include "TGraph.h"
45 #include "TMultiGraph.h"
46 #include "TPie.h"
47 #include "TGaxis.h"
48 #include "TColor.h"
49 #include "TPainter3dAlgorithms.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 #include "TVectorD.h"
57 #include "Hoption.h"
58 #include "Hparam.h"
59 #include "TPluginManager.h"
60 #include "TPaletteAxis.h"
61 #include "TCrown.h"
62 #include "TArrow.h"
63 #include "TVirtualPadEditor.h"
64 #include "TEnv.h"
65 #include "TPoint.h"
66 #include "TImage.h"
67 #include "TCandle.h"
68 
69 /*! \class THistPainter
70 \ingroup Histpainter
71 \brief The histogram painter class. Implements all histograms' drawing's options.
72 
73 - [Introduction](#HP00)
74 - [Histograms' plotting options](#HP01)
75  - [Options supported for 1D and 2D histograms](#HP01a)
76  - [Options supported for 1D histograms](#HP01b)
77  - [Options supported for 2D histograms](#HP01c)
78  - [Options supported for 3D histograms](#HP01d)
79  - [Options supported for histograms' stacks (THStack)](#HP01e)
80 - [Setting the Style](#HP02)
81 - [Setting line, fill, marker, and text attributes](#HP03)
82 - [Setting Tick marks on the histogram axis](#HP04)
83 - [Giving titles to the X, Y and Z axis](#HP05)
84 - [The option "SAME"](#HP060)
85  - [Limitations](#HP060a)
86 - [Colors automatically picked in palette](#HP061)
87 - [Superimposing two histograms with different scales in the same pad](#HP06)
88 - [Statistics Display](#HP07)
89 - [Fit Statistics](#HP08)
90 - [The error bars options](#HP09)
91 - [The bar chart option](#HP100)
92 - [The "BAR" and "HBAR" options](#HP10)
93 - [The SCATter plot option (default for 2D histograms)](#HP11)
94 - [The ARRow option](#HP12)
95 - [The BOX option](#HP13)
96 - [The COLor option](#HP14)
97 - [The CANDLE and VIOLIN options](#HP140)
98  - [The CANDLE option](#HP140a)
99  - [The VIOLIN option](#HP140b)
100 - [The TEXT and TEXTnn Option](#HP15)
101 - [The CONTour options](#HP16)
102  - [The LIST option](#HP16a)
103  - [The AITOFF, MERCATOR, SINUSOIDAL and PARABOLIC options](#HP16b)
104 - [The LEGO options](#HP17)
105 - [The "SURFace" options](#HP18)
106 - [Cylindrical, Polar, Spherical and PseudoRapidity/Phi options](#HP19)
107 - [Base line for bar-charts and lego plots](#HP20)
108 - [TH2Poly Drawing](#HP20a)
109 - [The SPEC option](#HP21)
110 - [Option "Z" : Adding the color palette on the right side of the pad](#HP22)
111 - [Setting the color palette](#HP23)
112 - [Drawing a sub-range of a 2-D histogram; the [cutg] option](#HP24)
113 - [Drawing options for 3D histograms](#HP25)
114 - [Drawing option for histograms' stacks](#HP26)
115 - [Drawing of 3D implicit functions](#HP27)
116 - [Associated functions drawing](#HP28)
117 - [Drawing using OpenGL](#HP29)
118  - [General information: plot types and supported options](#HP29a)
119  - [TH3 as color boxes](#HP290)
120  - [TH3 as boxes (spheres)](#HP29b)
121  - [TH3 as iso-surface(s)](#HP29c)
122  - [TF3 (implicit function)](#HP29d)
123  - [Parametric surfaces](#HP29e)
124  - [Interaction with the plots](#HP29f)
125  - [Selectable parts](#HP29g)
126  - [Rotation and zooming](#HP29h)
127  - [Panning](#HP29i)
128  - [Box cut](#HP29j)
129  - [Plot specific interactions (dynamic slicing etc.)](#HP29k)
130  - [Surface with option "GLSURF"](#HP29l)
131  - [TF3](#HP29m)
132  - [Box](#HP29n)
133  - [Iso](#HP29o)
134  - [Parametric plot](#HP29p)
135 - [Highlight mode for histogram](#HP30)
136  - [Highlight mode and user function](#HP30a)
137 
138 
139 ## <a name="HP00"></a> Introduction
140 
141 
142 Histograms are drawn via the `THistPainter` class. Each histogram has a
143 pointer to its own painter (to be usable in a multithreaded program). When the
144 canvas has to be redrawn, the `Paint` function of each objects in the
145 pad is called. In case of histograms, `TH1::Paint` invokes directly
146 `THistPainter::Paint`.
147 
148 To draw a histogram `h` it is enough to do:
149 
150  h->Draw();
151 
152 `h` can be of any kind: 1D, 2D or 3D. To choose how the histogram will
153 be drawn, the `Draw()` method can be invoked with an option. For instance
154 to draw a 2D histogram as a lego plot it is enough to do:
155 
156  h->Draw("lego");
157 
158 `THistPainter` offers many options to paint 1D, 2D and 3D histograms.
159 
160 When the `Draw()` method of a histogram is called for the first time
161 (`TH1::Draw`), it creates a `THistPainter` object and saves a
162 pointer to this "painter" as a data member of the histogram. The
163 `THistPainter` class specializes in the drawing of histograms. It is
164 separated from the histogram so that one can have histograms without the
165 graphics overhead, for example in a batch program. Each histogram having its own
166 painter (rather than a central singleton painter painting all histograms), allows
167 two histograms to be drawn in two threads without overwriting the painter's
168 values.
169 
170 When a displayed histogram is filled again, there is no need to call the
171 `Draw()` method again; the image will be refreshed the next time the
172 pad will be updated.
173 
174 A pad is updated after one of these three actions:
175 
176 1. a carriage control on the ROOT command line,
177 2. a click inside the pad,
178 3. a call to `TPad::Update`.
179 
180 
181 By default a call to `TH1::Draw()` clears the pad of all objects
182 before drawing the new image of the histogram. One can use the `SAME`
183 option to leave the previous display intact and superimpose the new histogram.
184 The same histogram can be drawn with different graphics options in different
185 pads.
186 
187 When a displayed histogram is deleted, its image is automatically removed
188 from the pad.
189 
190 To create a copy of the histogram when drawing it, one can use
191 `TH1::DrawClone()`. This will clone the histogram and allow to change
192 and delete the original one without affecting the clone.
193 
194 
195 ### <a name="HP01"></a> Histograms' plotting options
196 
197 
198 Most options can be concatenated with or without spaces or commas, for example:
199 
200  h->Draw("E1 SAME");
201 
202 The options are not case sensitive:
203 
204  h->Draw("e1 same");
205 
206 
207 The default drawing option can be set with `TH1::SetOption` and retrieve
208 using `TH1::GetOption`:
209 
210  root [0] h->Draw(); // Draw "h" using the standard histogram representation.
211  root [1] h->Draw("E"); // Draw "h" using error bars
212  root [3] h->SetOption("E"); // Change the default drawing option for "h"
213  root [4] h->Draw(); // Draw "h" using error bars
214  root [5] h->GetOption(); // Retrieve the default drawing option for "h"
215  (const Option_t* 0xa3ff948)"E"
216 
217 
218 #### <a name="HP01a"></a> Options supported for 1D and 2D histograms
219 
220 | Option | Description |
221 |----------|-------------------------------------------------------------------|
222 | "E" | Draw error bars. |
223 | "AXIS" | Draw only axis. |
224 | "AXIG" | Draw only grid (if the grid is requested). |
225 | <a name="OPTHIST">"HIST"</a> | 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). |
226 | "FUNC" | When an histogram has a fitted function, this option allows to draw the fit result only. |
227 | "SAME" | Superimpose on previous picture in the same pad. |
228 | "SAMES" | Same as "SAME" and draw the statistics box|
229 | "PFC" | Palette Fill Color: histogram's fill color is taken in the current palette. |
230 | "PLC" | Palette Line Color: histogram's line color is taken in the current palette. |
231 | "PMC" | Palette Marker Color: histogram's marker color is taken in the current palette. |
232 | "LEGO" | Draw a lego plot with hidden line removal. |
233 | "LEGO1" | Draw a lego plot with hidden surface removal. |
234 | "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.|
235 | "LEGO3" | Draw a lego plot with hidden surface removal, like LEGO1 but the border lines of each lego-bar are not drawn.|
236 | "LEGO4" | Draw a lego plot with hidden surface removal, like LEGO1 but without the shadow effect on each lego-bar.|
237 | "TEXT" | Draw bin contents as text (format set via `gStyle->SetPaintTextFormat`).|
238 | "TEXTnn" | Draw bin contents as text at angle nn (0 < nn < 90). |
239 | "X+" | The X-axis is drawn on the top side of the plot. |
240 | "Y+" | The Y-axis is drawn on the right side of the plot. |
241 | "MIN0" | Set minimum value for the Y axis to 0, equivalent to gStyle->SetHistMinimumZero(). |
242 
243 #### <a name="HP01b"></a> Options supported for 1D histograms
244 
245 | Option | Description |
246 |----------|-------------------------------------------------------------------|
247 | " " | Default. |
248 | "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.|
249 | "][" | When this option is selected the first and last vertical lines of the histogram are not drawn.|
250 | "B" | Bar chart option.|
251 | "BAR" | Like option "B", but bars can be drawn with a 3D effect.|
252 | "HBAR" | Like option "BAR", but bars are drawn horizontally.|
253 | "C" | Draw a smooth Curve through the histogram bins.|
254 | "E0" | Draw error bars. Markers are drawn for bins with 0 contents.|
255 | "E1" | Draw error bars with perpendicular lines at the edges.|
256 | "E2" | Draw error bars with rectangles.|
257 | "E3" | Draw a fill area through the end points of the vertical error bars.|
258 | "E4" | Draw a smoothed filled area through the end points of the error bars.|
259 | "E5" | Like E3 but ignore the bins with 0 contents.|
260 | "E6" | Like E4 but ignore the bins with 0 contents.|
261 | "X0" | When used with one of the "E" option, it suppress the error bar along X as `gStyle->SetErrorX(0)` would do.|
262 | "L" | Draw a line through the bin contents.|
263 | "P" | Draw current marker at each bin except empty bins.|
264 | "P0" | Draw current marker at each bin including empty bins.|
265 | "PIE" | Draw histogram as a Pie Chart.|
266 | "*H" | Draw histogram with a * at each bin.|
267 | "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.|
268 
269 
270 #### <a name="HP01c"></a> Options supported for 2D histograms
271 
272 | Option | Description |
273 |-----------|------------------------------------------------------------------|
274 | " " | Default (scatter plot).|
275 | "ARR" | Arrow mode. Shows gradient between adjacent cells.|
276 | "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.|
277 | "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.|
278 | "COL" | A box is drawn for each cell with a color scale varying with contents. All the none empty bins 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.|
279 | "COLZ" | Same as "COL". In addition the color palette is also drawn.|
280 | "COL2" | Alternative rendering algorithm to "COL". Can significantly improve rendering performance for large, non-sparse 2-D histograms.|
281 | "COLZ2" | Same as "COL2". In addition the color palette is also drawn.|
282 | "CANDLE" | Draw a candle plot along X axis.|
283 | "CANDLEX" | Same as "CANDLE".|
284 | "CANDLEY" | Draw a candle plot along Y axis.|
285 | "CANDLEXn"| Draw a candle plot along X axis. Different candle-styles with n from 1 to 6.|
286 | "CANDLEYn"| Draw a candle plot along Y axis. Different candle-styles with n from 1 to 6.|
287 | "VIOLIN" | Draw a violin plot along X axis.|
288 | "VIOLINX" | Same as "VIOLIN".|
289 | "VIOLINY" | Draw a violin plot along Y axis.|
290 | "VIOLINXn"| Draw a violin plot along X axis. Different violin-styles with n being 1 or 2.|
291 | "VIOLINYn"| Draw a violin plot along Y axis. Different violin-styles with n being 1 or 2.|
292 | "CONT" | Draw a contour plot (same as CONT0).|
293 | "CONT0" | Draw a contour plot using surface colors to distinguish contours.|
294 | "CONT1" | Draw a contour plot using line styles to distinguish contours.|
295 | "CONT2" | Draw a contour plot using the same line style for all contours.|
296 | "CONT3" | Draw a contour plot using fill area colors.|
297 | "CONT4" | Draw a contour plot using surface colors (SURF option at theta = 0).|
298 | "CONT5" | (TGraph2D only) Draw a contour plot using Delaunay triangles.|
299 | "LIST" | Generate a list of TGraph objects for each contour.|
300 | "CYL" | Use Cylindrical coordinates. The X coordinate is mapped on the angle and the Y coordinate on the cylinder length.|
301 | "POL" | Use Polar coordinates. The X coordinate is mapped on the angle and the Y coordinate on the radius.|
302 | "SAME0" | Same as "SAME" but do not use the z-axis range of the first plot. |
303 | "SAMES0" | Same as "SAMES" but do not use the z-axis range of the first plot. |
304 | "SPH" | Use Spherical coordinates. The X coordinate is mapped on the latitude and the Y coordinate on the longitude.|
305 | "PSR" | Use PseudoRapidity/Phi coordinates. The X coordinate is mapped on Phi.|
306 | "SURF" | Draw a surface plot with hidden line removal.|
307 | "SURF1" | Draw a surface plot with hidden surface removal.|
308 | "SURF2" | Draw a surface plot using colors to show the cell contents.|
309 | "SURF3" | Same as SURF with in addition a contour view drawn on the top.|
310 | "SURF4" | Draw a surface using Gouraud shading.|
311 | "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.|
312 | "LEGO9" | Draw the 3D axis only. Mainly needed for internal use |
313 | "FB" | With LEGO or SURFACE, suppress the Front-Box.|
314 | "BB" | With LEGO or SURFACE, suppress the Back-Box.|
315 | "A" | With LEGO or SURFACE, suppress the axis.|
316 | "SCAT" | Draw a scatter-plot (default).|
317 | "[cutg]" | Draw only the sub-range selected by the TCutG named "cutg".|
318 
319 
320 #### <a name="HP01d"></a> Options supported for 3D histograms
321 
322 | Option | Description |
323 |----------|-------------------------------------------------------------------|
324 | " " | Default (scatter plot).|
325 | "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)`.|
326 | "BOX" | Draw a for each cell with volume proportional to the content's absolute value. An hidden line removal algorithm is used|
327 | "BOX1" | Same as BOX but an hidden surface removal algorithm is used|
328 | "BOX2" | The boxes' colors are picked in the current palette according to the bins' contents|
329 | "BOX2Z" | Same as "BOX2". In addition the color palette is also drawn.|
330 | "BOX3" | Same as BOX1, but the border lines of each lego-bar are not drawn.|
331 | "LEGO" | Same as `BOX`.|
332 
333 
334 #### <a name="HP01e"></a> Options supported for histograms' stacks (`THStack`)
335 
336 | Option | Description |
337 |------------|-----------------------------------------------------------------|
338 | " " | Default, the histograms are drawn on top of each other (as lego plots for 2D histograms).|
339 | "NOSTACK" | Histograms in the stack are all paint in the same pad as if the option `SAME` had been specified.|
340 | "NOSTACKB" | Histograms are drawn next to each other as bar charts.|
341 | "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.|
342 | "PFC" | Palette Fill Color: stack's fill color is taken in the current palette. |
343 | "PLC" | Palette Line Color: stack's line color is taken in the current palette. |
344 | "PMC" | Palette Marker Color: stack's marker color is taken in the current palette. |
345 
346 
347 
348 ### <a name="HP02"></a> Setting the Style
349 
350 
351 Histograms use the current style (`gStyle`). When one changes the current
352 style and would like to propagate the changes to the histogram,
353 `TH1::UseCurrentStyle` should be called. Call `UseCurrentStyle` on
354 each histogram is needed.
355 
356 To force all the histogram to use the current style use:
357 
358  gROOT->ForceStyle();
359 
360 All the histograms read after this call will use the current style.
361 
362 
363 ### <a name="HP03"></a> Setting line, fill, marker, and text attributes
364 
365 
366 The histogram classes inherit from the attribute classes:
367 `TAttLine`, `TAttFill` and `TAttMarker`.
368 See the description of these classes for the list of options.
369 
370 
371 ### <a name="HP04"></a> Setting Tick marks on the histogram axis
372 
373 
374 The `TPad::SetTicks` method specifies the type of tick marks on the axis.
375 If ` tx = gPad->GetTickx()` and `ty = gPad->GetTicky()` then:
376 
377  tx = 1; tick marks on top side are drawn (inside)
378  tx = 2; tick marks and labels on top side are drawn
379  ty = 1; tick marks on right side are drawn (inside)
380  ty = 2; tick marks and labels on right side are drawn
381 
382 By default only the left Y axis and X bottom axis are drawn
383 (`tx = ty = 0`)
384 
385 `TPad::SetTicks(tx,ty)` allows to set these options.
386 See also The `TAxis` functions to set specific axis attributes.
387 
388 In case multiple color filled histograms are drawn on the same pad, the fill
389 area may hide the axis tick marks. One can force a redraw of the axis over all
390 the histograms by calling:
391 
392  gPad->RedrawAxis();
393 
394 
395 ### <a name="HP05"></a> Giving titles to the X, Y and Z axis
396 
397 
398  h->GetXaxis()->SetTitle("X axis title");
399  h->GetYaxis()->SetTitle("Y axis title");
400 
401 The histogram title and the axis titles can be any `TLatex` string.
402 The titles are part of the persistent histogram.
403 
404 
405 ### <a name="HP060"></a> The option "SAME"
406 
407 
408 By default, when an histogram is drawn, the current pad is cleared before
409 drawing. In order to keep the previous drawing and draw on top of it the
410 option `SAME` should be use. The histogram drawn with the option
411 `SAME` uses the coordinates system available in the current pad.
412 
413 This option can be used alone or combined with any valid drawing option but
414 some combinations must be use with care.
415 
416 #### <a name="HP060a"></a> Limitations
417 
418 - It does not work when combined with the `LEGO` and `SURF` options unless the
419  histogram plotted with the option `SAME` has exactly the same
420  ranges on the X, Y and Z axis as the currently drawn histogram. To superimpose
421  lego plots [histograms' stacks](#HP26) should be used.</li>
422 
423 
424 ### <a name="HP061"></a> Colors automatically picked in palette
425 
426 \since **ROOT version 6.09/01**
427 
428 When several histograms are painted in the same canvas thanks to the option "SAME"
429 or via a `THStack` it might be useful to have an easy and automatic way to choose
430 their color. The simplest way is to pick colors in the current active color
431 palette. Palette coloring for histogram is activated thanks to the options `PFC`
432 (Palette Fill Color), `PLC` (Palette Line Color) and `PMC` (Palette Marker Color).
433 When one of these options is given to `TH1::Draw` the histogram get its color
434 from the current color palette defined by `gStyle->SetPalette(…)`. The color
435 is determined according to the number of objects having palette coloring in
436 the current pad.
437 
438 Begin_Macro(source)
439 ../../../tutorials/hist/histpalettecolor.C
440 End_Macro
441 
442 Begin_Macro(source)
443 ../../../tutorials/hist/thstackpalettecolor.C
444 End_Macro
445 
446 Begin_Macro(source)
447 ../../../tutorials/hist/thstack2palettecolor.C
448 End_Macro
449 
450 ### <a name="HP06"></a> Superimposing two histograms with different scales in the same pad
451 
452 
453 The following example creates two histograms, the second histogram is the bins
454 integral of the first one. It shows a procedure to draw the two histograms in
455 the same pad and it draws the scale of the second histogram using a new vertical
456 axis on the right side. See also the tutorial `transpad.C` for a variant
457 of this example.
458 
459 Begin_Macro(source)
460 {
461  auto c1 = new TCanvas("c1","c1",600,400);
462  // create/fill draw h1
463  gStyle->SetOptStat(kFALSE);
464  auto h1 = new TH1F("h1","Superimposing two histograms with different scales",100,-3,3);
465  Int_t i;
466  for (i=0;i<10000;i++) h1->Fill(gRandom->Gaus(0,1));
467  h1->Draw();
468  c1->Update();
469 
470  // create hint1 filled with the bins integral of h1
471  auto hint1 = new TH1F("hint1","h1 bins integral",100,-3,3);
472  float sum = 0.f;
473  for (i=1;i<=100;i++) {
474  sum += h1->GetBinContent(i);
475  hint1->SetBinContent(i,sum);
476  }
477 
478  // scale hint1 to the pad coordinates
479  float rightmax = 1.1*hint1->GetMaximum();
480  float scale = gPad->GetUymax()/rightmax;
481  hint1->SetLineColor(kRed);
482  hint1->Scale(scale);
483  hint1->Draw("same");
484 
485  // draw an axis on the right side
486  auto axis = new TGaxis(gPad->GetUxmax(),gPad->GetUymin(),
487  gPad->GetUxmax(), gPad->GetUymax(),0,rightmax,510,"+L");
488  axis->SetLineColor(kRed);
489  axis->SetTextColor(kRed);
490  axis->Draw();
491 }
492 End_Macro
493 
494 
495 ### <a name="HP07"></a> Statistics Display
496 
497 
498 The type of information shown in the histogram statistics box can be selected
499 with:
500 
501  gStyle->SetOptStat(mode);
502 
503 The `mode` has up to nine digits that can be set to on (1 or 2), off (0).
504 
505  mode = ksiourmen (default = 000001111)
506  k = 1; kurtosis printed
507  k = 2; kurtosis and kurtosis error printed
508  s = 1; skewness printed
509  s = 2; skewness and skewness error printed
510  i = 1; integral of bins printed
511  i = 2; integral of bins with option "width" printed
512  o = 1; number of overflows printed
513  u = 1; number of underflows printed
514  r = 1; standard deviation printed
515  r = 2; standard deviation and standard deviation error printed
516  m = 1; mean value printed
517  m = 2; mean and mean error values printed
518  e = 1; number of entries printed
519  n = 1; name of histogram is printed
520 
521 For example:
522 
523  gStyle->SetOptStat(11);
524 
525 displays only the name of histogram and the number of entries, whereas:
526 
527  gStyle->SetOptStat(1101);
528 
529 displays the name of histogram, mean value and standard deviation.
530 
531 <b>WARNING 1:</b> never do:
532 
533  gStyle->SetOptStat(0001111);
534 
535 but instead do:
536 
537  gStyle->SetOptStat(1111);
538 
539 because `0001111` will be taken as an octal number!
540 
541 <b>WARNING 2:</b> for backward compatibility with older versions
542 
543  gStyle->SetOptStat(1);
544 
545 is taken as:
546 
547  gStyle->SetOptStat(1111)
548 
549 To print only the name of the histogram do:
550 
551  gStyle->SetOptStat(1000000001);
552 
553 <b>NOTE</b> that in case of 2D histograms, when selecting only underflow
554 (10000) or overflow (100000), the statistics box will show all combinations
555 of underflow/overflows and not just one single number.
556 
557 The parameter mode can be any combination of the letters `kKsSiIourRmMen`
558 
559  k : kurtosis printed
560  K : kurtosis and kurtosis error printed
561  s : skewness printed
562  S : skewness and skewness error printed
563  i : integral of bins printed
564  I : integral of bins with option "width" printed
565  o : number of overflows printed
566  u : number of underflows printed
567  r : standard deviation printed
568  R : standard deviation and standard deviation error printed
569  m : mean value printed
570  M : mean value mean error values printed
571  e : number of entries printed
572  n : name of histogram is printed
573 
574 For example, to print only name of histogram and number of entries do:
575 
576  gStyle->SetOptStat("ne");
577 
578 To print only the name of the histogram do:
579 
580  gStyle->SetOptStat("n");
581 
582 The default value is:
583 
584  gStyle->SetOptStat("nemr");
585 
586 When a histogram is painted, a `TPaveStats` object is created and added
587 to the list of functions of the histogram. If a `TPaveStats` object
588 already exists in the histogram list of functions, the existing object is just
589 updated with the current histogram parameters.
590 
591 Once a histogram is painted, the statistics box can be accessed using
592 `h->FindObject("stats")`. In the command line it is enough to do:
593 
594  Root > h->Draw()
595  Root > TPaveStats *st = (TPaveStats*)h->FindObject("stats")
596 
597 because after `h->Draw()` the histogram is automatically painted. But
598 in a script file the painting should be forced using `gPad->Update()`
599 in order to make sure the statistics box is created:
600 
601  h->Draw();
602  gPad->Update();
603  TPaveStats *st = (TPaveStats*)h->FindObject("stats");
604 
605 Without `gPad->Update()` the line `h->FindObject("stats")` returns a null pointer.
606 
607 When a histogram is drawn with the option `SAME`, the statistics box
608 is not drawn. To force the statistics box drawing with the option
609 `SAME`, the option `SAMES` must be used.
610 If the new statistics box hides the previous statistics box, one can change
611 its position with these lines (`h` being the pointer to the histogram):
612 
613  Root > TPaveStats *st = (TPaveStats*)h->FindObject("stats")
614  Root > st->SetX1NDC(newx1); //new x start position
615  Root > st->SetX2NDC(newx2); //new x end position
616 
617 To change the type of information for an histogram with an existing
618 `TPaveStats` one should do:
619 
620  st->SetOptStat(mode);
621 
622 Where `mode` has the same meaning than when calling `gStyle->SetOptStat(mode)`
623 (see above).
624 
625 One can delete the statistics box for a histogram `TH1* h` with:
626 
627  h->SetStats(0)
628 
629 and activate it again with:
630 
631  h->SetStats(1).
632 
633 Labels used in the statistics box ("Mean", "Std Dev", ...) can be changed from
634 `$ROOTSYS/etc/system.rootrc` or `.rootrc` (look for the string `Hist.Stats.`).
635 
636 
637 ### <a name="HP08"></a> Fit Statistics
638 
639 
640 The type of information about fit parameters printed in the histogram statistics
641 box can be selected via the parameter mode. The parameter mode can be
642 `= pcev` (default `= 0111`)
643 
644  p = 1; print Probability
645  c = 1; print Chisquare/Number of degrees of freedom
646  e = 1; print errors (if e=1, v must be 1)
647  v = 1; print name/values of parameters
648 
649 Example:
650 
651  gStyle->SetOptFit(1011);
652 
653 print fit probability, parameter names/values and errors.
654 
655 1. When `v" = 1` is specified, only the non-fixed parameters are shown.
656 2. When `v" = 2` all parameters are shown.
657 
658 Note: `gStyle->SetOptFit(1)` means "default value", so it is equivalent
659 to `gStyle->SetOptFit(111)`
660 
661 
662 ### <a name="HP09"></a> The error bars options
663 
664 
665 | Option | Description |
666 |----------|-------------------------------------------------------------------|
667 | "E" | Default. Shows only the error bars, not a marker.|
668 | "E1" | Small lines are drawn at the end of the error bars.|
669 | "E2" | Error rectangles are drawn.|
670 | "E3" | A filled area is drawn through the end points of the vertical error bars.|
671 | "E4" | A smoothed filled area is drawn through the end points of the vertical error bars.|
672 | "E0" | Draw also bins with null contents.|
673 
674 Begin_Macro(source)
675 {
676  auto c1 = new TCanvas("c1","c1",600,400);
677  auto he = new TH1F("he","Distribution drawn with error bars (option E1) ",100,-3,3);
678  for (int i=0; i<10000; i++) he->Fill(gRandom->Gaus(0,1));
679  gStyle->SetEndErrorSize(3);
680  gStyle->SetErrorX(1.);
681  he->SetMarkerStyle(20);
682  he->Draw("E1");
683 }
684 End_Macro
685 
686 The options "E3" and "E4" draw an error band through the end points of the
687 vertical error bars. With "E4" the error band is smoothed. Because of the
688 smoothing algorithm used some artefacts may appear at the end of the band
689 like in the following example. In such cases "E3" should be used instead
690 of "E4".
691 
692 Begin_Macro(source)
693 {
694  auto ce4 = new TCanvas("ce4","ce4",600,400);
695  ce4->Divide(2,1);
696  auto he4 = new TH1F("he4","Distribution drawn with option E4",100,-3,3);
697  Int_t i;
698  for (i=0;i<10000;i++) he4->Fill(gRandom->Gaus(0,1));
699  he4->SetFillColor(kRed);
700  he4->GetXaxis()->SetRange(40,48);
701  ce4->cd(1);
702  he4->Draw("E4");
703  ce4->cd(2);
704  auto he3 = (TH1F*)he4->DrawClone("E3");
705  he3->SetTitle("Distribution drawn option E3");
706 }
707 End_Macro
708 
709 2D histograms can be drawn with error bars as shown is the following example:
710 
711 Begin_Macro(source)
712 {
713  auto c2e = new TCanvas("c2e","c2e",600,400);
714  auto h2e = new TH2F("h2e","TH2 drawn with option E",40,-4,4,40,-20,20);
715  float px, py;
716  for (Int_t i = 0; i < 25000; i++) {
717  gRandom->Rannor(px,py);
718  h2e->Fill(px,5*py);
719  }
720  h2e->Draw("E");
721 }
722 End_Macro
723 
724 
725 ### <a name="HP100"></a> The bar chart option
726 
727 
728 The option "B" allows to draw simple vertical bar charts.
729 The bar width is controlled with `TH1::SetBarWidth()`,
730 and the bar offset within the bin, with `TH1::SetBarOffset()`.
731 These two settings are useful to draw several histograms on the
732 same plot as shown in the following example:
733 
734 Begin_Macro(source)
735 {
736  int i;
737  const Int_t nx = 8;
738  string os_X[nx] = {"8","32","128","512","2048","8192","32768","131072"};
739  float d_35_0[nx] = {0.75, -3.30, -0.92, 0.10, 0.08, -1.69, -1.29, -2.37};
740  float d_35_1[nx] = {1.01, -3.02, -0.65, 0.37, 0.34, -1.42, -1.02, -2.10};
741 
742  auto cb = new TCanvas("cb","cb",600,400);
743  cb->SetGrid();
744 
745  gStyle->SetHistMinimumZero();
746 
747  auto h1b = new TH1F("h1b","Option B example",nx,0,nx);
748  h1b->SetFillColor(4);
749  h1b->SetBarWidth(0.4);
750  h1b->SetBarOffset(0.1);
751  h1b->SetStats(0);
752  h1b->SetMinimum(-5);
753  h1b->SetMaximum(5);
754 
755  for (i=1; i<=nx; i++) {
756  h1b->SetBinContent(i, d_35_0[i-1]);
757  h1b->GetXaxis()->SetBinLabel(i,os_X[i-1].c_str());
758  }
759 
760  h1b->Draw("b");
761 
762  auto h2b = new TH1F("h2b","h2b",nx,0,nx);
763  h2b->SetFillColor(38);
764  h2b->SetBarWidth(0.4);
765  h2b->SetBarOffset(0.5);
766  h2b->SetStats(0);
767  for (i=1;i<=nx;i++) h2b->SetBinContent(i, d_35_1[i-1]);
768 
769  h2b->Draw("b same");
770 }
771 End_Macro
772 
773 
774 ### <a name="HP10"></a> The "BAR" and "HBAR" options
775 
776 
777 When the option `bar` or `hbar` is specified, a bar chart is drawn. A vertical
778 bar-chart is drawn with the options `bar`, `bar0`, `bar1`, `bar2`, `bar3`, `bar4`.
779 An horizontal bar-chart is drawn with the options `hbar`, `hbar0`, `hbar1`,
780 `hbar2`, `hbar3`, `hbar4` (hbars.C).
781 
782 - The bar is filled with the histogram fill color.
783 - The left side of the bar is drawn with a light fill color.
784 - The right side of the bar is drawn with a dark fill color.
785 - The percentage of the bar drawn with either the light or dark color is:
786  - 0% for option "(h)bar" or "(h)bar0"
787  - 10% for option "(h)bar1"
788  - 20% for option "(h)bar2"
789  - 30% for option "(h)bar3"
790  - 40% for option "(h)bar4"
791 
792 When an histogram has errors the option ["HIST"](#OPTHIST) together with the `(h)bar` option.
793 
794 Begin_Macro(source)
795 ../../../tutorials/hist/hbars.C
796 End_Macro
797 
798 To control the bar width (default is the bin width) `TH1::SetBarWidth()`
799 should be used.
800 
801 To control the bar offset (default is 0) `TH1::SetBarOffset()` should
802 be used.
803 
804 These two parameters are useful when several histograms are plotted using
805 the option `SAME`. They allow to plot the histograms next to each other.
806 
807 
808 ### <a name="HP11"></a> The SCATter plot option (default for 2D histograms)
809 
810 
811 For each cell (i,j) a number of points proportional to the cell content is
812 drawn. A maximum of `kNMAX` points per cell is drawn. If the maximum is above
813 `kNMAX` contents are normalized to `kNMAX` (`kNMAX=2000`).
814 If option is of the form `scat=ff`, (eg `scat=1.8`,
815 `scat=1e-3`), then `ff` is used as a scale factor to compute the
816 number of dots. `scat=1` is the default.
817 
818 By default the scatter plot is painted with a "dot marker" which not scalable
819 (see the `TAttMarker` documentation). To change the marker size, a scalable marker
820 type should be used. For instance a circle (marker style 20).
821 
822 Begin_Macro(source)
823 {
824  auto c1 = new TCanvas("c1","c1",600,400);
825  auto hscat = new TH2F("hscat","Option SCATter example (default for 2D histograms) ",40,-4,4,40,-20,20);
826  float px, py;
827  for (Int_t i = 0; i < 25000; i++) {
828  gRandom->Rannor(px,py);
829  hscat->Fill(px,5*py);
830  hscat->Fill(3+0.5*px,2*py-10.);
831  }
832  hscat->Draw("scat=0.5");
833 }
834 End_Macro
835 
836 
837 ### <a name="HP12"></a> The ARRow option
838 
839 
840 Shows gradient between adjacent cells. For each cell (i,j) an arrow is drawn
841 The orientation of the arrow follows the cell gradient.
842 
843 Begin_Macro(source)
844 {
845  auto c1 = new TCanvas("c1","c1",600,400);
846  auto harr = new TH2F("harr","Option ARRow example",20,-4,4,20,-20,20);
847  harr->SetLineColor(kRed);
848  float px, py;
849  for (Int_t i = 0; i < 25000; i++) {
850  gRandom->Rannor(px,py);
851  harr->Fill(px,5*py);
852  harr->Fill(3+0.5*px,2*py-10.,0.1);
853  }
854  harr->Draw("ARR");
855 }
856 End_Macro
857 
858 \since **ROOT version 6.17/01**
859 
860 The option `ARR` can be combined with the option `COL` or `COLZ`.
861 
862 Begin_Macro(source)
863 {
864  auto c1 = new TCanvas("c1","c1",600,400);
865  auto harr = new TH2F("harr","Option ARR + COLZ example",20,-4,4,20,-20,20);
866  harr->SetStats(0);
867  float px, py;
868  for (Int_t i = 0; i < 25000; i++) {
869  gRandom->Rannor(px,py);
870  harr->Fill(px,5*py);
871  harr->Fill(3+0.5*px,2*py-10.,0.1);
872  }
873  harr->Draw("ARR COLZ");
874 }
875 End_Macro
876 
877 
878 ### <a name="HP13"></a> The BOX option
879 
880 
881 For each cell (i,j) a box is drawn. The size (surface) of the box is
882 proportional to the absolute value of the cell content.
883 The cells with a negative content are drawn with a `X` on top of the box.
884 
885 Begin_Macro(source)
886 {
887  auto c1 = new TCanvas("c1","c1",600,400);
888  auto hbox = new TH2F("hbox","Option BOX example",3,0,3,3,0,3);
889  hbox->SetFillColor(42);
890  hbox->Fill(0.5, 0.5, 1.);
891  hbox->Fill(0.5, 1.5, 4.);
892  hbox->Fill(0.5, 2.5, 3.);
893  hbox->Fill(1.5, 0.5, 2.);
894  hbox->Fill(1.5, 1.5, 12.);
895  hbox->Fill(1.5, 2.5, -6.);
896  hbox->Fill(2.5, 0.5, -4.);
897  hbox->Fill(2.5, 1.5, 6.);
898  hbox->Fill(2.5, 2.5, 0.5);
899  hbox->Draw("BOX");
900 }
901 End_Macro
902 
903 With option `BOX1` a button is drawn for each cell with surface
904 proportional to content's absolute value. A sunken button is drawn for
905 negative values a raised one for positive.
906 
907 Begin_Macro(source)
908 {
909  auto c1 = new TCanvas("c1","c1",600,400);
910  auto hbox1 = new TH2F("hbox1","Option BOX1 example",3,0,3,3,0,3);
911  hbox1->SetFillColor(42);
912  hbox1->Fill(0.5, 0.5, 1.);
913  hbox1->Fill(0.5, 1.5, 4.);
914  hbox1->Fill(0.5, 2.5, 3.);
915  hbox1->Fill(1.5, 0.5, 2.);
916  hbox1->Fill(1.5, 1.5, 12.);
917  hbox1->Fill(1.5, 2.5, -6.);
918  hbox1->Fill(2.5, 0.5, -4.);
919  hbox1->Fill(2.5, 1.5, 6.);
920  hbox1->Fill(2.5, 2.5, 0.5);
921  hbox1->Draw("BOX1");
922 }
923 End_Macro
924 
925 When the option `SAME` (or "SAMES") is used with the option `BOX`,
926 the boxes' sizes are computing taking the previous plots into account. The range
927 along the Z axis is imposed by the first plot (the one without option
928 `SAME`); therefore the order in which the plots are done is relevant.
929 
930 Begin_Macro(source)
931 {
932  auto c1 = new TCanvas("c1","c1",600,400);
933  auto hb1 = new TH2F("hb1","Example of BOX plots with option SAME ",40,-3,3,40,-3,3);
934  auto hb2 = new TH2F("hb2","hb2",40,-3,3,40,-3,3);
935  auto hb3 = new TH2F("hb3","hb3",40,-3,3,40,-3,3);
936  auto hb4 = new TH2F("hb4","hb4",40,-3,3,40,-3,3);
937  for (Int_t i=0;i<1000;i++) {
938  double x,y;
939  gRandom->Rannor(x,y);
940  if (x>0 && y>0) hb1->Fill(x,y,4);
941  if (x<0 && y<0) hb2->Fill(x,y,3);
942  if (x>0 && y<0) hb3->Fill(x,y,2);
943  if (x<0 && y>0) hb4->Fill(x,y,1);
944  }
945  hb1->SetFillColor(1);
946  hb2->SetFillColor(2);
947  hb3->SetFillColor(3);
948  hb4->SetFillColor(4);
949  hb1->Draw("box");
950  hb2->Draw("box same");
951  hb3->Draw("box same");
952  hb4->Draw("box same");
953 }
954 End_Macro
955 
956 \since **ROOT version 6.17/01:**
957 
958 Sometimes the change of the range of the Z axis is unwanted, in which case, one
959 can use `SAME0` (or `SAMES0`) option to opt out of this change.
960 
961 Begin_Macro(source)
962 {
963  auto h2 = new TH2F("h2"," ",10,0,10,10,20,30);
964  auto hf = (TH2F*)h2->Clone("hf");
965  h2->SetBit(TH1::kNoStats);
966  hf->SetBit(TH1::kNoStats);
967  h2->Fill(5,22);
968  h2->Fill(5,23);
969  h2->Fill(6,22);
970  h2->Fill(6,23);
971  hf->Fill(6,23);
972  hf->Fill(6,23);
973  hf->Fill(6,23);
974  hf->Fill(6,23);
975  hf->Fill(5,23);
976 
977  auto hf_copy1 = hf->Clone("hf_copy1");
978  auto lt = new TLatex();
979 
980  auto cx = new TCanvas(); cx->Divide(2,1);
981 
982  cx->cd(1);
983  h2->Draw("box");
984  hf->Draw("text colz same");
985  lt->DrawLatexNDC(0.3,0.5,"SAME");
986 
987  cx->cd(2);
988  h2->Draw("box");
989  hf_copy1->Draw("text colz same0");
990  lt->DrawLatexNDC(0.3,0.5,"SAME0");
991 }
992 End_Macro
993 
994 
995 ### <a name="HP14"></a> The COLor option
996 
997 
998 For each cell (i,j) a box is drawn with a color proportional to the cell
999 content.
1000 
1001 The color table used is defined in the current style.
1002 
1003 If the histogram's minimum and maximum are the same (flat histogram), the
1004 mapping on colors is not possible, therefore nothing is painted. To paint a
1005 flat histogram it is enough to set the histogram minimum
1006 (`TH1::SetMinimum()`) different from the bins' content.
1007 
1008 The default number of color levels used to paint the cells is 20.
1009 It can be changed with `TH1::SetContour()` or
1010 `TStyle::SetNumberContours()`. The higher this number is, the smoother
1011 is the color change between cells.
1012 
1013 The color palette in TStyle can be modified via `gStyle->SetPalette()`.
1014 
1015 All the non-empty bins are painted. Empty bins are not painted unless
1016 some bins have a negative content because in that case the null bins
1017 might be not empty.
1018 
1019 `TProfile2D` histograms are handled differently because, for this type of 2D
1020 histograms, it is possible to know if an empty bin has been filled or not. So even
1021 if all the bins' contents are positive some empty bins might be painted. And vice versa,
1022 if some bins have a negative content some empty bins might be not painted.
1023 
1024 Combined with the option `COL`, the option `Z` allows to
1025 display the color palette defined by `gStyle->SetPalette()`.
1026 
1027 In the following example, the histogram has only positive bins; the empty
1028 bins (containing 0) are not drawn.
1029 
1030 Begin_Macro(source)
1031 {
1032  auto c1 = new TCanvas("c1","c1",600,400);
1033  auto hcol1 = new TH2F("hcol1","Option COLor example ",40,-4,4,40,-20,20);
1034  float px, py;
1035  for (Int_t i = 0; i < 25000; i++) {
1036  gRandom->Rannor(px,py);
1037  hcol1->Fill(px,5*py);
1038  }
1039  hcol1->Draw("COLZ");
1040 }
1041 End_Macro
1042 
1043 In the first plot of following example, the histogram has some negative bins;
1044 the empty bins (containing 0) are drawn. In some cases one wants to not draw
1045 empty bins (containing 0) of histograms having a negative minimum. The option
1046 `1`, used to produce the second plot in the following picture, allows to do that.
1047 
1048 Begin_Macro(source)
1049 {
1050  auto c1 = new TCanvas("c1","c1",600,600);
1051  c1->Divide(1,2);
1052  auto hcol23 = new TH2F("hcol23","Option COLZ example ",40,-4,4,40,-20,20);
1053  auto hcol24 = new TH2F("hcol24","Option COLZ1 example ",40,-4,4,40,-20,20);
1054  float px, py;
1055  for (Int_t i = 0; i < 25000; i++) {
1056  gRandom->Rannor(px,py);
1057  hcol23->Fill(px,5*py);
1058  hcol24->Fill(px,5*py);
1059  }
1060  hcol23->Fill(0.,0.,-200.);
1061  hcol24->Fill(0.,0.,-200.);
1062  c1->cd(1); hcol23->Draw("COLZ");
1063  c1->cd(2); hcol24->Draw("COLZ1");
1064 }
1065 End_Macro
1066 
1067 When the maximum of the histogram is set to a smaller value than the real maximum,
1068  the bins having a content between the new maximum and the real maximum are
1069 painted with the color corresponding to the new maximum.
1070 
1071 When the minimum of the histogram is set to a greater value than the real minimum,
1072  the bins having a value between the real minimum and the new minimum are not drawn
1073  unless the option `0` is set.
1074 
1075 The following example illustrates the option `0` combined with the option `COL`.
1076 
1077 Begin_Macro(source)
1078 {
1079  auto c1 = new TCanvas("c1","c1",600,600);
1080  c1->Divide(1,2);
1081  auto hcol21 = new TH2F("hcol21","Option COLZ",40,-4,4,40,-20,20);
1082  auto hcol22 = new TH2F("hcol22","Option COLZ0",40,-4,4,40,-20,20);
1083  float px, py;
1084  for (Int_t i = 0; i < 25000; i++) {
1085  gRandom->Rannor(px,py);
1086  hcol21->Fill(px,5*py);
1087  hcol22->Fill(px,5*py);
1088  }
1089  hcol21->SetBit(TH1::kNoStats);
1090  hcol22->SetBit(TH1::kNoStats);
1091  c1->cd(1); hcol21->Draw("COLZ");
1092  c1->cd(2); hcol22->Draw("COLZ0");
1093  hcol22->SetMaximum(100);
1094  hcol22->SetMinimum(40);
1095 }
1096 End_Macro
1097 
1098 \since **ROOT version 6.09/01:**
1099 
1100 When the option SAME (or "SAMES") is used with the option COL, the boxes' color
1101 are computing taking the previous plots into account. The range along the Z axis
1102 is imposed by the first plot (the one without option SAME); therefore the order
1103 in which the plots are done is relevant. Same as [in the `BOX` option](#HP13), one can use
1104 `SAME0` (or `SAMES0`) to opt out of this imposition.
1105 
1106 Begin_Macro(source)
1107 {
1108  auto c = new TCanvas("c","Example of col plots with option SAME",200,10,700,500);
1109  auto h1 = new TH2F("h1","h1",40,-3,3,40,-3,3);
1110  auto h2 = new TH2F("h2","h2",40,-3,3,40,-3,3);
1111  auto h3 = new TH2F("h3","h3",40,-3,3,40,-3,3);
1112  auto h4 = new TH2F("h4","h4",40,-3,3,40,-3,3);
1113  h1->SetBit(TH1::kNoStats);
1114  for (Int_t i=0;i<5000;i++) {
1115  double x,y;
1116  gRandom->Rannor(x,y);
1117  if(x>0 && y>0) h1->Fill(x,y,4);
1118  if(x<0 && y<0) h2->Fill(x,y,3);
1119  if(x>0 && y<0) h3->Fill(x,y,2);
1120  if(x<0 && y>0) h4->Fill(x,y,1);
1121  }
1122  h1->Draw("colz");
1123  h2->Draw("col same");
1124  h3->Draw("col same");
1125  h4->Draw("col same");
1126 }
1127 End_Macro
1128 
1129 The option `COL` can be combined with the option `POL`:
1130 
1131 Begin_Macro(source)
1132 {
1133  auto c1 = new TCanvas("c1","c1",600,400);
1134  auto hcol1 = new TH2F("hcol1","Option COLor combined with POL",40,-4,4,40,-4,4);
1135  float px, py;
1136  for (Int_t i = 0; i < 25000; i++) {
1137  gRandom->Rannor(px,py);
1138  hcol1->Fill(px,py);
1139  }
1140  hcol1->Draw("COLZPOL");
1141 }
1142 End_Macro
1143 
1144 \since **ROOT version 6.07/03:**
1145 
1146 A second rendering technique is also available with the COL2 and COLZ2 options.
1147 
1148 These options provide potential performance improvements compared to the standard
1149 COL option. The performance comparison of the COL2 to the COL option depends on
1150 the histogram and the size of the rendering region in the current pad. In general,
1151 a small (approx. less than 100 bins per axis), sparsely populated TH2 will render
1152 faster with the COL option.
1153 
1154 However, for larger histograms (approx. more than 100 bins per axis)
1155 that are not sparse, the COL2 option will provide up to 20 times performance improvements.
1156 For example, a 1000x1000 bin TH2 that is not sparse will render an order of magnitude
1157 faster with the COL2 option.
1158 
1159 The COL2 option will also scale its performance based on the size of the
1160 pixmap the histogram image is being rendered into. It also is much better optimized for
1161 sessions where the user is forwarding X11 windows through an `ssh` connection.
1162 
1163 For the most part, the COL2 and COLZ2 options are a drop in replacement to the COL
1164 and COLZ options. There is one major difference and that concerns the treatment of
1165 bins with zero content. The COL2 and COLZ2 options color these bins the color of zero.
1166 
1167 COL2 option renders the histogram as a bitmap. Therefore it cannot be saved in vector
1168 graphics file format like PostScript or PDF (an empty image will be generated). It can
1169 be saved only in bitmap files like PNG format for instance.
1170 
1171 
1172 ### <a name="HP140"></a> The CANDLE and VIOLIN options
1173 
1174 The mechanism behind Candle plots and Violin plots is very similar. Because of this they are
1175 implemented in the same class TCandle. The keywords CANDLE or VIOLIN will initiate the drawing of
1176 the corresponding plots. Followed by the keyword the user can select a plot direction (X or V for
1177 vertical projections, or Y or H for horizontal projections) and/or predefined definitions
1178 (1-6 for candles, 1-2 for violins). The order doesn't matter. Default is X and 1.
1179 
1180 Instead of using the predefined representations, the candle and violin parameters can be
1181 changed individually. In that case the option have the following form:
1182 
1183  CANDLEX(<option-string>)
1184  CANDLEY(<option-string>)
1185  VIOLINX(<option-string>)
1186  VIOLINY(<option-string>).
1187 
1188 All zeros at the beginning of `option-string` can be omitted.
1189 
1190 `option-string` consists eight values, defined as follow:
1191 
1192  "CANDLEX(zhpawMmb)"
1193 
1194 Where:
1195 
1196  - `b = 0`; no box drawn
1197  - `b = 1`; the box is drawn. As the candle-plot is also called a box-plot it
1198  makes sense in the very most cases to always draw the box
1199  - `b = 2`; draw a filled box with border
1200 
1201  - `m = 0`; no median drawn
1202  - `m = 1`; median is drawn as a line
1203  - `m = 2`; median is drawn with errors (notches)
1204  - `m = 3`; median is drawn as a circle
1205 
1206  - `M = 0`; no mean drawn
1207  - `M = 1`; mean is drawn as a dashed line
1208  - `M = 3`; mean is drawn as a circle
1209 
1210  - `w = 0`; no whisker drawn
1211  - `w = 1`; whisker is drawn to end of distribution.
1212  - `w = 2`; whisker is drawn to max 1.5*iqr
1213 
1214  - `a = 0`; no anchor drawn
1215  - `a = 1`; the anchors are drawn
1216 
1217  - `p = 0`; no points drawn
1218  - `p = 1`; only outliers are drawn
1219  - `p = 2`; all datapoints are drawn
1220  - `p = 3`: all datapoints are drawn scattered
1221 
1222  - `h = 0`; no histogram is drawn
1223  - `h = 1`; histogram at the left or bottom side is drawn
1224  - `h = 2`; histogram at the right or top side is drawn
1225  - `h = 3`; histogram at left and right or top and bottom (violin-style) is drawn
1226 
1227  - `z = 0`; no zero indicator line is drawn
1228  - `z = 1`; zero indicator line is drawn.
1229 
1230 As one can see all individual options for both candle and violin plots can be accessed by this
1231 mechanism. In deed the keywords CANDLE(<option-string>) and VIOLIN(<option-string>) have the same
1232 meaning. So you can parametrise an option-string for a candle plot and use the keywords VIOLIN and
1233 vice versa, if you wish.
1234 
1235 Using a logarithmic x- or y-axis is possible for candle and violin charts.
1236 
1237 \since **ROOT version 6.11/01**
1238 
1239 a logarithmic z-axis is possible, too but will only affect violin charts of course.
1240 
1241 #### <a name="HP140a"></a> The CANDLE option
1242 
1243 <a href="http://en.wikipedia.org/wiki/Box_plot">A Candle plot</a> (also known as
1244 a "box plot" or "whisker plot") was invented in 1977 by John Tukey. It is a convenient
1245 way to describe graphically a data distribution (D) with only five numbers:
1246 
1247  1. The minimum value of the distribution D (bottom or left whisker).
1248  2. The lower quartile (Q1): 25% of the data points in D are less than Q1 (bottom of the box).
1249  3. The median (M): 50% of the data points in D are less than M.
1250  4. The upper quartile (Q3): 75% of the data points in D are less than Q3 (top of the box).
1251  5. The maximum value of the distribution D (top or right whisker).
1252 
1253 In this implementation a TH2 is considered as a collection of TH1 along
1254 X (option `CANDLE` or `CANDLEX`) or Y (option `CANDLEY`).
1255 Each TH1 is represented as one candle.
1256 
1257 Begin_Macro(source)
1258 ../../../tutorials/hist/candleplotwhiskers.C
1259 End_Macro
1260 
1261 The candle reduces the information coming from a whole distribution into few values.
1262 Independently from the number of entries or the significance of the underlying distribution
1263 a candle will always look like a candle. So candle plots should be used carefully in
1264 particular with unknown distributions. The definition of a candle is based on
1265 __unbinned data__. Here, candles are created from binned data. Because of this, the
1266 deviation is connected to the bin width used. The calculation of the quantiles
1267 normally done on unbinned data also. Because data are binned, this will
1268 only work the best possible way within the resolution of one bin
1269 
1270 Because of all these facts one should take care that:
1271 
1272  - there are enough points per candle
1273  - the bin width is small enough (more bins will increase the maximum
1274  available resolution of the quantiles although there will be some
1275  bins with no entries)
1276  - never make a candle-plot if the underlying distribution is double-distributed
1277  - only create candles of distributions that are more-or-less gaussian (the
1278  MPV should be not too far away from the mean).
1279 
1280 #### What a candle is made of
1281 
1282 \since **ROOT version 6.07/05**
1283 
1284 ##### The box
1285 The box displays the position of the inter-quantile-range of the underlying
1286 distribution. The box contains 25% of the distribution below the median
1287 and 25% of the distribution above the median. If the underlying distribution is large
1288 enough and gaussian shaped the end-points of the box represent \f$ 0.6745\times\sigma \f$
1289 (Where \f$ \sigma \f$ is the standard deviation of the gaussian). The width and
1290 the position of the box can be modified by SetBarWidth() and SetBarOffset().
1291 The +-25% quantiles are calculated by the GetQuantiles() methods.
1292 
1293 \since **ROOT version 6.11/01**
1294 
1295 Using the static function TCandle::SetBoxRange(double) the box definition will be
1296 overwritten. E.g. using a box range of 0.68 will redefine the area of the lower box edge
1297 to the upper box edge in order to cover 68% of the distribution illustrated by that candle.
1298 The static function will affect all candle-charts in the running program.
1299 Default is 0.5.
1300 
1301 Using the static function TCandle::SetScaledCandle(bool) the width of the box (and the
1302 whole candle) can be influenced. Deactivated, the width is constant (to be set by
1303 SetBarWidth() ). Activated, the width of the boxes will be scaled to each other based on the
1304 amount of data in the corresponding candle, the maximum width can be influenced by
1305 SetBarWidth(). The static function will affect all candle-charts in the running program.
1306 Default is false. Scaling between multiple candle-charts (using "same" or THStack) is not
1307 supported, yet
1308 
1309 ##### The Median
1310 For a sorted list of numbers, the median is the value in the middle of the list.
1311 E.g. if a sorted list is made of five numbers "1,2,3,6,7" 3 will be the median
1312 because it is in the middle of the list. If the number of entries is even the
1313 average of the two values in the middle will be used. As histograms are binned
1314 data, the situation is a bit more complex. The following example shows this:
1315 
1316 ~~~ {.cpp}
1317 void quantiles() {
1318  auto h = new TH1I("h","h",10,0,10);
1319  //h->Fill(3);
1320  //h->Fill(3);
1321  h->Fill(4);
1322  h->Draw();
1323  double p = 0.;
1324  double q = 0.;
1325  h->GetQuantiles(1,&q,&p);
1326 
1327  cout << "Median is: " << q << std::endl;
1328 }
1329 ~~~
1330 
1331 Here the bin-width is 1.0. If the two Fill(3) are commented out, as there are currently,
1332 the example will return a calculated median of 4.5, because that's the bin center
1333 of the bin in which the value 4.0 has been dropped. If the two Fill(3) are not
1334 commented out, it will return 3.75, because the algorithm tries to evenly distribute
1335 the individual values of a bin with bin content > 0. It means the sorted list
1336 would be "3.25, 3.75, 4.5".
1337 
1338 The consequence is a median of 3.75. This shows how important it is to use a
1339 small enough bin-width when using candle-plots on binned data.
1340 If the distribution is large enough and gaussian shaped the median will be exactly
1341 equal to the mean.
1342 The median can be shown as a line or as a circle or not shown at all.
1343 
1344 In order to show the significance of the median notched candle plots apply a "notch" or
1345 narrowing of the box around the median. The significance is defined by
1346 \f$ 1.57\times\frac{iqr}{N} \f$ and will be represented as the size of the notch
1347 (where iqr is the size of the box and N is the number of entries of the whole
1348 distribution). Candle plots like these are usually called "notched candle plots".
1349 
1350 In case the significance of the median is greater that the size of the box, the
1351 box will have an unnatural shape. Usually it means the chart has not enough data,
1352 or that representing this uncertainty is not useful
1353 
1354 ##### The Mean
1355 The mean can be drawn as a dashed line or as a circle or not drawn at all.
1356 The mean is the arithmetic average of the values in the distribution.
1357 It is calculated using GetMean(). Because histograms are
1358 binned data, the mean value can differ from a calculation on the raw-data.
1359 If the distribution is large enough and gaussian shaped the mean will be
1360 exactly the median.
1361 
1362 ##### The Whiskers
1363 The whiskers represent the part of the distribution not covered by the box.
1364 The upper 25% and the lower 25% of the distribution are located within the whiskers.
1365 Two representations are available.
1366 
1367  - A simple one (using w=1) defining the lower whisker from the lowest data value
1368  to the bottom of the box, and the upper whisker from the top of the box to the
1369  highest data value. In this representation the whisker-lines are dashed.
1370  - A more complex one having a further restriction. The whiskers are still connected
1371  to the box but their length cannot exceed \f$ 1.5\times iqr \f$. So it might
1372  be that the outermost part of the underlying distribution will not be covered
1373  by the whiskers. Usually these missing parts will be represented by the outliers
1374  (see points). Of course the upper and the lower whisker may differ in length.
1375  In this representation the whiskers are drawn as solid lines.
1376 
1377 \since **ROOT version 6.11/01**
1378 
1379 Using the static function TCandle::SetWhiskerRange(double) the whisker definition w=1
1380 will be overwritten. E.g. using a whisker-range of 0.95 and w=1 will redefine the area of
1381 the lower whisker to the upper whisker in order to cover 95% of the distribution inside
1382 that candle. The static function will affect all candle-charts in the running program.
1383 Default is 1.
1384 
1385 If the distribution is large enough and gaussian shaped, the maximum length of
1386 the whisker will be located at \f$ \pm 2.698 \sigma \f$ (when using the
1387 1.5*iqr-definition (w=2), where \f$ \sigma \f$ is the standard deviation
1388 (see picture above). In that case 99.3% of the total distribution will be covered
1389 by the box and the whiskers, whereas 0.7% are represented by the outliers.
1390 
1391 ##### The Anchors
1392 The anchors have no special meaning in terms of statistical calculation. They mark
1393 the end of the whiskers and they have the width of the box. Both representation
1394 with and without anchors are common.
1395 
1396 ##### The Points
1397 Depending on the configuration the points can have different meanings:
1398  - If p=1 the points represent the outliers. If they are shown, it means
1399  some parts of the underlying distribution are not covered by the whiskers.
1400  This can only occur when the whiskers are set to option w=2. Here the whiskers
1401  can have a maximum length of \f$ 1.5 \times iqr \f$. So any points outside the
1402  whiskers will be drawn as outliers. The outliers will be represented by crosses.
1403  - If p=2 all points in the distribution will be painted as crosses. This is
1404  useful for small datasets only (up to 10 or 20 points per candle).
1405  The outliers are shown along the candle. Because the underlying distribution
1406  is binned, is frequently occurs that a bin contains more than one value.
1407  Because of this the points will be randomly scattered within their bin along
1408  the candle axis. If the bin content for a bin is exactly 1 (usually
1409  this happens for the outliers) if will be drawn in the middle of the bin along
1410  the candle axis. As the maximum number of points per candle is limited by kNMax/2
1411  on very large datasets scaling will be performed automatically. In that case one
1412  would loose all outliers because they have usually a bin content of 1 (and a
1413  bin content between 0 and 1 after the scaling). Because of this all bin contents
1414  between 0 and 1 - after the scaling - will be forced to be 1.
1415  - As the drawing of all values on large datasets can lead to big amounts of crosses,
1416  one can show all values as a scatter plot instead by choosing p=3. The points will be
1417  drawn as dots and will be scattered within the width of the candle. The color
1418  of the points will be the color of the candle-chart.
1419 
1420 ##### Other Options
1421 Is is possible to combine all options of candle and violin plots with each other. E.g. a box-plot
1422 with a histogram.
1423 
1424 #### How to use the candle-plots drawing option
1425 
1426 There are six predefined candle-plot representations:
1427 
1428  - "CANDLEX1": Standard candle (whiskers cover the whole distribution)
1429  - "CANDLEX2": Standard candle with better whisker definition + outliers.
1430  It is a good compromise
1431  - "CANDLEX3": Like candle2 but with a mean as a circle.
1432  It is easier to distinguish mean and median
1433  - "CANDLEX4": Like candle3 but showing the uncertainty of the median as well
1434  (notched candle plots).
1435  For bigger datasets per candle
1436  - "CANDLEX5": Like candle2 but showing all data points.
1437  For very small datasets
1438  - "CANDLEX6": Like candle2 but showing all datapoints scattered.
1439  For huge datasets
1440 
1441 
1442 The following picture shows how the six predefined representations look.
1443 
1444 Begin_Macro
1445 {
1446  auto c1 = new TCanvas("c1","c1",700,800);
1447  c1->Divide(2,3);
1448  gStyle->SetOptStat(kFALSE);
1449 
1450  auto hcandle = new TH2F("hcandle"," ",10,-4,4,40,-20,20);
1451  float px, py;
1452  for (Int_t i = 0; i < 15000; i++) {
1453  gRandom->Rannor(px,py);
1454  hcandle->Fill(px,5*py);
1455  }
1456  hcandle->SetMarkerSize(0.5);
1457 
1458  TH2F *h2;
1459  for (Int_t i=1; i<7; i++) {
1460  c1->cd(i);
1461  h2 = (TH2F*)hcandle->DrawClone(Form("CANDLE%d",i));
1462  h2->SetTitle(Form("CANDLE%d",i));
1463  }
1464 }
1465 End_Macro
1466 
1467 
1468 #### Example 1
1469 Box and improved whisker, no mean, no median, no anchor no outliers
1470 
1471  h1->Draw("CANDLEX(2001)");
1472 
1473 #### Example 2
1474 A Candle-definition like "CANDLEX2" (New standard candle with better whisker definition + outliers)
1475 
1476  h1->Draw("CANDLEX(112111)");
1477 
1478 #### Example 3
1479 The following example shows how several candle plots can be super-imposed using
1480 the option SAME. Note that the bar-width and bar-offset are active on candle plots.
1481 Also the color, the line width, the size of the points and so on can be changed by the
1482 standard attribute setting methods such as SetLineColor() SetLineWidth().
1483 
1484 Begin_Macro(source)
1485 ../../../tutorials/hist/candleplot.C
1486 End_Macro
1487 
1488 #### <a name="HP140b"></a> The VIOLIN option
1489 
1490 <a href="http://en.wikipedia.org/wiki/Violin_plot">A violin plot</a> is a candle plot
1491 that also encodes the pdf information at each point.
1492 
1493 
1494 Quartiles and mean are also represented at each point, with a marker
1495 and two lines.
1496 
1497 In this implementation a TH2 is considered as a collection of TH1 along
1498 X (option `VIOLIN` or `VIOLINX`) or Y (option `VIOLINY`).
1499 
1500 #### What a violin is made of
1501 
1502 \since **ROOT version 6.09/02**
1503 
1504 ##### The histogram
1505 The histogram is typically drawn to both directions with respect to the middle-line of the
1506 corresponding bin. This can be achieved by using h=3. It is possible to draw a histogram only to
1507 one side (h=1, or h=2).
1508 The maximum number of bins in the histogram is limited to 500, if the number of bins in the used
1509 histogram is higher it will be rebinned automatically. The maximum height of the histogram can
1510 be modified by using SetBarWidth() and the position can be changed with SetBarOffset().
1511 A solid fill style is recommended.
1512 
1513 \since **ROOT version 6.11/01**
1514 
1515 Using the static function TCandle::SetScaledViolin(bool) the height of the histogram or the
1516 violin can be influenced. Activated, the height of the bins of the individual violins will be
1517 scaled with respect to each other, the maximum height can be influenced by SetBarWidth().
1518 Deactivated, the height of the bin with the maximum content of each individual violin is
1519 set to a constant value using SetBarWidth(). The static function will affect all violin-charts
1520 in the running program. Default is true. Scaling between multiple violin-charts
1521 (using "same" or THStack) is not supported, yet.
1522 
1523 ##### The zero indicator line
1524 Typical for violin charts is a line in the background over the whole histogram indicating
1525 the bins with zero entries. The zero indicator line can be activated with z=1. The line color
1526 will always be the same as the fill-color of the histogram.
1527 
1528 ##### The Mean
1529 The Mean is illustrated with the same mechanism as used for candle plots. Usually a circle is used.
1530 
1531 ##### Whiskers
1532 The whiskers are illustrated by the same mechanism as used for candle plots. There is only one
1533 difference. When using the simple whisker definition (w=1) and the zero indicator line (z=1), then
1534 the whiskers will be forced to be solid (usually hashed)
1535 
1536 ##### Points
1537 The points are illustrated by the same mechanism as used for candle plots. E.g. VIOLIN2 uses
1538 better whisker definition (w=2) and outliers (p=1).
1539 
1540 ##### Other options
1541 It is possible to combine all options of candle or violin plots with each other. E.g. a violin plot
1542 including a box-plot.
1543 
1544 #### How to use the violin-plots drawing option
1545 
1546 There are two predefined violin-plot representations:
1547  - "VIOLINX1": Standard violin (histogram, mean, whisker over full distribution,
1548  zero indicator line)
1549  - "VIOLINX2": Line VIOLINX1 both with better whisker definition + outliers.
1550 
1551 A solid fill style is recommended for this plot (as opposed to a hollow or
1552 hashed style).
1553 
1554 Begin_Macro(source)
1555 {
1556  auto c1 = new TCanvas("c1","c1",600,400);
1557  Int_t nx(6), ny(40);
1558  double xmin(0.0), xmax(+6.0), ymin(0.0), ymax(+4.0);
1559  auto hviolin = new TH2F("hviolin", "Option VIOLIN example", nx, xmin, xmax, ny, ymin, ymax);
1560  TF1 f1("f1", "gaus", +0,0 +4.0);
1561  double x,y;
1562  for (Int_t iBin=1; iBin<hviolin->GetNbinsX(); ++iBin) {
1563  double xc = hviolin->GetXaxis()->GetBinCenter(iBin);
1564  f1.SetParameters(1, 2.0+TMath::Sin(1.0+xc), 0.2+0.1*(xc-xmin)/xmax);
1565  for(Int_t i=0; i<10000; ++i){
1566  x = xc;
1567  y = f1.GetRandom();
1568  hviolin->Fill(x, y);
1569  }
1570  }
1571  hviolin->SetFillColor(kGray);
1572  hviolin->SetMarkerStyle(20);
1573  hviolin->SetMarkerSize(0.5);
1574  hviolin->Draw("VIOLIN");
1575  c1->Update();
1576 }
1577 End_Macro
1578 
1579 The next example illustrates a time development of a certain value:
1580 
1581 Begin_Macro(source)
1582 ../../../tutorials/hist/candledecay.C
1583 End_Macro
1584 
1585 
1586 ### <a name="HP15"></a> The TEXT and TEXTnn Option
1587 
1588 
1589 For each bin the content is printed. The text attributes are:
1590 
1591 - text font = current TStyle font (`gStyle->SetTextFont()`).
1592 - text size = 0.02*padheight*markersize (if `h` is the histogram drawn
1593  with the option `TEXT` the marker size can be changed with
1594  `h->SetMarkerSize(markersize)`).
1595 - text color = marker color.
1596 
1597 By default the format `g` is used. This format can be redefined
1598 by calling `gStyle->SetPaintTextFormat()`.
1599 
1600 It is also possible to use `TEXTnn` in order to draw the text with
1601 the angle `nn` (`0 < nn < 90`).
1602 
1603 For 2D histograms the text is plotted in the center of each non empty cells.
1604 It is possible to plot empty cells by calling `gStyle->SetHistMinimumZero()`
1605 or providing MIN0 draw option. For 1D histogram the text is plotted at a y
1606 position equal to the bin content.
1607 
1608 For 2D histograms when the option "E" (errors) is combined with the option
1609 text ("TEXTE"), the error for each bin is also printed.
1610 
1611 Begin_Macro(source)
1612 {
1613  auto c01 = new TCanvas("c01","c01",700,400);
1614  c01->Divide(2,1);
1615  auto htext1 = new TH1F("htext1","Option TEXT on 1D histograms ",10,-4,4);
1616  auto htext2 = new TH2F("htext2","Option TEXT on 2D histograms ",10,-4,4,10,-20,20);
1617  float px, py;
1618  for (Int_t i = 0; i < 25000; i++) {
1619  gRandom->Rannor(px,py);
1620  htext1->Fill(px,0.1);
1621  htext2->Fill(px,5*py,0.1);
1622  }
1623  gStyle->SetPaintTextFormat("4.1f m");
1624  htext2->SetMarkerSize(1.8);
1625  c01->cd(1);
1626  htext2->Draw("TEXT45");
1627  c01->cd(2);
1628  htext1->Draw();
1629  htext1->Draw("HIST TEXT0 SAME");
1630 }
1631 End_Macro
1632 
1633 \since **ROOT version 6.07/07:**
1634 
1635 In case several histograms are drawn on top ot each other (using option `SAME`),
1636 the text can be shifted using `SetBarOffset()`. It specifies an offset for the
1637 text position in each cell, in percentage of the bin width.
1638 
1639 Begin_Macro(source)
1640 {
1641  auto c03 = new TCanvas("c03","c03",700,400);
1642  gStyle->SetOptStat(0);
1643  auto htext3 = new TH2F("htext3","Several 2D histograms drawn with option TEXT",10,-4,4,10,-20,20);
1644  auto htext4 = new TH2F("htext4","htext4",10,-4,4,10,-20,20);
1645  auto htext5 = new TH2F("htext5","htext5",10,-4,4,10,-20,20);
1646  float px, py;
1647  for (Int_t i = 0; i < 25000; i++) {
1648  gRandom->Rannor(px,py);
1649  htext3->Fill(4*px,20*py,0.1);
1650  htext4->Fill(4*px,20*py,0.5);
1651  htext5->Fill(4*px,20*py,1.0);
1652  }
1653  htext4->SetMarkerSize(1.8);
1654  htext5->SetMarkerSize(1.8);
1655  htext5->SetMarkerColor(kRed);
1656  htext3->Draw("COL");
1657  htext4->SetBarOffset(0.2);
1658  htext4->Draw("TEXT SAME");
1659  htext5->SetBarOffset(-0.2);
1660  htext5->Draw("TEXT SAME");
1661 }
1662 End_Macro
1663 
1664 In the case of profile histograms it is possible to print the number
1665 of entries instead of the bin content. It is enough to combine the
1666 option "E" (for entries) with the option "TEXT".
1667 
1668 Begin_Macro(source)
1669 {
1670  auto c02 = new TCanvas("c02","c02",700,400);
1671  c02->Divide(2,1);
1672  gStyle->SetPaintTextFormat("g");
1673 
1674  auto profile = new TProfile("profile","profile",10,0,10);
1675  profile->SetMarkerSize(2.2);
1676  profile->Fill(0.5,1);
1677  profile->Fill(1.5,2);
1678  profile->Fill(2.5,3);
1679  profile->Fill(3.5,4);
1680  profile->Fill(4.5,5);
1681  profile->Fill(5.5,5);
1682  profile->Fill(6.5,4);
1683  profile->Fill(7.5,3);
1684  profile->Fill(8.5,2);
1685  profile->Fill(9.5,1);
1686  c02->cd(1); profile->Draw("HIST TEXT0");
1687  c02->cd(2); profile->Draw("HIST TEXT0E");
1688 }
1689 End_Macro
1690 
1691 ### <a name="HP16"></a> The CONTour options
1692 
1693 
1694 The following contour options are supported:
1695 
1696 | Option | Description |
1697 |----------|-------------------------------------------------------------------|
1698 | "CONT" | Draw a contour plot (same as CONT0).|
1699 | "CONT0" | Draw a contour plot using surface colors to distinguish contours.|
1700 | "CONT1" | Draw a contour plot using the line colors to distinguish contours.|
1701 | "CONT2" | Draw a contour plot using the line styles to distinguish contours.|
1702 | "CONT3" | Draw a contour plot solid lines for all contours.|
1703 | "CONT4" | Draw a contour plot using surface colors (`SURF` option at theta = 0).|
1704 | "CONT5" | Draw a contour plot using Delaunay triangles.|
1705 
1706 
1707 
1708 The following example shows a 2D histogram plotted with the option
1709 `CONTZ`. The option `CONT` draws a contour plot using surface
1710 colors to distinguish contours. Combined with the option `CONT` (or
1711 `CONT0`), the option `Z` allows to display the color palette
1712 defined by `gStyle->SetPalette()`.
1713 
1714 Begin_Macro(source)
1715 {
1716  auto c1 = new TCanvas("c1","c1",600,400);
1717  auto hcontz = new TH2F("hcontz","Option CONTZ example ",40,-4,4,40,-20,20);
1718  float px, py;
1719  for (Int_t i = 0; i < 25000; i++) {
1720  gRandom->Rannor(px,py);
1721  hcontz->Fill(px-1,5*py);
1722  hcontz->Fill(2+0.5*px,2*py-10.,0.1);
1723  }
1724  hcontz->Draw("CONTZ");
1725 }
1726 End_Macro
1727 
1728 The following example shows a 2D histogram plotted with the option
1729 `CONT1Z`. The option `CONT1` draws a contour plot using the
1730 line colors to distinguish contours. Combined with the option `CONT1`,
1731 the option `Z` allows to display the color palette defined by
1732 `gStyle->SetPalette()`.
1733 
1734 Begin_Macro(source)
1735 {
1736  auto c1 = new TCanvas("c1","c1",600,400);
1737  auto hcont1 = new TH2F("hcont1","Option CONT1Z example ",40,-4,4,40,-20,20);
1738  float px, py;
1739  for (Int_t i = 0; i < 25000; i++) {
1740  gRandom->Rannor(px,py);
1741  hcont1->Fill(px-1,5*py);
1742  hcont1->Fill(2+0.5*px,2*py-10.,0.1);
1743  }
1744  hcont1->Draw("CONT1Z");
1745 }
1746 End_Macro
1747 
1748 The following example shows a 2D histogram plotted with the option
1749 `CONT2`. The option `CONT2` draws a contour plot using the
1750 line styles to distinguish contours.
1751 
1752 Begin_Macro(source)
1753 {
1754  auto c1 = new TCanvas("c1","c1",600,400);
1755  auto hcont2 = new TH2F("hcont2","Option CONT2 example ",40,-4,4,40,-20,20);
1756  float px, py;
1757  for (Int_t i = 0; i < 25000; i++) {
1758  gRandom->Rannor(px,py);
1759  hcont2->Fill(px-1,5*py);
1760  hcont2->Fill(2+0.5*px,2*py-10.,0.1);
1761  }
1762  hcont2->Draw("CONT2");
1763 }
1764 End_Macro
1765 
1766 The following example shows a 2D histogram plotted with the option
1767 `CONT3`. The option `CONT3` draws contour plot solid lines for
1768 all contours.
1769 
1770 Begin_Macro(source)
1771 {
1772  auto c1 = new TCanvas("c1","c1",600,400);
1773  auto hcont3 = new TH2F("hcont3","Option CONT3 example ",40,-4,4,40,-20,20);
1774  float px, py;
1775  for (Int_t i = 0; i < 25000; i++) {
1776  gRandom->Rannor(px,py);
1777  hcont3->Fill(px-1,5*py);
1778  hcont3->Fill(2+0.5*px,2*py-10.,0.1);
1779  }
1780  hcont3->Draw("CONT3");
1781 }
1782 End_Macro
1783 
1784 The following example shows a 2D histogram plotted with the option
1785 `CONT4`. The option `CONT4` draws a contour plot using surface
1786 colors to distinguish contours (`SURF` option at theta = 0). Combined
1787 with the option `CONT` (or `CONT0`), the option `Z`
1788 allows to display the color palette defined by `gStyle->SetPalette()`.
1789 
1790 Begin_Macro(source)
1791 {
1792  auto c1 = new TCanvas("c1","c1",600,400);
1793  auto hcont4 = new TH2F("hcont4","Option CONT4Z example ",40,-4,4,40,-20,20);
1794  float px, py;
1795  for (Int_t i = 0; i < 25000; i++) {
1796  gRandom->Rannor(px,py);
1797  hcont4->Fill(px-1,5*py);
1798  hcont4->Fill(2+0.5*px,2*py-10.,0.1);
1799  }
1800  hcont4->Draw("CONT4Z");
1801 }
1802 End_Macro
1803 
1804 The default number of contour levels is 20 equidistant levels and can be changed
1805 with `TH1::SetContour()` or `TStyle::SetNumberContours()`.
1806 
1807 #### <a name="HP16a"></a> The LIST option
1808 
1809 When option `LIST` is specified together with option
1810 `CONT`, the points used to draw the contours are saved in
1811 `TGraph` objects:
1812 
1813  h->Draw("CONT LIST");
1814  gPad->Update();
1815 
1816 The contour are saved in `TGraph` objects once the pad is painted.
1817 Therefore to use this functionality in a macro, `gPad->Update()`
1818 should be performed after the histogram drawing. Once the list is
1819 built, the contours are accessible in the following way:
1820 
1821  TObjArray *contours = gROOT->GetListOfSpecials()->FindObject("contours")
1822  Int_t ncontours = contours->GetSize();
1823  TList *list = (TList*)contours->At(i);
1824 
1825 Where `i` is a contour number, and list contains a list of
1826 `TGraph` objects.
1827 For one given contour, more than one disjoint polyline may be generated.
1828 The number of TGraphs per contour is given by:
1829 
1830  list->GetSize();
1831 
1832 To access the first graph in the list one should do:
1833 
1834  TGraph *gr1 = (TGraph*)list->First();
1835 
1836 
1837 The following example (ContourList.C) shows how to use this functionality.
1838 
1839 Begin_Macro(source)
1840 ../../../tutorials/hist/ContourList.C
1841 End_Macro
1842 
1843 #### <a name="HP16b"></a> The AITOFF, MERCATOR, SINUSOIDAL and PARABOLIC options
1844 
1845 The following options select the `CONT4` option and are useful for
1846 sky maps or exposure maps (earth.C).
1847 
1848 | Option | Description |
1849 |--------------|---------------------------------------------------------------|
1850 | "AITOFF" | Draw a contour via an AITOFF projection.|
1851 | "MERCATOR" | Draw a contour via an Mercator projection.|
1852 | "SINUSOIDAL" | Draw a contour via an Sinusoidal projection.|
1853 | "PARABOLIC" | Draw a contour via an Parabolic projection.|
1854 
1855 Begin_Macro(source)
1856 ../../../tutorials/graphics/earth.C
1857 End_Macro
1858 
1859 
1860 ### <a name="HP17"></a> The LEGO options
1861 
1862 
1863 In a lego plot the cell contents are drawn as 3-d boxes. The height of each box
1864 is proportional to the cell content. The lego aspect is control with the
1865 following options:
1866 
1867 | Option | Description |
1868 |----------|-------------------------------------------------------------------|
1869 | "LEGO" | Draw a lego plot using the hidden lines removal technique.|
1870 | "LEGO1" | Draw a lego plot using the hidden surface removal technique.|
1871 | "LEGO2" | Draw a lego plot using colors to show the cell contents.|
1872 | "LEGO3" | Draw a lego plot with hidden surface removal, like LEGO1 but the border lines of each lego-bar are not drawn.|
1873 | "LEGO4" | Draw a lego plot with hidden surface removal, like LEGO1 but without the shadow effect on each lego-bar.|
1874 | "0" | When used with any LEGO option, the empty bins are not drawn.|
1875 
1876 
1877 See the limitations with [the option "SAME"](#HP060a).
1878 
1879 Line attributes can be used in lego plots to change the edges' style.
1880 
1881 The following example shows a 2D histogram plotted with the option
1882 `LEGO`. The option `LEGO` draws a lego plot using the hidden
1883 lines removal technique.
1884 
1885 Begin_Macro(source)
1886 {
1887  auto c2 = new TCanvas("c2","c2",600,400);
1888  auto hlego = new TH2F("hlego","Option LEGO example ",40,-4,4,40,-20,20);
1889  float px, py;
1890  for (Int_t i = 0; i < 25000; i++) {
1891  gRandom->Rannor(px,py);
1892  hlego->Fill(px-1,5*py);
1893  hlego->Fill(2+0.5*px,2*py-10.,0.1);
1894  }
1895  hlego->Draw("LEGO");
1896 }
1897 End_Macro
1898 
1899 The following example shows a 2D histogram plotted with the option
1900 `LEGO1`. The option `LEGO1` draws a lego plot using the
1901 hidden surface removal technique. Combined with any `LEGOn` option, the
1902 option `0` allows to not drawn the empty bins.
1903 
1904 Begin_Macro(source)
1905 {
1906  auto c2 = new TCanvas("c2","c2",600,400);
1907  auto hlego1 = new TH2F("hlego1","Option LEGO1 example (with option 0) ",40,-4,4,40,-20,20);
1908  float px, py;
1909  for (Int_t i = 0; i < 25000; i++) {
1910  gRandom->Rannor(px,py);
1911  hlego1->Fill(px-1,5*py);
1912  hlego1->Fill(2+0.5*px,2*py-10.,0.1);
1913  }
1914  hlego1->SetFillColor(kYellow);
1915  hlego1->Draw("LEGO1 0");
1916 }
1917 End_Macro
1918 
1919 The following example shows a 2D histogram plotted with the option
1920 `LEGO3`. Like the option `LEGO1`, the option `LEGO3`
1921 draws a lego plot using the hidden surface removal technique but doesn't draw
1922 the border lines of each individual lego-bar. This is very useful for histograms
1923 having many bins. With such histograms the option `LEGO1` gives a black
1924 image because of the border lines. This option also works with stacked legos.
1925 
1926 Begin_Macro(source)
1927 {
1928  auto c2 = new TCanvas("c2","c2",600,400);
1929  auto hlego3 = new TH2F("hlego3","Option LEGO3 example",40,-4,4,40,-20,20);
1930  float px, py;
1931  for (Int_t i = 0; i < 25000; i++) {
1932  gRandom->Rannor(px,py);
1933  hlego3->Fill(px-1,5*py);
1934  hlego3->Fill(2+0.5*px,2*py-10.,0.1);
1935  }
1936  hlego3->SetFillColor(kRed);
1937  hlego3->Draw("LEGO3");
1938 }
1939 End_Macro
1940 
1941 The following example shows a 2D histogram plotted with the option
1942 `LEGO2`. The option `LEGO2` draws a lego plot using colors to
1943 show the cell contents. Combined with the option `LEGO2`, the option
1944 `Z` allows to display the color palette defined by
1945 `gStyle->SetPalette()`.
1946 
1947 Begin_Macro(source)
1948 {
1949  auto c2 = new TCanvas("c2","c2",600,400);
1950  auto hlego2 = new TH2F("hlego2","Option LEGO2Z example ",40,-4,4,40,-20,20);
1951  float px, py;
1952  for (Int_t i = 0; i < 25000; i++) {
1953  gRandom->Rannor(px,py);
1954  hlego2->Fill(px-1,5*py);
1955  hlego2->Fill(2+0.5*px,2*py-10.,0.1);
1956  }
1957  hlego2->Draw("LEGO2Z");
1958 }
1959 End_Macro
1960 
1961 
1962 
1963 ### <a name="HP18"></a> The "SURFace" options
1964 
1965 
1966 In a surface plot, cell contents are represented as a mesh.
1967 The height of the mesh is proportional to the cell content.
1968 
1969 | Option | Description |
1970 |----------|-------------------------------------------------------------------|
1971 | "SURF" | Draw a surface plot using the hidden line removal technique.|
1972 | "SURF1" | Draw a surface plot using the hidden surface removal technique.|
1973 | "SURF2" | Draw a surface plot using colors to show the cell contents.|
1974 | "SURF3" | Same as `SURF` with an additional filled contour plot on top.|
1975 | "SURF4" | Draw a surface using the Gouraud shading technique.|
1976 | "SURF5" | Used with one of the options CYL, PSR and CYL this option allows to draw a a filled contour plot.|
1977 | "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.|
1978 | "SURF7" | Same as `SURF2` with an additional line contour plot on top.|
1979 
1980 
1981 
1982 See the limitations with [the option "SAME"](#HP060a).
1983 
1984 The following example shows a 2D histogram plotted with the option
1985 `SURF`. The option `SURF` draws a lego plot using the hidden
1986 lines removal technique.
1987 
1988 Begin_Macro(source)
1989 {
1990  auto c2 = new TCanvas("c2","c2",600,400);
1991  auto hsurf = new TH2F("hsurf","Option SURF example ",30,-4,4,30,-20,20);
1992  float px, py;
1993  for (Int_t i = 0; i < 25000; i++) {
1994  gRandom->Rannor(px,py);
1995  hsurf->Fill(px-1,5*py);
1996  hsurf->Fill(2+0.5*px,2*py-10.,0.1);
1997  }
1998  hsurf->Draw("SURF");
1999 }
2000 End_Macro
2001 
2002 The following example shows a 2D histogram plotted with the option
2003 `SURF1`. The option `SURF1` draws a surface plot using the
2004 hidden surface removal technique. Combined with the option `SURF1`,
2005 the option `Z` allows to display the color palette defined by
2006 `gStyle->SetPalette()`.
2007 
2008 Begin_Macro(source)
2009 {
2010  auto c2 = new TCanvas("c2","c2",600,400);
2011  auto hsurf1 = new TH2F("hsurf1","Option SURF1 example ",30,-4,4,30,-20,20);
2012  float px, py;
2013  for (Int_t i = 0; i < 25000; i++) {
2014  gRandom->Rannor(px,py);
2015  hsurf1->Fill(px-1,5*py);
2016  hsurf1->Fill(2+0.5*px,2*py-10.,0.1);
2017  }
2018  hsurf1->Draw("SURF1");
2019 }
2020 End_Macro
2021 
2022 The following example shows a 2D histogram plotted with the option
2023 `SURF2`. The option `SURF2` draws a surface plot using colors
2024 to show the cell contents. Combined with the option `SURF2`, the option
2025 `Z` allows to display the color palette defined by
2026 `gStyle->SetPalette()`.
2027 
2028 Begin_Macro(source)
2029 {
2030  auto c2 = new TCanvas("c2","c2",600,400);
2031  auto hsurf2 = new TH2F("hsurf2","Option SURF2 example ",30,-4,4,30,-20,20);
2032  float px, py;
2033  for (Int_t i = 0; i < 25000; i++) {
2034  gRandom->Rannor(px,py);
2035  hsurf2->Fill(px-1,5*py);
2036  hsurf2->Fill(2+0.5*px,2*py-10.,0.1);
2037  }
2038  hsurf2->Draw("SURF2");
2039 }
2040 End_Macro
2041 
2042 The following example shows a 2D histogram plotted with the option
2043 `SURF3`. The option `SURF3` draws a surface plot using the
2044 hidden line removal technique with, in addition, a filled contour view drawn on the
2045 top. Combined with the option `SURF3`, the option `Z` allows
2046 to display the color palette defined by `gStyle->SetPalette()`.
2047 
2048 Begin_Macro(source)
2049 {
2050  auto c2 = new TCanvas("c2","c2",600,400);
2051  auto hsurf3 = new TH2F("hsurf3","Option SURF3 example ",30,-4,4,30,-20,20);
2052  float px, py;
2053  for (Int_t i = 0; i < 25000; i++) {
2054  gRandom->Rannor(px,py);
2055  hsurf3->Fill(px-1,5*py);
2056  hsurf3->Fill(2+0.5*px,2*py-10.,0.1);
2057  }
2058  hsurf3->Draw("SURF3");
2059 }
2060 End_Macro
2061 
2062 The following example shows a 2D histogram plotted with the option
2063 `SURF4`. The option `SURF4` draws a surface using the Gouraud
2064 shading technique.
2065 
2066 Begin_Macro(source)
2067 {
2068  auto c2 = new TCanvas("c2","c2",600,400);
2069  auto hsurf4 = new TH2F("hsurf4","Option SURF4 example ",30,-4,4,30,-20,20);
2070  float px, py;
2071  for (Int_t i = 0; i < 25000; i++) {
2072  gRandom->Rannor(px,py);
2073  hsurf4->Fill(px-1,5*py);
2074  hsurf4->Fill(2+0.5*px,2*py-10.,0.1);
2075  }
2076  hsurf4->SetFillColor(kOrange);
2077  hsurf4->Draw("SURF4");
2078 }
2079 End_Macro
2080 
2081 The following example shows a 2D histogram plotted with the option
2082 `SURF5 CYL`. Combined with the option `SURF5`, the option
2083 `Z` allows to display the color palette defined by `gStyle->SetPalette()`.
2084 
2085 Begin_Macro(source)
2086 {
2087  auto c2 = new TCanvas("c2","c2",600,400);
2088  auto hsurf5 = new TH2F("hsurf4","Option SURF5 example ",30,-4,4,30,-20,20);
2089  float px, py;
2090  for (Int_t i = 0; i < 25000; i++) {
2091  gRandom->Rannor(px,py);
2092  hsurf5->Fill(px-1,5*py);
2093  hsurf5->Fill(2+0.5*px,2*py-10.,0.1);
2094  }
2095  hsurf5->Draw("SURF5 CYL");
2096 }
2097 End_Macro
2098 
2099 The following example shows a 2D histogram plotted with the option
2100 `SURF7`. The option `SURF7` draws a surface plot using the
2101 hidden surfaces removal technique with, in addition, a line contour view drawn on the
2102 top. Combined with the option `SURF7`, the option `Z` allows
2103 to display the color palette defined by `gStyle->SetPalette()`.
2104 
2105 Begin_Macro(source)
2106 {
2107  auto c2 = new TCanvas("c2","c2",600,400);
2108  auto hsurf7 = new TH2F("hsurf3","Option SURF7 example ",30,-4,4,30,-20,20);
2109  float px, py;
2110  for (Int_t i = 0; i < 25000; i++) {
2111  gRandom->Rannor(px,py);
2112  hsurf7->Fill(px-1,5*py);
2113  hsurf7->Fill(2+0.5*px,2*py-10.,0.1);
2114  }
2115  hsurf7->Draw("SURF7");
2116 }
2117 End_Macro
2118 
2119 As shown in the following example, when a contour plot is painted on top of a
2120 surface plot using the option `SAME`, the contours appear in 3D on the
2121 surface.
2122 
2123 Begin_Macro(source)
2124 {
2125  auto c20=new TCanvas("c20","c20",600,400);
2126  int NBins = 50;
2127  double d = 2;
2128  auto hsc = new TH2F("hsc", "Surface and contour with option SAME ", NBins, -d, d, NBins, -d, d);
2129  for (int bx = 1; bx <= NBins; ++bx) {
2130  for (int by = 1; by <= NBins; ++by) {
2131  double x = hsc->GetXaxis()->GetBinCenter(bx);
2132  double y = hsc->GetYaxis()->GetBinCenter(by);
2133  hsc->SetBinContent(bx, by, exp(-x*x)*exp(-y*y));
2134  }
2135  }
2136  hsc->Draw("surf2");
2137  hsc->Draw("CONT1 SAME");
2138 }
2139 End_Macro
2140 
2141 
2142 ### <a name="HP19"></a> Cylindrical, Polar, Spherical and PseudoRapidity/Phi options
2143 
2144 
2145 Legos and surfaces plots are represented by default in Cartesian coordinates.
2146 Combined with any `LEGOn` or `SURFn` options the following
2147 options allow to draw a lego or a surface in other coordinates systems.
2148 
2149 | Option | Description |
2150 |----------|-------------------------------------------------------------------|
2151 | "CYL" | Use Cylindrical coordinates. The X coordinate is mapped on the angle and the Y coordinate on the cylinder length.|
2152 | "POL" | Use Polar coordinates. The X coordinate is mapped on the angle and the Y coordinate on the radius.|
2153 | "SPH" | Use Spherical coordinates. The X coordinate is mapped on the latitude and the Y coordinate on the longitude.|
2154 | "PSR" | Use PseudoRapidity/Phi coordinates. The X coordinate is mapped on Phi.|
2155 
2156 
2157 
2158 <b>WARNING:</b> Axis are not drawn with these options.
2159 
2160 The following example shows the same histogram as a lego plot is the four
2161 different coordinates systems.
2162 
2163 Begin_Macro(source)
2164 {
2165  auto c3 = new TCanvas("c3","c3",600,400);
2166  c3->Divide(2,2);
2167  auto hlcc = new TH2F("hlcc","Cylindrical coordinates",20,-4,4,20,-20,20);
2168  float px, py;
2169  for (Int_t i = 0; i < 25000; i++) {
2170  gRandom->Rannor(px,py);
2171  hlcc->Fill(px-1,5*py);
2172  hlcc->Fill(2+0.5*px,2*py-10.,0.1);
2173  }
2174  hlcc->SetFillColor(kYellow);
2175  c3->cd(1); hlcc->Draw("LEGO1 CYL");
2176  c3->cd(2); auto hlpc = (TH2F*) hlcc->DrawClone("LEGO1 POL");
2177  hlpc->SetTitle("Polar coordinates");
2178  c3->cd(3); auto hlsc = (TH2F*) hlcc->DrawClone("LEGO1 SPH");
2179  hlsc->SetTitle("Spherical coordinates");
2180  c3->cd(4); auto hlprpc = (TH2F*) hlcc->DrawClone("LEGO1 PSR");
2181  hlprpc->SetTitle("PseudoRapidity/Phi coordinates");
2182 }
2183 End_Macro
2184 
2185 The following example shows the same histogram as a surface plot is the four different coordinates systems.
2186 
2187 Begin_Macro(source)
2188 {
2189  auto c4 = new TCanvas("c4","c4",600,400);
2190  c4->Divide(2,2);
2191  auto hscc = new TH2F("hscc","Cylindrical coordinates",20,-4,4,20,-20,20);
2192  float px, py;
2193  for (Int_t i = 0; i < 25000; i++) {
2194  gRandom->Rannor(px,py);
2195  hscc->Fill(px-1,5*py);
2196  hscc->Fill(2+0.5*px,2*py-10.,0.1);
2197  }
2198  c4->cd(1); hscc->Draw("SURF1 CYL");
2199  c4->cd(2); auto hspc = (TH2F*) hscc->DrawClone("SURF1 POL");
2200  hspc->SetTitle("Polar coordinates");
2201  c4->cd(3); auto hssc = (TH2F*) hscc->DrawClone("SURF1 SPH");
2202  hssc->SetTitle("Spherical coordinates");
2203  c4->cd(4); auto hsprpc = (TH2F*) hscc->DrawClone("SURF1 PSR");
2204  hsprpc->SetTitle("PseudoRapidity/Phi coordinates");
2205 }
2206 End_Macro
2207 
2208 
2209 ### <a name="HP20"></a> Base line for bar-charts and lego plots
2210 
2211 
2212 By default the base line used to draw the boxes for bar-charts and lego plots is
2213 the histogram minimum. It is possible to force this base line to be 0, using MIN0 draw
2214 option or with the command:
2215 
2216  gStyle->SetHistMinimumZero();
2217 
2218 Begin_Macro(source)
2219 {
2220  auto c5 = new TCanvas("c5","c5",700,400);
2221  c5->Divide(2,1);
2222  auto hz1 = new TH1F("hz1","Bar-chart drawn from 0",20,-3,3);
2223  auto hz2 = new TH2F("hz2","Lego plot drawn from 0",20,-3,3,20,-3,3);
2224  Int_t i;
2225  double x,y;
2226  hz1->SetFillColor(kBlue);
2227  hz2->SetFillColor(kBlue);
2228  for (i=0;i<10000;i++) {
2229  x = gRandom->Gaus(0,1);
2230  y = gRandom->Gaus(0,1);
2231  if (x>0) {
2232  hz1->Fill(x,1);
2233  hz2->Fill(x,y,1);
2234  } else {
2235  hz1->Fill(x,-1);
2236  hz2->Fill(x,y,-2);
2237  }
2238  }
2239  c5->cd(1); hz1->Draw("bar2 min0");
2240  c5->cd(2); hz2->Draw("lego1 min0");
2241 }
2242 End_Macro
2243 
2244 This option also works for horizontal plots. The example given in the section
2245 ["The bar chart option"](#HP100) appears as follow:
2246 
2247 Begin_Macro(source)
2248 {
2249  int i;
2250  const Int_t nx = 8;
2251  string os_X[nx] = {"8","32","128","512","2048","8192","32768","131072"};
2252  float d_35_0[nx] = {0.75, -3.30, -0.92, 0.10, 0.08, -1.69, -1.29, -2.37};
2253  float d_35_1[nx] = {1.01, -3.02, -0.65, 0.37, 0.34, -1.42, -1.02, -2.10};
2254 
2255  auto cbh = new TCanvas("cbh","cbh",400,600);
2256  cbh->SetGrid();
2257 
2258  auto h1bh = new TH1F("h1bh","Option HBAR centered on 0",nx,0,nx);
2259  h1bh->SetFillColor(4);
2260  h1bh->SetBarWidth(0.4);
2261  h1bh->SetBarOffset(0.1);
2262  h1bh->SetStats(0);
2263  h1bh->SetMinimum(-5);
2264  h1bh->SetMaximum(5);
2265 
2266  for (i=1; i<=nx; i++) {
2267  h1bh->Fill(os_X[i-1].c_str(), d_35_0[i-1]);
2268  h1bh->GetXaxis()->SetBinLabel(i,os_X[i-1].c_str());
2269  }
2270 
2271  h1bh->Draw("hbar min0");
2272 
2273  auto h2bh = new TH1F("h2bh","h2bh",nx,0,nx);
2274  h2bh->SetFillColor(38);
2275  h2bh->SetBarWidth(0.4);
2276  h2bh->SetBarOffset(0.5);
2277  h2bh->SetStats(0);
2278  for (i=1;i<=nx;i++) h2bh->Fill(os_X[i-1].c_str(), d_35_1[i-1]);
2279 
2280  h2bh->Draw("hbar min0 same");
2281 }
2282 End_Macro
2283 
2284 
2285 ### <a name="HP20a"></a> TH2Poly Drawing
2286 
2287 
2288 The following options are supported:
2289 
2290 | Option | Description |
2291 |----------|-------------------------------------------------------------------|
2292 | "SCAT" | Draw a scatter plot (default).|
2293 | "COL" | Draw a color plot. All the bins are painted even the empty bins.|
2294 | "COLZ" | Same as "COL". In addition the color palette is also drawn.|
2295 | "0" | When used with any COL options, the empty bins are not drawn.|
2296 | "TEXT" | Draw bin contents as text (format set via `gStyle->SetPaintTextFormat`).|
2297 | "TEXTN" | Draw bin names as text.|
2298 | "TEXTnn" | Draw bin contents as text at angle nn (0 < nn < 90).|
2299 | "L" | Draw the bins boundaries as lines. The lines attributes are the TGraphs ones.|
2300 | "P" | Draw the bins boundaries as markers. The markers attributes are the TGraphs ones.|
2301 | "F" | Draw the bins boundaries as filled polygons. The filled polygons attributes are the TGraphs ones.|
2302 
2303 
2304 
2305 `TH2Poly` can be drawn as a color plot (option COL). `TH2Poly` bins can have any
2306 shapes. The bins are defined as graphs. The following macro is a very simple
2307 example showing how to book a TH2Poly and draw it.
2308 
2309 Begin_Macro(source)
2310 {
2311  auto ch2p1 = new TCanvas("ch2p1","ch2p1",600,400);
2312  auto h2p = new TH2Poly();
2313  h2p->SetName("h2poly_name");
2314  h2p->SetTitle("h2poly_title");
2315  double px1[] = {0, 5, 6};
2316  double py1[] = {0, 0, 5};
2317  double px2[] = {0, -1, -1, 0};
2318  double py2[] = {0, 0, -1, 3};
2319  double px3[] = {4, 3, 0, 1, 2.4};
2320  double py3[] = {4, 3.7, 1, 3.7, 2.5};
2321  h2p->AddBin(3, px1, py1);
2322  h2p->AddBin(4, px2, py2);
2323  h2p->AddBin(5, px3, py3);
2324  h2p->Fill(0.1, 0.01, 3);
2325  h2p->Fill(-0.5, -0.5, 7);
2326  h2p->Fill(-0.7, -0.5, 1);
2327  h2p->Fill(1, 3, 1.5);
2328  double fx[] = {0.1, -0.5, -0.7, 1};
2329  double fy[] = {0.01, -0.5, -0.5, 3};
2330  double fw[] = {3, 1, 1, 1.5};
2331  h2p->FillN(4, fx, fy, fw);
2332  h2p->Draw("col");
2333 }
2334 End_Macro
2335 
2336 Rectangular bins are a frequent case. The special version of
2337 the `AddBin` method allows to define them more easily like
2338 shown in the following example (th2polyBoxes.C).
2339 
2340 Begin_Macro(source)
2341 ../../../tutorials/hist/th2polyBoxes.C
2342 End_Macro
2343 
2344 One `TH2Poly` bin can be a list of polygons. Such bins are defined
2345 by calling `AddBin` with a `TMultiGraph`. The following example
2346 shows a such case:
2347 
2348 Begin_Macro(source)
2349 {
2350  auto ch2p2 = new TCanvas("ch2p2","ch2p2",600,400);
2351 
2352  Int_t i, bin;
2353  const Int_t nx = 48;
2354  const char *states [nx] = {
2355  "alabama", "arizona", "arkansas", "california",
2356  "colorado", "connecticut", "delaware", "florida",
2357  "georgia", "idaho", "illinois", "indiana",
2358  "iowa", "kansas", "kentucky", "louisiana",
2359  "maine", "maryland", "massachusetts", "michigan",
2360  "minnesota", "mississippi", "missouri", "montana",
2361  "nebraska", "nevada", "new_hampshire", "new_jersey",
2362  "new_mexico", "new_york", "north_carolina", "north_dakota",
2363  "ohio", "oklahoma", "oregon", "pennsylvania",
2364  "rhode_island", "south_carolina", "south_dakota", "tennessee",
2365  "texas", "utah", "vermont", "virginia",
2366  "washington", "west_virginia", "wisconsin", "wyoming"
2367  };
2368  Double_t pop[nx] = {
2369  4708708, 6595778, 2889450, 36961664, 5024748, 3518288, 885122, 18537969,
2370  9829211, 1545801, 12910409, 6423113, 3007856, 2818747, 4314113, 4492076,
2371  1318301, 5699478, 6593587, 9969727, 5266214, 2951996, 5987580, 974989,
2372  1796619, 2643085, 1324575, 8707739, 2009671, 19541453, 9380884, 646844,
2373  11542645, 3687050, 3825657, 12604767, 1053209, 4561242, 812383, 6296254,
2374  24782302, 2784572, 621760, 7882590, 6664195, 1819777, 5654774, 544270
2375  };
2376 
2377  Double_t lon1 = -130;
2378  Double_t lon2 = -65;
2379  Double_t lat1 = 24;
2380  Double_t lat2 = 50;
2381  auto p = new TH2Poly("USA","USA Population",lon1,lon2,lat1,lat2);
2382 
2383  TFile::SetCacheFileDir(".");
2384  auto f = TFile::Open("http://root.cern.ch/files/usa.root", "CACHEREAD");
2385 
2386  TMultiGraph *mg;
2387  TKey *key;
2388  TIter nextkey(gDirectory->GetListOfKeys());
2389  while ((key = (TKey*)nextkey())) {
2390  TObject *obj = key->ReadObj();
2391  if (obj->InheritsFrom("TMultiGraph")) {
2392  mg = (TMultiGraph*)obj;
2393  bin = p->AddBin(mg);
2394  }
2395  }
2396 
2397  for (i=0; i<nx; i++) p->Fill(states[i], pop[i]);
2398 
2399  gStyle->SetOptStat(11);
2400  p->Draw("COLZ L");
2401 }
2402 End_Macro
2403 
2404 `TH2Poly` histograms can also be plotted using the GL interface using
2405 the option "GLLEGO".
2406 
2407 \since **ROOT version 6.09/01**
2408 
2409 In some cases it can be useful to not draw the empty bins. the option "0"
2410 combined with the option "COL" et COLZ allows to do that.
2411 
2412 Begin_Macro(source)
2413 {
2414  auto chc = new TCanvas("chc","chc",600,400);
2415 
2416  auto hc = new TH2Poly();
2417  hc->Honeycomb(0,0,.1,25,25);
2418  hc->SetName("hc");
2419  hc->SetTitle("Option COLZ 0");
2420  TRandom ran;
2421  for (int i = 0; i<300; i++) hc->Fill(ran.Gaus(2.,1), ran.Gaus(2.,1));
2422  hc->Draw("colz 0");
2423 }
2424 End_Macro
2425 
2426 ### <a name="HP21"></a> The SPEC option
2427 
2428 
2429 This option allows to use the `TSpectrum2Painter` tools. See the full
2430 documentation in `TSpectrum2Painter::PaintSpectrum`.
2431 
2432 
2433 ### <a name="HP22"></a> Option "Z" : Adding the color palette on the right side of the pad
2434 
2435 
2436 When this option is specified, a color palette with an axis indicating the value
2437 of the corresponding color is drawn on the right side of the picture. In case,
2438 not enough space is left, one can increase the size of the right margin by
2439 calling `TPad::SetRightMargin()`. The attributes used to display the
2440 palette axis values are taken from the Z axis of the object. For example, to
2441 set the labels size on the palette axis do:
2442 
2443  hist->GetZaxis()->SetLabelSize().
2444 
2445 <b>WARNING:</b> The palette axis is always drawn vertically.
2446 
2447 
2448 ### <a name="HP23"></a> Setting the color palette
2449 
2450 
2451 To change the color palette `TStyle::SetPalette` should be used, eg:
2452 
2453  gStyle->SetPalette(ncolors,colors);
2454 
2455 For example the option `COL` draws a 2D histogram with cells
2456 represented by a box filled with a color index which is a function
2457 of the cell content.
2458 If the cell content is N, the color index used will be the color number
2459 in `colors[N]`, etc. If the maximum cell content is greater than
2460 `ncolors`, all cell contents are scaled to `ncolors`.
2461 
2462 If ` ncolors <= 0`, a default palette (see below) of 50 colors is
2463 defined. This palette is recommended for pads, labels ...
2464 
2465 `if ncolors == 1 && colors == 0`, then a Pretty Palette with a
2466 Spectrum Violet->Red is created with 50 colors. That's the default rain bow
2467 palette.
2468 
2469 Other pre-defined palettes with 255 colors are available when `colors == 0`.
2470 The following value of `ncolors` give access to:
2471 
2472 
2473  if ncolors = 51 and colors=0, a Deep Sea palette is used.
2474  if ncolors = 52 and colors=0, a Grey Scale palette is used.
2475  if ncolors = 53 and colors=0, a Dark Body Radiator palette is used.
2476  if ncolors = 54 and colors=0, a two-color hue palette palette is used.(dark blue through neutral gray to bright yellow)
2477  if ncolors = 55 and colors=0, a Rain Bow palette is used.
2478  if ncolors = 56 and colors=0, an inverted Dark Body Radiator palette is used.
2479 
2480 
2481 If `ncolors > 0 && colors == 0`, the default palette is used with a maximum of ncolors.
2482 
2483 The default palette defines:
2484 
2485 - index 0 to 9 : shades of grey
2486 - index 10 to 19 : shades of brown
2487 - index 20 to 29 : shades of blue
2488 - index 30 to 39 : shades of red
2489 - index 40 to 49 : basic colors
2490 
2491 The color numbers specified in the palette can be viewed by selecting
2492 the item `colors` in the `VIEW` menu of the canvas tool bar.
2493 The red, green, and blue components of a color can be changed thanks to
2494 `TColor::SetRGB()`.
2495 
2496 
2497 ### <a name="HP24"></a> Drawing a sub-range of a 2D histogram; the [cutg] option
2498 
2499 
2500 Using a `TCutG` object, it is possible to draw a sub-range of a 2D
2501 histogram. One must create a graphical cut (mouse or C++) and specify the name
2502 of the cut between `[]` in the `Draw()` option.
2503 For example (fit2a.C), with a `TCutG` named `cutg`, one can call:
2504 
2505  myhist->Draw("surf1 [cutg]");
2506 
2507 To invert the cut, it is enough to put a `-` in front of its name:
2508 
2509  myhist->Draw("surf1 [-cutg]");
2510 
2511 It is possible to apply several cuts (`,` means logical AND):
2512 
2513  myhist->Draw("surf1 [cutg1,cutg2]");
2514 
2515 Begin_Macro(source)
2516 ../../../tutorials/fit/fit2a.C
2517 End_Macro
2518 
2519 ### <a name="HP25"></a> Drawing options for 3D histograms
2520 
2521 
2522 | Option | Description |
2523 |----------|-------------------------------------------------------------------|
2524 | "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)`|
2525 | "BOX" | Draw a for each cell with volume proportional to the content's absolute value. An hidden line removal algorithm is used|
2526 | "BOX1" | Same as BOX but an hidden surface removal algorithm is used|
2527 | "BOX2" | The boxes' colors are picked in the current palette according to the bins' contents|
2528 | "BOX2Z" | Same as "BOX2". In addition the color palette is also drawn.|
2529 | "BOX3" | Same as BOX1, but the border lines of each lego-bar are not drawn.|
2530 
2531 Note that instead of `BOX` one can also use `LEGO`.
2532 
2533 By default, like 2D histograms, 3D histograms are drawn as scatter plots.
2534 
2535 The following example shows a 3D histogram plotted as a scatter plot.
2536 
2537 Begin_Macro(source)
2538 {
2539  auto c06 = new TCanvas("c06","c06",600,400);
2540  gStyle->SetOptStat(kFALSE);
2541  auto h3scat = new TH3F("h3scat","Option SCAT (default) ",15,-2,2,15,-2,2,15,0,4);
2542  double x, y, z;
2543  for (Int_t i=0;i<10000;i++) {
2544  gRandom->Rannor(x, y);
2545  z = x*x + y*y;
2546  h3scat->Fill(x,y,z);
2547  }
2548  h3scat->Draw();
2549 }
2550 End_Macro
2551 
2552 The following example shows a 3D histogram plotted with the option `BOX`.
2553 
2554 Begin_Macro(source)
2555 {
2556  auto c16 = new TCanvas("c16","c16",600,400);
2557  gStyle->SetOptStat(kFALSE);
2558  auto h3box = new TH3F("h3box","Option BOX",15,-2,2,15,-2,2,15,0,4);
2559  double x, y, z;
2560  for (Int_t i=0;i<10000;i++) {
2561  gRandom->Rannor(x, y);
2562  z = x*x + y*y;
2563  h3box->Fill(x,y,z);
2564  }
2565  h3box->Draw("BOX");
2566 }
2567 End_Macro
2568 
2569 The following example shows a 3D histogram plotted with the option `BOX1`.
2570 
2571 Begin_Macro(source)
2572 {
2573  auto c36 = new TCanvas("c36","c36",600,400);
2574  gStyle->SetOptStat(kFALSE);
2575  auto h3box = new TH3F("h3box","Option BOX1",10,-2.,2.,10,-2.,2.,10,-0.5,2.);
2576  double x, y, z;
2577  for (Int_t i=0;i<10000;i++) {
2578  gRandom->Rannor(x, y);
2579  z = abs(sin(x)/x + cos(y)*y);
2580  h3box->Fill(x,y,z);
2581  }
2582  h3box->SetFillColor(9);
2583  h3box->Draw("BOX1");
2584 }
2585 End_Macro
2586 
2587 The following example shows a 3D histogram plotted with the option `BOX2`.
2588 
2589 Begin_Macro(source)
2590 {
2591  auto c56 = new TCanvas("c56","c56",600,400);
2592  gStyle->SetOptStat(kFALSE);
2593  auto h3box = new TH3F("h3box","Option BOX2",10,-2.,2.,10,-2.,2.,10,-0.5,2.);
2594  double x, y, z;
2595  for (Int_t i=0;i<10000;i++) {
2596  gRandom->Rannor(x, y);
2597  z = abs(sin(x)/x + cos(y)*y);
2598  h3box->Fill(x,y,z);
2599  }
2600  h3box->Draw("BOX2 Z");
2601 }
2602 End_Macro
2603 
2604 The following example shows a 3D histogram plotted with the option `BOX3`.
2605 
2606 Begin_Macro(source)
2607 {
2608  auto c46 = new TCanvas("c46","c46",600,400);
2609  c46->SetFillColor(38);
2610  gStyle->SetOptStat(kFALSE);
2611  auto h3box = new TH3F("h3box","Option BOX3",15,-2,2,15,-2,2,15,0,4);
2612  double x, y, z;
2613  for (Int_t i=0;i<10000;i++) {
2614  gRandom->Rannor(x, y);
2615  z = x*x + y*y;
2616  h3box->Fill(x,y,z);
2617  }
2618  h3box->Draw("BOX3");
2619 }
2620 End_Macro
2621 
2622 For all the `BOX` options each bin is drawn as a 3D box with a volume proportional
2623 to the absolute value of the bin content. The bins with a negative content are
2624 drawn with a X on each face of the box as shown in the following example:
2625 
2626 Begin_Macro(source)
2627 {
2628  auto c = new TCanvas("c","c",600,400);
2629  gStyle->SetOptStat(kFALSE);
2630  auto h3box = new TH3F("h3box","Option BOX1 with negative bins",3, 0., 4., 3, 0.,4., 3, 0., 4.);
2631  h3box->Fill(0., 2., 2., 10.);
2632  h3box->Fill(2., 2., 2., 5.);
2633  h3box->Fill(2., 2., .5, 2.);
2634  h3box->Fill(2., 2., 3., -1.);
2635  h3box->Fill(3., 2., 2., -10.);
2636  h3box->SetFillColor(8);
2637  h3box->Draw("box1");
2638 }
2639 End_Macro
2640 
2641 The following example shows a 3D histogram plotted with the option `ISO`.
2642 
2643 Begin_Macro(source)
2644 {
2645  auto c26 = new TCanvas("c26","c26",600,400);
2646  gStyle->SetOptStat(kFALSE);
2647  auto h3iso = new TH3F("h3iso","Option ISO",15,-2,2,15,-2,2,15,0,4);
2648  double x, y, z;
2649  for (Int_t i=0;i<10000;i++) {
2650  gRandom->Rannor(x, y);
2651  z = x*x + y*y;
2652  h3iso->Fill(x,y,z);
2653  }
2654  h3iso->SetFillColor(kCyan);
2655  h3iso->Draw("ISO");
2656 }
2657 End_Macro
2658 
2659 
2660 ### <a name="HP26"></a> Drawing option for histograms' stacks
2661 
2662 
2663 Stacks of histograms are managed with the `THStack`. A `THStack`
2664 is a collection of `TH1` (or derived) objects. For painting only the
2665 `THStack` containing `TH1` only or
2666 `THStack` containing `TH2` only will be considered.
2667 
2668 By default, histograms are shown stacked:
2669 
2670 1. The first histogram is paint.
2671 2. The the sum of the first and second, etc...
2672 
2673 If the option `NOSTACK` is specified, the histograms are all paint in
2674 the same pad as if the option `SAME` had been specified. This allows to
2675 compute X and Y scales common to all the histograms, like
2676 `TMultiGraph` does for graphs.
2677 
2678 If the option `PADS` is specified, the current pad/canvas is
2679 subdivided into a number of pads equal to the number of histograms and each
2680 histogram is paint into a separate pad.
2681 
2682 The following example shows various types of stacks (hstack.C).
2683 
2684 Begin_Macro(source)
2685 ../../../tutorials/hist/hstack.C
2686 End_Macro
2687 
2688 The option `nostackb` allows to draw the histograms next to each
2689 other as bar charts:
2690 
2691 Begin_Macro(source)
2692 {
2693  auto cst0 = new TCanvas("cst0","cst0",600,400);
2694  auto hs = new THStack("hs","Stacked 1D histograms: option #font[82]{\"nostackb\"}");
2695 
2696  auto h1 = new TH1F("h1","h1",10,-4,4);
2697  h1->FillRandom("gaus",20000);
2698  h1->SetFillColor(kRed);
2699  hs->Add(h1);
2700 
2701  auto h2 = new TH1F("h2","h2",10,-4,4);
2702  h2->FillRandom("gaus",15000);
2703  h2->SetFillColor(kBlue);
2704  hs->Add(h2);
2705 
2706  auto h3 = new TH1F("h3","h3",10,-4,4);
2707  h3->FillRandom("gaus",10000);
2708  h3->SetFillColor(kGreen);
2709  hs->Add(h3);
2710 
2711  hs->Draw("nostackb");
2712  hs->GetXaxis()->SetNdivisions(-10);
2713  cst0->SetGridx();
2714 }
2715 End_Macro
2716 
2717 If at least one of the histograms in the stack has errors, the whole stack is
2718 visualized by default with error bars. To visualize it without errors the
2719 option `HIST` should be used.
2720 
2721 Begin_Macro(source)
2722 {
2723  auto cst1 = new TCanvas("cst1","cst1",700,400);
2724  cst1->Divide(2,1);
2725 
2726  auto hst11 = new TH1F("hst11", "", 20, -10, 10);
2727  hst11->Sumw2();
2728  hst11->FillRandom("gaus", 1000);
2729  hst11->SetFillColor(kViolet);
2730  hst11->SetLineColor(kViolet);
2731 
2732  auto hst12 = new TH1F("hst12", "", 20, -10, 10);
2733  hst12->FillRandom("gaus", 500);
2734  hst12->SetFillColor(kBlue);
2735  hst12->SetLineColor(kBlue);
2736 
2737  THStack st1("st1", "st1");
2738  st1.Add(hst11);
2739  st1.Add(hst12);
2740 
2741  cst1->cd(1); st1.Draw();
2742  cst1->cd(2); st1.Draw("hist");
2743 }
2744 End_Macro
2745 
2746 ### <a name="HP27"></a> Drawing of 3D implicit functions
2747 
2748 
2749 3D implicit functions (`TF3`) can be drawn as iso-surfaces.
2750 The implicit function f(x,y,z) = 0 is drawn in cartesian coordinates.
2751 In the following example the options "FB" and "BB" suppress the
2752 "Front Box" and "Back Box" around the plot.
2753 
2754 Begin_Macro(source)
2755 {
2756  auto c2 = new TCanvas("c2","c2",600,400);
2757  auto f3 = new TF3("f3","sin(x*x+y*y+z*z-36)",-2,2,-2,2,-2,2);
2758  f3->SetClippingBoxOn(0,0,0);
2759  f3->SetFillColor(30);
2760  f3->SetLineColor(15);
2761  f3->Draw("FBBB");
2762 }
2763 End_Macro
2764 
2765 
2766 ### <a name="HP28"></a> Associated functions drawing
2767 
2768 
2769 An associated function is created by `TH1::Fit`. More than on fitted
2770 function can be associated with one histogram (see `TH1::Fit`).
2771 
2772 A `TF1` object `f1` can be added to the list of associated
2773 functions of an histogram `h` without calling `TH1::Fit`
2774 simply doing:
2775 
2776  h->GetListOfFunctions()->Add(f1);
2777 
2778 or
2779 
2780  h->GetListOfFunctions()->Add(f1,someoption);
2781 
2782 To retrieve a function by name from this list, do:
2783 
2784  TF1 *f1 = (TF1*)h->GetListOfFunctions()->FindObject(name);
2785 
2786 or
2787 
2788  TF1 *f1 = h->GetFunction(name);
2789 
2790 Associated functions are automatically painted when an histogram is drawn.
2791 To avoid the painting of the associated functions the option `HIST`
2792 should be added to the list of the options used to paint the histogram.
2793 
2794 
2795 ### <a name="HP29"></a> Drawing using OpenGL
2796 
2797 
2798 The class `TGLHistPainter` allows to paint data set using the OpenGL 3D
2799 graphics library. The plotting options start with `GL` keyword.
2800 In addition, in order to inform canvases that OpenGL should be used to render
2801 3D representations, the following option should be set:
2802 
2803  gStyle->SetCanvasPreferGL(true);
2804 
2805 
2806 #### <a name="HP29a"></a> General information: plot types and supported options
2807 
2808 The following types of plots are provided:
2809 
2810 For lego plots the supported options are:
2811 
2812 | Option | Description |
2813 |----------|-------------------------------------------------------------------|
2814 | "GLLEGO" | Draw a lego plot. It works also for `TH2Poly`.|
2815 | "GLLEGO2"| Bins with color levels.|
2816 | "GLLEGO3"| Cylindrical bars.|
2817 
2818 
2819 
2820 Lego painter in cartesian supports logarithmic scales for X, Y, Z.
2821 In polar only Z axis can be logarithmic, in cylindrical only Y.
2822 
2823 For surface plots (`TF2` and `TH2`) the supported options are:
2824 
2825 | Option | Description |
2826 |-----------|------------------------------------------------------------------|
2827 | "GLSURF" | Draw a surface.|
2828 | "GLSURF1" | Surface with color levels|
2829 | "GLSURF2" | The same as "GLSURF1" but without polygon outlines.|
2830 | "GLSURF3" | Color level projection on top of plot (works only in cartesian coordinate system).|
2831 | "GLSURF4" | Same as "GLSURF" but without polygon outlines.|
2832 
2833 
2834 
2835 The surface painting in cartesian coordinates supports logarithmic scales along
2836 X, Y, Z axis. In polar coordinates only the Z axis can be logarithmic,
2837 in cylindrical coordinates only the Y axis.
2838 
2839 Additional options to SURF and LEGO - Coordinate systems:
2840 
2841 | Option | Description |
2842 |----------|-------------------------------------------------------------------|
2843 | " " | Default, cartesian coordinates system.|
2844 | "POL" | Polar coordinates system.|
2845 | "CYL" | Cylindrical coordinates system.|
2846 | "SPH" | Spherical coordinates system.|
2847 
2848 
2849 
2850 #### <a name="HP290"></a> TH3 as color boxes
2851 
2852 The supported option is:
2853 
2854 | Option | Description |
2855 |----------|-------------------------------------------------------------------|
2856 | "GLCOL" | H3 is drawn using semi-transparent colored boxes. See `$ROOTSYS/tutorials/gl/glvox1.C`.|
2857 
2858 
2859 
2860 #### <a name="HP29b"></a> TH3 as boxes (spheres)
2861 
2862 The supported options are:
2863 
2864 | Option | Description |
2865 |----------|-------------------------------------------------------------------|
2866 | "GLBOX" | TH3 as a set of boxes, size of box is proportional to bin content.|
2867 | "GLBOX1" | The same as "glbox", but spheres are drawn instead of boxes.|
2868 
2869 
2870 
2871 #### <a name="HP29c"></a> TH3 as iso-surface(s)
2872 
2873 The supported option is:
2874 
2875 | Option | Description |
2876 |----------|-------------------------------------------------------------------|
2877 | "GLISO" | TH3 is drawn using iso-surfaces.|
2878 
2879 
2880 
2881 #### <a name="HP29d"></a> TF3 (implicit function)
2882 
2883 The supported option is:
2884 
2885 | Option | Description |
2886 |----------|-------------------------------------------------------------------|
2887 | "GLTF3" | Draw a TF3.|
2888 
2889 
2890 
2891 #### <a name="HP29e"></a> Parametric surfaces
2892 
2893 `$ROOTSYS/tutorials/gl/glparametric.C` shows how to create parametric
2894 equations and visualize the surface.
2895 
2896 #### <a name="HP29f"></a> Interaction with the plots
2897 
2898 All the interactions are implemented via standard methods
2899 `DistancetoPrimitive()` and `ExecuteEvent()`. That's why all the
2900 interactions with the OpenGL plots are possible only when the mouse cursor is
2901 in the plot's area (the plot's area is the part of a the pad occupied by
2902 gl-produced picture). If the mouse cursor is not above gl-picture, the standard
2903 pad interaction is performed.
2904 
2905 #### <a name="HP29g"></a> Selectable parts
2906 
2907 Different parts of the plot can be selected:
2908 
2909 - xoz, yoz, xoy back planes: When such a plane selected, it's highlighted in green
2910  if the dynamic slicing by this plane is supported, and it's highlighted in red,
2911  if the dynamic slicing is not supported.
2912 - The plot itself:
2913  On surfaces, the selected surface is outlined in red. (TF3 and
2914  ISO are not outlined). On lego plots, the selected bin is
2915  highlighted. The bin number and content are displayed in pad's
2916  status bar. In box plots, the box or sphere is highlighted and
2917  the bin info is displayed in pad's status bar.
2918 
2919 
2920 #### <a name="HP29h"></a> Rotation and zooming
2921 
2922 
2923 - Rotation:
2924  When the plot is selected, it can be rotated by pressing and
2925  holding the left mouse button and move the cursor.
2926 - Zoom/Unzoom:
2927  Mouse wheel or 'j', 'J', 'k', 'K' keys.
2928 
2929 
2930 #### <a name="HP29i"></a> Panning
2931 
2932 The selected plot can be moved in a pad's area by pressing and
2933 holding the left mouse button and the shift key.
2934 
2935 #### <a name="HP29j"></a> Box cut
2936 
2937 Surface, iso, box, TF3 and parametric painters support box cut by
2938 pressing the 'c' or 'C' key when the mouse cursor is in a plot's
2939 area. That will display a transparent box, cutting away part of the
2940 surface (or boxes) in order to show internal part of plot. This box
2941 can be moved inside the plot's area (the full size of the box is
2942 equal to the plot's surrounding box) by selecting one of the box
2943 cut axes and pressing the left mouse button to move it.
2944 
2945 #### <a name="HP29k"></a> Plot specific interactions (dynamic slicing etc.)
2946 
2947 Currently, all gl-plots support some form of slicing. When back plane
2948 is selected (and if it's highlighted in green) you can press and hold
2949 left mouse button and shift key and move this back plane inside
2950 plot's area, creating the slice. During this "slicing" plot becomes
2951 semi-transparent. To remove all slices (and projected curves for
2952 surfaces) double click with left mouse button in a plot's area.
2953 
2954 #### <a name="HP29l"></a> Surface with option "GLSURF"
2955 
2956 The surface profile is displayed on the slicing plane.
2957 The profile projection is drawn on the back plane
2958 by pressing `'p'` or `'P'` key.
2959 
2960 #### <a name="HP29m"></a> TF3
2961 
2962 The contour plot is drawn on the slicing plane. For TF3 the color
2963 scheme can be changed by pressing 's' or 'S'.
2964 
2965 #### <a name="HP29n"></a> Box
2966 
2967 The contour plot corresponding to slice plane position is drawn in real time.
2968 
2969 #### <a name="HP29o"></a> Iso
2970 
2971 Slicing is similar to "GLBOX" option.
2972 
2973 #### <a name="HP29p"></a> Parametric plot
2974 
2975 No slicing. Additional keys: 's' or 'S' to change color scheme -
2976 about 20 color schemes supported ('s' for "scheme"); 'l' or 'L' to
2977 increase number of polygons ('l' for "level" of details), 'w' or 'W'
2978 to show outlines ('w' for "wireframe").
2979 
2980 #### <a name="HP30"></a> Highlight mode for histogram
2981 
2982 \since **ROOT version 6.15/01**
2983 
2984 \image html hlHisto3_top.gif "Highlight mode"
2985 
2986 Highlight mode is implemented for `TH1` (and for `TGraph`) class. When
2987 highlight mode is on, mouse movement over the bin will be represented
2988 graphically. Bin will be highlighted as "bin box" (presented by box
2989 object). Moreover, any highlight (change of bin) emits signal
2990 `TCanvas::Highlighted()` which allows the user to react and call their own
2991 function. For a better understanding see also the tutorials
2992 `$ROOTSYS/tutorials/hist/hlHisto*.C` files.
2993 
2994 Highlight mode is switched on/off by `TH1::SetHighlight()` function
2995 or interactively from `TH1` context menu. `TH1::IsHighlight()` to verify
2996 whether the highlight mode enabled or disabled, default it is disabled.
2997 
2998 ~~~ {.cpp}
2999  root [0] .x $ROOTSYS/tutorials/hsimple.C
3000  root [1] hpx->SetHighlight(kTRUE) // or interactively from TH1 context menu
3001  root [2] hpx->IsHighlight()
3002  (bool) true
3003 ~~~
3004 
3005 \image html hlsimple_nofun.gif "Highlight mode for histogram"
3006 
3007 #### <a name="HP30a"></a> Highlight mode and user function
3008 
3009 The user can use (connect) `TCanvas::Highlighted()` signal, which is always
3010 emitted if there is a highlight bin and call user function via signal
3011 and slot communication mechanism. `TCanvas::Highlighted()` is similar
3012 `TCanvas::Picked()`
3013 
3014 - when selected object (histogram as a whole) is different from previous
3015 then emit `Picked()` signal
3016 - when selected (highlighted) bin from histogram is different from previous
3017 then emit `Highlighted()` signal
3018 
3019 Any user function (or functions) has to be defined
3020 `UserFunction(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)`.
3021 In example (see below) has name `PrintInfo()`. All parameters of user
3022 function are taken from
3023 
3024  void TCanvas::Highlighted(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)
3025 
3026 - `pad` is pointer to pad with highlighted histogram
3027 - `obj` is pointer to highlighted histogram
3028 - `x` is highlighted x bin for 1D histogram
3029 - `y` is highlighted y bin for 2D histogram (for 1D histogram not in use)
3030 
3031 Example how to create a connection from any `TCanvas` object to a user
3032 `UserFunction()` slot (see also `TQObject::Connect()` for additional info)
3033 
3034  TQObject::Connect("TCanvas", "Highlighted(TVirtualPad*,TObject*,Int_t,Int_t)",
3035  0, 0, "UserFunction(TVirtualPad*,TObject*,Int_t,Int_t)");
3036 
3037 or use non-static "simplified" function
3038 `TCanvas::HighlightConnect(const char *slot)`
3039 
3040  c1->HighlightConnect("UserFunction(TVirtualPad*,TObject*,Int_t,Int_t)");
3041 
3042 NOTE the signal and slot string must have a form
3043 "(TVirtualPad*,TObject*,Int_t,Int_t)"
3044 
3045  root [0] .x $ROOTSYS/tutorials/hsimple.C
3046  root [1] hpx->SetHighlight(kTRUE)
3047  root [2] .x hlprint.C
3048 
3049 file `hlprint.C`
3050 ~~~ {.cpp}
3051 void PrintInfo(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)
3052 {
3053  auto h = (TH1F *)obj;
3054  if (!h->IsHighlight()) // after highlight disabled
3055  h->SetTitle("highlight disable");
3056  else
3057  h->SetTitle(TString::Format("bin[%03d] (%5.2f) content %g", x,
3058  h->GetBinCenter(x), h->GetBinContent(x)));
3059  pad->Update();
3060 }
3061 
3062 void hlprint()
3063 {
3064  if (!gPad) return;
3065  gPad->GetCanvas()->HighlightConnect("PrintInfo(TVirtualPad*,TObject*,Int_t,Int_t)");
3066 }
3067 ~~~
3068 
3069 \image html hlsimple.gif "Highlight mode and simple user function"
3070 
3071 For more complex demo please see for example `$ROOTSYS/tutorials/tree/temperature.C` file.
3072 
3073 */
3074 
3076 
3079 
3080 const Int_t kNMAX = 2000;
3081 
3082 const Int_t kMAXCONTOUR = 104;
3084 
3085 static TBox *gXHighlightBox = 0; // highlight X box
3086 static TBox *gYHighlightBox = 0; // highlight Y box
3087 
3109 
3111 
3112 ////////////////////////////////////////////////////////////////////////////////
3113 /// Default constructor.
3114 
3116 {
3117 
3118  fH = 0;
3119  fXaxis = 0;
3120  fYaxis = 0;
3121  fZaxis = 0;
3122  fFunctions = 0;
3123  fXbuf = 0;
3124  fYbuf = 0;
3125  fNcuts = 0;
3126  fStack = 0;
3127  fLego = 0;
3128  fPie = 0;
3129  fGraph2DPainter = 0;
3130  fShowProjection = 0;
3131  fShowOption = "";
3132  for (int i=0; i<kMaxCuts; i++) {
3133  fCuts[i] = 0;
3134  fCutsOpt[i] = 0;
3135  }
3136  fXHighlightBin = -1;
3137  fYHighlightBin = -1;
3138 
3139  gStringEntries = gEnv->GetValue("Hist.Stats.Entries", "Entries");
3140  gStringMean = gEnv->GetValue("Hist.Stats.Mean", "Mean");
3141  gStringMeanX = gEnv->GetValue("Hist.Stats.MeanX", "Mean x");
3142  gStringMeanY = gEnv->GetValue("Hist.Stats.MeanY", "Mean y");
3143  gStringMeanZ = gEnv->GetValue("Hist.Stats.MeanZ", "Mean z");
3144  gStringStdDev = gEnv->GetValue("Hist.Stats.StdDev", "Std Dev");
3145  gStringStdDevX = gEnv->GetValue("Hist.Stats.StdDevX", "Std Dev x");
3146  gStringStdDevY = gEnv->GetValue("Hist.Stats.StdDevY", "Std Dev y");
3147  gStringStdDevZ = gEnv->GetValue("Hist.Stats.StdDevZ", "Std Dev z");
3148  gStringUnderflow = gEnv->GetValue("Hist.Stats.Underflow", "Underflow");
3149  gStringOverflow = gEnv->GetValue("Hist.Stats.Overflow", "Overflow");
3150  gStringIntegral = gEnv->GetValue("Hist.Stats.Integral", "Integral");
3151  gStringIntegralBinWidth = gEnv->GetValue("Hist.Stats.IntegralBinWidth", "Integral(w)");
3152  gStringSkewness = gEnv->GetValue("Hist.Stats.Skewness", "Skewness");
3153  gStringSkewnessX = gEnv->GetValue("Hist.Stats.SkewnessX", "Skewness x");
3154  gStringSkewnessY = gEnv->GetValue("Hist.Stats.SkewnessY", "Skewness y");
3155  gStringSkewnessZ = gEnv->GetValue("Hist.Stats.SkewnessZ", "Skewness z");
3156  gStringKurtosis = gEnv->GetValue("Hist.Stats.Kurtosis", "Kurtosis");
3157  gStringKurtosisX = gEnv->GetValue("Hist.Stats.KurtosisX", "Kurtosis x");
3158  gStringKurtosisY = gEnv->GetValue("Hist.Stats.KurtosisY", "Kurtosis y");
3159  gStringKurtosisZ = gEnv->GetValue("Hist.Stats.KurtosisZ", "Kurtosis z");
3160 }
3161 
3162 ////////////////////////////////////////////////////////////////////////////////
3163 /// Default destructor.
3164 
3166 {
3167 }
3168 
3169 ////////////////////////////////////////////////////////////////////////////////
3170 /// Compute the distance from the point px,py to a line.
3171 ///
3172 /// Compute the closest distance of approach from point px,py to elements of
3173 /// an histogram. The distance is computed in pixels units.
3174 ///
3175 /// Algorithm: Currently, this simple model computes the distance from the mouse
3176 /// to the histogram contour only.
3177 
3179 {
3180 
3181  Double_t defaultLabelSize = 0.04; // See TAttAxis.h for source of this value
3182 
3183  const Int_t big = 9999;
3184  const Int_t kMaxDiff = 7;
3185 
3186  if (fPie) return fPie->DistancetoPrimitive(px, py);
3187 
3188  Double_t x = gPad->AbsPixeltoX(px);
3189  Double_t x1 = gPad->AbsPixeltoX(px+1);
3190 
3191  Int_t puxmin = gPad->XtoAbsPixel(gPad->GetUxmin());
3192  Int_t puymin = gPad->YtoAbsPixel(gPad->GetUymin());
3193  Int_t puxmax = gPad->XtoAbsPixel(gPad->GetUxmax());
3194  Int_t puymax = gPad->YtoAbsPixel(gPad->GetUymax());
3195  Int_t curdist = big;
3196  Int_t yxaxis, dyaxis,xyaxis, dxaxis;
3197  Bool_t dsame;
3198  TObject *PadPointer = gPad->GetPadPointer();
3199  if (!PadPointer) return 0;
3200  TString doption = PadPointer->GetDrawOption();
3201  Double_t factor = 1;
3202  if (fH->GetNormFactor() != 0) {
3203  factor = fH->GetNormFactor()/fH->GetSumOfWeights();
3204  }
3205  // return if point is not in the histogram area
3206 
3207  // If a 3D view exists, check distance to axis
3208  TView *view = gPad->GetView();
3209  Int_t d1,d2,d3;
3210  if (view && Hoption.Contour != 14) {
3211  Double_t ratio;
3212  d3 = view->GetDistancetoAxis(3, px, py, ratio);
3213  if (d3 <= kMaxDiff) {gPad->SetSelected(fZaxis); return 0;}
3214  d1 = view->GetDistancetoAxis(1, px, py, ratio);
3215  if (d1 <= kMaxDiff) {gPad->SetSelected(fXaxis); return 0;}
3216  d2 = view->GetDistancetoAxis(2, px, py, ratio);
3217  if (d2 <= kMaxDiff) {gPad->SetSelected(fYaxis); return 0;}
3218  if ( px > puxmin && px < puxmax && py > puymax && py < puymin) curdist = 1;
3219  goto FUNCTIONS;
3220  }
3221  // check if point is close to an axis
3222  doption.ToLower();
3223  dsame = kFALSE;
3224  if (doption.Contains("same")) dsame = kTRUE;
3225 
3226  dyaxis = Int_t(2*(puymin-puymax)*TMath::Max(Double_t(fYaxis->GetLabelSize()), defaultLabelSize));
3227  if (doption.Contains("y+")) {
3228  xyaxis = puxmax + Int_t((puxmax-puxmin)*fYaxis->GetLabelOffset());
3229  if (px <= xyaxis+dyaxis && px >= xyaxis && py >puymax && py < puymin) {
3230  if (!dsame) {
3231  if (gPad->IsVertical()) gPad->SetSelected(fYaxis);
3232  else gPad->SetSelected(fXaxis);
3233  return 0;
3234  }
3235  }
3236  } else {
3237  xyaxis = puxmin - Int_t((puxmax-puxmin)*fYaxis->GetLabelOffset());
3238  if (px >= xyaxis-dyaxis && px <= xyaxis && py >puymax && py < puymin) {
3239  if (!dsame) {
3240  if (gPad->IsVertical()) gPad->SetSelected(fYaxis);
3241  else gPad->SetSelected(fXaxis);
3242  return 0;
3243  }
3244  }
3245  }
3246 
3247  dxaxis = Int_t((puymin-puymax)*TMath::Max(Double_t(fXaxis->GetLabelSize()), defaultLabelSize));
3248  if (doption.Contains("x+")) {
3249  yxaxis = puymax - Int_t((puymin-puymax)*fXaxis->GetLabelOffset());
3250  if (py >= yxaxis-dxaxis && py <= yxaxis && px <puxmax && px > puxmin) {
3251  if (!dsame) {
3252  if (gPad->IsVertical()) gPad->SetSelected(fXaxis);
3253  else gPad->SetSelected(fYaxis);
3254  return 0;
3255  }
3256  }
3257  } else {
3258  yxaxis = puymin + Int_t((puymin-puymax)*fXaxis->GetLabelOffset());
3259  if (yxaxis < puymin) yxaxis = puymin;
3260  if (py <= yxaxis+dxaxis && py >= yxaxis && px <puxmax && px > puxmin) {
3261  if (!dsame) {
3262  if (gPad->IsVertical()) gPad->SetSelected(fXaxis);
3263  else gPad->SetSelected(fYaxis);
3264  return 0;
3265  }
3266  }
3267  }
3268 
3269  if (fH->IsHighlight()) { // only if highlight is enable
3270  if ((px > puxmin) && (py < puymin) && (px < puxmax) && (py > puymax))
3271  HighlightBin(px, py);
3272  }
3273 
3274  // if object is 2D or 3D return this object
3275  if (fH->GetDimension() == 2) {
3276  if (fH->InheritsFrom(TH2Poly::Class())) {
3277  TH2Poly *th2 = (TH2Poly*)fH;
3278  Double_t xmin, ymin, xmax, ymax;
3279  gPad->GetRangeAxis(xmin, ymin, xmax, ymax);
3280  Double_t pxu = gPad->AbsPixeltoX(px);
3281  Double_t pyu = gPad->AbsPixeltoY(py);
3282  if ((pxu>xmax) || (pxu < xmin) || (pyu>ymax) || (pyu < ymin)) {
3283  curdist = big;
3284  goto FUNCTIONS;
3285  } else {
3286  Int_t bin = th2->FindBin(pxu, pyu);
3287  if (bin>0) curdist = 1;
3288  else curdist = big;
3289  goto FUNCTIONS;
3290  }
3291  }
3292  Int_t delta2 = 5; //Give a margin of delta2 pixels to be in the 2-d area
3293  if ( px > puxmin + delta2
3294  && px < puxmax - delta2
3295  && py > puymax + delta2
3296  && py < puymin - delta2) {curdist =1; goto FUNCTIONS;}
3297  }
3298 
3299  // point is inside histogram area. Find channel number
3300  if (gPad->IsVertical()) {
3301  Int_t bin = fXaxis->FindFixBin(gPad->PadtoX(x));
3302  Int_t binsup = fXaxis->FindFixBin(gPad->PadtoX(x1));
3303  Double_t binval = factor*fH->GetBinContent(bin);
3304  Int_t pybin = gPad->YtoAbsPixel(gPad->YtoPad(binval));
3305  if (binval == 0 && pybin < puymin) pybin = 10000;
3306  // special case if more than one bin for the pixel
3307  if (binsup-bin>1) {
3308  Double_t binvalmin, binvalmax;
3309  binvalmin=binval;
3310  binvalmax=binval;
3311  for (Int_t ibin=bin+1; ibin<binsup; ibin++) {
3312  Double_t binvaltmp = factor*fH->GetBinContent(ibin);
3313  if (binvalmin>binvaltmp) binvalmin=binvaltmp;
3314  if (binvalmax<binvaltmp) binvalmax=binvaltmp;
3315  }
3316  Int_t pybinmin = gPad->YtoAbsPixel(gPad->YtoPad(binvalmax));
3317  Int_t pybinmax = gPad->YtoAbsPixel(gPad->YtoPad(binvalmin));
3318  if (py<pybinmax+kMaxDiff/2 && py>pybinmin-kMaxDiff/2) pybin = py;
3319  }
3320  if (bin != binsup) { // Mouse on bin border
3321  Double_t binsupval = factor*fH->GetBinContent(binsup);
3322  Int_t pybinsub = gPad->YtoAbsPixel(gPad->YtoPad(binsupval));
3323  if (py <= TMath::Max(pybinsub,pybin) && py >= TMath::Min(pybinsub,pybin) && pybin != 10000) return 0;
3324  }
3325  if (TMath::Abs(py - pybin) <= kMaxDiff) return TMath::Abs(py - pybin);
3326  } else {
3327  Double_t y = gPad->AbsPixeltoY(py);
3328  Double_t y1 = gPad->AbsPixeltoY(py+1);
3329  Int_t bin = fXaxis->FindFixBin(gPad->PadtoY(y));
3330  Int_t binsup = fXaxis->FindFixBin(gPad->PadtoY(y1));
3331  Double_t binval = factor*fH->GetBinContent(bin);
3332  Int_t pxbin = gPad->XtoAbsPixel(gPad->XtoPad(binval));
3333  if (binval == 0 && pxbin > puxmin) pxbin = 10000;
3334  // special case if more than one bin for the pixel
3335  if (binsup-bin>1) {
3336  Double_t binvalmin, binvalmax;
3337  binvalmin=binval;
3338  binvalmax=binval;
3339  for (Int_t ibin=bin+1; ibin<binsup; ibin++) {
3340  Double_t binvaltmp = factor*fH->GetBinContent(ibin);
3341  if (binvalmin>binvaltmp) binvalmin=binvaltmp;
3342  if (binvalmax<binvaltmp) binvalmax=binvaltmp;
3343  }
3344  Int_t pxbinmin = gPad->XtoAbsPixel(gPad->XtoPad(binvalmax));
3345  Int_t pxbinmax = gPad->XtoAbsPixel(gPad->XtoPad(binvalmin));
3346  if (px<pxbinmax+kMaxDiff/2 && px>pxbinmin-kMaxDiff/2) pxbin = px;
3347  }
3348  if (TMath::Abs(px - pxbin) <= kMaxDiff) return TMath::Abs(px - pxbin);
3349  }
3350  // Loop on the list of associated functions and user objects
3351 FUNCTIONS:
3352  TObject *f;
3353  TIter next(fFunctions);
3354  while ((f = (TObject*) next())) {
3355  Int_t dist;
3356  if (f->InheritsFrom(TF1::Class())) dist = f->DistancetoPrimitive(-px,py);
3357  else dist = f->DistancetoPrimitive(px,py);
3358  if (dist < kMaxDiff) {gPad->SetSelected(f); return dist;}
3359  }
3360  return curdist;
3361 }
3362 
3363 ////////////////////////////////////////////////////////////////////////////////
3364 /// Display a panel with all histogram drawing options.
3365 
3367 {
3368 
3369  gCurrentHist = fH;
3370  if (!gPad) {
3371  Error("DrawPanel", "need to draw histogram first");
3372  return;
3373  }
3375  editor->Show();
3376  gROOT->ProcessLine(Form("((TCanvas*)0x%lx)->Selected((TVirtualPad*)0x%lx,(TObject*)0x%lx,1)",
3377  (ULong_t)gPad->GetCanvas(), (ULong_t)gPad, (ULong_t)fH));
3378 }
3379 
3380 ////////////////////////////////////////////////////////////////////////////////
3381 /// Execute the actions corresponding to `event`.
3382 ///
3383 /// This function is called when a histogram is clicked with the locator at
3384 /// the pixel position px,py.
3385 
3387 {
3388 
3389  if (!gPad) return;
3390 
3391  static Int_t bin, px1, py1, px2, py2, pyold;
3392  static TBox *zoombox;
3393  Double_t zbx1,zbx2,zby1,zby2;
3394 
3395  Int_t bin1, bin2;
3396  Double_t xlow, xup, ylow, binval, x, baroffset, barwidth, binwidth;
3397  Bool_t opaque = gPad->OpaqueMoving();
3398 
3399  if (!gPad->IsEditable()) return;
3400 
3401  if (fPie) {
3402  fPie->ExecuteEvent(event, px, py);
3403  return;
3404  }
3405  // come here if we have a lego/surface in the pad
3406  TView *view = gPad->GetView();
3407 
3408  if (!fShowProjection && view && view->TestBit(kCannotRotate) == 0) {
3409  view->ExecuteRotateView(event, px, py);
3410  return;
3411  }
3412 
3413  TAxis *xaxis = fH->GetXaxis();
3414  TAxis *yaxis = fH->GetYaxis();
3415  Int_t dimension = fH->GetDimension();
3416 
3417  // In case of option SAME the axis must be the ones of the first drawn histogram
3418  TString IsSame = fH->GetDrawOption();
3419  IsSame.ToLower();
3420  if (IsSame.Index("same")>=0) {
3421  TH1 *h1;
3422  TIter next(gPad->GetListOfPrimitives());
3423  while ((h1 = (TH1 *)next())) {
3424  if (!h1->InheritsFrom(TH1::Class())) continue;
3425  xaxis = h1->GetXaxis();
3426  yaxis = h1->GetYaxis();
3427  break;
3428  }
3429  }
3430 
3431  Double_t factor = 1;
3432  if (fH->GetNormFactor() != 0) {
3433  factor = fH->GetNormFactor()/fH->GetSumOfWeights();
3434  }
3435 
3436  switch (event) {
3437 
3438  case kButton1Down:
3439 
3440  if (!opaque) gVirtualX->SetLineColor(-1);
3441  fH->TAttLine::Modify();
3442 
3443  if (opaque && dimension ==2) {
3444  zbx1 = gPad->AbsPixeltoX(px);
3445  zbx2 = gPad->AbsPixeltoX(px);
3446  zby1 = gPad->AbsPixeltoY(py);
3447  zby2 = gPad->AbsPixeltoY(py);
3448  px1 = px;
3449  py1 = py;
3450  if (gPad->GetLogx()) {
3451  zbx1 = TMath::Power(10,zbx1);
3452  zbx2 = TMath::Power(10,zbx2);
3453  }
3454  if (gPad->GetLogy()) {
3455  zby1 = TMath::Power(10,zby1);
3456  zby2 = TMath::Power(10,zby2);
3457  }
3458  zoombox = new TBox(zbx1, zby1, zbx2, zby2);
3459  Int_t ci = TColor::GetColor("#7d7dff");
3460  TColor *zoomcolor = gROOT->GetColor(ci);
3461  if (!TCanvas::SupportAlpha() || !zoomcolor) zoombox->SetFillStyle(3002);
3462  else zoomcolor->SetAlpha(0.5);
3463  zoombox->SetFillColor(ci);
3464  zoombox->Draw();
3465  gPad->Modified();
3466  gPad->Update();
3467  }
3468  // No break !!!
3469 
3470  case kMouseMotion:
3471 
3472  if (fShowProjection) {ShowProjection3(px,py); break;}
3473 
3474  gPad->SetCursor(kPointer);
3475  if (dimension ==1) {
3476  if (Hoption.Bar) {
3477  baroffset = fH->GetBarOffset();
3478  barwidth = fH->GetBarWidth();
3479  } else {
3480  baroffset = 0;
3481  barwidth = 1;
3482  }
3483  x = gPad->AbsPixeltoX(px);
3484  bin = fXaxis->FindFixBin(gPad->PadtoX(x));
3485  binwidth = fXaxis->GetBinWidth(bin);
3486  xlow = gPad->XtoPad(fXaxis->GetBinLowEdge(bin) + baroffset*binwidth);
3487  xup = gPad->XtoPad(xlow + barwidth*binwidth);
3488  ylow = gPad->GetUymin();
3489  px1 = gPad->XtoAbsPixel(xlow);
3490  px2 = gPad->XtoAbsPixel(xup);
3491  py1 = gPad->YtoAbsPixel(ylow);
3492  py2 = py;
3493  pyold = py;
3494  if (gROOT->GetEditHistograms()) gPad->SetCursor(kArrowVer);
3495  }
3496 
3497  break;
3498 
3499  case kButton1Motion:
3500 
3501  if (dimension ==1) {
3502  if (gROOT->GetEditHistograms()) {
3503  if (!opaque) {
3504  gVirtualX->DrawBox(px1, py1, px2, py2,TVirtualX::kHollow); // Draw the old box
3505  py2 += py - pyold;
3506  gVirtualX->DrawBox(px1, py1, px2, py2,TVirtualX::kHollow); // Draw the new box
3507  pyold = py;
3508  } else {
3509  py2 += py - pyold;
3510  pyold = py;
3511  binval = gPad->PadtoY(gPad->AbsPixeltoY(py2))/factor;
3512  fH->SetBinContent(bin,binval);
3513  gPad->Modified(kTRUE);
3514  }
3515  }
3516  }
3517 
3518  if (opaque && dimension ==2) {
3519  if (TMath::Abs(px1-px)>5 && TMath::Abs(py1-py)>5) {
3520  zbx2 = gPad->AbsPixeltoX(px);
3521  zby2 = gPad->AbsPixeltoY(py);
3522  if (gPad->GetLogx()) zbx2 = TMath::Power(10,zbx2);
3523  if (gPad->GetLogy()) zby2 = TMath::Power(10,zby2);
3524  zoombox->SetX2(zbx2);
3525  zoombox->SetY2(zby2);
3526  gPad->Modified();
3527  gPad->Update();
3528  }
3529  }
3530 
3531  break;
3532 
3533  case kWheelUp:
3534 
3535  if (dimension ==2) {
3536  bin1 = xaxis->GetFirst()+1;
3537  bin2 = xaxis->GetLast()-1;
3538  bin1 = TMath::Max(bin1, 1);
3539  bin2 = TMath::Min(bin2, xaxis->GetNbins());
3540  if (bin2>bin1) xaxis->SetRange(bin1,bin2);
3541  bin1 = yaxis->GetFirst()+1;
3542  bin2 = yaxis->GetLast()-1;
3543  bin1 = TMath::Max(bin1, 1);
3544  bin2 = TMath::Min(bin2, yaxis->GetNbins());
3545  if (bin2>bin1) yaxis->SetRange(bin1,bin2);
3546  }
3547  gPad->Modified();
3548  gPad->Update();
3549 
3550  break;
3551 
3552  case kWheelDown:
3553 
3554  if (dimension == 2) {
3555  bin1 = xaxis->GetFirst()-1;
3556  bin2 = xaxis->GetLast()+1;
3557  bin1 = TMath::Max(bin1, 1);
3558  bin2 = TMath::Min(bin2, xaxis->GetNbins());
3559  if (bin2>bin1) xaxis->SetRange(bin1,bin2);
3560  bin1 = yaxis->GetFirst()-1;
3561  bin2 = yaxis->GetLast()+1;
3562  bin1 = TMath::Max(bin1, 1);
3563  bin2 = TMath::Min(bin2, yaxis->GetNbins());
3564  if (bin2>bin1) yaxis->SetRange(bin1,bin2);
3565  }
3566  gPad->Modified();
3567  gPad->Update();
3568 
3569  break;
3570 
3571  case kButton1Up:
3572  if (dimension ==1) {
3573  if (gROOT->GetEditHistograms()) {
3574  binval = gPad->PadtoY(gPad->AbsPixeltoY(py2))/factor;
3575  fH->SetBinContent(bin,binval);
3576  PaintInit(); // recalculate Hparam structure and recalculate range
3577  }
3578 
3579  // might resize pad pixmap so should be called before any paint routine
3580  RecalculateRange();
3581  }
3582  if (opaque && dimension ==2) {
3583  if (zoombox) {
3584  Double_t x1 = TMath::Min(zoombox->GetX1(), zoombox->GetX2());
3585  Double_t x2 = TMath::Max(zoombox->GetX1(), zoombox->GetX2());
3586  Double_t y1 = TMath::Min(zoombox->GetY1(), zoombox->GetY2());
3587  Double_t y2 = TMath::Max(zoombox->GetY1(), zoombox->GetY2());
3588  x1 = TMath::Max(x1,xaxis->GetXmin());
3589  x2 = TMath::Min(x2,xaxis->GetXmax());
3590  y1 = TMath::Max(y1,yaxis->GetXmin());
3591  y2 = TMath::Min(y2,yaxis->GetXmax());
3592  if (x1<x2 && y1<y2) {
3593  xaxis->SetRangeUser(x1, x2);
3594  yaxis->SetRangeUser(y1, y2);
3595  }
3596  zoombox->Delete();
3597  zoombox = 0;
3598  }
3599  }
3600  gPad->Modified(kTRUE);
3601  if (opaque) gVirtualX->SetLineColor(-1);
3602 
3603  break;
3604 
3605  case kButton1Locate:
3606 
3607  ExecuteEvent(kButton1Down, px, py);
3608 
3609  while (1) {
3610  px = py = 0;
3611  event = gVirtualX->RequestLocator(1, 1, px, py);
3612 
3613  ExecuteEvent(kButton1Motion, px, py);
3614 
3615  if (event != -1) { // button is released
3616  ExecuteEvent(kButton1Up, px, py);
3617  return;
3618  }
3619  }
3620  }
3621 }
3622 
3623 ////////////////////////////////////////////////////////////////////////////////
3624 /// Get a contour (as a list of TGraphs) using the Delaunay triangulation.
3625 
3627 {
3628 
3629 
3630 
3631  // Check if fH contains a TGraphDelaunay2D
3632  TList *hl = fH->GetListOfFunctions();
3633  TGraphDelaunay2D *dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
3634  // try with the old painter
3635  TGraphDelaunay *dtOld = nullptr;
3636  if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
3637 
3638  if (!dt && !dtOld) return nullptr;
3639 
3640  gCurrentHist = fH;
3641 
3642  if (!fGraph2DPainter) {
3643  if (dt) ((THistPainter*)this)->fGraph2DPainter = new TGraph2DPainter(dt);
3644  else ((THistPainter*)this)->fGraph2DPainter = new TGraph2DPainter(dtOld);
3645  }
3646 
3647  return fGraph2DPainter->GetContourList(contour);
3648 }
3649 
3650 ////////////////////////////////////////////////////////////////////////////////
3651 /// Display the histogram info (bin number, contents, integral up to bin
3652 /// corresponding to cursor position px,py.
3653 
3655 {
3656 
3657  if (!gPad) return (char*)"";
3658 
3659  Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
3660  Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
3661  Double_t x1 = gPad->PadtoX(gPad->AbsPixeltoX(px+1));
3662  TString drawOption = fH->GetDrawOption();
3663  drawOption.ToLower();
3664  Double_t xmin, xmax, uxmin,uxmax;
3665  Double_t ymin, ymax, uymin,uymax;
3666  if (fH->GetDimension() == 2) {
3667  if (gPad->GetView() || drawOption.Index("cont") >= 0) {
3668  uxmin=gPad->GetUxmin();
3669  uxmax=gPad->GetUxmax();
3672  x = xmin +(xmax-xmin)*(x-uxmin)/(uxmax-uxmin);
3673  uymin=gPad->GetUymin();
3674  uymax=gPad->GetUymax();
3677  y = ymin +(ymax-ymin)*(y-uymin)/(uymax-uymin);
3678  }
3679  }
3680  Int_t binx,biny,binmin=0,binx1;
3681  if (gPad->IsVertical()) {
3682  binx = fXaxis->FindFixBin(x);
3683  if (drawOption.Index("same") >= 0) {
3684  TH1 *h1;
3685  TIter next(gPad->GetListOfPrimitives());
3686  while ((h1 = (TH1 *)next())) {
3687  if (!h1->InheritsFrom(TH1::Class())) continue;
3688  binmin = h1->GetXaxis()->GetFirst();
3689  break;
3690  }
3691  } else {
3692  binmin = fXaxis->GetFirst();
3693  }
3694  binx1 = fXaxis->FindFixBin(x1);
3695  // special case if more than 1 bin in x per pixel
3696  if (binx1-binx>1 && fH->GetDimension() == 1) {
3697  Double_t binval=fH->GetBinContent(binx);
3698  Int_t binnear=binx;
3699  for (Int_t ibin=binx+1; ibin<binx1; ibin++) {
3700  Double_t binvaltmp = fH->GetBinContent(ibin);
3701  if (TMath::Abs(y-binvaltmp) < TMath::Abs(y-binval)) {
3702  binval=binvaltmp;
3703  binnear=ibin;
3704  }
3705  }
3706  binx = binnear;
3707  }
3708  } else {
3709  x1 = gPad->PadtoY(gPad->AbsPixeltoY(py+1));
3710  binx = fXaxis->FindFixBin(y);
3711  if (drawOption.Index("same") >= 0) {
3712  TH1 *h1;
3713  TIter next(gPad->GetListOfPrimitives());
3714  while ((h1 = (TH1 *)next())) {
3715  if (!h1->InheritsFrom(TH1::Class())) continue;
3716  binmin = h1->GetXaxis()->GetFirst();
3717  break;
3718  }
3719  } else {
3720  binmin = fXaxis->GetFirst();
3721  }
3722  binx1 = fXaxis->FindFixBin(x1);
3723  // special case if more than 1 bin in x per pixel
3724  if (binx1-binx>1 && fH->GetDimension() == 1) {
3725  Double_t binval=fH->GetBinContent(binx);
3726  Int_t binnear=binx;
3727  for (Int_t ibin=binx+1; ibin<binx1; ibin++) {
3728  Double_t binvaltmp = fH->GetBinContent(ibin);
3729  if (TMath::Abs(x-binvaltmp) < TMath::Abs(x-binval)) {
3730  binval=binvaltmp;
3731  binnear=ibin;
3732  }
3733  }
3734  binx = binnear;
3735  }
3736  }
3737  if (fH->GetDimension() == 1) {
3738  if (fH->InheritsFrom(TProfile::Class())) {
3739  TProfile *tp = (TProfile*)fH;
3740  fObjectInfo.Form("(x=%g, y=%g, binx=%d, binc=%g, bine=%g, binn=%d)",
3741  x, y, binx, fH->GetBinContent(binx), fH->GetBinError(binx),
3742  (Int_t) tp->GetBinEntries(binx));
3743  }
3744  else {
3745  Double_t integ = 0;
3746  for (Int_t bin=binmin;bin<=binx;bin++) {integ += fH->GetBinContent(bin);}
3747  fObjectInfo.Form("(x=%g, y=%g, binx=%d, binc=%g, Sum=%g)",
3748  x,y,binx,fH->GetBinContent(binx),integ);
3749  }
3750  } else if (fH->GetDimension() == 2) {
3751  if (fH->InheritsFrom(TH2Poly::Class())) {
3752  TH2Poly *th2 = (TH2Poly*)fH;
3753  biny = th2->FindBin(x,y);
3754  fObjectInfo.Form("%s (x=%g, y=%g, bin=%d, binc=%g)",
3755  th2->GetBinTitle(biny),x,y,biny,th2->GetBinContent(biny));
3756  }
3757  else if (fH->InheritsFrom(TProfile2D::Class())) {
3758  TProfile2D *tp = (TProfile2D*)fH;
3759  biny = fYaxis->FindFixBin(y);
3760  Int_t bin = fH->GetBin(binx,biny);
3761  fObjectInfo.Form("(x=%g, y=%g, binx=%d, biny=%d, binc=%g, bine=%g, binn=%d)",
3762  x, y, binx, biny, fH->GetBinContent(bin),
3763  fH->GetBinError(bin), (Int_t) tp->GetBinEntries(bin));
3764  } else {
3765  biny = fYaxis->FindFixBin(y);
3766  fObjectInfo.Form("(x=%g, y=%g, binx=%d, biny=%d, binc=%g bine=%g)",
3767  x,y,binx,biny,fH->GetBinContent(binx,biny),
3768  fH->GetBinError(binx,biny));
3769  }
3770  } else {
3771  // 3d case: retrieving the x,y,z bin is not yet implemented
3772  // print just the x,y info
3773  fObjectInfo.Form("(x=%g, y=%g)",x,y);
3774  }
3775 
3776  return (char *)fObjectInfo.Data();
3777 }
3778 
3779 ////////////////////////////////////////////////////////////////////////////////
3780 /// Set highlight (enable/disable) mode for fH
3781 
3783 {
3784  if (fH->IsHighlight()) return;
3785 
3786  fXHighlightBin = -1;
3787  fYHighlightBin = -1;
3788  // delete previous highlight box
3791  // emit Highlighted() signal (user can check on disabled)
3792  if (gPad->GetCanvas()) gPad->GetCanvas()->Highlighted(gPad, fH, fXHighlightBin, fYHighlightBin);
3793 }
3794 
3795 ////////////////////////////////////////////////////////////////////////////////
3796 /// Check on highlight bin
3797 
3799 {
3800  // call from DistancetoPrimitive (only if highlight is enable)
3801 
3802  Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
3803  Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
3804  Int_t binx = fXaxis->FindFixBin(x);
3805  Int_t biny = fYaxis->FindFixBin(y);
3806  if (!gPad->IsVertical()) binx = fXaxis->FindFixBin(y);
3807 
3808  Bool_t changedBin = kFALSE;
3809  if (binx != fXHighlightBin) {
3810  fXHighlightBin = binx;
3811  changedBin = kTRUE;
3812  } else if (fH->GetDimension() == 1) return;
3813  if (biny != fYHighlightBin) {
3814  fYHighlightBin = biny;
3815  changedBin = kTRUE;
3816  }
3817  if (!changedBin) return;
3818 
3819  // Info("HighlightBin", "histo: %p '%s'\txbin: %d, ybin: %d",
3820  // (void *)fH, fH->GetName(), fXHighlightBin, fYHighlightBin);
3821 
3822  // paint highlight bin as box (recursive calls PaintHighlightBin)
3823  gPad->Modified(kTRUE);
3824  gPad->Update();
3825 
3826  // emit Highlighted() signal
3827  if (gPad->GetCanvas()) gPad->GetCanvas()->Highlighted(gPad, fH, fXHighlightBin, fYHighlightBin);
3828 }
3829 
3830 ////////////////////////////////////////////////////////////////////////////////
3831 /// Paint highlight bin as TBox object
3832 
3834 {
3835  // call from PaintTitle
3836 
3837  if (!fH->IsHighlight()) return;
3838 
3839  Double_t uxmin = gPad->GetUxmin();
3840  Double_t uxmax = gPad->GetUxmax();
3841  Double_t uymin = gPad->GetUymin();
3842  Double_t uymax = gPad->GetUymax();
3843  if (gPad->GetLogx()) {
3844  uxmin = TMath::Power(10.0, uxmin);
3845  uxmax = TMath::Power(10.0, uxmax);
3846  }
3847  if (gPad->GetLogy()) {
3848  uymin = TMath::Power(10.0, uymin);
3849  uymax = TMath::Power(10.0, uymax);
3850  }
3851 
3852  // testing specific possibility (after zoom, draw with "same", log, etc.)
3853  Double_t hcenter;
3854  if (gPad->IsVertical()) {
3855  hcenter = fXaxis->GetBinCenter(fXHighlightBin);
3856  if ((hcenter < uxmin) || (hcenter > uxmax)) return;
3857  } else {
3858  hcenter = fYaxis->GetBinCenter(fXHighlightBin);
3859  if ((hcenter < uymin) || (hcenter > uymax)) return;
3860  }
3861  if (fH->GetDimension() == 2) {
3862  hcenter = fYaxis->GetBinCenter(fYHighlightBin);
3863  if ((hcenter < uymin) || (hcenter > uymax)) return;
3864  }
3865 
3866  // paint X highlight bin (for 1D or 2D)
3867  Double_t hbx1, hbx2, hby1, hby2;
3868  if (gPad->IsVertical()) {
3871  hby1 = uymin;
3872  hby2 = uymax;
3873  } else {
3874  hbx1 = uxmin;
3875  hbx2 = uxmax;
3878  }
3879 
3880  if (!gXHighlightBox) {
3881  gXHighlightBox = new TBox(hbx1, hby1, hbx2, hby2);
3885  else gROOT->GetColor(gXHighlightBox->GetFillColor())->SetAlpha(0.5);
3886  }
3887  gXHighlightBox->SetX1(hbx1);
3888  gXHighlightBox->SetX2(hbx2);
3889  gXHighlightBox->SetY1(hby1);
3890  gXHighlightBox->SetY2(hby2);
3891  gXHighlightBox->Paint();
3892 
3893  // Info("PaintHighlightBin", "histo: %p '%s'\txbin: %d, ybin: %d",
3894  // (void *)fH, fH->GetName(), fXHighlightBin, fYHighlightBin);
3895 
3896  // paint Y highlight bin (only for 2D)
3897  if (fH->GetDimension() != 2) return;
3898  hbx1 = uxmin;
3899  hbx2 = uxmax;
3902 
3903  if (!gYHighlightBox) {
3904  gYHighlightBox = new TBox(hbx1, hby1, hbx2, hby2);
3908  }
3909  gYHighlightBox->SetX1(hbx1);
3910  gYHighlightBox->SetX2(hbx2);
3911  gYHighlightBox->SetY1(hby1);
3912  gYHighlightBox->SetY2(hby2);
3913  gYHighlightBox->Paint();
3914 }
3915 
3916 ////////////////////////////////////////////////////////////////////////////////
3917 /// Return `kTRUE` if the cell `ix`, `iy` is inside one of the graphical cuts.
3918 
3920 {
3921 
3922  for (Int_t i=0;i<fNcuts;i++) {
3923  Double_t x = fXaxis->GetBinCenter(ix);
3924  Double_t y = fYaxis->GetBinCenter(iy);
3925  if (fCutsOpt[i] > 0) {
3926  if (!fCuts[i]->IsInside(x,y)) return kFALSE;
3927  } else {
3928  if (fCuts[i]->IsInside(x,y)) return kFALSE;
3929  }
3930  }
3931  return kTRUE;
3932 }
3933 
3934 ////////////////////////////////////////////////////////////////////////////////
3935 /// Return `kTRUE` if the point `x`, `y` is inside one of the graphical cuts.
3936 
3938 {
3939 
3940  for (Int_t i=0;i<fNcuts;i++) {
3941  if (fCutsOpt[i] > 0) {
3942  if (!fCuts[i]->IsInside(x,y)) return kFALSE;
3943  } else {
3944  if (fCuts[i]->IsInside(x,y)) return kFALSE;
3945  }
3946  }
3947  return kTRUE;
3948 }
3949 
3950 ////////////////////////////////////////////////////////////////////////////////
3951 /// Decode string `choptin` and fill Hoption structure.
3952 
3954 {
3955 
3956  char *l;
3957  char chopt[128];
3958  Int_t nch = strlen(choptin);
3959  strlcpy(chopt,choptin,128);
3960  Int_t hdim = fH->GetDimension();
3961 
3964  Hoption.Same = Hoption.Func = Hoption.Scat = 0;
3970 
3971  // special 2D options
3972  Hoption.List = 0;
3973  Hoption.Zscale = 0;
3974  Hoption.FrontBox = 1;
3975  Hoption.BackBox = 1;
3977 
3978  Hoption.Zero = 0;
3979 
3981 
3982  //check for graphical cuts
3983  MakeCuts(chopt);
3984 
3985  for (Int_t i=0;i<nch;i++) chopt[i] = toupper(chopt[i]);
3986  if (hdim > 1) Hoption.Scat = 1;
3987  if (!nch) Hoption.Hist = 1;
3988  if (fFunctions->First()) Hoption.Func = 1;
3989  if (fH->GetSumw2N() && hdim == 1) Hoption.Error = 2;
3990 
3991  char *l1 = strstr(chopt,"PFC"); // Automatic Fill Color
3992  char *l2 = strstr(chopt,"PLC"); // Automatic Line Color
3993  char *l3 = strstr(chopt,"PMC"); // Automatic Marker Color
3994  if (l1 || l2 || l3) {
3995  Int_t i = gPad->NextPaletteColor();
3996  if (l1) {memcpy(l1," ",3); fH->SetFillColor(i);}
3997  if (l2) {memcpy(l2," ",3); fH->SetLineColor(i);}
3998  if (l3) {memcpy(l3," ",3); fH->SetMarkerColor(i);}
3999  Hoption.Hist = 1; // Make sure something is drawn in case there is no drawing option specified.
4000  }
4001 
4002  l = strstr(chopt,"MIN0");
4003  if (l) {
4004  Hoption.MinimumZero = 1;
4005  memcpy(l," ",4);
4006  }
4007 
4008  l = strstr(chopt,"SPEC");
4009  if (l) {
4010  Hoption.Scat = 0;
4011  memcpy(l," ",4);
4012  Int_t bs=0;
4013  l = strstr(chopt,"BF(");
4014  if (l) {
4015  if (sscanf(&l[3],"%d",&bs) > 0) {
4016  Int_t i=0;
4017  while (l[i]!=')') {
4018  l[i] = ' ';
4019  i++;
4020  }
4021  l[i] = ' ';
4022  }
4023  }
4024  Hoption.Spec = TMath::Max(1600,bs);
4025  return 1;
4026  }
4027 
4028  l = strstr(chopt,"GL");
4029  if (l) {
4030  memcpy(l," ",2);
4031  }
4032  l = strstr(chopt,"X+");
4033  if (l) {
4034  Hoption.AxisPos = 10;
4035  memcpy(l," ",2);
4036  }
4037  l = strstr(chopt,"Y+");
4038  if (l) {
4039  Hoption.AxisPos += 1;
4040  memcpy(l," ",2);
4041  }
4042  if ((Hoption.AxisPos == 10 || Hoption.AxisPos == 1) && (nch == 2)) Hoption.Hist = 1;
4043  if (Hoption.AxisPos == 11 && nch == 4) Hoption.Hist = 1;
4044 
4045  l = strstr(chopt,"SAMES");
4046  if (l) {
4047  if (nch == 5) Hoption.Hist = 1;
4048  Hoption.Same = 2;
4049  memcpy(l," ",5);
4050  if (l[5] == '0') { Hoption.Same += 10; l[5] = ' '; }
4051  }
4052  l = strstr(chopt,"SAME");
4053  if (l) {
4054  if (nch == 4) Hoption.Hist = 1;
4055  Hoption.Same = 1;
4056  memcpy(l," ",4);
4057  if (l[4] == '0') { Hoption.Same += 10; l[4] = ' '; }
4058  }
4059 
4060  l = strstr(chopt,"PIE");
4061  if (l) {
4062  Hoption.Pie = 1;
4063  memcpy(l," ",3);
4064  }
4065 
4066 
4067  l = strstr(chopt,"CANDLE");
4068  if (l) {
4069  TCandle candle;
4070  Hoption.Candle = candle.ParseOption(l);
4071  Hoption.Scat = 0;
4072  }
4073 
4074  l = strstr(chopt,"VIOLIN");
4075  if (l) {
4076  TCandle candle;
4077  Hoption.Candle = candle.ParseOption(l);
4078  Hoption.Scat = 0;
4079  }
4080 
4081  l = strstr(chopt,"LEGO");
4082  if (l) {
4083  Hoption.Scat = 0;
4084  Hoption.Lego = 1; memcpy(l," ",4);
4085  if (l[4] == '1') { Hoption.Lego = 11; l[4] = ' '; }
4086  if (l[4] == '2') { Hoption.Lego = 12; l[4] = ' '; }
4087  if (l[4] == '3') { Hoption.Lego = 13; l[4] = ' '; }
4088  if (l[4] == '4') { Hoption.Lego = 14; l[4] = ' '; }
4089  if (l[4] == '9') { Hoption.Lego = 19; l[4] = ' '; }
4090  l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4091  l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4092  l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4093  }
4094 
4095  l = strstr(chopt,"SURF");
4096  if (l) {
4097  Hoption.Scat = 0;
4098  Hoption.Surf = 1; memcpy(l," ",4);
4099  if (l[4] == '1') { Hoption.Surf = 11; l[4] = ' '; }
4100  if (l[4] == '2') { Hoption.Surf = 12; l[4] = ' '; }
4101  if (l[4] == '3') { Hoption.Surf = 13; l[4] = ' '; }
4102  if (l[4] == '4') { Hoption.Surf = 14; l[4] = ' '; }
4103  if (l[4] == '5') { Hoption.Surf = 15; l[4] = ' '; }
4104  if (l[4] == '6') { Hoption.Surf = 16; l[4] = ' '; }
4105  if (l[4] == '7') { Hoption.Surf = 17; l[4] = ' '; }
4106  l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4107  l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4108  }
4109 
4110  l = strstr(chopt,"TF3");
4111  if (l) {
4112  l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4113  l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4114  }
4115 
4116  l = strstr(chopt,"ISO");
4117  if (l) {
4118  l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4119  l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4120  }
4121 
4122  l = strstr(chopt,"LIST"); if (l) { Hoption.List = 1; memcpy(l," ",4);}
4123 
4124  l = strstr(chopt,"CONT");
4125  if (l) {
4126  memcpy(l," ",4);
4127  if (hdim>1) {
4128  Hoption.Scat = 0;
4129  Hoption.Contour = 1;
4130  if (l[4] == '1') { Hoption.Contour = 11; l[4] = ' '; }
4131  if (l[4] == '2') { Hoption.Contour = 12; l[4] = ' '; }
4132  if (l[4] == '3') { Hoption.Contour = 13; l[4] = ' '; }
4133  if (l[4] == '4') { Hoption.Contour = 14; l[4] = ' '; }
4134  if (l[4] == '5') { Hoption.Contour = 15; l[4] = ' '; }
4135  } else {
4136  Hoption.Hist = 1;
4137  }
4138  }
4139  l = strstr(chopt,"HBAR");
4140  if (l) {
4141  Hoption.Hist = 0;
4142  Hoption.Bar = 20; memcpy(l," ",4);
4143  if (l[4] == '1') { Hoption.Bar = 21; l[4] = ' '; }
4144  if (l[4] == '2') { Hoption.Bar = 22; l[4] = ' '; }
4145  if (l[4] == '3') { Hoption.Bar = 23; l[4] = ' '; }
4146  if (l[4] == '4') { Hoption.Bar = 24; l[4] = ' '; }
4147  }
4148  l = strstr(chopt,"BAR");
4149  if (l) {
4150  Hoption.Hist = 0;
4151  Hoption.Bar = 10; memcpy(l," ",3);
4152  if (l[3] == '1') { Hoption.Bar = 11; l[3] = ' '; }
4153  if (l[3] == '2') { Hoption.Bar = 12; l[3] = ' '; }
4154  if (l[3] == '3') { Hoption.Bar = 13; l[3] = ' '; }
4155  if (l[3] == '4') { Hoption.Bar = 14; l[3] = ' '; }
4156  }
4157 
4158  l = strstr(chopt,"ARR" );
4159  if (l) {
4160  memcpy(l," ", 3);
4161  if (hdim>1) {
4162  Hoption.Arrow = 1;
4163  Hoption.Scat = 0;
4164  l = strstr(chopt,"COL"); if (l) { Hoption.Arrow = 2; memcpy(l," ",3); }
4165  l = strstr(chopt,"Z"); if (l) { Hoption.Zscale = 1; memcpy(l," ",1); }
4166  } else {
4167  Hoption.Hist = 1;
4168  }
4169  }
4170  l = strstr(chopt,"BOX" );
4171  if (l) {
4172  memcpy(l," ", 3);
4173  if (hdim>1) {
4174  Hoption.Scat = 0;
4175  Hoption.Box = 1;
4176  if (l[3] == '1') { Hoption.Box = 11; l[3] = ' '; }
4177  if (l[3] == '2') { Hoption.Box = 12; l[3] = ' '; }
4178  if (l[3] == '3') { Hoption.Box = 13; l[3] = ' '; }
4179  } else {
4180  Hoption.Hist = 1;
4181  }
4182  }
4183  l = strstr(chopt,"COLZ");
4184  if (l) {
4185  memcpy(l," ",4);
4186  if (hdim>1) {
4187  Hoption.Color = 1;
4188  Hoption.Scat = 0;
4189  Hoption.Zscale = 1;
4190  if (l[4] == '2') { Hoption.Color = 3; l[4] = ' '; }
4191  l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4192  l = strstr(chopt,"1"); if (l) { Hoption.Color = 2; memcpy(l," ",1); }
4193  } else {
4194  Hoption.Hist = 1;
4195  }
4196  }
4197  l = strstr(chopt,"COL" );
4198  if (l) {
4199  memcpy(l," ", 3);
4200  if (hdim>1) {
4201  Hoption.Color = 1;
4202  Hoption.Scat = 0;
4203  if (l[3] == '2') { Hoption.Color = 3; l[3] = ' '; }
4204  l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4205  l = strstr(chopt,"1"); if (l) { Hoption.Color = 2; memcpy(l," ",1); }
4206  } else {
4207  Hoption.Hist = 1;
4208  }
4209  }
4210  l = strstr(chopt,"CHAR"); if (l) { Hoption.Char = 1; memcpy(l," ",4); Hoption.Scat = 0; }
4211  l = strstr(chopt,"FUNC"); if (l) { Hoption.Func = 2; memcpy(l," ",4); Hoption.Hist = 0; }
4212  l = strstr(chopt,"HIST"); if (l) { Hoption.Hist = 2; memcpy(l," ",4); Hoption.Func = 0; Hoption.Error = 0;}
4213  l = strstr(chopt,"AXIS"); if (l) { Hoption.Axis = 1; memcpy(l," ",4); }
4214  l = strstr(chopt,"AXIG"); if (l) { Hoption.Axis = 2; memcpy(l," ",4); }
4215  l = strstr(chopt,"SCAT"); if (l) { Hoption.Scat = 1; memcpy(l," ",4); }
4216  l = strstr(chopt,"TEXT");
4217  if (l) {
4218  Int_t angle;
4219  if (sscanf(&l[4],"%d",&angle) > 0) {
4220  if (angle < 0) angle=0;
4221  if (angle > 90) angle=90;
4222  Hoption.Text = 1000+angle;
4223  } else {
4224  Hoption.Text = 1;
4225  }
4226  memcpy(l," ", 4);
4227  l = strstr(chopt,"N");
4228  if (l && fH->InheritsFrom(TH2Poly::Class())) Hoption.Text += 3000;
4229  Hoption.Scat = 0;
4230  }
4231  l = strstr(chopt,"POL"); if (l) { Hoption.System = kPOLAR; memcpy(l," ",3); }
4232  l = strstr(chopt,"CYL"); if (l) { Hoption.System = kCYLINDRICAL; memcpy(l," ",3); }
4233  l = strstr(chopt,"SPH"); if (l) { Hoption.System = kSPHERICAL; memcpy(l," ",3); }
4234  l = strstr(chopt,"PSR"); if (l) { Hoption.System = kRAPIDITY; memcpy(l," ",3); }
4235 
4236  l = strstr(chopt,"TRI");
4237  if (l) {
4238  Hoption.Scat = 0;
4239  Hoption.Color = 0;
4240  Hoption.Tri = 1; memcpy(l," ",3);
4241  l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4242  l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4243  l = strstr(chopt,"ERR"); if (l) memcpy(l," ",3);
4244  }
4245 
4246  l = strstr(chopt,"AITOFF");
4247  if (l) {
4248  Hoption.Proj = 1; memcpy(l," ",6); //Aitoff projection
4249  }
4250  l = strstr(chopt,"MERCATOR");
4251  if (l) {
4252  Hoption.Proj = 2; memcpy(l," ",8); //Mercator projection
4253  }
4254  l = strstr(chopt,"SINUSOIDAL");
4255  if (l) {
4256  Hoption.Proj = 3; memcpy(l," ",10); //Sinusoidal projection
4257  }
4258  l = strstr(chopt,"PARABOLIC");
4259  if (l) {
4260  Hoption.Proj = 4; memcpy(l," ",9); //Parabolic projection
4261  }
4262  if (Hoption.Proj > 0) {
4263  Hoption.Scat = 0;
4264  Hoption.Contour = 14;
4265  }
4266 
4267  if (strstr(chopt,"A")) Hoption.Axis = -1;
4268  if (strstr(chopt,"B")) Hoption.Bar = 1;
4269  if (strstr(chopt,"C")) { Hoption.Curve =1; Hoption.Hist = -1;}
4270  if (strstr(chopt,"F")) Hoption.Fill =1;
4271  if (strstr(chopt,"][")) {Hoption.Off =1; Hoption.Hist =1;}
4272  if (strstr(chopt,"F2")) Hoption.Fill =2;
4273  if (strstr(chopt,"L")) { Hoption.Line =1; Hoption.Hist = -1;}
4274  if (strstr(chopt,"P")) { Hoption.Mark =1; Hoption.Hist = -1;}
4275  if (strstr(chopt,"Z")) Hoption.Zscale =1;
4276  if (strstr(chopt,"*")) Hoption.Star =1;
4277  if (strstr(chopt,"H")) Hoption.Hist =2;
4278  if (strstr(chopt,"P0")) Hoption.Mark =10;
4279 
4280  if (fH->InheritsFrom(TH2Poly::Class())) {
4281  if (Hoption.Fill+Hoption.Line+Hoption.Mark != 0 ) Hoption.Scat = 0;
4282  }
4283 
4284  if (strstr(chopt,"E")) {
4285  if (hdim == 1) {
4286  Hoption.Error = 1;
4287  if (strstr(chopt,"E0")) Hoption.Error = 10;
4288  if (strstr(chopt,"E1")) Hoption.Error = 11;
4289  if (strstr(chopt,"E2")) Hoption.Error = 12;
4290  if (strstr(chopt,"E3")) Hoption.Error = 13;
4291  if (strstr(chopt,"E4")) Hoption.Error = 14;
4292  if (strstr(chopt,"E5")) Hoption.Error = 15;
4293  if (strstr(chopt,"E6")) Hoption.Error = 16;
4294  if (strstr(chopt,"X0")) {
4295  if (Hoption.Error == 1) Hoption.Error += 20;
4296  Hoption.Error += 10;
4297  }
4299  Hoption.Text += 2000;
4300  Hoption.Error = 0;
4301  }
4302  } else {
4303  if (Hoption.Error == 0) {
4304  Hoption.Error = 100;
4305  Hoption.Scat = 0;
4306  }
4307  if (Hoption.Text) {
4308  Hoption.Text += 2000;
4309  Hoption.Error = 0;
4310  }
4311  }
4312  }
4313 
4314  if (Hoption.Surf == 15) {
4315  if (Hoption.System == kPOLAR || Hoption.System == kCARTESIAN) {
4316  Hoption.Surf = 13;
4317  Warning("MakeChopt","option SURF5 is not supported in Cartesian and Polar modes");
4318  }
4319  }
4320 
4321  // Copy options from current style
4322  Hoption.Logx = gPad->GetLogx();
4323  Hoption.Logy = gPad->GetLogy();
4324  Hoption.Logz = gPad->GetLogz();
4325 
4326  // Check options incompatibilities
4327  if (Hoption.Bar == 1) Hoption.Hist = -1;
4328  return 1;
4329 }
4330 
4331 ////////////////////////////////////////////////////////////////////////////////
4332 /// Decode string `choptin` and fill Graphical cuts structure.
4333 
4335 {
4336 
4337  fNcuts = 0;
4338  char *left = (char*)strchr(choptin,'[');
4339  if (!left) return 0;
4340  char *right = (char*)strchr(choptin,']');
4341  if (!right) return 0;
4342  Int_t nch = right-left;
4343  if (nch < 2) return 0;
4344  char *cuts = left+1;
4345  *right = 0;
4346  char *comma, *minus;
4347  Int_t i;
4348  while (1) {
4349  comma = strchr(cuts,',');
4350  if (comma) *comma = 0;
4351  minus = strchr(cuts,'-');
4352  if (minus) cuts = minus+1;
4353  while (*cuts == ' ') cuts++;
4354  Int_t nc = strlen(cuts);
4355  while (cuts[nc-1] == ' ') {cuts[nc-1] = 0; nc--;}
4356  TIter next(gROOT->GetListOfSpecials());
4357  TCutG *cut=0;
4358  TObject *obj;
4359  while ((obj = next())) {
4360  if (!obj->InheritsFrom(TCutG::Class())) continue;
4361  if (strcmp(obj->GetName(),cuts)) continue;
4362  cut = (TCutG*)obj;
4363  break;
4364  }
4365  if (cut) {
4366  fCuts[fNcuts] = cut;
4367  fCutsOpt[fNcuts] = 1;
4368  if (minus) fCutsOpt[fNcuts] = -1;
4369  fNcuts++;
4370  }
4371  if (!comma) break;
4372  cuts = comma+1;
4373  }
4374  for (i=0;i<=nch;i++) left[i] = ' ';
4375  return fNcuts;
4376 }
4377 
4378 ////////////////////////////////////////////////////////////////////////////////
4379 /// [Control routine to paint any kind of histograms](#HP00)
4380 
4382 {
4383 
4384  if (fH->GetBuffer()) fH->BufferEmpty(-1);
4385 
4386  //For iOS: put the histogram on the top of stack of pickable objects.
4387  const TPickerStackGuard topPush(fH);
4388 
4389  gPad->SetVertical(kTRUE);
4390 
4391  TH1 *oldhist = gCurrentHist;
4392  gCurrentHist = fH;
4393  TH1 *hsave = fH;
4394  Double_t minsav = fH->GetMinimumStored();
4395 
4396  if (!MakeChopt(option)) return; //check options and fill Hoption structure
4397 
4398  // Paint using TSpectrum2Painter
4399  if (Hoption.Spec) {
4400  if (!TableInit()) return;
4401  if (!TClass::GetClass("TSpectrum2Painter")) gSystem->Load("libSpectrumPainter");
4402  gROOT->ProcessLineFast(Form("TSpectrum2Painter::PaintSpectrum((TH2F*)0x%lx,\"%s\",%d)",
4403  (ULong_t)fH, option, Hoption.Spec));
4404  return;
4405  }
4406 
4407  if (Hoption.Pie) {
4408  if (fH->GetDimension() == 1) {
4409  if (!fPie) fPie = new TPie(fH);
4410  fPie->Paint(option);
4411  } else {
4412  Error("Paint", "Option PIE is for 1D histograms only");
4413  }
4414  return;
4415  } else {
4416  if (fPie) delete fPie;
4417  fPie = 0;
4418  }
4419 
4420  fXbuf = new Double_t[kNMAX];
4421  fYbuf = new Double_t[kNMAX];
4422  if (fH->GetDimension() > 2) {
4423  PaintH3(option);
4424  fH->SetMinimum(minsav);
4425  if (Hoption.Func) {
4426  Hoption_t hoptsave = Hoption;
4427  Hparam_t hparsave = Hparam;
4428  PaintFunction(option);
4429  SetHistogram(hsave);
4430  Hoption = hoptsave;
4431  Hparam = hparsave;
4432  }
4433  gCurrentHist = oldhist;
4434  delete [] fXbuf; delete [] fYbuf;
4435  return;
4436  }
4437  TView *view = gPad->GetView();
4438  if (view) {
4439  if (!Hoption.Lego && !Hoption.Surf && !Hoption.Tri) {
4440  delete view;
4441  gPad->SetView(0);
4442  }
4443  }
4444  if (fH->GetDimension() > 1 || Hoption.Lego || Hoption.Surf) {
4445  // In case of 1D histogram, Z axis becomes Y axis.
4446  Int_t logysav=0, logzsav=0;
4447  if (fH->GetDimension() == 1) {
4448  logysav = Hoption.Logy;
4449  logzsav = Hoption.Logz;
4450  Hoption.Logz = 0;
4451  if (Hoption.Logy) {
4452  Hoption.Logz = 1;
4453  Hoption.Logy = 0;
4454  }
4455  }
4456  PaintTable(option);
4457  if (Hoption.Func) {
4458  Hoption_t hoptsave = Hoption;
4459  Hparam_t hparsave = Hparam;
4460  PaintFunction(option);
4461  SetHistogram(hsave);
4462  Hoption = hoptsave;
4463  Hparam = hparsave;
4464  }
4465  fH->SetMinimum(minsav);
4466  gCurrentHist = oldhist;
4467  delete [] fXbuf; delete [] fYbuf;
4468  if (fH->GetDimension() == 1) {
4469  Hoption.Logy = logysav;
4470  Hoption.Logz = logzsav;
4471  }
4472  return;
4473  }
4474 
4475  if (Hoption.Bar >= 20) {
4476  PaintBarH(option);
4477  delete [] fXbuf; delete [] fYbuf;
4478  return;
4479  }
4480 
4481  // fill Hparam structure with histo parameters
4482  if (!PaintInit()) {
4483  delete [] fXbuf; delete [] fYbuf;
4484  return;
4485  }
4486 
4487  // Picture surround (if new page) and page number (if requested).
4488  // Histogram surround (if not option "Same").
4489  PaintFrame();
4490 
4491  // Paint histogram axis only
4492  Bool_t gridx = gPad->GetGridx();
4493  Bool_t gridy = gPad->GetGridy();
4494  if (Hoption.Axis > 0) {
4495  if (Hoption.Axis > 1) PaintAxis(kTRUE); //axis with grid
4496  else {
4497  if (gridx) gPad->SetGridx(0);
4498  if (gridy) gPad->SetGridy(0);
4499  PaintAxis(kFALSE);
4500  if (gridx) gPad->SetGridx(1);
4501  if (gridy) gPad->SetGridy(1);
4502  }
4503  if ((Hoption.Same%10) ==1) Hoption.Same += 1;
4504  goto paintstat;
4505  }
4506  if (gridx || gridy) PaintAxis(kTRUE); // Draw the grid only
4507 
4508  // test for options BAR or HBAR
4509  if (Hoption.Bar >= 10) {
4510  PaintBar(option);
4511  }
4512 
4513  // do not draw histogram if error bars required
4514  if (!Hoption.Error) {
4515  if (Hoption.Hist && Hoption.Bar<10) PaintHist(option);
4516  }
4517 
4518  // test for error bars or option E
4519  if (Hoption.Error) {
4520  PaintErrors(option);
4521  if (Hoption.Hist == 2) PaintHist(option);
4522  }
4523 
4524  if (Hoption.Text) PaintText(option);
4525 
4526  // test for associated function
4527  if (Hoption.Func) {
4528  Hoption_t hoptsave = Hoption;
4529  Hparam_t hparsave = Hparam;
4530  PaintFunction(option);
4531  SetHistogram(hsave);
4532  Hoption = hoptsave;
4533  Hparam = hparsave;
4534  }
4535 
4536  if (gridx) gPad->SetGridx(0);
4537  if (gridy) gPad->SetGridy(0);
4538  PaintAxis(kFALSE);
4539  if (gridx) gPad->SetGridx(1);
4540  if (gridy) gPad->SetGridy(1);
4541 
4542  PaintTitle(); // Draw histogram title
4543 
4544  // Draw box with histogram statistics and/or fit parameters
4545 paintstat:
4546  if ((Hoption.Same%10) != 1 && !fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
4547  TIter next(fFunctions);
4548  TObject *obj = 0;
4549  while ((obj = next())) {
4550  if (obj->InheritsFrom(TF1::Class())) break;
4551  obj = 0;
4552  }
4553 
4554  //Stat is painted twice (first, it will be in canvas' list of primitives),
4555  //second, it will be here, this is not required on iOS.
4556  //Condition is ALWAYS true on a platform different from iOS.
4557  if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode())
4558  PaintStat(gStyle->GetOptStat(),(TF1*)obj);
4559  }
4560  fH->SetMinimum(minsav);
4561  gCurrentHist = oldhist;
4562  delete [] fXbuf; fXbuf = 0;
4563  delete [] fYbuf; fYbuf = 0;
4564 
4565 }
4566 
4567 ////////////////////////////////////////////////////////////////////////////////
4568 /// [Control function to draw a table as an arrow plot](#HP12)
4569 
4571 {
4572  Double_t xk, xstep, yk, ystep;
4573  Double_t dx, dy, x1, x2, y1, y2, xc, yc, dxn, dyn;
4574  Int_t ncx = Hparam.xlast - Hparam.xfirst + 1;
4575  Int_t ncy = Hparam.ylast - Hparam.yfirst + 1;
4576  Double_t xrg = gPad->GetUxmin();
4577  Double_t yrg = gPad->GetUymin();
4578  Double_t xln = gPad->GetUxmax() - xrg;
4579  Double_t yln = gPad->GetUymax() - yrg;
4580  Double_t cx = (xln/Double_t(ncx) -0.03)/2;
4581  Double_t cy = (yln/Double_t(ncy) -0.03)/2;
4582  Double_t dn = 1.E-30;
4583 
4584  auto arrow = new TArrow();
4585  arrow->SetAngle(30);
4586  arrow->SetFillStyle(1001);
4587  arrow->SetFillColor(fH->GetLineColor());
4588  arrow->SetLineColor(fH->GetLineColor());
4589  arrow->SetLineWidth(fH->GetLineWidth());
4590 
4591  // Initialize the levels on the Z axis
4592  Int_t ncolors=0, ndivz=0;
4593  Double_t scale=0.;
4594  if (Hoption.Arrow>1) {
4595  ncolors = gStyle->GetNumberOfColors();
4596  Int_t ndiv = fH->GetContour();
4597  if (ndiv == 0 ) {
4598  ndiv = gStyle->GetNumberContours();
4599  fH->SetContour(ndiv);
4600  }
4601  ndivz = TMath::Abs(ndiv);
4602  if (fH->TestBit(TH1::kUserContour) == 0) fH->SetContour(ndiv);
4603  scale = ndivz/(fH->GetMaximum()-fH->GetMinimum());
4604  }
4605 
4606  for (Int_t id=1;id<=2;id++) {
4607  for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
4608  yk = fYaxis->GetBinLowEdge(j);
4609  ystep = fYaxis->GetBinWidth(j);
4610  for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
4611  xk = fXaxis->GetBinLowEdge(i);
4612  xstep = fXaxis->GetBinWidth(i);
4613  if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
4614  if (i == Hparam.xfirst) {
4615  dx = fH->GetBinContent(i+1, j) - fH->GetBinContent(i, j);
4616  } else if (i == Hparam.xlast) {
4617  dx = fH->GetBinContent(i, j) - fH->GetBinContent(i-1, j);
4618  } else {
4619  dx = 0.5*(fH->GetBinContent(i+1, j) - fH->GetBinContent(i-1, j));
4620  }
4621  if (j == Hparam.yfirst) {
4622  dy = fH->GetBinContent(i, j+1) - fH->GetBinContent(i, j);
4623  } else if (j == Hparam.ylast) {
4624  dy = fH->GetBinContent(i, j) - fH->GetBinContent(i, j-1);
4625  } else {
4626  dy = 0.5*(fH->GetBinContent(i, j+1) - fH->GetBinContent(i, j-1));
4627  }
4628  if (id == 1) {
4629  dn = TMath::Max(dn, TMath::Abs(dx));
4630  dn = TMath::Max(dn, TMath::Abs(dy));
4631  } else if (id == 2) {
4632  xc = xrg + xln*(Double_t(i - Hparam.xfirst+1)-0.5)/Double_t(ncx);
4633  dxn = cx*dx/dn;
4634  x1 = xc - dxn;
4635  x2 = xc + dxn;
4636  yc = yrg + yln*(Double_t(j - Hparam.yfirst+1)-0.5)/Double_t(ncy);
4637  dyn = cy*dy/dn;
4638  y1 = yc - dyn;
4639  y2 = yc + dyn;
4640  if (Hoption.Arrow>1) {
4641  int color = Int_t(0.01+(fH->GetBinContent(i, j)-fH->GetMinimum())*scale);
4642  Int_t theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
4643  if (theColor > ncolors-1) theColor = ncolors-1;
4644  arrow->SetFillColor(gStyle->GetColorPalette(theColor));
4645  arrow->SetLineColor(gStyle->GetColorPalette(theColor));
4646  }
4647  if (TMath::Abs(x2-x1) > 0. || TMath::Abs(y2-y1) > 0.) {
4648  arrow->PaintArrow(x1, y1, x2, y2, 0.015, "|>");
4649  } else {
4650  arrow->PaintArrow(x1, y1, x2, y2, 0.005, "|>");
4651  }
4652  }
4653  }
4654  }
4655  }
4656 
4657  if (Hoption.Zscale) PaintPalette();
4658 }
4659 
4660 ////////////////////////////////////////////////////////////////////////////////
4661 /// Draw axis (2D case) of an histogram.
4662 ///
4663 /// If `drawGridOnly` is `TRUE`, only the grid is painted (if needed). This allows
4664 /// to draw the grid and the axis separately. In `THistPainter::Paint` this
4665 /// feature is used to make sure that the grid is drawn in the background and
4666 /// the axis tick marks in the foreground of the pad.
4667 
4669 {
4670 
4671  //On iOS, grid should not be pickable and can not be highlighted.
4672  //Condition is never true on a platform different from iOS.
4673  if (drawGridOnly && (gPad->PadInHighlightMode() || gPad->PadInSelectionMode()))
4674  return;
4675 
4676  if (Hoption.Axis == -1) return;
4677  if (Hoption.Same && Hoption.Axis <= 0) return;
4678 
4679  // Repainting alphanumeric labels axis on a plot done with
4680  // the option HBAR (horizontal) needs some adjustments.
4681  TAxis *xaxis = 0;
4682  TAxis *yaxis = 0;
4683  if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4684  if (fXaxis->GetLabels() || fYaxis->GetLabels()) { // One axis has alphanumeric labels
4685  TIter next(gPad->GetListOfPrimitives());
4686  TObject *obj;
4687  // Check if the first TH1 of THStack in the pad is drawn with the option HBAR
4688  while ((obj = next())) {
4689  if (!obj->InheritsFrom(TH1::Class()) &&
4690  !obj->InheritsFrom(THStack::Class())) continue;
4691  TString opt = obj->GetDrawOption();
4692  opt.ToLower();
4693  // if drawn with HBAR, the axis should be inverted and the pad set to horizontal
4694  if (strstr(opt,"hbar")) {
4695  gPad->SetVertical(kFALSE);
4696  xaxis = fXaxis;
4697  yaxis = fYaxis;
4698  if (!strcmp(xaxis->GetName(),"xaxis")) {
4699  fXaxis = yaxis;
4700  fYaxis = xaxis;
4701  }
4702  }
4703  break;
4704  }
4705  }
4706  }
4707 
4708  static char chopt[10] = "";
4709  Double_t gridl = 0;
4710  Int_t ndiv, ndivx, ndivy, nx1, nx2, ndivsave;
4711  Int_t useHparam = 0;
4712  Double_t umin, umax, uminsave, umaxsave;
4713  Short_t xAxisPos = Hoption.AxisPos/10;
4714  Short_t yAxisPos = Hoption.AxisPos - 10*xAxisPos;
4715 
4716  Double_t axmin = gPad->GetUxmin();
4717  Double_t axmax = gPad->GetUxmax();
4718  Double_t aymin = gPad->GetUymin();
4719  Double_t aymax = gPad->GetUymax();
4720  char *cw = 0;
4721  TGaxis axis;
4722 
4723  // In case of option 'cont4' or in case of option 'same' over a 'cont4 plot'
4724  // Hparam must be use for the axis limits.
4725  if (Hoption.Contour == 14) useHparam = 1;
4726  if (Hoption.Same) {
4727  TObject *obj;
4728  TIter next(gPad->GetListOfPrimitives());
4729  while ((obj=next())) {
4730  if (strstr(obj->GetDrawOption(),"cont4")) {
4731  useHparam = 1;
4732  break;
4733  }
4734  }
4735  }
4736 
4737  // Paint X axis
4738 
4739  //To make X-axis selectable on iOS device.
4740  if (gPad->PadInSelectionMode())
4741  gPad->PushSelectableObject(fXaxis);
4742 
4743  //This condition is ALWAYS true, unless it works on iOS (can be false on iOS).
4744  if (gPad->PadInSelectionMode() || !gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && gPad->GetSelected() == fXaxis)) {
4745  ndivx = fXaxis->GetNdivisions();
4746  if (ndivx > 1000) {
4747  nx2 = ndivx/100;
4748  nx1 = TMath::Max(1, ndivx%100);
4749  ndivx = 100*nx2 + Int_t(Float_t(nx1)*gPad->GetAbsWNDC());
4750  }
4751  axis.SetTextAngle(0);
4753 
4754  chopt[0] = 0;
4755  strlcat(chopt, "SDH",10);
4756  if (ndivx < 0) strlcat(chopt, "N",10);
4757  if (gPad->GetGridx()) {
4758  gridl = (aymax-aymin)/(gPad->GetY2() - gPad->GetY1());
4759  strlcat(chopt, "W",10);
4760  }
4761 
4762  // Define X-Axis limits
4763  if (Hoption.Logx) {
4764  strlcat(chopt, "G",10);
4765  ndiv = TMath::Abs(ndivx);
4766  if (useHparam) {
4767  umin = TMath::Power(10,Hparam.xmin);
4768  umax = TMath::Power(10,Hparam.xmax);
4769  } else {
4770  umin = TMath::Power(10,axmin);
4771  umax = TMath::Power(10,axmax);
4772  }
4773  } else {
4774  ndiv = TMath::Abs(ndivx);
4775  if (useHparam) {
4776  umin = Hparam.xmin;
4777  umax = Hparam.xmax;
4778  } else {
4779  umin = axmin;
4780  umax = axmax;
4781  }
4782  }
4783 
4784  // Display axis as time
4785  if (fXaxis->GetTimeDisplay()) {
4786  strlcat(chopt,"t",10);
4787  if (strlen(fXaxis->GetTimeFormatOnly()) == 0) {
4789  }
4790  }
4791 
4792  // The main X axis can be on the bottom or on the top of the pad
4793  Double_t xAxisYPos1, xAxisYPos2;
4794  if (xAxisPos == 1) {
4795  // Main X axis top
4796  xAxisYPos1 = aymax;
4797  xAxisYPos2 = aymin;
4798  } else {
4799  // Main X axis bottom
4800  xAxisYPos1 = aymin;
4801  xAxisYPos2 = aymax;
4802  }
4803 
4804  // Paint the main X axis (always)
4805  uminsave = umin;
4806  umaxsave = umax;
4807  ndivsave = ndiv;
4808  axis.SetOption(chopt);
4809  if (xAxisPos) {
4810  strlcat(chopt, "-",10);
4811  gridl = -gridl;
4812  }
4813  if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4814  axis.SetLabelSize(0.);
4815  axis.SetTitle("");
4816  }
4817  axis.PaintAxis(axmin, xAxisYPos1,
4818  axmax, xAxisYPos1,
4819  umin, umax, ndiv, chopt, gridl, drawGridOnly);
4820 
4821  // Paint additional X axis (if needed)
4822  // On iOS, this additional X axis is neither pickable, nor highlighted.
4823  // Additional checks PadInSelectionMode etc. does not effect non-iOS platform.
4824  if (gPad->GetTickx() && !gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
4825  if (xAxisPos) {
4826  cw=strstr(chopt,"-");
4827  *cw='z';
4828  } else {
4829  strlcat(chopt, "-",10);
4830  }
4831  if (gPad->GetTickx() < 2) strlcat(chopt, "U",10);
4832  if ((cw=strstr(chopt,"W"))) *cw='z';
4833  axis.SetTitle("");
4834  axis.PaintAxis(axmin, xAxisYPos2,
4835  axmax, xAxisYPos2,
4836  uminsave, umaxsave, ndivsave, chopt, gridl, drawGridOnly);
4837  }
4838  }//End of "if pad in selection mode etc".
4839 
4840  // Paint Y axis
4841  //On iOS, Y axis must pushed into the stack of selectable objects.
4842  if (gPad->PadInSelectionMode())
4843  gPad->PushSelectableObject(fYaxis);
4844 
4845  //This conditions is ALWAYS true on a platform, different from iOS (on iOS can be true, can be false).
4846  if (gPad->PadInSelectionMode() || !gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && gPad->GetSelected() == fYaxis)) {
4847  ndivy = fYaxis->GetNdivisions();
4849 
4850  chopt[0] = 0;
4851  strlcat(chopt, "SDH",10);
4852  if (ndivy < 0) strlcat(chopt, "N",10);
4853  if (gPad->GetGridy()) {
4854  gridl = (axmax-axmin)/(gPad->GetX2() - gPad->GetX1());
4855  strlcat(chopt, "W",10);
4856  }
4857 
4858  // Define Y-Axis limits
4859  if (Hoption.Logy) {
4860  strlcat(chopt, "G",10);
4861  ndiv = TMath::Abs(ndivy);
4862  if (useHparam) {
4863  umin = TMath::Power(10,Hparam.ymin);
4864  umax = TMath::Power(10,Hparam.ymax);
4865  } else {
4866  umin = TMath::Power(10,aymin);
4867  umax = TMath::Power(10,aymax);
4868  }
4869  } else {
4870  ndiv = TMath::Abs(ndivy);
4871  if (useHparam) {
4872  umin = Hparam.ymin;
4873  umax = Hparam.ymax;
4874  } else {
4875  umin = aymin;
4876  umax = aymax;
4877  }
4878  }
4879 
4880  // Display axis as time
4881  if (fYaxis->GetTimeDisplay()) {
4882  strlcat(chopt,"t",10);
4883  if (strlen(fYaxis->GetTimeFormatOnly()) == 0) {
4885  }
4886  }
4887 
4888  // The main Y axis can be on the left or on the right of the pad
4889  Double_t yAxisXPos1, yAxisXPos2;
4890  if (yAxisPos == 1) {
4891  // Main Y axis left
4892  yAxisXPos1 = axmax;
4893  yAxisXPos2 = axmin;
4894  } else {
4895  // Main Y axis right
4896  yAxisXPos1 = axmin;
4897  yAxisXPos2 = axmax;
4898  }
4899 
4900  // Paint the main Y axis (always)
4901  uminsave = umin;
4902  umaxsave = umax;
4903  ndivsave = ndiv;
4904  axis.SetOption(chopt);
4905  if (yAxisPos) {
4906  strlcat(chopt, "+L",10);
4907  gridl = -gridl;
4908  }
4909  if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4910  axis.SetLabelSize(0.);
4911  axis.SetTitle("");
4912  }
4913  axis.PaintAxis(yAxisXPos1, aymin,
4914  yAxisXPos1, aymax,
4915  umin, umax, ndiv, chopt, gridl, drawGridOnly);
4916 
4917  // Paint the additional Y axis (if needed)
4918  // Additional checks for pad mode are required on iOS: this "second" axis is
4919  // neither pickable, nor highlighted. Additional checks have no effect on non-iOS platform.
4920  if (gPad->GetTicky() && !gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
4921  if (gPad->GetTicky() < 2) {
4922  strlcat(chopt, "U",10);
4923  axis.SetTickSize(-fYaxis->GetTickLength());
4924  } else {
4925  strlcat(chopt, "+L",10);
4926  }
4927  if ((cw=strstr(chopt,"W"))) *cw='z';
4928  axis.SetTitle("");
4929  axis.PaintAxis(yAxisXPos2, aymin,
4930  yAxisXPos2, aymax,
4931  uminsave, umaxsave, ndivsave, chopt, gridl, drawGridOnly);
4932  }
4933  }//End of "if pad is in selection mode etc."
4934 
4935  // Reset the axis if they have been inverted in case of option HBAR
4936  if (xaxis) {
4937  fXaxis = xaxis;
4938  fYaxis = yaxis;
4939  }
4940 }
4941 
4942 ////////////////////////////////////////////////////////////////////////////////
4943 /// [Draw a bar-chart in a normal pad.](#HP10)
4944 
4946 {
4947 
4948  Int_t bar = Hoption.Bar - 10;
4949  Double_t xmin,xmax,ymin,ymax,umin,umax,w,y;
4950  Double_t offset = fH->GetBarOffset();
4952  TBox box;
4953  Int_t hcolor = fH->GetFillColor();
4954  if (hcolor == gPad->GetFrameFillColor()) ++hcolor;
4955  Int_t hstyle = fH->GetFillStyle();
4956  box.SetFillColor(hcolor);
4957  box.SetFillStyle(hstyle);
4958  box.SetLineStyle(fH->GetLineStyle());
4959  box.SetLineColor(fH->GetLineColor());
4960  box.SetLineWidth(fH->GetLineWidth());
4961  for (Int_t bin=fXaxis->GetFirst();bin<=fXaxis->GetLast();bin++) {
4962  y = fH->GetBinContent(bin);
4963  xmin = gPad->XtoPad(fXaxis->GetBinLowEdge(bin));
4964  xmax = gPad->XtoPad(fXaxis->GetBinUpEdge(bin));
4965  ymin = gPad->GetUymin();
4966  ymax = gPad->YtoPad(y);
4967  if (ymax < gPad->GetUymin()) continue;
4968  if (ymax > gPad->GetUymax()) ymax = gPad->GetUymax();
4969  if (ymin < gPad->GetUymin()) ymin = gPad->GetUymin();
4970  if (Hoption.MinimumZero && ymin < 0)
4971  ymin=TMath::Min(0.,gPad->GetUymax());
4972  w = (xmax-xmin)*width;
4973  xmin += offset*(xmax-xmin);
4974  xmax = xmin + w;
4975  if (bar < 1) {
4976  box.PaintBox(xmin,ymin,xmax,ymax);
4977  } else {
4978  umin = xmin + bar*(xmax-xmin)/10.;
4979  umax = xmax - bar*(xmax-xmin)/10.;
4980  //box.SetFillColor(hcolor+150); //bright
4981  box.SetFillColor(TColor::GetColorBright(hcolor)); //bright
4982  box.PaintBox(xmin,ymin,umin,ymax);
4983  box.SetFillColor(hcolor);
4984  box.PaintBox(umin,ymin,umax,ymax);
4985  box.SetFillColor(TColor::GetColorDark(hcolor)); //dark
4986  box.PaintBox(umax,ymin,xmax,ymax);
4987  }
4988  }
4989 }
4990 
4991 ////////////////////////////////////////////////////////////////////////////////
4992 /// [Draw a bar char in a rotated pad (X vertical, Y horizontal)](#HP10)
4993 
4995 {
4996 
4997  gPad->SetVertical(kFALSE);
4998 
4999  PaintInitH();
5000 
5001  TAxis *xaxis = fXaxis;
5002  TAxis *yaxis = fYaxis;
5003  if (!strcmp(xaxis->GetName(),"xaxis")) {
5004  fXaxis = yaxis;
5005  fYaxis = xaxis;
5006  }
5007 
5008  PaintFrame();
5009  PaintAxis(kFALSE);
5010 
5011  Int_t bar = Hoption.Bar - 20;
5012  Double_t xmin,xmax,ymin,ymax,umin,umax,w;
5013  Double_t offset = fH->GetBarOffset();
5015  TBox box;
5016  Int_t hcolor = fH->GetFillColor();
5017  if (hcolor == gPad->GetFrameFillColor()) ++hcolor;
5018  Int_t hstyle = fH->GetFillStyle();
5019  box.SetFillColor(hcolor);
5020  box.SetFillStyle(hstyle);
5021  box.SetLineStyle(fH->GetLineStyle());
5022  box.SetLineColor(fH->GetLineColor());
5023  box.SetLineWidth(fH->GetLineWidth());
5024  for (Int_t bin=fYaxis->GetFirst();bin<=fYaxis->GetLast();bin++) {
5025  ymin = gPad->YtoPad(fYaxis->GetBinLowEdge(bin));
5026  ymax = gPad->YtoPad(fYaxis->GetBinUpEdge(bin));
5027  xmin = gPad->GetUxmin();
5028  xmax = gPad->XtoPad(fH->GetBinContent(bin));
5029  if (xmax < gPad->GetUxmin()) continue;
5030  if (xmax > gPad->GetUxmax()) xmax = gPad->GetUxmax();
5031  if (xmin < gPad->GetUxmin()) xmin = gPad->GetUxmin();
5032  if (Hoption.MinimumZero && xmin < 0)
5033  xmin=TMath::Min(0.,gPad->GetUxmax());
5034  w = (ymax-ymin)*width;
5035  ymin += offset*(ymax-ymin);
5036  ymax = ymin + w;
5037  if (bar < 1) {
5038  box.PaintBox(xmin,ymin,xmax,ymax);
5039  } else {
5040  umin = ymin + bar*(ymax-ymin)/10.;
5041  umax = ymax - bar*(ymax-ymin)/10.;
5042  box.SetFillColor(TColor::GetColorDark(hcolor)); //dark
5043  box.PaintBox(xmin,ymin,xmax,umin);
5044  box.SetFillColor(hcolor);
5045  box.PaintBox(xmin,umin,xmax,umax);
5046  box.SetFillColor(TColor::GetColorBright(hcolor)); //bright
5047  box.PaintBox(xmin,umax,xmax,ymax);
5048  }
5049  }
5050 
5051  PaintTitle();
5052 
5053  // Draw box with histogram statistics and/or fit parameters
5054  if ((Hoption.Same%10) != 1 && !fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
5055  TIter next(fFunctions);
5056  TObject *obj = 0;
5057  while ((obj = next())) {
5058  if (obj->InheritsFrom(TF1::Class())) break;
5059  obj = 0;
5060  }
5061  PaintStat(gStyle->GetOptStat(),(TF1*)obj);
5062  }
5063 
5064  fXaxis = xaxis;
5065  fYaxis = yaxis;
5066 }
5067 
5068 ////////////////////////////////////////////////////////////////////////////////
5069 /// [Control function to draw a 2D histogram as a box plot](#HP13)
5070 
5072 {
5073 
5074  Style_t fillsav = fH->GetFillStyle();
5075  Style_t colsav = fH->GetFillColor();
5076  if (fH->GetFillColor() == 0) fH->SetFillStyle(0);
5077  if (Hoption.Box == 11) fH->SetFillStyle(1001);
5078  fH->TAttLine::Modify();
5079  fH->TAttFill::Modify();
5080 
5081  Double_t z, xk,xstep, yk, ystep, xcent, ycent, xlow, xup, ylow, yup;
5082  Double_t ux1 = gPad->PixeltoX(1);
5083  Double_t ux0 = gPad->PixeltoX(0);
5084  Double_t uy1 = gPad->PixeltoY(1);
5085  Double_t uy0 = gPad->PixeltoY(0);
5086  Double_t dxmin = 0.51*(gPad->PadtoX(ux1)-gPad->PadtoX(ux0));
5087  Double_t dymin = 0.51*(gPad->PadtoY(uy0)-gPad->PadtoY(uy1));
5088 
5089  Double_t zmin = TMath::Max(fH->GetMinimum(),0.);
5091  TMath::Abs(fH->GetMinimum()));
5092  Double_t zminlin = zmin, zmaxlin = zmax;
5093 
5094  // In case of option SAME, zmin and zmax values are taken from the
5095  // first plotted 2D histogram.
5096  if (Hoption.Same > 0 && Hoption.Same < 10) {
5097  TH2 *h2;
5098  TIter next(gPad->GetListOfPrimitives());
5099  while ((h2 = (TH2 *)next())) {
5100  if (!h2->InheritsFrom(TH2::Class())) continue;
5101  zmin = TMath::Max(h2->GetMinimum(), 0.);
5102  zmax = TMath::Max(TMath::Abs(h2->GetMaximum()),
5103  TMath::Abs(h2->GetMinimum()));
5104  zminlin = zmin;
5105  zmaxlin = zmax;
5106  if (Hoption.Logz) {
5107  if (zmin <= 0) {
5108  zmin = TMath::Log10(zmax*0.001);
5109  } else {
5110  zmin = TMath::Log10(zmin);
5111  }
5112  zmax = TMath::Log10(zmax);
5113  }
5114  break;
5115  }
5116  } else {
5117  if (Hoption.Logz) {
5118  if (zmin > 0) {
5119  zmin = TMath::Log10(zmin);
5120  zmax = TMath::Log10(zmax);
5121  } else {
5122  return;
5123  }
5124  }
5125  }
5126 
5127  Double_t zratio, dz = zmax - zmin;
5128  Bool_t kZminNeg = kFALSE;
5129  if (fH->GetMinimum()<0) kZminNeg = kTRUE;
5130  Bool_t kZNeg = kFALSE;
5131 
5132  // Define the dark and light colors the "button style" boxes.
5133  Color_t color = fH->GetFillColor();
5134  Color_t light=0, dark=0;
5135  if (Hoption.Box == 11) {
5136  light = TColor::GetColorBright(color);
5137  dark = TColor::GetColorDark(color);
5138  }
5139 
5140  // Loop over all the bins and draw the boxes
5141  for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
5142  yk = fYaxis->GetBinLowEdge(j);
5143  ystep = fYaxis->GetBinWidth(j);
5144  ycent = 0.5*ystep;
5145  for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
5146  Int_t bin = j*(fXaxis->GetNbins()+2) + i;
5147  xk = fXaxis->GetBinLowEdge(i);
5148  xstep = fXaxis->GetBinWidth(i);
5149  if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
5150  xcent = 0.5*xstep;
5151  z = Hparam.factor*fH->GetBinContent(bin);
5152  kZNeg = kFALSE;
5153 
5154  if (TMath::Abs(z) < zminlin) continue; // Can be the case with ...
5155  if (TMath::Abs(z) > zmaxlin) z = zmaxlin; // ... option Same
5156  if (kZminNeg && z==0) continue; // Do not draw empty bins if case of histo with netgative bins.
5157 
5158  if (z < 0) {
5159  if (Hoption.Logz) continue;
5160  z = -z;
5161  kZNeg = kTRUE;
5162  }
5163  if (Hoption.Logz) {
5164  if (z != 0) z = TMath::Log10(z);
5165  else z = zmin;
5166  }
5167 
5168  if (dz == 0) continue;
5169  zratio = TMath::Sqrt((z-zmin)/dz);
5170  if (zratio == 0) continue;
5171 
5172  xup = xcent*zratio + xk + xcent;
5173  xlow = 2*(xk + xcent) - xup;
5174  if (xup-xlow < dxmin) xup = xlow+dxmin;
5175  if (Hoption.Logx) {
5176  if (xup > 0) xup = TMath::Log10(xup);
5177  else continue;
5178  if (xlow > 0) xlow = TMath::Log10(xlow);
5179  else continue;
5180  }
5181 
5182  yup = ycent*zratio + yk + ycent;
5183  ylow = 2*(yk + ycent) - yup;
5184  if (yup-ylow < dymin) yup = ylow+dymin;
5185  if (Hoption.Logy) {
5186  if (yup > 0) yup = TMath::Log10(yup);
5187  else continue;
5188  if (ylow > 0) ylow = TMath::Log10(ylow);
5189  else continue;
5190  }
5191 
5192  xlow = TMath::Max(xlow, gPad->GetUxmin());
5193  ylow = TMath::Max(ylow, gPad->GetUymin());
5194  xup = TMath::Min(xup , gPad->GetUxmax());
5195  yup = TMath::Min(yup , gPad->GetUymax());
5196 
5197  if (xlow >= xup) continue;
5198  if (ylow >= yup) continue;
5199 
5200  if (Hoption.Box == 1) {
5201  fH->SetFillColor(color);
5202  fH->TAttFill::Modify();
5203  gPad->PaintBox(xlow, ylow, xup, yup);
5204  if (kZNeg) {
5205  gPad->PaintLine(xlow, ylow, xup, yup);
5206  gPad->PaintLine(xlow, yup, xup, ylow);
5207  }
5208  } else if (Hoption.Box == 11) {
5209  // Draw the center of the box
5210  fH->SetFillColor(color);
5211  fH->TAttFill::Modify();
5212  gPad->PaintBox(xlow, ylow, xup, yup);
5213 
5214  // Draw top&left part of the box
5215  Double_t x[7], y[7];
5216  Double_t bwidth = 0.1;
5217  x[0] = xlow; y[0] = ylow;
5218  x[1] = xlow + bwidth*(xup-xlow); y[1] = ylow + bwidth*(yup-ylow);
5219  x[2] = x[1]; y[2] = yup - bwidth*(yup-ylow);
5220  x[3] = xup - bwidth*(xup-xlow); y[3] = y[2];
5221  x[4] = xup; y[4] = yup;
5222  x[5] = xlow; y[5] = yup;
5223  x[6] = xlow; y[6] = ylow;
5224  if (kZNeg) fH->SetFillColor(dark);
5225  else fH->SetFillColor(light);
5226  fH->TAttFill::Modify();
5227  gPad->PaintFillArea(7, x, y);
5228 
5229  // Draw bottom&right part of the box
5230  x[0] = xlow; y[0] = ylow;
5231  x[1] = xlow + bwidth*(xup-xlow); y[1] = ylow + bwidth*(yup-ylow);
5232  x[2] = xup - bwidth*(xup-xlow); y[2] = y[1];
5233  x[3] = x[2]; y[3] = yup - bwidth*(yup-ylow);
5234  x[4] = xup; y[4] = yup;
5235  x[5] = xup; y[5] = ylow;
5236  x[6] = xlow; y[6] = ylow;
5237  if (kZNeg) fH->SetFillColor(light);
5238  else fH->SetFillColor(dark);
5239  fH->TAttFill::Modify();
5240  gPad->PaintFillArea(7, x, y);
5241  }
5242  }
5243  }
5244 
5245  if (Hoption.Zscale) PaintPalette();
5246  fH->SetFillStyle(fillsav);
5247  fH->SetFillColor(colsav);
5248  fH->TAttFill::Modify();
5249 }
5250 
5251 
5252 
5253 ////////////////////////////////////////////////////////////////////////////////
5254 /// [Control function to draw a 2D histogram as a candle (box) plot or violin plot](#HP14)
5255 
5257 {
5258  TH1D *hproj;
5259  TH2D *h2 = (TH2D*)fH;
5260 
5261  TCandle myCandle;
5263  myCandle.SetMarkerColor(fH->GetLineColor());
5264  myCandle.SetLineColor(fH->GetLineColor());
5265  myCandle.SetLineWidth(fH->GetLineWidth());
5266  myCandle.SetFillColor(fH->GetFillColor());
5267  myCandle.SetFillStyle(fH->GetFillStyle());
5268  myCandle.SetMarkerSize(fH->GetMarkerSize());
5269  myCandle.SetMarkerStyle(fH->GetMarkerStyle());
5270  myCandle.SetLog(Hoption.Logx,Hoption.Logy, Hoption.Logz);
5271 
5272  Bool_t swapXY = myCandle.IsHorizontal();
5273  const Double_t standardCandleWidth = 0.66;
5274  const Double_t standardHistoWidth = 0.8;
5275 
5276  double allMaxContent = h2->GetBinContent(h2->GetMaximumBin());
5277  double allMaxIntegral = 0;
5278 
5279  if (!swapXY) { // Vertical candle
5280  //Determining the slice with the maximum content
5281  for (Int_t i=Hparam.xfirst; i<=Hparam.xlast; i++) {
5282  hproj = h2->ProjectionY("_px", i, i);
5283  if (hproj->Integral() > allMaxIntegral) allMaxIntegral = hproj->Integral();
5284  }
5285  for (Int_t i=Hparam.xfirst; i<=Hparam.xlast; i++) {
5286  Double_t binPosX = fXaxis->GetBinLowEdge(i);
5287  Double_t binWidth = fXaxis->GetBinWidth(i);
5288  hproj = h2->ProjectionY("_px", i, i);
5289  if (hproj->GetEntries() !=0) {
5290  Double_t candleWidth = fH->GetBarWidth();
5291  Double_t offset = fH->GetBarOffset()*binWidth;
5292  double myMaxContent = hproj->GetBinContent(hproj->GetMaximumBin());
5293  double myIntegral = hproj->Integral();
5294  Double_t histoWidth = candleWidth;
5295  if (candleWidth > 0.999 && candleWidth < 1.001) {
5296  candleWidth = standardCandleWidth;
5297  histoWidth = standardHistoWidth;
5298  }
5299  if (Hoption.Logz && myMaxContent > 0) {
5300  histoWidth *= myMaxContent/TMath::Log10(myMaxContent);
5301  if (myCandle.IsViolinScaled() && myMaxContent > 0 && allMaxContent > 0) histoWidth *= TMath::Log10(myMaxContent)/TMath::Log10(allMaxContent);
5302  } else if (myCandle.IsViolinScaled()) histoWidth *= myMaxContent/allMaxContent;
5303  if (myCandle.IsCandleScaled()) candleWidth *= myIntegral/allMaxIntegral;
5304 
5305  myCandle.SetAxisPosition(binPosX+binWidth/2. + offset);
5306  myCandle.SetCandleWidth(candleWidth*binWidth);
5307  myCandle.SetHistoWidth(histoWidth*binWidth);
5308  myCandle.SetHistogram(hproj);
5309  myCandle.Paint();
5310  }
5311  }
5312  } else { // Horizontal candle
5313  //Determining the slice with the maximum content
5314  for (Int_t i=Hparam.yfirst; i<=Hparam.ylast; i++) {
5315  hproj = h2->ProjectionX("_py", i, i);
5316  if (hproj->Integral() > allMaxIntegral) allMaxIntegral = hproj->Integral();
5317  }
5318  for (Int_t i=Hparam.yfirst; i<=Hparam.ylast; i++) {
5319  Double_t binPosY = fYaxis->GetBinLowEdge(i);
5320  Double_t binWidth = fYaxis->GetBinWidth(i);
5321  hproj = h2->ProjectionX("_py", i, i);
5322  if (hproj->GetEntries() !=0) {
5323  Double_t candleWidth = fH->GetBarWidth();
5324  Double_t offset = fH->GetBarOffset()*binWidth;
5325  double myMaxContent = hproj->GetBinContent(hproj->GetMaximumBin());
5326  double myIntegral = hproj->Integral();
5327  Double_t histoWidth = candleWidth;
5328  if (candleWidth > 0.999 && candleWidth < 1.001) {
5329  candleWidth = standardCandleWidth;
5330  histoWidth = standardHistoWidth;
5331  }
5332  if (Hoption.Logz && myMaxContent > 0) {
5333  histoWidth *= myMaxContent/TMath::Log10(myMaxContent);
5334  if (myCandle.IsViolinScaled() && myMaxContent > 0 && allMaxContent > 0) histoWidth *= TMath::Log10(myMaxContent)/TMath::Log10(allMaxContent);
5335  } else if (myCandle.IsViolinScaled()) histoWidth *= myMaxContent/allMaxContent;
5336  if (myCandle.IsCandleScaled()) candleWidth *= myIntegral/allMaxIntegral;
5337 
5338  myCandle.SetAxisPosition(binPosY+binWidth/2. + offset);
5339  myCandle.SetCandleWidth(candleWidth*binWidth);
5340  myCandle.SetHistoWidth(histoWidth*binWidth);
5341  myCandle.SetHistogram(hproj);
5342  myCandle.Paint();
5343  }
5344  }
5345  }
5346 }
5347 
5348 
5349 
5350 ////////////////////////////////////////////////////////////////////////////////
5351 /// Returns the rendering regions for an axis to use in the COL2 option
5352 ///
5353 /// The algorithm analyses the size of the axis compared to the size of
5354 /// the rendering region. It figures out the boundaries to use for each color
5355 /// of the rendering region. Only one axis is computed here.
5356 ///
5357 /// This allows for a single computation of the boundaries before iterating
5358 /// through all of the bins.
5359 ///
5360 /// \param pAxis the axis to consider
5361 /// \param nPixels the number of pixels to render axis into
5362 /// \param isLog whether the axis is log scale
5363 
5364 std::vector<THistRenderingRegion>
5366 {
5367  std::vector<THistRenderingRegion> regions;
5368 
5369  enum STRATEGY { Bins, Pixels } strategy;
5370 
5371  Int_t nBins = (pAxis->GetLast() - pAxis->GetFirst() + 1);
5372 
5373  if (nBins >= nPixels) {
5374  // more bins than pixels... we should loop over pixels and sample
5375  strategy = Pixels;
5376  } else {
5377  // fewer bins than pixels... we should loop over bins
5378  strategy = Bins;
5379  }
5380 
5381  if (isLog) {
5382 
5383  Double_t xMin = pAxis->GetBinLowEdge(pAxis->GetFirst());
5384  Int_t binOffset=0;
5385  while (xMin <= 0 && ((pAxis->GetFirst()+binOffset) != pAxis->GetLast()) ) {
5386  binOffset++;
5387  xMin = pAxis->GetBinLowEdge(pAxis->GetFirst()+binOffset);
5388  }
5389  if (xMin <= 0) {
5390  // this should cause an error if we have
5391  return regions;
5392  }
5393  Double_t xMax = pAxis->GetBinUpEdge(pAxis->GetLast());
5394 
5395  if (strategy == Bins) {
5396  // logarithmic plot. we find the pixel for the bin
5397  // pixel = eta * log10(V) - alpha
5398  // where eta = nPixels/(log10(Vmax)-log10(Vmin))
5399  // and alpha = nPixels*log10(Vmin)/(log10(Vmax)-log10(Vmin))
5400  // and V is axis value
5401  Double_t eta = (nPixels-1.0)/(TMath::Log10(xMax) - TMath::Log10(xMin));
5402  Double_t offset = -1.0 * eta * TMath::Log10(xMin);
5403 
5404  for (Int_t bin=pAxis->GetFirst()+binOffset; bin<=pAxis->GetLast(); bin++) {
5405 
5406  // linear plot. we simply need to find the appropriate bin
5407  // for the
5408  Double_t xLowValue = pAxis->GetBinLowEdge(bin);
5409  Double_t xUpValue = pAxis->GetBinUpEdge(bin);
5410  Int_t xPx0 = eta*TMath::Log10(xLowValue)+ offset;
5411  Int_t xPx1 = eta*TMath::Log10(xUpValue) + offset;
5412  THistRenderingRegion region = {std::make_pair(xPx0, xPx1),
5413  std::make_pair(bin, bin+1)};
5414  regions.push_back(region);
5415  }
5416 
5417  } else {
5418 
5419  // loop over pixels
5420 
5421  Double_t beta = (TMath::Log10(xMax) - TMath::Log10(xMin))/(nPixels-1.0);
5422 
5423  for (Int_t pixelIndex=0; pixelIndex<(nPixels-1); pixelIndex++) {
5424  // linear plot
5425  Int_t binLow = pAxis->FindBin(xMin*TMath::Power(10.0, beta*pixelIndex));
5426  Int_t binHigh = pAxis->FindBin(xMin*TMath::Power(10.0, beta*(pixelIndex+1)));
5427  THistRenderingRegion region = { std::make_pair(pixelIndex, pixelIndex+1),
5428  std::make_pair(binLow, binHigh)};
5429