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