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