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