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