Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
THistPainter.cxx
Go to the documentation of this file.
1// @(#)root/histpainter:$Id$
2// Author: Rene Brun, Olivier Couet
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12#include <cstdlib>
13#include <cstring>
14#include <cstdio>
15#include <cctype>
16#include <iostream>
17
18#include "TROOT.h"
19#include "TSystem.h"
20#include "THistPainter.h"
21#include "TH2.h"
22#include "TH2Poly.h"
23#include "TH3.h"
24#include "TProfile.h"
25#include "TProfile2D.h"
26#include "THStack.h"
27#include "TF2.h"
28#include "TF3.h"
29#include "TCutG.h"
30#include "TMatrixDBase.h"
31#include "TMatrixFBase.h"
32#include "TVectorD.h"
33#include "TVectorF.h"
34#include "TCanvas.h"
35#include "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"
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
141Histograms are drawn via the `THistPainter` class. Each histogram has a
142pointer to its own painter (to be usable in a multithreaded program). When the
143canvas has to be redrawn, the `Paint` function of each objects in the
144pad is called. In case of histograms, `TH1::Paint` invokes directly
145`THistPainter::Paint`.
146
147To 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
152be drawn, the `Draw()` method can be invoked with an option. For instance
153to 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
159When the `Draw()` method of a histogram is called for the first time
160(`TH1::Draw`), it creates a `THistPainter` object and saves a
161pointer to this "painter" as a data member of the histogram. The
162`THistPainter` class specializes in the drawing of histograms. It is
163separated from the histogram so that one can have histograms without the
164graphics overhead, for example in a batch program. Each histogram having its own
165painter (rather than a central singleton painter painting all histograms), allows
166two histograms to be drawn in two threads without overwriting the painter's
167values.
168
169When 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
171pad will be updated.
172
173A pad is updated after one of these three actions:
174
1751. a carriage control on the ROOT command line,
1762. a click inside the pad,
1773. a call to `TPad::Update`.
178
179
180By default a call to `TH1::Draw()` clears the pad of all objects
181before drawing the new image of the histogram. One can use the `SAME`
182option to leave the previous display intact and superimpose the new histogram.
183The same histogram can be drawn with different graphics options in different
184pads.
185
186When a displayed histogram is deleted, its image is automatically removed
187from the pad.
188
189To create a copy of the histogram when drawing it, one can use
190`TH1::DrawClone()`. This will clone the histogram and allow to change
191and delete the original one without affecting the clone.
192
193
194### <a name="HP01"></a> Histograms' plotting options
195
196
197Most options can be concatenated with or without spaces or commas, for example:
198
199 h->Draw("E1 SAME");
200
201The options are not case sensitive:
202
203 h->Draw("e1 same");
204
205
206The default drawing option can be set with `TH1::SetOption` and retrieve
207using `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
351Histograms use the current style (`gStyle`). When one changes the current
352style and would like to propagate the changes to the histogram,
353`TH1::UseCurrentStyle` should be called. Call `UseCurrentStyle` on
354each histogram is needed.
355
356To force all the histogram to use the current style use:
357
358 gROOT->ForceStyle();
359
360All 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
366The histogram classes inherit from the attribute classes:
367`TAttLine`, `TAttFill` and `TAttMarker`.
368See 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
374The `TPad::SetTicks` method specifies the type of tick marks on the axis.
375If ` 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
382By 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.
386See also The `TAxis` functions to set specific axis attributes.
387
388In case multiple color filled histograms are drawn on the same pad, the fill
389area may hide the axis tick marks. One can force a redraw of the axis over all
390the 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
401The histogram title and the axis titles can be any `TLatex` string.
402The titles are part of the persistent histogram.
403
404
405### <a name="HP060"></a> The option "SAME"
406
407
408By default, when an histogram is drawn, the current pad is cleared before
409drawing. In order to keep the previous drawing and draw on top of it the
410option `SAME` should be use. The histogram drawn with the option
411`SAME` uses the coordinates system available in the current pad.
412
413This option can be used alone or combined with any valid drawing option but
414some 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
428When several histograms are painted in the same canvas thanks to the option "SAME"
429or via a `THStack` it might be useful to have an easy and automatic way to choose
430their color. The simplest way is to pick colors in the current active color
431palette. Palette coloring for histogram is activated thanks to the options `PFC`
432(Palette Fill Color), `PLC` (Palette Line Color) and `PMC` (Palette Marker Color).
433When one of these options is given to `TH1::Draw` the histogram get its color
434from the current color palette defined by `gStyle->SetPalette(…)`. The color
435is determined according to the number of objects having palette coloring in
436the current pad.
437
438Begin_Macro(source)
439../../../tutorials/hist/histpalettecolor.C
440End_Macro
441
442Begin_Macro(source)
443../../../tutorials/hist/thstackpalettecolor.C
444End_Macro
445
446Begin_Macro(source)
447../../../tutorials/hist/thstack2palettecolor.C
448End_Macro
449
450### <a name="HP06"></a> Superimposing two histograms with different scales in the same pad
451
452
453The following example creates two histograms, the second histogram is the bins
454integral of the first one. It shows a procedure to draw the two histograms in
455the same pad and it draws the scale of the second histogram using a new vertical
456axis on the right side. See also the tutorial `transpad.C` for a variant
457of this example.
458
459Begin_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}
492End_Macro
493
494
495### <a name="HP07"></a> Statistics Display
496
497
498The type of information shown in the histogram statistics box can be selected
499with:
500
501 gStyle->SetOptStat(mode);
502
503The `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
521For example:
522
523 gStyle->SetOptStat(11);
524
525displays only the name of histogram and the number of entries, whereas:
526
527 gStyle->SetOptStat(1101);
528
529displays the name of histogram, mean value and standard deviation.
530
531<b>WARNING 1:</b> never do:
532
533 gStyle->SetOptStat(0001111);
534
535but instead do:
536
537 gStyle->SetOptStat(1111);
538
539because `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
545is taken as:
546
547 gStyle->SetOptStat(1111)
548
549To 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
555of underflow/overflows and not just one single number.
556
557The 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
574For example, to print only name of histogram and number of entries do:
575
576 gStyle->SetOptStat("ne");
577
578To print only the name of the histogram do:
579
580 gStyle->SetOptStat("n");
581
582The default value is:
583
584 gStyle->SetOptStat("nemr");
585
586When a histogram is painted, a `TPaveStats` object is created and added
587to the list of functions of the histogram. If a `TPaveStats` object
588already exists in the histogram list of functions, the existing object is just
589updated with the current histogram parameters.
590
591Once 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
597because after `h->Draw()` the histogram is automatically painted. But
598in a script file the painting should be forced using `gPad->Update()`
599in order to make sure the statistics box is created:
600
601 h->Draw();
602 gPad->Update();
603 TPaveStats *st = (TPaveStats*)h->FindObject("stats");
604
605Without `gPad->Update()` the line `h->FindObject("stats")` returns a null pointer.
606
607When a histogram is drawn with the option `SAME`, the statistics box
608is not drawn. To force the statistics box drawing with the option
609`SAME`, the option `SAMES` must be used.
610If the new statistics box hides the previous statistics box, one can change
611its 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
617To change the type of information for an histogram with an existing
618`TPaveStats` one should do:
619
620 st->SetOptStat(mode);
621
622Where `mode` has the same meaning than when calling `gStyle->SetOptStat(mode)`
623(see above).
624
625One can delete the statistics box for a histogram `TH1* h` with:
626
627 h->SetStats(0)
628
629and activate it again with:
630
631 h->SetStats(1).
632
633Labels 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
640The type of information about fit parameters printed in the histogram statistics
641box 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
649Example:
650
651 gStyle->SetOptFit(1011);
652
653print fit probability, parameter names/values and errors.
654
6551. When `v = 1` is specified, only the non-fixed parameters are shown.
6562. When `v = 2` all parameters are shown.
657
658Note: `gStyle->SetOptFit(1)` means "default value", so it is equivalent
659to `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
677Begin_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}
687End_Macro
688
689The options "E3" and "E4" draw an error band through the end points of the
690vertical error bars. With "E4" the error band is smoothed. Because of the
691smoothing algorithm used some artefacts may appear at the end of the band
692like in the following example. In such cases "E3" should be used instead
693of "E4".
694
695Begin_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}
710End_Macro
711
7122D histograms can be drawn with error bars as shown is the following example:
713
714Begin_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}
725End_Macro
726
727
728### <a name="HP100"></a> The bar chart option
729
730
731The option "B" allows to draw simple vertical bar charts.
732The bar width is controlled with `TH1::SetBarWidth()`,
733and the bar offset within the bin, with `TH1::SetBarOffset()`.
734These two settings are useful to draw several histograms on the
735same plot as shown in the following example:
736
737Begin_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}
774End_Macro
775
776
777### <a name="HP10"></a> The "BAR" and "HBAR" options
778
779
780When the option `bar` or `hbar` is specified, a bar chart is drawn. A vertical
781bar-chart is drawn with the options `bar`, `bar0`, `bar1`, `bar2`, `bar3`, `bar4`.
782An 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
795When an histogram has errors the option ["HIST"](#OPTHIST) together with the `(h)bar` option.
796
797Begin_Macro(source)
798../../../tutorials/hist/hbars.C
799End_Macro
800
801To control the bar width (default is the bin width) `TH1::SetBarWidth()`
802should be used.
803
804To control the bar offset (default is 0) `TH1::SetBarOffset()` should
805be used.
806
807These two parameters are useful when several histograms are plotted using
808the 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
814For each cell (i,j) a number of points proportional to the cell content is
815drawn. A maximum of `kNMAX` points per cell is drawn. If the maximum is above
816`kNMAX` contents are normalized to `kNMAX` (`kNMAX=2000`).
817If 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
819number of dots. `scat=1` is the default.
820
821By 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
823type should be used. For instance a circle (marker style 20).
824
825Begin_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}
837End_Macro
838
839
840### <a name="HP12"></a> The ARRow option
841
842
843Shows gradient between adjacent cells. For each cell (i,j) an arrow is drawn
844The orientation of the arrow follows the cell gradient.
845
846Begin_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}
859End_Macro
860
861\since **ROOT version 6.17/01**
862
863The option `ARR` can be combined with the option `COL` or `COLZ`.
864
865Begin_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}
878End_Macro
879
880
881### <a name="HP13"></a> The BOX option
882
883
884For each cell (i,j) a box is drawn. The size (surface) of the box is
885proportional to the absolute value of the cell content.
886The cells with a negative content are drawn with a `X` on top of the box.
887
888Begin_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}
904End_Macro
905
906With option `BOX1` a button is drawn for each cell with surface
907proportional to content's absolute value. A sunken button is drawn for
908negative values a raised one for positive.
909
910Begin_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}
926End_Macro
927
928When the option `SAME` (or "SAMES") is used with the option `BOX`,
929the boxes' sizes are computing taking the previous plots into account. The range
930along 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
933Begin_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}
957End_Macro
958
959\since **ROOT version 6.17/01:**
960
961Sometimes the change of the range of the Z axis is unwanted, in which case, one
962can use `SAME0` (or `SAMES0`) option to opt out of this change.
963
964Begin_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}
995End_Macro
996
997
998### <a name="HP14"></a> The COLor option
999
1000
1001For each cell (i,j) a box is drawn with a color proportional to the cell
1002content.
1003
1004The color table used is defined in the current style.
1005
1006If the histogram's minimum and maximum are the same (flat histogram), the
1007mapping on colors is not possible, therefore nothing is painted. To paint a
1008flat histogram it is enough to set the histogram minimum
1009(`TH1::SetMinimum()`) different from the bins' content.
1010
1011The default number of color levels used to paint the cells is 20.
1012It can be changed with `TH1::SetContour()` or
1013`TStyle::SetNumberContours()`. The higher this number is, the smoother
1014is the color change between cells.
1015
1016The color palette in TStyle can be modified via `gStyle->SetPalette()`.
1017
1018All the non-empty bins are painted. Empty bins are not painted unless
1019some bins have a negative content because in that case the null bins
1020might be not empty.
1021
1022`TProfile2D` histograms are handled differently because, for this type of 2D
1023histograms, it is possible to know if an empty bin has been filled or not. So even
1024if all the bins' contents are positive some empty bins might be painted. And vice versa,
1025if some bins have a negative content some empty bins might be not painted.
1026
1027Combined with the option `COL`, the option `Z` allows to
1028display the color palette defined by `gStyle->SetPalette()`.
1029
1030In the following example, the histogram has only positive bins; the empty
1031bins (containing 0) are not drawn.
1032
1033Begin_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}
1044End_Macro
1045
1046In the first plot of following example, the histogram has some negative bins;
1047the empty bins (containing 0) are drawn. In some cases one wants to not draw
1048empty 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
1051Begin_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}
1068End_Macro
1069
1070When 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
1072painted with the color corresponding to the new maximum.
1073
1074When 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
1078The following example illustrates the option `0` combined with the option `COL`.
1079
1080Begin_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}
1099End_Macro
1100
1101\since **ROOT version 6.09/01:**
1102
1103When the option SAME (or "SAMES") is used with the option COL, the boxes' color
1104are computing taking the previous plots into account. The range along the Z axis
1105is imposed by the first plot (the one without option SAME); therefore the order
1106in 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
1109Begin_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}
1130End_Macro
1131
1132The option `COL` can be combined with the option `POL`:
1133
1134Begin_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}
1145End_Macro
1146
1147\since **ROOT version 6.07/03:**
1148
1149A second rendering technique is also available with the COL2 and COLZ2 options.
1150
1151These options provide potential performance improvements compared to the standard
1152COL option. The performance comparison of the COL2 to the COL option depends on
1153the histogram and the size of the rendering region in the current pad. In general,
1154a small (approx. less than 100 bins per axis), sparsely populated TH2 will render
1155faster with the COL option.
1156
1157However, for larger histograms (approx. more than 100 bins per axis)
1158that are not sparse, the COL2 option will provide up to 20 times performance improvements.
1159For example, a 1000x1000 bin TH2 that is not sparse will render an order of magnitude
1160faster with the COL2 option.
1161
1162The COL2 option will also scale its performance based on the size of the
1163pixmap the histogram image is being rendered into. It also is much better optimized for
1164sessions where the user is forwarding X11 windows through an `ssh` connection.
1165
1166For the most part, the COL2 and COLZ2 options are a drop in replacement to the COL
1167and COLZ options. There is one major difference and that concerns the treatment of
1168bins with zero content. The COL2 and COLZ2 options color these bins the color of zero.
1169
1170COL2 option renders the histogram as a bitmap. Therefore it cannot be saved in vector
1171graphics file format like PostScript or PDF (an empty image will be generated). It can
1172be saved only in bitmap files like PNG format for instance.
1173
1174
1175### <a name="HP140"></a> The CANDLE and VIOLIN options
1176
1177The mechanism behind Candle plots and Violin plots is very similar. Because of this they are
1178implemented in the same class TCandle. The keywords CANDLE or VIOLIN will initiate the drawing of
1179the corresponding plots. Followed by the keyword the user can select a plot direction (X or V for
1180vertical 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
1183Instead of using the predefined representations, the candle and violin parameters can be
1184changed 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
1191All 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
1197Where:
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
1233As one can see all individual options for both candle and violin plots can be accessed by this
1234mechanism. In deed the keywords CANDLE(<option-string>) and VIOLIN(<option-string>) have the same
1235meaning. So you can parametrise an option-string for a candle plot and use the keywords VIOLIN and
1236vice versa, if you wish.
1237
1238Using a logarithmic x- or y-axis is possible for candle and violin charts.
1239
1240\since **ROOT version 6.11/01**
1241
1242a 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
1247a "box plot" or "whisker plot") was invented in 1977 by John Tukey. It is a convenient
1248way 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
1256In this implementation a TH2 is considered as a collection of TH1 along
1257X (option `CANDLE` or `CANDLEX`) or Y (option `CANDLEY`).
1258Each TH1 is represented as one candle.
1259
1260Begin_Macro(source)
1261../../../tutorials/hist/candleplotwhiskers.C
1262End_Macro
1263
1264The candle reduces the information coming from a whole distribution into few values.
1265Independently from the number of entries or the significance of the underlying distribution
1266a candle will always look like a candle. So candle plots should be used carefully in
1267particular 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
1269deviation is connected to the bin width used. The calculation of the quantiles
1270normally done on unbinned data also. Because data are binned, this will
1271only work the best possible way within the resolution of one bin
1272
1273Because 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
1288The box displays the position of the inter-quantile-range of the underlying
1289distribution. The box contains 25% of the distribution below the median
1290and 25% of the distribution above the median. If the underlying distribution is large
1291enough 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
1293the position of the box can be modified by SetBarWidth() and SetBarOffset().
1294The +-25% quantiles are calculated by the GetQuantiles() methods.
1295
1296\since **ROOT version 6.11/01**
1297
1298Using the static function TCandle::SetBoxRange(double) the box definition will be
1299overwritten. E.g. using a box range of 0.68 will redefine the area of the lower box edge
1300to the upper box edge in order to cover 68% of the distribution illustrated by that candle.
1301The static function will affect all candle-charts in the running program.
1302Default is 0.5.
1303
1304Using the static function TCandle::SetScaledCandle(bool) the width of the box (and the
1305whole candle) can be influenced. Deactivated, the width is constant (to be set by
1306SetBarWidth() ). Activated, the width of the boxes will be scaled to each other based on the
1307amount of data in the corresponding candle, the maximum width can be influenced by
1308SetBarWidth(). The static function will affect all candle-charts in the running program.
1309Default is false. Scaling between multiple candle-charts (using "same" or THStack) is not
1310supported, yet
1311
1312##### The Median
1313For a sorted list of numbers, the median is the value in the middle of the list.
1314E.g. if a sorted list is made of five numbers "1,2,3,6,7" 3 will be the median
1315because it is in the middle of the list. If the number of entries is even the
1316average of the two values in the middle will be used. As histograms are binned
1317data, the situation is a bit more complex. The following example shows this:
1318
1319~~~ {.cpp}
1320void 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
1334Here the bin-width is 1.0. If the two Fill(3) are commented out, as there are currently,
1335the example will return a calculated median of 4.5, because that's the bin center
1336of the bin in which the value 4.0 has been dropped. If the two Fill(3) are not
1337commented out, it will return 3.75, because the algorithm tries to evenly distribute
1338the individual values of a bin with bin content > 0. It means the sorted list
1339would be "3.25, 3.75, 4.5".
1340
1341The consequence is a median of 3.75. This shows how important it is to use a
1342small enough bin-width when using candle-plots on binned data.
1343If the distribution is large enough and gaussian shaped the median will be exactly
1344equal to the mean.
1345The median can be shown as a line or as a circle or not shown at all.
1346
1347In order to show the significance of the median notched candle plots apply a "notch" or
1348narrowing 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
1351distribution). Candle plots like these are usually called "notched candle plots".
1352
1353In case the significance of the median is greater that the size of the box, the
1354box will have an unnatural shape. Usually it means the chart has not enough data,
1355or that representing this uncertainty is not useful
1356
1357##### The Mean
1358The mean can be drawn as a dashed line or as a circle or not drawn at all.
1359The mean is the arithmetic average of the values in the distribution.
1360It is calculated using GetMean(). Because histograms are
1361binned data, the mean value can differ from a calculation on the raw-data.
1362If the distribution is large enough and gaussian shaped the mean will be
1363exactly the median.
1364
1365##### The Whiskers
1366The whiskers represent the part of the distribution not covered by the box.
1367The upper 25% and the lower 25% of the distribution are located within the whiskers.
1368Two 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
1382Using the static function TCandle::SetWhiskerRange(double) the whisker definition w=1
1383will be overwritten. E.g. using a whisker-range of 0.95 and w=1 will redefine the area of
1384the lower whisker to the upper whisker in order to cover 95% of the distribution inside
1385that candle. The static function will affect all candle-charts in the running program.
1386Default is 1.
1387
1388If the distribution is large enough and gaussian shaped, the maximum length of
1389the whisker will be located at \f$ \pm 2.698 \sigma \f$ (when using the
13901.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
1392by the box and the whiskers, whereas 0.7% are represented by the outliers.
1393
1394##### The Anchors
1395The anchors have no special meaning in terms of statistical calculation. They mark
1396the end of the whiskers and they have the width of the box. Both representation
1397with and without anchors are common.
1398
1399##### The Points
1400Depending 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
1424Is is possible to combine all options of candle and violin plots with each other. E.g. a box-plot
1425with a histogram.
1426
1427#### How to use the candle-plots drawing option
1428
1429There 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
1445The following picture shows how the six predefined representations look.
1446
1447Begin_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}
1468End_Macro
1469
1470
1471#### Example 1
1472Box and improved whisker, no mean, no median, no anchor no outliers
1473
1474 h1->Draw("CANDLEX(2001)");
1475
1476#### Example 2
1477A Candle-definition like "CANDLEX2" (New standard candle with better whisker definition + outliers)
1478
1479 h1->Draw("CANDLEX(112111)");
1480
1481#### Example 3
1482The following example shows how several candle plots can be super-imposed using
1483the option SAME. Note that the bar-width and bar-offset are active on candle plots.
1484Also the color, the line width, the size of the points and so on can be changed by the
1485standard attribute setting methods such as SetLineColor() SetLineWidth().
1486
1487Begin_Macro(source)
1488../../../tutorials/hist/candleplot.C
1489End_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
1494that also encodes the pdf information at each point.
1495
1496
1497Quartiles and mean are also represented at each point, with a marker
1498and two lines.
1499
1500In this implementation a TH2 is considered as a collection of TH1 along
1501X (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
1508The histogram is typically drawn to both directions with respect to the middle-line of the
1509corresponding bin. This can be achieved by using h=3. It is possible to draw a histogram only to
1510one side (h=1, or h=2).
1511The maximum number of bins in the histogram is limited to 500, if the number of bins in the used
1512histogram is higher it will be rebinned automatically. The maximum height of the histogram can
1513be modified by using SetBarWidth() and the position can be changed with SetBarOffset().
1514A solid fill style is recommended.
1515
1516\since **ROOT version 6.11/01**
1517
1518Using the static function TCandle::SetScaledViolin(bool) the height of the histogram or the
1519violin can be influenced. Activated, the height of the bins of the individual violins will be
1520scaled with respect to each other, the maximum height can be influenced by SetBarWidth().
1521Deactivated, the height of the bin with the maximum content of each individual violin is
1522set to a constant value using SetBarWidth(). The static function will affect all violin-charts
1523in 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
1527Typical for violin charts is a line in the background over the whole histogram indicating
1528the bins with zero entries. The zero indicator line can be activated with z=1. The line color
1529will always be the same as the fill-color of the histogram.
1530
1531##### The Mean
1532The Mean is illustrated with the same mechanism as used for candle plots. Usually a circle is used.
1533
1534##### Whiskers
1535The whiskers are illustrated by the same mechanism as used for candle plots. There is only one
1536difference. When using the simple whisker definition (w=1) and the zero indicator line (z=1), then
1537the whiskers will be forced to be solid (usually hashed)
1538
1539##### Points
1540The points are illustrated by the same mechanism as used for candle plots. E.g. VIOLIN2 uses
1541better whisker definition (w=2) and outliers (p=1).
1542
1543##### Other options
1544It is possible to combine all options of candle or violin plots with each other. E.g. a violin plot
1545including a box-plot.
1546
1547#### How to use the violin-plots drawing option
1548
1549There 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
1554A solid fill style is recommended for this plot (as opposed to a hollow or
1555hashed style).
1556
1557Begin_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}
1580End_Macro
1581
1582The next example illustrates a time development of a certain value:
1583
1584Begin_Macro(source)
1585../../../tutorials/hist/candledecay.C
1586End_Macro
1587
1588
1589### <a name="HP15"></a> The TEXT and TEXTnn Option
1590
1591
1592For 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
1600By default the format `g` is used. This format can be redefined
1601by calling `gStyle->SetPaintTextFormat()`.
1602
1603It is also possible to use `TEXTnn` in order to draw the text with
1604the angle `nn` (`0 < nn < 90`).
1605
1606For 2D histograms the text is plotted in the center of each non empty cells.
1607It is possible to plot empty cells by calling `gStyle->SetHistMinimumZero()`
1608or providing MIN0 draw option. For 1D histogram the text is plotted at a y
1609position equal to the bin content.
1610
1611For 2D histograms when the option "E" (errors) is combined with the option
1612text ("TEXTE"), the error for each bin is also printed.
1613
1614Begin_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}
1634End_Macro
1635
1636\since **ROOT version 6.07/07:**
1637
1638In case several histograms are drawn on top ot each other (using option `SAME`),
1639the text can be shifted using `SetBarOffset()`. It specifies an offset for the
1640text position in each cell, in percentage of the bin width.
1641
1642Begin_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}
1665End_Macro
1666
1667In the case of profile histograms it is possible to print the number
1668of entries instead of the bin content. It is enough to combine the
1669option "E" (for entries) with the option "TEXT".
1670
1671Begin_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}
1692End_Macro
1693
1694### <a name="HP16"></a> The CONTour options
1695
1696
1697The 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
1711The following example shows a 2D histogram plotted with the option
1712`CONTZ`. The option `CONT` draws a contour plot using surface
1713colors to distinguish contours. Combined with the option `CONT` (or
1714`CONT0`), the option `Z` allows to display the color palette
1715defined by `gStyle->SetPalette()`.
1716
1717Begin_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}
1729End_Macro
1730
1731The following example shows a 2D histogram plotted with the option
1732`CONT1Z`. The option `CONT1` draws a contour plot using the
1733line colors to distinguish contours. Combined with the option `CONT1`,
1734the option `Z` allows to display the color palette defined by
1735`gStyle->SetPalette()`.
1736
1737Begin_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}
1749End_Macro
1750
1751The following example shows a 2D histogram plotted with the option
1752`CONT2`. The option `CONT2` draws a contour plot using the
1753line styles (1 to 5) to distinguish contours.
1754
1755Begin_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}
1767End_Macro
1768
1769The following example shows a 2D histogram plotted with the option
1770`CONT3`. The option `CONT3` draws contour plot using the same line style for
1771all contours.
1772
1773Begin_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}
1786End_Macro
1787
1788The following example shows a 2D histogram plotted with the option
1789`CONT4`. The option `CONT4` draws a contour plot using surface
1790colors to distinguish contours (`SURF` option at theta = 0). Combined
1791with the option `CONT` (or `CONT0`), the option `Z`
1792allows to display the color palette defined by `gStyle->SetPalette()`.
1793
1794Begin_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}
1806End_Macro
1807
1808The default number of contour levels is 20 equidistant levels and can be changed
1809with `TH1::SetContour()` or `TStyle::SetNumberContours()`.
1810
1811#### <a name="HP16a"></a> The LIST option
1812
1813When 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
1820The contour are saved in `TGraph` objects once the pad is painted.
1821Therefore to use this functionality in a macro, `gPad->Update()`
1822should be performed after the histogram drawing. Once the list is
1823built, 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
1829Where `i` is a contour number, and list contains a list of
1830`TGraph` objects.
1831For one given contour, more than one disjoint polyline may be generated.
1832The number of TGraphs per contour is given by:
1833
1834 list->GetSize();
1835
1836To access the first graph in the list one should do:
1837
1838 TGraph *gr1 = (TGraph*)list->First();
1839
1840
1841The following example (ContourList.C) shows how to use this functionality.
1842
1843Begin_Macro(source)
1844../../../tutorials/hist/ContourList.C
1845End_Macro
1846
1847#### <a name="HP16b"></a> The AITOFF, MERCATOR, SINUSOIDAL and PARABOLIC options
1848
1849The following options select the `CONT4` option and are useful for
1850sky 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
1859Begin_Macro(source)
1860../../../tutorials/graphics/earth.C
1861End_Macro
1862
1863
1864### <a name="HP17"></a> The LEGO options
1865
1866
1867In a lego plot the cell contents are drawn as 3-d boxes. The height of each box
1868is proportional to the cell content. The lego aspect is control with the
1869following 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
1881See the limitations with [the option "SAME"](#HP060a).
1882
1883Line attributes can be used in lego plots to change the edges' style.
1884
1885The following example shows a 2D histogram plotted with the option
1886`LEGO`. The option `LEGO` draws a lego plot using the hidden
1887lines removal technique.
1888
1889Begin_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}
1901End_Macro
1902
1903The following example shows a 2D histogram plotted with the option
1904`LEGO1`. The option `LEGO1` draws a lego plot using the
1905hidden surface removal technique. Combined with any `LEGOn` option, the
1906option `0` allows to not drawn the empty bins.
1907
1908Begin_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}
1921End_Macro
1922
1923The following example shows a 2D histogram plotted with the option
1924`LEGO3`. Like the option `LEGO1`, the option `LEGO3`
1925draws a lego plot using the hidden surface removal technique but doesn't draw
1926the border lines of each individual lego-bar. This is very useful for histograms
1927having many bins. With such histograms the option `LEGO1` gives a black
1928image because of the border lines. This option also works with stacked legos.
1929
1930Begin_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}
1943End_Macro
1944
1945The following example shows a 2D histogram plotted with the option
1946`LEGO2`. The option `LEGO2` draws a lego plot using colors to
1947show the cell contents. Combined with the option `LEGO2`, the option
1948`Z` allows to display the color palette defined by
1949`gStyle->SetPalette()`.
1950
1951Begin_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}
1963End_Macro
1964
1965
1966
1967### <a name="HP18"></a> The "SURFace" options
1968
1969
1970In a surface plot, cell contents are represented as a mesh.
1971The 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
1986See the limitations with [the option "SAME"](#HP060a).
1987
1988The following example shows a 2D histogram plotted with the option
1989`SURF`. The option `SURF` draws a lego plot using the hidden
1990lines removal technique.
1991
1992Begin_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}
2004End_Macro
2005
2006The following example shows a 2D histogram plotted with the option
2007`SURF1`. The option `SURF1` draws a surface plot using the
2008hidden surface removal technique. Combined with the option `SURF1`,
2009the option `Z` allows to display the color palette defined by
2010`gStyle->SetPalette()`.
2011
2012Begin_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}
2024End_Macro
2025
2026The following example shows a 2D histogram plotted with the option
2027`SURF2`. The option `SURF2` draws a surface plot using colors
2028to 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
2032Begin_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}
2044End_Macro
2045
2046The following example shows a 2D histogram plotted with the option
2047`SURF3`. The option `SURF3` draws a surface plot using the
2048hidden line removal technique with, in addition, a filled contour view drawn on the
2049top. Combined with the option `SURF3`, the option `Z` allows
2050to display the color palette defined by `gStyle->SetPalette()`.
2051
2052Begin_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}
2064End_Macro
2065
2066The following example shows a 2D histogram plotted with the option
2067`SURF4`. The option `SURF4` draws a surface using the Gouraud
2068shading technique.
2069
2070Begin_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}
2083End_Macro
2084
2085The 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
2089Begin_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}
2101End_Macro
2102
2103The following example shows a 2D histogram plotted with the option
2104`SURF7`. The option `SURF7` draws a surface plot using the
2105hidden surfaces removal technique with, in addition, a line contour view drawn on the
2106top. Combined with the option `SURF7`, the option `Z` allows
2107to display the color palette defined by `gStyle->SetPalette()`.
2108
2109Begin_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}
2121End_Macro
2122
2123As shown in the following example, when a contour plot is painted on top of a
2124surface plot using the option `SAME`, the contours appear in 3D on the
2125surface.
2126
2127Begin_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}
2143End_Macro
2144
2145
2146### <a name="HP19"></a> Cylindrical, Polar, Spherical and PseudoRapidity/Phi options
2147
2148
2149Legos and surfaces plots are represented by default in Cartesian coordinates.
2150Combined with any `LEGOn` or `SURFn` options the following
2151options 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
2164The following example shows the same histogram as a lego plot is the four
2165different coordinates systems.
2166
2167Begin_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}
2187End_Macro
2188
2189The following example shows the same histogram as a surface plot is the four different coordinates systems.
2190
2191Begin_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}
2210End_Macro
2211
2212
2213### <a name="HP20"></a> Base line for bar-charts and lego plots
2214
2215
2216By default the base line used to draw the boxes for bar-charts and lego plots is
2217the histogram minimum. It is possible to force this base line to be 0, using MIN0 draw
2218option or with the command:
2219
2220 gStyle->SetHistMinimumZero();
2221
2222Begin_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}
2246End_Macro
2247
2248This option also works for horizontal plots. The example given in the section
2249["The bar chart option"](#HP100) appears as follow:
2250
2251Begin_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}
2286End_Macro
2287
2288
2289### <a name="HP20a"></a> TH2Poly Drawing
2290
2291
2292The 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
2310shapes. The bins are defined as graphs. The following macro is a very simple
2311example showing how to book a TH2Poly and draw it.
2312
2313Begin_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}
2338End_Macro
2339
2340Rectangular bins are a frequent case. The special version of
2341the `AddBin` method allows to define them more easily like
2342shown in the following example (th2polyBoxes.C).
2343
2344Begin_Macro(source)
2345../../../tutorials/hist/th2polyBoxes.C
2346End_Macro
2347
2348One `TH2Poly` bin can be a list of polygons. Such bins are defined
2349by calling `AddBin` with a `TMultiGraph`. The following example
2350shows a such case:
2351
2352Begin_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}
2406End_Macro
2407
2408`TH2Poly` histograms can also be plotted using the GL interface using
2409the option "GLLEGO".
2410
2411\since **ROOT version 6.09/01**
2412
2413In some cases it can be useful to not draw the empty bins. the option "0"
2414combined with the option "COL" et COLZ allows to do that.
2415
2416Begin_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}
2428End_Macro
2429
2430### <a name="HP21"></a> The SPEC option
2431
2432
2433This option allows to use the `TSpectrum2Painter` tools. See the full
2434documentation 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
2440When this option is specified, a color palette with an axis indicating the value
2441of the corresponding color is drawn on the right side of the picture. In case,
2442not enough space is left, one can increase the size of the right margin by
2443calling `TPad::SetRightMargin()`. The attributes used to display the
2444palette axis values are taken from the Z axis of the object. For example, to
2445set 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
2455To change the color palette `TStyle::SetPalette` should be used, eg:
2456
2457 gStyle->SetPalette(ncolors,colors);
2458
2459For example the option `COL` draws a 2D histogram with cells
2460represented by a box filled with a color index which is a function
2461of the cell content.
2462If the cell content is N, the color index used will be the color number
2463in `colors[N]`, etc. If the maximum cell content is greater than
2464`ncolors`, all cell contents are scaled to `ncolors`.
2465
2466If ` ncolors <= 0`, a default palette (see below) of 50 colors is
2467defined. This palette is recommended for pads, labels ...
2468
2469`if ncolors == 1 && colors == 0`, then a Pretty Palette with a
2470Spectrum Violet->Red is created with 50 colors. That's the default rain bow
2471palette.
2472
2473Other pre-defined palettes with 255 colors are available when `colors == 0`.
2474The 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
2485If `ncolors > 0 && colors == 0`, the default palette is used with a maximum of ncolors.
2486
2487The 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
2495The color numbers specified in the palette can be viewed by selecting
2496the item `colors` in the `VIEW` menu of the canvas tool bar.
2497The 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
2502As default labels and ticks are drawn by `TGAxis` at equidistant (lin or log)
2503points as controlled by SetNdivisions.
2504If option "CJUST" is given labels and ticks are justified at the
2505color boundaries defined by the contour levels.
2506For more details see `TPaletteAxis`
2507
2508### <a name="HP24"></a> Drawing a sub-range of a 2D histogram; the [cutg] option
2509
2510
2511Using a `TCutG` object, it is possible to draw a sub-range of a 2D
2512histogram. One must create a graphical cut (mouse or C++) and specify the name
2513of the cut between `[]` in the `Draw()` option.
2514For example (fit2a.C), with a `TCutG` named `cutg`, one can call:
2515
2516 myhist->Draw("surf1 [cutg]");
2517
2518To invert the cut, it is enough to put a `-` in front of its name:
2519
2520 myhist->Draw("surf1 [-cutg]");
2521
2522It is possible to apply several cuts (`,` means logical AND):
2523
2524 myhist->Draw("surf1 [cutg1,cutg2]");
2525
2526Begin_Macro(source)
2527../../../tutorials/fit/fit2a.C
2528End_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
2542Note that instead of `BOX` one can also use `LEGO`.
2543
2544By default, like 2D histograms, 3D histograms are drawn as scatter plots.
2545
2546The following example shows a 3D histogram plotted as a scatter plot.
2547
2548Begin_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}
2561End_Macro
2562
2563The following example shows a 3D histogram plotted with the option `BOX`.
2564
2565Begin_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}
2578End_Macro
2579
2580The following example shows a 3D histogram plotted with the option `BOX1`.
2581
2582Begin_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}
2596End_Macro
2597
2598The following example shows a 3D histogram plotted with the option `BOX2`.
2599
2600Begin_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}
2613End_Macro
2614
2615The following example shows a 3D histogram plotted with the option `BOX3`.
2616
2617Begin_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}
2631End_Macro
2632
2633For all the `BOX` options each bin is drawn as a 3D box with a volume proportional
2634to the absolute value of the bin content. The bins with a negative content are
2635drawn with a X on each face of the box as shown in the following example:
2636
2637Begin_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}
2650End_Macro
2651
2652The following example shows a 3D histogram plotted with the option `ISO`.
2653
2654Begin_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}
2668End_Macro
2669
2670
2671### <a name="HP26"></a> Drawing option for histograms' stacks
2672
2673
2674Stacks of histograms are managed with the `THStack`. A `THStack`
2675is 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
2679By default, histograms are shown stacked:
2680
26811. The first histogram is paint.
26822. The the sum of the first and second, etc...
2683
2684If the option `NOSTACK` is specified, the histograms are all paint in
2685the same pad as if the option `SAME` had been specified. This allows to
2686compute X and Y scales common to all the histograms, like
2687`TMultiGraph` does for graphs.
2688
2689If the option `PADS` is specified, the current pad/canvas is
2690subdivided into a number of pads equal to the number of histograms and each
2691histogram is paint into a separate pad.
2692
2693The following example shows various types of stacks (hstack.C).
2694
2695Begin_Macro(source)
2696../../../tutorials/hist/hstack.C
2697End_Macro
2698
2699The option `nostackb` allows to draw the histograms next to each
2700other as bar charts:
2701
2702Begin_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}
2726End_Macro
2727
2728If at least one of the histograms in the stack has errors, the whole stack is
2729visualized by default with error bars. To visualize it without errors the
2730option `HIST` should be used.
2731
2732Begin_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}
2755End_Macro
2756
2757### <a name="HP27"></a> Drawing of 3D implicit functions
2758
2759
27603D implicit functions (`TF3`) can be drawn as iso-surfaces.
2761The implicit function f(x,y,z) = 0 is drawn in cartesian coordinates.
2762In the following example the options "FB" and "BB" suppress the
2763"Front Box" and "Back Box" around the plot.
2764
2765Begin_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}
2774End_Macro
2775
2776
2777### <a name="HP28"></a> Associated functions drawing
2778
2779
2780An associated function is created by `TH1::Fit`. More than on fitted
2781function can be associated with one histogram (see `TH1::Fit`).
2782
2783A `TF1` object `f1` can be added to the list of associated
2784functions of an histogram `h` without calling `TH1::Fit`
2785simply doing:
2786
2787 h->GetListOfFunctions()->Add(f1);
2788
2789or
2790
2791 h->GetListOfFunctions()->Add(f1,someoption);
2792
2793To retrieve a function by name from this list, do:
2794
2795 TF1 *f1 = (TF1*)h->GetListOfFunctions()->FindObject(name);
2796
2797or
2798
2799 TF1 *f1 = h->GetFunction(name);
2800
2801Associated functions are automatically painted when an histogram is drawn.
2802To avoid the painting of the associated functions the option `HIST`
2803should 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
2809The class `TGLHistPainter` allows to paint data set using the OpenGL 3D
2810graphics library. The plotting options start with `GL` keyword.
2811In addition, in order to inform canvases that OpenGL should be used to render
28123D 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
2819The following types of plots are provided:
2820
2821For 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
2831Lego painter in cartesian supports logarithmic scales for X, Y, Z.
2832In polar only Z axis can be logarithmic, in cylindrical only Y.
2833
2834For 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
2846The surface painting in cartesian coordinates supports logarithmic scales along
2847X, Y, Z axis. In polar coordinates only the Z axis can be logarithmic,
2848in cylindrical coordinates only the Y axis.
2849
2850Additional 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
2863The 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
2873The 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
2884The 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
2894The 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
2905equations and visualize the surface.
2906
2907#### <a name="HP29f"></a> Interaction with the plots
2908
2909All the interactions are implemented via standard methods
2910`DistancetoPrimitive()` and `ExecuteEvent()`. That's why all the
2911interactions with the OpenGL plots are possible only when the mouse cursor is
2912in the plot's area (the plot's area is the part of a the pad occupied by
2913gl-produced picture). If the mouse cursor is not above gl-picture, the standard
2914pad interaction is performed.
2915
2916#### <a name="HP29g"></a> Selectable parts
2917
2918Different 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
2943The selected plot can be moved in a pad's area by pressing and
2944holding the left mouse button and the shift key.
2945
2946#### <a name="HP29j"></a> Box cut
2947
2948Surface, iso, box, TF3 and parametric painters support box cut by
2949pressing the 'c' or 'C' key when the mouse cursor is in a plot's
2950area. That will display a transparent box, cutting away part of the
2951surface (or boxes) in order to show internal part of plot. This box
2952can be moved inside the plot's area (the full size of the box is
2953equal to the plot's surrounding box) by selecting one of the box
2954cut axes and pressing the left mouse button to move it.
2955
2956#### <a name="HP29k"></a> Plot specific interactions (dynamic slicing etc.)
2957
2958Currently, all gl-plots support some form of slicing. When back plane
2959is selected (and if it's highlighted in green) you can press and hold
2960left mouse button and shift key and move this back plane inside
2961plot's area, creating the slice. During this "slicing" plot becomes
2962semi-transparent. To remove all slices (and projected curves for
2963surfaces) double click with left mouse button in a plot's area.
2964
2965#### <a name="HP29l"></a> Surface with option "GLSURF"
2966
2967The surface profile is displayed on the slicing plane.
2968The profile projection is drawn on the back plane
2969by pressing `'p'` or `'P'` key.
2970
2971#### <a name="HP29m"></a> TF3
2972
2973The contour plot is drawn on the slicing plane. For TF3 the color
2974scheme can be changed by pressing 's' or 'S'.
2975
2976#### <a name="HP29n"></a> Box
2977
2978The contour plot corresponding to slice plane position is drawn in real time.
2979
2980#### <a name="HP29o"></a> Iso
2981
2982Slicing is similar to "GLBOX" option.
2983
2984#### <a name="HP29p"></a> Parametric plot
2985
2986No slicing. Additional keys: 's' or 'S' to change color scheme -
2987about 20 color schemes supported ('s' for "scheme"); 'l' or 'L' to
2988increase number of polygons ('l' for "level" of details), 'w' or 'W'
2989to 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
2997Highlight mode is implemented for `TH1` (and for `TGraph`) class. When
2998highlight mode is on, mouse movement over the bin will be represented
2999graphically. Bin will be highlighted as "bin box" (presented by box
3000object). Moreover, any highlight (change of bin) emits signal
3001`TCanvas::Highlighted()` which allows the user to react and call their own
3002function. For a better understanding see also the tutorials
3003`$ROOTSYS/tutorials/hist/hlHisto*.C` files.
3004
3005Highlight mode is switched on/off by `TH1::SetHighlight()` function
3006or interactively from `TH1` context menu. `TH1::IsHighlight()` to verify
3007whether 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
3020The user can use (connect) `TCanvas::Highlighted()` signal, which is always
3021emitted if there is a highlight bin and call user function via signal
3022and slot communication mechanism. `TCanvas::Highlighted()` is similar
3023`TCanvas::Picked()`
3024
3025- when selected object (histogram as a whole) is different from previous
3026then emit `Picked()` signal
3027- when selected (highlighted) bin from histogram is different from previous
3028then emit `Highlighted()` signal
3029
3030Any user function (or functions) has to be defined
3031`UserFunction(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)`.
3032In example (see below) has name `PrintInfo()`. All parameters of user
3033function 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
3042Example 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
3048or use non-static "simplified" function
3049`TCanvas::HighlightConnect(const char *slot)`
3050
3051 c1->HighlightConnect("UserFunction(TVirtualPad*,TObject*,Int_t,Int_t)");
3052
3053NOTE 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
3060file `hlprint.C`
3061~~~ {.cpp}
3062void 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
3073void 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
3082For more complex demo please see for example `$ROOTSYS/tutorials/tree/temperature.C` file.
3083
3084*/
3085
3087
3090
3091const Int_t kNMAX = 2000;
3092
3093const Int_t kMAXCONTOUR = 104;
3095
3096static TBox *gXHighlightBox = 0; // highlight X box
3097static 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;
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
3364FUNCTIONS:
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
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
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()) {
3869 if ((hcenter < uxmin) || (hcenter > uxmax)) return;
3870 } else {
3872 if ((hcenter < uymin) || (hcenter > uymax)) return;
3873 }
3874 if (fH->GetDimension() == 2) {
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);
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);
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++) {
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
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())) {
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 }
4313 if (Hoption.Text && fH->InheritsFrom(TProfile::Class())) {
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) {
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);
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);
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
4560paintstat:
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;
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
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);
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();
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.);
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;