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 "TCanvasImp.h"
36#include "TPad.h"
37#include "TPaveStats.h"
38#include "TFrame.h"
39#include "TLatex.h"
40#include "TPolyLine.h"
41#include "TPoints.h"
42#include "TStyle.h"
43#include "TGraph.h"
44#include "TMultiGraph.h"
45#include "TPie.h"
46#include "TGaxis.h"
47#include "TColor.h"
49#include "TGraph2D.h"
50#include "TGraph2DPainter.h"
51#include "TGraphDelaunay2D.h"
52#include "TView.h"
53#include "TMath.h"
54#include "TRandom2.h"
55#include "TObjArray.h"
56#define ROOT_Hoption_cxx
57#include "Hoption.h"
58#define ROOT_Hparam_cxx
59#include "Hparam.h"
60#include "TPluginManager.h"
61#include "TPaletteAxis.h"
62#include "TCrown.h"
63#include "TArrow.h"
64#include "TVirtualPadPainter.h"
65#include "TVirtualPadEditor.h"
66#include "TEnv.h"
67#include "TPoint.h"
68#include "TImage.h"
69#include "TCandle.h"
70#include "strlcpy.h"
71
72/*! \class THistPainter
73 \ingroup Histpainter
74 \brief The histogram painter class. Implements all histograms' drawing's options.
75
76- [Introduction](\ref HP00)
77- [Histograms' plotting options](\ref HP01)
78 - [Options supported for 1D and 2D histograms](\ref HP01a)
79 - [Options supported for 1D histograms](\ref HP01b)
80 - [Options supported for 2D histograms](\ref HP01c)
81 - [Options supported for 3D histograms](\ref HP01d)
82 - [Options supported for histograms' stacks (THStack)](\ref HP01e)
83- [Setting the Style](\ref HP02)
84- [Setting line, fill, marker, and text attributes](\ref HP03)
85- [Setting Tick marks on the histogram axis](\ref HP04)
86- [Giving titles to the X, Y and Z axis](\ref HP05)
87- [The option SAME](\ref HP060)
88 - [Limitations](\ref HP060a)
89- [Colors automatically picked in palette](\ref HP061)
90- [Superimposing two histograms with different scales in the same pad](\ref HP06)
91- [Statistics Display](\ref HP07)
92- [Fit Statistics](\ref HP08)
93- [The error bars options](\ref HP09)
94- [The bar chart option](\ref HP100)
95- [The BAR and HBAR options](\ref HP10)
96- [The SCATter plot option (legacy draw option)](\ref HP11)
97- [The ARRow option](\ref HP12)
98- [The BOX option](\ref HP13)
99- [The COLor option (default for 2D and 3D histograms)](\ref HP14)
100- [The CANDLE and VIOLIN options](\ref HP140)
101 - [The CANDLE option](\ref HP140a)
102 - [The VIOLIN option](\ref HP140b)
103- [The TEXT and TEXTnn Option](\ref HP15)
104- [The CONTour options](\ref HP16)
105 - [The LIST option](\ref HP16a)
106 - [The AITOFF, MERCATOR, SINUSOIDAL and PARABOLIC options](\ref HP16b)
107- [The LEGO options](\ref HP17)
108- [The SURFace options](\ref HP18)
109- [Cylindrical, Polar, Spherical and PseudoRapidity/Phi options](\ref HP19)
110- [Base line for bar-charts and lego plots](\ref HP20)
111- [TH2Poly Drawing](\ref HP20a)
112- [The SPEC option](\ref HP21)
113- [Option Z : Adding the color palette on the right side of the pad](\ref HP22)
114- [Setting the color palette](\ref HP23)
115- [Drawing a sub-range of a 2-D histogram; the [cutg] option](\ref HP24)
116- [Drawing options for 3D histograms](\ref HP25)
117- [Drawing option for histograms' stacks](\ref HP26)
118- [Drawing of 3D implicit functions](\ref HP27)
119- [Associated functions drawing](\ref HP28)
120- [Drawing using OpenGL](\ref HP29)
121 - [General information: plot types and supported options](\ref HP29a)
122 - [TH3 as color boxes](\ref HP290)
123 - [TH3 as boxes (spheres)](\ref HP29b)
124 - [TH3 as iso-surface(s)](\ref HP29c)
125 - [TF3 (implicit function)](\ref HP29d)
126 - [Parametric surfaces](\ref HP29e)
127 - [Interaction with the plots](\ref HP29f)
128 - [Selectable parts](\ref HP29g)
129 - [Rotation and zooming](\ref HP29h)
130 - [Panning](\ref HP29i)
131 - [Box cut](\ref HP29j)
132 - [Plot specific interactions (dynamic slicing etc.)](\ref HP29k)
133 - [Surface with option GLSURF](\ref HP29l)
134 - [TF3](\ref HP29m)
135 - [Box](\ref HP29n)
136 - [Iso](\ref HP29o)
137 - [Parametric plot](\ref HP29p)
138- [Highlight mode for histogram](\ref HP30)
139 - [Highlight mode and user function](\ref HP30a)
140
141
142\anchor HP00
143## Introduction
144
145
146Histograms are drawn via the `THistPainter` class. Each histogram has a
147pointer to its own painter (to be usable in a multithreaded program). When the
148canvas has to be redrawn, the `Paint` function of each objects in the
149pad is called. In case of histograms, `TH1::Paint` invokes directly
150`THistPainter::Paint`.
151
152To draw a histogram `h` it is enough to do:
153
154 h->Draw();
155
156`h` can be of any kind: 1D, 2D or 3D. To choose how the histogram will
157be drawn, the `Draw()` method can be invoked with an option. For instance
158to draw a 2D histogram as a lego plot it is enough to do:
159
160 h->Draw("lego");
161
162`THistPainter` offers many options to paint 1D, 2D and 3D histograms.
163
164When the `Draw()` method of a histogram is called for the first time
165(`TH1::Draw`), it creates a `THistPainter` object and saves a
166pointer to this "painter" as a data member of the histogram. The
167`THistPainter` class specializes in the drawing of histograms. It is
168separated from the histogram so that one can have histograms without the
169graphics overhead, for example in a batch program. Each histogram having its own
170painter (rather than a central singleton painter painting all histograms), allows
171two histograms to be drawn in two threads without overwriting the painter's
172values.
173
174When a displayed histogram is filled again, there is no need to call the
175`Draw()` method again; the image will be refreshed the next time the
176pad will be updated.
177
178A pad is updated after one of these three actions:
179
1801. a carriage control on the ROOT command line,
1812. a click inside the pad,
1823. a call to `TPad::Update`.
183
184
185By default a call to `TH1::Draw()` clears the pad of all objects
186before drawing the new image of the histogram. One can use the `SAME`
187option to leave the previous display intact and superimpose the new histogram.
188The same histogram can be drawn with different graphics options in different
189pads.
190
191When a displayed histogram is deleted, its image is automatically removed
192from the pad.
193
194To create a copy of the histogram when drawing it, one can use
195`TH1::DrawClone()`. This will clone the histogram and allow to change
196and delete the original one without affecting the clone.
197
198
199\anchor HP01
200### Histograms' plotting options
201
202
203Most options can be concatenated with or without spaces or commas, for example:
204
205 h->Draw("E1 SAME");
206
207The options are not case sensitive:
208
209 h->Draw("e1 same");
210
211
212The default drawing option can be set with `TH1::SetOption` and retrieve
213using `TH1::GetOption`:
214
215 root [0] h->Draw(); // Draw "h" using the standard histogram representation.
216 root [1] h->Draw("E"); // Draw "h" using error bars
217 root [3] h->SetOption("E"); // Change the default drawing option for "h"
218 root [4] h->Draw(); // Draw "h" using error bars
219 root [5] h->GetOption(); // Retrieve the default drawing option for "h"
220 (const Option_t* 0xa3ff948)"E"
221
222
223\anchor HP01a
224#### Options supported for 1D and 2D histograms
225
226| Option | Description |
227|----------|-------------------------------------------------------------------|
228| "E" | Draw error bars. |
229| "AXIS" | Draw only axis. |
230| "AXIG" | Draw only grid (if the grid is requested). |
231| \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). |
232| "FUNC" | When an histogram has a fitted function, this option allows to draw the fit result only. |
233| "SAME" | Superimpose on previous picture in the same pad. |
234| "SAMES" | Same as "SAME" and draw the statistics box|
235| "PFC" | Palette Fill Color: histogram's fill color is taken in the current palette. |
236| "PLC" | Palette Line Color: histogram's line color is taken in the current palette. |
237| "PMC" | Palette Marker Color: histogram's marker color is taken in the current palette. |
238| "LEGO" | Draw a lego plot with hidden line removal. |
239| "LEGO1" | Draw a lego plot with hidden surface removal. |
240| "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.|
241| "LEGO3" | Draw a lego plot with hidden surface removal, like LEGO1 but the border lines of each lego-bar are not drawn.|
242| "LEGO4" | Draw a lego plot with hidden surface removal, like LEGO1 but without the shadow effect on each lego-bar.|
243| "TEXT" | Draw bin contents as text (format set via `gStyle->SetPaintTextFormat`).|
244| "TEXTnn" | Draw bin contents as text at angle nn (0 < nn <= 90). |
245| "X+" | The X-axis is drawn on the top side of the plot. |
246| "Y+" | The Y-axis is drawn on the right side of the plot. |
247| "MIN0" | Set minimum value for the Y axis to 0, equivalent to gStyle->SetHistMinimumZero(). |
248
249
250\anchor HP01b
251#### Options supported for 1D histograms
252
253| Option | Description |
254|----------|-------------------------------------------------------------------|
255| " " | Default. |
256| "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.|
257| "][" | When this option is selected the first and last vertical lines of the histogram are not drawn.|
258| "B" | Bar chart option.|
259| "BAR" | Like option "B", but bars can be drawn with a 3D effect.|
260| "HBAR" | Like option "BAR", but bars are drawn horizontally.|
261| "C" | Draw a smooth Curve through the histogram bins.|
262| "E0" | Draw error bars. Markers are drawn for bins with 0 contents. Combined with E1 or E2 it avoids error bars clipping|
263| "E1" | Draw error bars with perpendicular lines at the edges.|
264| "E2" | Draw error bars with rectangles.|
265| "E3" | Draw a fill area through the end points of the vertical error bars.|
266| "E4" | Draw a smoothed filled area through the end points of the error bars.|
267| "E5" | Like E3 but ignore the bins with 0 contents.|
268| "E6" | Like E4 but ignore the bins with 0 contents.|
269| "X0" | When used with one of the "E" option, it suppress the error bar along X as `gStyle->SetErrorX(0)` would do.|
270| "L" | Draw a line through the bin contents.|
271| "P" | Draw current marker at each bin except empty bins.|
272| "P*" | Draw a star marker at each bin except empty bins.|
273| "P0" | Draw current marker at each bin including empty bins.|
274| "PIE" | Draw histogram as a Pie Chart.|
275| "*H" | Draw histogram with a * at each bin.|
276| "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.|
277
278
279
280\anchor HP01c
281#### Options supported for 2D histograms
282
283| Option | Description |
284|--------------|------------------------------------------------------------------|
285| " " | Default (color plot).|
286| "ARR" | Arrow mode. Shows gradient between adjacent cells.|
287| "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. |
288| "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.|
289| "COL" | A box is drawn for each cell with a color scale varying with contents. All the none empty bins (bins with content and error equal to 0) 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).|
290| "COL1" | Same as "COL" but in case of histogram with negative content the empty bins are not drawn.
291| "COLZ" | Same as "COL". In addition the color palette is also drawn.|
292| "COL2" | Alternative rendering algorithm to "COL". Can significantly improve rendering performance for large, non-sparse 2-D histograms.|
293| "COLZ2" | Same as "COL2". In addition the color palette is also drawn.|
294| "Z CJUST" | In combination with colored options "COL","CONT0" etc: Justify labels in the color palette at color boundaries. For more details see `TPaletteAxis`|
295| "CANDLE" | Draw a candle plot along X axis.|
296| "CANDLEX" | Same as "CANDLE".|
297| "CANDLEY" | Draw a candle plot along Y axis.|
298| "CANDLEXn" | Draw a candle plot along X axis. Different candle-styles with n from 1 to 6.|
299| "CANDLEYn" | Draw a candle plot along Y axis. Different candle-styles with n from 1 to 6.|
300| "VIOLIN" | Draw a violin plot along X axis.|
301| "VIOLINX" | Same as "VIOLIN".|
302| "VIOLINY" | Draw a violin plot along Y axis.|
303| "VIOLINXn" | Draw a violin plot along X axis. Different violin-styles with n being 1 or 2.|
304| "VIOLINYn" | Draw a violin plot along Y axis. Different violin-styles with n being 1 or 2.|
305| "CONT" | Draw a contour plot (same as CONT0).|
306| "CONT0" | Draw a contour plot using surface colors to distinguish contours.|
307| "CONT1" | Draw a contour plot using line styles to distinguish contours.|
308| "CONT2" | Draw a contour plot using the same line style for all contours.|
309| "CONT3" | Draw a contour plot using fill area colors.|
310| "CONT4" | Draw a contour plot using surface colors (SURF option at theta = 0).|
311| "LIST" | Generate a list of TGraph objects for each contour.|
312| "SAME0" | Same as "SAME" but do not use the z-axis range of the first plot. |
313| "SAMES0" | Same as "SAMES" but do not use the z-axis range of the first plot. |
314| "CYL" | Use Cylindrical coordinates. The X coordinate is mapped on the angle and the Y coordinate on the cylinder length.|
315| "POL" | Use Polar coordinates. The visible X range mapped on the angle and the visible Y coordinate on the radius.|
316| "POLF" | Fixed Polar coordinates. The histogram X coordinate mapped on the angle and the Y coordinate on the radius.|
317| "POLN" | Natural Polar coordinates. The X coordinate directly represent angle in radian and the Y coordinate is the radius.|
318| "SPH" | Use Spherical coordinates. The X coordinate is mapped on the latitude and the Y coordinate on the longitude.|
319| "PSR" | Use PseudoRapidity/Phi coordinates. The X coordinate is mapped on Phi.|
320| "SURF" | Draw a surface plot with hidden line removal.|
321| "SURF1" | Draw a surface plot with hidden surface removal.|
322| "SURF2" | Draw a surface plot using colors to show the cell contents.|
323| "SURF3" | Same as SURF with in addition a contour view drawn on the top.|
324| "SURF4" | Draw a surface using Gouraud shading.|
325| "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.|
326| "AITOFF" | Draw a contour via an AITOFF projection.|
327| "MERCATOR" | Draw a contour via an Mercator projection.|
328| "SINUSOIDAL" | Draw a contour via an Sinusoidal projection.|
329| "PARABOLIC" | Draw a contour via an Parabolic projection.|
330| "MOLLWEIDE" | Draw a contour via an Mollweide projection.|
331| "LEGO9" | Draw the 3D axis only. Mainly needed for internal use |
332| "FB" | With LEGO or SURFACE, suppress the Front-Box.|
333| "BB" | With LEGO or SURFACE, suppress the Back-Box.|
334| "A" | With LEGO or SURFACE, suppress the axis.|
335| "SCAT" | Draw a scatter-plot (legacy draw option).|
336| "[cutg]" | Draw only the sub-range selected by the TCutG named "cutg".|
337
338
339
340\anchor HP01d
341#### Options supported for 3D histograms
342
343| Option | Description |
344|----------|-------------------------------------------------------------------|
345| " " | Default (color plot).|
346| "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)`.|
347| "BOX" | Draw a for each cell with volume proportional to the content's absolute value. An hidden line removal algorithm is used|
348| "BOX1" | Same as BOX but an hidden surface removal algorithm is used|
349| "BOX2" | The boxes' colors are picked in the current palette according to the bins' contents|
350| "BOX2Z" | Same as "BOX2". In addition the color palette is also drawn.|
351| "BOX3" | Same as BOX1, but the border lines of each lego-bar are not drawn.|
352| "LEGO" | Same as `BOX`.|
353
354\anchor HP01e
355#### Options supported for histograms' stacks (`THStack`)
356
357| Option | Description |
358|------------|-----------------------------------------------------------------|
359| " " | Default, the histograms are drawn on top of each other (as lego plots for 2D histograms).|
360| "NOSTACK" | Histograms in the stack are all paint in the same pad as if the option `SAME` had been specified.|
361| "NOSTACKB" | Histograms are drawn next to each other as bar charts.|
362| "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.|
363| "PADSn" | Like PADS but the current pad/canvas is subdivided into a `n` columns, automatically calculating the number of rows.|
364| "PFC" | Palette Fill Color: stack's fill color is taken in the current palette. |
365| "PLC" | Palette Line Color: stack's line color is taken in the current palette. |
366| "PMC" | Palette Marker Color: stack's marker color is taken in the current palette. |
367
368
369
370\anchor HP02
371### Setting the Style
372
373
374Histograms use the current style (`gStyle`). When one changes the current
375style and would like to propagate the changes to the histogram,
376`TH1::UseCurrentStyle` should be called. Call `UseCurrentStyle` on
377each histogram is needed.
378
379To force all the histogram to use the current style use:
380
381 gROOT->ForceStyle();
382
383All the histograms read after this call will use the current style.
384
385
386\anchor HP03
387### Setting line, fill, marker, and text attributes
388
389
390The histogram classes inherit from the attribute classes:
391`TAttLine`, `TAttFill` and `TAttMarker`.
392See the description of these classes for the list of options.
393
394
395\anchor HP04
396### Setting Tick marks on the histogram axis
397
398
399The `TPad::SetTicks` method specifies the type of tick marks on the axis.
400If ` tx = gPad->GetTickx()` and `ty = gPad->GetTicky()` then:
401
402 tx = 1; tick marks on top side are drawn (inside)
403 tx = 2; tick marks and labels on top side are drawn
404 ty = 1; tick marks on right side are drawn (inside)
405 ty = 2; tick marks and labels on right side are drawn
406
407By default only the left Y axis and X bottom axis are drawn
408(`tx = ty = 0`)
409
410`TPad::SetTicks(tx,ty)` allows to set these options.
411See also The `TAxis` functions to set specific axis attributes.
412
413In case multiple color filled histograms are drawn on the same pad, the fill
414area may hide the axis tick marks. One can force a redraw of the axis over all
415the histograms by calling:
416
417 gPad->RedrawAxis();
418
419
420\anchor HP05
421### Giving titles to the X, Y and Z axis
422
423
424 h->GetXaxis()->SetTitle("X axis title");
425 h->GetYaxis()->SetTitle("Y axis title");
426
427The histogram title and the axis titles can be any `TLatex` string.
428The titles are part of the persistent histogram.
429
430
431\anchor HP060
432### The option "SAME"
433
434
435By default, when an histogram is drawn, the current pad is cleared before
436drawing. In order to keep the previous drawing and draw on top of it the
437option `SAME` should be use. The histogram drawn with the option
438`SAME` uses the coordinates system available in the current pad.
439
440This option can be used alone or combined with any valid drawing option but
441some combinations must be use with care.
442
443\anchor HP060a
444#### Limitations
445
446- It does not work when combined with the `LEGO` and `SURF` options unless the
447 histogram plotted with the option `SAME` has exactly the same
448 ranges on the X, Y and Z axis as the currently drawn histogram. To superimpose
449 lego plots [histograms' stacks](\ref HP26) should be used.
450
451
452\anchor HP061
453### Colors automatically picked in palette
454
455\since **ROOT version 6.09/01**
456
457When several histograms are painted in the same canvas thanks to the option "SAME"
458or via a `THStack` it might be useful to have an easy and automatic way to choose
459their color. The simplest way is to pick colors in the current active color
460palette. Palette coloring for histogram is activated thanks to the options `PFC`
461(Palette Fill Color), `PLC` (Palette Line Color) and `PMC` (Palette Marker Color).
462When one of these options is given to `TH1::Draw` the histogram get its color
463from the current color palette defined by `gStyle->SetPalette(...)`. The color
464is determined according to the number of objects having palette coloring in
465the current pad.
466
467Begin_Macro(source)
468../../../tutorials/hist/hist005_TH1_palettecolor.C
469End_Macro
470
471Begin_Macro(source)
472../../../tutorials/hist/hist027_THStack_palette_color.C
473End_Macro
474
475Begin_Macro(source)
476../../../tutorials/hist/hist025_THStack_2d_palette_color.C
477End_Macro
478
479\anchor HP06
480### Superimposing two histograms with different scales in the same pad
481
482
483The following example creates two histograms, the second histogram is the bins
484integral of the first one. It shows a procedure to draw the two histograms in
485the same pad and it draws the scale of the second histogram using a new vertical
486axis on the right side. See also the tutorial `transpad.C` for a variant
487of this example.
488
489Begin_Macro(source)
490{
491 auto c1 = new TCanvas("c1","c1",600,400);
492 // create/fill draw h1
493 gStyle->SetOptStat(kFALSE);
494 auto h1 = new TH1F("h1","Superimposing two histograms with different scales",100,-3,3);
495 Int_t i;
496 for (i=0;i<10000;i++) h1->Fill(gRandom->Gaus(0,1));
497 h1->Draw();
498 c1->Update();
499
500 // create hint1 filled with the bins integral of h1
501 auto hint1 = new TH1F("hint1","h1 bins integral",100,-3,3);
502 float sum = 0.f;
503 for (i=1;i<=100;i++) {
504 sum += h1->GetBinContent(i);
505 hint1->SetBinContent(i,sum);
506 }
507
508 // scale hint1 to the pad coordinates
509 float rightmax = 1.1*hint1->GetMaximum();
510 float scale = gPad->GetUymax()/rightmax;
511 hint1->SetLineColor(kRed);
512 hint1->Scale(scale);
513 hint1->Draw("same");
514
515 // draw an axis on the right side
516 auto axis = new TGaxis(gPad->GetUxmax(),gPad->GetUymin(),
517 gPad->GetUxmax(), gPad->GetUymax(),0,rightmax,510,"+L");
518 axis->SetLineColor(kRed);
519 axis->SetTextColor(kRed);
520 axis->Draw();
521}
522End_Macro
523
524
525\anchor HP07
526### Statistics Display
527
528
529The type of information shown in the histogram statistics box can be selected
530with:
531
532 gStyle->SetOptStat(mode);
533
534The `mode` has up to nine digits that can be set to on (1 or 2), off (0).
535
536 mode = ksiourmen (default = 000001111)
537 k = 1; kurtosis printed
538 k = 2; kurtosis and kurtosis error printed
539 s = 1; skewness printed
540 s = 2; skewness and skewness error printed
541 i = 1; integral of bins printed
542 i = 2; integral of bins with option "width" printed
543 o = 1; number of overflows printed
544 u = 1; number of underflows printed
545 r = 1; standard deviation printed
546 r = 2; standard deviation and standard deviation error printed
547 m = 1; mean value printed
548 m = 2; mean and mean error values printed
549 e = 1; number of entries printed
550 n = 1; name of histogram is printed
551
552For example:
553
554 gStyle->SetOptStat(11);
555
556displays only the name of histogram and the number of entries, whereas:
557
558 gStyle->SetOptStat(1101);
559
560displays the name of histogram, mean value and standard deviation.
561
562<b>WARNING 1:</b> never do:
563
564 gStyle->SetOptStat(0001111);
565
566but instead do:
567
568 gStyle->SetOptStat(1111);
569
570because `0001111` will be taken as an octal number!
571
572<b>WARNING 2:</b> for backward compatibility with older versions
573
574 gStyle->SetOptStat(1);
575
576is taken as:
577
578 gStyle->SetOptStat(1111)
579
580To print only the name of the histogram do:
581
582 gStyle->SetOptStat(1000000001);
583
584<b>NOTE</b> that in case of 2D histograms, when selecting only underflow
585(10000) or overflow (100000), the statistics box will show all combinations
586of underflow/overflows and not just one single number.
587
588The parameter mode can be any combination of the letters `kKsSiIourRmMen`
589
590 k : kurtosis printed
591 K : kurtosis and kurtosis error printed
592 s : skewness printed
593 S : skewness and skewness error printed
594 i : integral of bins printed
595 I : integral of bins with option "width" printed
596 o : number of overflows printed
597 u : number of underflows printed
598 r : standard deviation printed
599 R : standard deviation and standard deviation error printed
600 m : mean value printed
601 M : mean value mean error values printed
602 e : number of entries printed
603 n : name of histogram is printed
604
605For example, to print only name of histogram and number of entries do:
606
607 gStyle->SetOptStat("ne");
608
609To print only the name of the histogram do:
610
611 gStyle->SetOptStat("n");
612
613The default value is:
614
615 gStyle->SetOptStat("nemr");
616
617When a histogram is painted, a `TPaveStats` object is created and added
618to the list of functions of the histogram. If a `TPaveStats` object
619already exists in the histogram list of functions, the existing object is just
620updated with the current histogram parameters.
621
622Once a histogram is painted, the statistics box can be accessed using
623`h->FindObject("stats")`. In the command line it is enough to do:
624
625 Root > h->Draw()
626 Root > TPaveStats *st = (TPaveStats*)h->FindObject("stats")
627
628because after `h->Draw()` the histogram is automatically painted. But
629in a script file the painting should be forced using `gPad->Update()`
630in order to make sure the statistics box is created:
631
632 h->Draw();
633 gPad->Update();
634 TPaveStats *st = (TPaveStats*)h->FindObject("stats");
635
636Without `gPad->Update()` the line `h->FindObject("stats")` returns a null pointer.
637
638When a histogram is drawn with the option `SAME`, the statistics box
639is not drawn. To force the statistics box drawing with the option
640`SAME`, the option `SAMES` must be used.
641If the new statistics box hides the previous statistics box, one can change
642its position with these lines (`h` being the pointer to the histogram):
643
644 Root > TPaveStats *st = (TPaveStats*)h->FindObject("stats")
645 Root > st->SetX1NDC(newx1); //new x start position
646 Root > st->SetX2NDC(newx2); //new x end position
647
648To change the type of information for an histogram with an existing
649`TPaveStats` one should do:
650
651 st->SetOptStat(mode);
652
653Where `mode` has the same meaning than when calling `gStyle->SetOptStat(mode)`
654(see above).
655
656One can delete the statistics box for a histogram `TH1* h` with:
657
658 h->SetStats(0)
659
660and activate it again with:
661
662 h->SetStats(1).
663
664Labels used in the statistics box ("Mean", "Std Dev", ...) can be changed from
665`$ROOTSYS/etc/system.rootrc` or `.rootrc` (look for the string `Hist.Stats.`).
666
667
668\anchor HP08
669### Fit Statistics
670
671
672The type of information about fit parameters printed in the histogram statistics
673box can be selected via the parameter mode. The parameter mode can be
674`= pcev` (default `= 0111`)
675
676 p = 1; print Probability
677 c = 1; print Chisquare/Number of degrees of freedom
678 e = 1; print errors (if e=1, v must be 1)
679 v = 1; print name/values of parameters
680
681Example:
682
683 gStyle->SetOptFit(1011);
684
685print fit probability, parameter names/values and errors.
686
6871. When `v = 1` is specified, only the non-fixed parameters are shown.
6882. When `v = 2` all parameters are shown.
689
690Note: `gStyle->SetOptFit(1)` means "default value", so it is equivalent
691to `gStyle->SetOptFit(111)`
692
693
694\anchor HP09
695### The error bars options
696
697
698| Option | Description |
699|----------|-------------------------------------------------------------------|
700| "E" | Default. Shows only the error bars, not a marker.|
701| "E1" | Small lines are drawn at the end of the error bars.|
702| "E2" | Error rectangles are drawn.|
703| "E3" | A filled area is drawn through the end points of the vertical error bars.|
704| "E4" | A smoothed filled area is drawn through the end points of the vertical error bars.|
705| "E0" | Draw error bars. Markers are drawn for bins with 0 contents. Combined with E1 or E2 it avoids error bars clipping|
706| "E5" | Like E3 but ignore the bins with 0 contents.|
707| "E6" | Like E4 but ignore the bins with 0 contents.|
708| "X0" | When used with one of the "E" option, it suppress the error bar along X as `gStyle->SetErrorX(0)` would do.|
709
710Begin_Macro(source)
711{
712 auto c1 = new TCanvas("c1","c1",600,400);
713 auto he = new TH1F("he","Distribution drawn with error bars (option E1) ",100,-3,3);
714 for (int i=0; i<10000; i++) he->Fill(gRandom->Gaus(0,1));
715 gStyle->SetEndErrorSize(3);
716 gStyle->SetErrorX(1.);
717 he->SetMarkerStyle(20);
718 he->Draw("E1");
719}
720End_Macro
721
722The options "E3" and "E4" draw an error band through the end points of the
723vertical error bars. With "E4" the error band is smoothed. Because of the
724smoothing algorithm used some artefacts may appear at the end of the band
725like in the following example. In such cases "E3" should be used instead
726of "E4".
727
728Begin_Macro(source)
729{
730 auto ce4 = new TCanvas("ce4","ce4",600,400);
731 ce4->Divide(2,1);
732 auto he4 = new TH1F("he4","Distribution drawn with option E4",100,-3,3);
733 Int_t i;
734 for (i=0;i<10000;i++) he4->Fill(gRandom->Gaus(0,1));
735 he4->SetFillColor(kRed);
736 he4->GetXaxis()->SetRange(40,48);
737 ce4->cd(1);
738 he4->Draw("E4");
739 ce4->cd(2);
740 auto he3 = (TH1F*)he4->DrawClone("E3");
741 he3->SetTitle("Distribution drawn option E3");
742}
743End_Macro
744
7452D histograms can be drawn with error bars as shown is the following example:
746
747Begin_Macro(source)
748{
749 auto c2e = new TCanvas("c2e","c2e",600,400);
750 auto h2e = new TH2F("h2e","TH2 drawn with option E",40,-4,4,40,-20,20);
751 float px, py;
752 for (Int_t i = 0; i < 25000; i++) {
753 gRandom->Rannor(px,py);
754 h2e->Fill(px,5*py);
755 }
756 h2e->Draw("E");
757}
758End_Macro
759
760
761\anchor HP100
762### The bar chart option
763
764
765The option "B" allows to draw simple vertical bar charts.
766The bar width is controlled with `TH1::SetBarWidth()`,
767and the bar offset within the bin, with `TH1::SetBarOffset()`.
768These two settings are useful to draw several histograms on the
769same plot as shown in the following example:
770
771Begin_Macro(source)
772{
773 int i;
774 const Int_t nx = 8;
775 string os_X[nx] = {"8","32","128","512","2048","8192","32768","131072"};
776 float d_35_0[nx] = {0.75, -3.30, -0.92, 0.10, 0.08, -1.69, -1.29, -2.37};
777 float d_35_1[nx] = {1.01, -3.02, -0.65, 0.37, 0.34, -1.42, -1.02, -2.10};
778
779 auto cb = new TCanvas("cb","cb",600,400);
780 cb->SetGrid();
781
782 gStyle->SetHistMinimumZero();
783
784 auto h1b = new TH1F("h1b","Option B example",nx,0,nx);
785 h1b->SetFillColor(4);
786 h1b->SetBarWidth(0.4);
787 h1b->SetBarOffset(0.1);
788 h1b->SetStats(0);
789 h1b->SetMinimum(-5);
790 h1b->SetMaximum(5);
791
792 for (i=1; i<=nx; i++) {
793 h1b->SetBinContent(i, d_35_0[i-1]);
794 h1b->GetXaxis()->SetBinLabel(i,os_X[i-1].c_str());
795 }
796
797 h1b->Draw("b");
798
799 auto h2b = new TH1F("h2b","h2b",nx,0,nx);
800 h2b->SetFillColor(38);
801 h2b->SetBarWidth(0.4);
802 h2b->SetBarOffset(0.5);
803 h2b->SetStats(0);
804 for (i=1;i<=nx;i++) h2b->SetBinContent(i, d_35_1[i-1]);
805
806 h2b->Draw("b same");
807}
808End_Macro
809
810
811\anchor HP10
812### The "BAR" and "HBAR" options
813
814
815When the option `bar` or `hbar` is specified, a bar chart is drawn. A vertical
816bar-chart is drawn with the options `bar`, `bar0`, `bar1`, `bar2`, `bar3`, `bar4`.
817An horizontal bar-chart is drawn with the options `hbar`, `hbar0`, `hbar1`,
818`hbar2`, `hbar3`, `hbar4` (hist006_TH1_bar_charts.C).
819
820- The bar is filled with the histogram fill color.
821- The left side of the bar is drawn with a light fill color.
822- The right side of the bar is drawn with a dark fill color.
823- The percentage of the bar drawn with either the light or dark color is:
824 - 0% for option "(h)bar" or "(h)bar0"
825 - 10% for option "(h)bar1"
826 - 20% for option "(h)bar2"
827 - 30% for option "(h)bar3"
828 - 40% for option "(h)bar4"
829
830When an histogram has errors the option ["HIST"](\ref OPTHIST) together with the `(h)bar` option.
831
832Begin_Macro(source)
833../../../tutorials/hist/hist006_TH1_bar_charts.C
834End_Macro
835
836To control the bar width (default is the bin width) `TH1::SetBarWidth()`
837should be used.
838
839To control the bar offset (default is 0) `TH1::SetBarOffset()` should
840be used.
841
842These two parameters are useful when several histograms are plotted using
843the option `SAME`. They allow to plot the histograms next to each other.
844
845
846\anchor HP11
847### The SCATter plot option (legacy draw option)
848
849\attention
850Use of option `SCAT` has been deprecated. It was the default drawing option for 2D and
8513D histograms. The new default option is `COL` (heat-map).
852
853
854For each cell (i,j) a number of points proportional to the cell content is
855drawn. A maximum of `kNMAX` points per cell is drawn. If the maximum is above
856`kNMAX` contents are normalized to `kNMAX` (`kNMAX=2000`).
857If option is of the form `scat=ff`, (eg `scat=1.8`,
858`scat=1e-3`), then `ff` is used as a scale factor to compute the
859number of dots. `scat=1` is the default.
860
861By default the scatter plot is painted with a "dot marker" which not scalable
862(see the `TAttMarker` documentation). To change the marker size, a scalable marker
863type should be used. For instance a circle (marker style 20).
864
865Begin_Macro(source)
866{
867 auto c1 = new TCanvas("c1","c1",600,400);
868 auto hscat = new TH2F("hscat","Option SCATter example (default for 2D histograms) ",40,-4,4,40,-20,20);
869 float px, py;
870 for (Int_t i = 0; i < 25000; i++) {
871 gRandom->Rannor(px,py);
872 hscat->Fill(px,5*py);
873 hscat->Fill(3+0.5*px,2*py-10.);
874 }
875 hscat->Draw("scat=0.5"); // This a legacy draw option. Please consider using TScatter
876}
877End_Macro
878
879
880\anchor HP12
881### The ARRow option
882
883
884Shows gradient between adjacent cells. For each cell (i,j) an arrow is drawn
885The orientation of the arrow follows the cell gradient.
886
887Begin_Macro(source)
888{
889 auto c1 = new TCanvas("c1","c1",600,400);
890 auto harr = new TH2F("harr","Option ARRow example",20,-4,4,20,-20,20);
891 harr->SetLineColor(kRed);
892 float px, py;
893 for (Int_t i = 0; i < 25000; i++) {
894 gRandom->Rannor(px,py);
895 harr->Fill(px,5*py);
896 harr->Fill(3+0.5*px,2*py-10.,0.1);
897 }
898 harr->Draw("ARR");
899}
900End_Macro
901
902\since **ROOT version 6.17/01**
903
904The option `ARR` can be combined with the option `COL` or `COLZ`.
905
906Begin_Macro(source)
907{
908 auto c1 = new TCanvas("c1","c1",600,400);
909 auto harr = new TH2F("harr","Option ARR + COLZ example",20,-4,4,20,-20,20);
910 harr->SetStats(0);
911 float px, py;
912 for (Int_t i = 0; i < 25000; i++) {
913 gRandom->Rannor(px,py);
914 harr->Fill(px,5*py);
915 harr->Fill(3+0.5*px,2*py-10.,0.1);
916 }
917 harr->Draw("ARR COLZ");
918}
919End_Macro
920
921
922\anchor HP13
923### The BOX option
924
925
926For each cell (i,j) a box is drawn. The size (surface) of the box is
927proportional to the absolute value of the cell content.
928The cells with a negative content are drawn with a `X` on top of the box.
929
930Begin_Macro(source)
931{
932 auto c1 = new TCanvas("c1","c1",600,400);
933 auto hbox = new TH2F("hbox","Option BOX example",3,0,3,3,0,3);
934 hbox->SetFillColor(42);
935 hbox->Fill(0.5, 0.5, 1.);
936 hbox->Fill(0.5, 1.5, 4.);
937 hbox->Fill(0.5, 2.5, 3.);
938 hbox->Fill(1.5, 0.5, 2.);
939 hbox->Fill(1.5, 1.5, 12.);
940 hbox->Fill(1.5, 2.5, -6.);
941 hbox->Fill(2.5, 0.5, -4.);
942 hbox->Fill(2.5, 1.5, 6.);
943 hbox->Fill(2.5, 2.5, 0.5);
944 hbox->Draw("BOX");
945}
946End_Macro
947
948With option `BOX1` a button is drawn for each cell with surface
949proportional to content's absolute value. A sunken button is drawn for
950negative values a raised one for positive.
951
952Begin_Macro(source)
953{
954 auto c1 = new TCanvas("c1","c1",600,400);
955 auto hbox1 = new TH2F("hbox1","Option BOX1 example",3,0,3,3,0,3);
956 hbox1->SetFillColor(42);
957 hbox1->Fill(0.5, 0.5, 1.);
958 hbox1->Fill(0.5, 1.5, 4.);
959 hbox1->Fill(0.5, 2.5, 3.);
960 hbox1->Fill(1.5, 0.5, 2.);
961 hbox1->Fill(1.5, 1.5, 12.);
962 hbox1->Fill(1.5, 2.5, -6.);
963 hbox1->Fill(2.5, 0.5, -4.);
964 hbox1->Fill(2.5, 1.5, 6.);
965 hbox1->Fill(2.5, 2.5, 0.5);
966 hbox1->Draw("BOX1");
967}
968End_Macro
969
970When the option `SAME` (or "SAMES") is used with the option `BOX`,
971the boxes' sizes are computed taking the previous plots into account. The range
972along the Z axis is imposed by the first plot (the one without option
973`SAME`); therefore the order in which the plots are done is relevant.
974
975Begin_Macro(source)
976{
977 auto c1 = new TCanvas("c1","c1",600,400);
978 auto hb1 = new TH2F("hb1","Example of BOX plots with option SAME ",40,-3,3,40,-3,3);
979 auto hb2 = new TH2F("hb2","hb2",40,-3,3,40,-3,3);
980 auto hb3 = new TH2F("hb3","hb3",40,-3,3,40,-3,3);
981 auto hb4 = new TH2F("hb4","hb4",40,-3,3,40,-3,3);
982 for (Int_t i=0;i<1000;i++) {
983 double x,y;
984 gRandom->Rannor(x,y);
985 if (x>0 && y>0) hb1->Fill(x,y,4);
986 if (x<0 && y<0) hb2->Fill(x,y,3);
987 if (x>0 && y<0) hb3->Fill(x,y,2);
988 if (x<0 && y>0) hb4->Fill(x,y,1);
989 }
990 hb1->SetFillColor(1);
991 hb2->SetFillColor(2);
992 hb3->SetFillColor(3);
993 hb4->SetFillColor(4);
994 hb1->Draw("box");
995 hb2->Draw("box same");
996 hb3->Draw("box same");
997 hb4->Draw("box same");
998}
999End_Macro
1000
1001\since **ROOT version 6.17/01:**
1002
1003Sometimes the change of the range of the Z axis is unwanted, in which case, one
1004can use `SAME0` (or `SAMES0`) option to opt out of this change.
1005
1006Begin_Macro(source)
1007{
1008 auto h2 = new TH2F("h2"," ",10,0,10,10,20,30);
1009 auto hf = (TH2F*)h2->Clone("hf");
1010 h2->SetBit(TH1::kNoStats);
1011 hf->SetBit(TH1::kNoStats);
1012 h2->Fill(5,22);
1013 h2->Fill(5,23);
1014 h2->Fill(6,22);
1015 h2->Fill(6,23);
1016 hf->Fill(6,23);
1017 hf->Fill(6,23);
1018 hf->Fill(6,23);
1019 hf->Fill(6,23);
1020 hf->Fill(5,23);
1021
1022 auto hf_copy1 = hf->Clone("hf_copy1");
1023 TLatex lt;
1024
1025 auto cx = new TCanvas(); cx->Divide(2,1);
1026
1027 cx->cd(1);
1028 h2->Draw("box");
1029 hf->Draw("text colz same");
1030 lt.DrawLatexNDC(0.3,0.5,"SAME");
1031
1032 cx->cd(2);
1033 h2->Draw("box");
1034 hf_copy1->Draw("text colz same0");
1035 lt.DrawLatexNDC(0.3,0.5,"SAME0");
1036}
1037End_Macro
1038
1039
1040\anchor HP14
1041### The COLor option (default for 2D histograms)
1042
1043The magnitude of individual cell (i,j) is represented as a color picked in the current color palette.
1044This data visualization technique is often called a heat map (or heat-map).
1045
1046The color table used is defined in the current style.
1047
1048If the histogram's minimum and maximum are the same (flat histogram), the
1049mapping on colors is not possible, therefore nothing is painted. To paint a
1050flat histogram it is enough to set the histogram minimum
1051(`TH1::SetMinimum()`) different from the bins' content.
1052
1053The default number of color levels used to paint the cells is 20.
1054It can be changed with `TH1::SetContour()` or
1055`TStyle::SetNumberContours()`. The higher this number is, the smoother
1056is the color change between cells.
1057
1058The color palette in TStyle can be modified via `gStyle->SetPalette()`.
1059
1060All the non-empty bins are painted. Empty bins (bins with content and error equal to 0) are
1061not painted unless some bins have a negative content because in that case the null bins
1062might be not empty.
1063
1064`TProfile2D` histograms are handled differently because, for this type of 2D
1065histograms, it is possible to know if an empty bin has been filled or not. So even
1066if all the bins' contents are positive some empty bins might be painted. And vice versa,
1067if some bins have a negative content some empty bins might be not painted.
1068
1069Combined with the option `COL`, the option `Z` allows to
1070display the color palette defined by `gStyle->SetPalette()`.
1071
1072In the following example, the histogram has only positive bins; the empty
1073bins (containing 0) are not drawn.
1074
1075Begin_Macro(source)
1076{
1077 auto c1 = new TCanvas("c1","c1",600,400);
1078 auto hcol1 = new TH2F("hcol1","Option COLor example ",40,-4,4,40,-20,20);
1079 float px, py;
1080 for (Int_t i = 0; i < 25000; i++) {
1081 gRandom->Rannor(px,py);
1082 hcol1->Fill(px,5*py);
1083 }
1084 hcol1->Draw("COLZ");
1085}
1086End_Macro
1087
1088In the first plot of following example, the histogram has some negative bins;
1089the empty bins (containing 0) are drawn. In some cases one wants to not draw
1090empty bins (containing 0) of histograms having a negative minimum. The option
1091`1`, used to produce the second plot in the following picture, allows to do that.
1092
1093Begin_Macro(source)
1094{
1095 auto c1 = new TCanvas("c1","c1",600,600);
1096 c1->Divide(1,2);
1097 auto hcol23 = new TH2F("hcol23","Option COLZ example ",40,-4,4,40,-20,20);
1098 auto hcol24 = new TH2F("hcol24","Option COLZ1 example ",40,-4,4,40,-20,20);
1099 float px, py;
1100 for (Int_t i = 0; i < 25000; i++) {
1101 gRandom->Rannor(px,py);
1102 hcol23->Fill(px,5*py);
1103 hcol24->Fill(px,5*py);
1104 }
1105 hcol23->Fill(0.,0.,-200.);
1106 hcol24->Fill(0.,0.,-200.);
1107 c1->cd(1); hcol23->Draw("COLZ");
1108 c1->cd(2); hcol24->Draw("COLZ1");
1109}
1110End_Macro
1111
1112When the maximum of the histogram is set to a smaller value than the real maximum,
1113 the bins having a content between the new maximum and the real maximum are
1114painted with the color corresponding to the new maximum.
1115
1116When the minimum of the histogram is set to a greater value than the real minimum,
1117 the bins having a value between the real minimum and the new minimum are not drawn
1118 unless the option `0` is set.
1119In other words, option `COLZ0` forces the painting of bins with content < set minimum with
1120 a color corresponding to the set minimum. In contrast, option `COLZ` would not draw values
1121 smaller than the specified minimum. Note that both `COLZ` and `COLZ0` still do not draw
1122 empty bins, ie bins with `content == error == 0`, if the set min is not negative.
1123(Note that option `COLZ0` for TH2Poly has a different behavior than for TH2.)
1124
1125The following example illustrates the option `0` combined with the option `COL`.
1126
1127Begin_Macro(source)
1128{
1129 auto c1 = new TCanvas("c1","c1",600,600);
1130 c1->Divide(1,2);
1131 auto hcol21 = new TH2F("hcol21","Option COLZ",40,-4,4,40,-20,20);
1132 auto hcol22 = new TH2F("hcol22","Option COLZ0",40,-4,4,40,-20,20);
1133 float px, py;
1134 for (Int_t i = 0; i < 25000; i++) {
1135 gRandom->Rannor(px,py);
1136 hcol21->Fill(px,5*py);
1137 hcol22->Fill(px,5*py);
1138 }
1139 hcol21->SetBit(TH1::kNoStats);
1140 hcol22->SetBit(TH1::kNoStats);
1141 c1->cd(1); hcol21->Draw("COLZ");
1142 c1->cd(2); hcol22->Draw("COLZ0");
1143 hcol21->SetMaximum(100);
1144 hcol21->SetMinimum(40);
1145 hcol22->SetMaximum(100);
1146 hcol22->SetMinimum(40);
1147}
1148End_Macro
1149
1150Note that the behavior of `COLZ` is not symmetric: it does not draw values below the specified minimum,
1151but does draw values above the specified maximum by clipping them to the maximum color. In contrast, `COLZ0`
1152clips color on both lower and upper sides. Both `COLZ0` and `COLZ` exclude drawing empty bins (`content == error == 0`),
1153if the set minimum is not negative.
1154
1155\since **ROOT version 6.09/01:**
1156
1157When the option SAME (or "SAMES") is used with the option COL, the boxes' color
1158are computed taking the previous plots into account. The range along the Z axis
1159is imposed by the first plot (the one without option SAME); therefore the order
1160in which the plots are done is relevant. Same as [in the `BOX` option](\ref HP13), one can use
1161`SAME0` (or `SAMES0`) to opt out of this imposition.
1162
1163Begin_Macro(source)
1164{
1165 auto c = new TCanvas("c","Example of col plots with option SAME",200,10,700,500);
1166 auto h1 = new TH2F("h1","h1",40,-3,3,40,-3,3);
1167 auto h2 = new TH2F("h2","h2",40,-3,3,40,-3,3);
1168 auto h3 = new TH2F("h3","h3",40,-3,3,40,-3,3);
1169 auto h4 = new TH2F("h4","h4",40,-3,3,40,-3,3);
1170 h1->SetBit(TH1::kNoStats);
1171 for (Int_t i=0;i<5000;i++) {
1172 double x,y;
1173 gRandom->Rannor(x,y);
1174 if(x>0 && y>0) h1->Fill(x,y,4);
1175 if(x<0 && y<0) h2->Fill(x,y,3);
1176 if(x>0 && y<0) h3->Fill(x,y,2);
1177 if(x<0 && y>0) h4->Fill(x,y,1);
1178 }
1179 h1->Draw("colz");
1180 h2->Draw("col same");
1181 h3->Draw("col same");
1182 h4->Draw("col same");
1183}
1184End_Macro
1185
1186The option `COL` can be combined with the option `POL`:
1187
1188Begin_Macro(source)
1189{
1190 auto c1 = new TCanvas("c1","c1",600,400);
1191 auto hcol1 = new TH2F("hcol1","Option COLor combined with POL",40,-4,4,40,-4,4);
1192 float px, py;
1193 for (Int_t i = 0; i < 25000; i++) {
1194 gRandom->Rannor(px,py);
1195 hcol1->Fill(px,py);
1196 }
1197 hcol1->Draw("COLZPOL");
1198}
1199End_Macro
1200
1201\since **ROOT version 6.07/03:**
1202
1203A second rendering technique is also available with the COL2 and COLZ2 options.
1204
1205These options provide potential performance improvements compared to the standard
1206COL option. The performance comparison of the COL2 to the COL option depends on
1207the histogram and the size of the rendering region in the current pad. In general,
1208a small (approx. less than 100 bins per axis), sparsely populated TH2 will render
1209faster with the COL option.
1210
1211However, for larger histograms (approx. more than 100 bins per axis)
1212that are not sparse, the COL2 option will provide up to 20 times performance improvements.
1213For example, a 1000x1000 bin TH2 that is not sparse will render an order of magnitude
1214faster with the COL2 option.
1215
1216The COL2 option will also scale its performance based on the size of the
1217pixmap the histogram image is being rendered into. It also is much better optimized for
1218sessions where the user is forwarding X11 windows through an `ssh` connection.
1219
1220For the most part, the COL2 and COLZ2 options are a drop in replacement to the COL
1221and COLZ options. There is one major difference and that concerns the treatment of
1222bins with zero content. The COL2 and COLZ2 options color these bins the color of zero.
1223
1224COL2 option renders the histogram as a bitmap. Therefore it cannot be saved in vector
1225graphics file format like PostScript or PDF (an empty image will be generated). It can
1226be saved only in bitmap files like PNG format for instance.
1227
1228
1229\anchor HP140
1230### The CANDLE and VIOLIN options
1231
1232The mechanism behind Candle plots and Violin plots is very similar. Because of this they are
1233implemented in the same class TCandle. The keywords CANDLE or VIOLIN will initiate the drawing of
1234the corresponding plots. Followed by the keyword the user can select a plot direction (X or V for
1235vertical projections, or Y or H for horizontal projections) and/or predefined definitions
1236(1-6 for candles, 1-2 for violins). The order doesn't matter. Default is X and 1.
1237
1238Instead of using the predefined representations, the candle and violin parameters can be
1239changed individually. In that case the option have the following form:
1240
1241 CANDLEX(<option-string>)
1242 CANDLEY(<option-string>)
1243 VIOLINX(<option-string>)
1244 VIOLINY(<option-string>).
1245
1246All zeros at the beginning of `option-string` can be omitted.
1247
1248`option-string` consists eight values, defined as follow:
1249
1250 "CANDLEX(zhpawMmb)"
1251
1252Where:
1253
1254 - `b = 0`; no box drawn
1255 - `b = 1`; the box is drawn. As the candle-plot is also called a box-plot it
1256 makes sense in the very most cases to always draw the box
1257 - `b = 2`; draw a filled box with border
1258
1259 - `m = 0`; no median drawn
1260 - `m = 1`; median is drawn as a line
1261 - `m = 2`; median is drawn with errors (notches)
1262 - `m = 3`; median is drawn as a circle
1263
1264 - `M = 0`; no mean drawn
1265 - `M = 1`; mean is drawn as a dashed line
1266 - `M = 3`; mean is drawn as a circle
1267
1268 - `w = 0`; no whisker drawn
1269 - `w = 1`; whisker is drawn to end of distribution.
1270 - `w = 2`; whisker is drawn to max 1.5*iqr
1271
1272 - `a = 0`; no anchor drawn
1273 - `a = 1`; the anchors are drawn
1274
1275 - `p = 0`; no points drawn
1276 - `p = 1`; only outliers are drawn
1277 - `p = 2`; all datapoints are drawn
1278 - `p = 3`: all datapoints are drawn scattered
1279
1280 - `h = 0`; no histogram is drawn
1281 - `h = 1`; histogram at the left or bottom side is drawn
1282 - `h = 2`; histogram at the right or top side is drawn
1283 - `h = 3`; histogram at left and right or top and bottom (violin-style) is drawn
1284
1285 - `z = 0`; no zero indicator line is drawn
1286 - `z = 1`; zero indicator line is drawn.
1287
1288As one can see all individual options for both candle and violin plots can be accessed by this
1289mechanism. In deed the keywords CANDLE(<option-string>) and VIOLIN(<option-string>) have the same
1290meaning. So you can parametrise an option-string for a candle plot and use the keywords VIOLIN and
1291vice versa, if you wish.
1292
1293Using a logarithmic x- or y-axis is possible for candle and violin charts.
1294
1295\since **ROOT version 6.11/01**
1296
1297a logarithmic z-axis is possible, too but will only affect violin charts of course.
1298
1299\anchor HP140a
1300#### The CANDLE option
1301
1302<a href="http://en.wikipedia.org/wiki/Box_plot">A Candle plot</a> (also known as
1303a "box plot" or "whisker plot") was invented in 1977 by John Tukey. It is a convenient
1304way to describe graphically a data distribution (D) with only five numbers:
1305
1306 1. The minimum value of the distribution D (bottom or left whisker).
1307 2. The lower quartile (Q1): 25% of the data points in D are less than Q1 (bottom of the box).
1308 3. The median (M): 50% of the data points in D are less than M.
1309 4. The upper quartile (Q3): 75% of the data points in D are less than Q3 (top of the box).
1310 5. The maximum value of the distribution D (top or right whisker).
1311
1312In this implementation a TH2 is considered as a collection of TH1 along
1313X (option `CANDLE` or `CANDLEX`) or Y (option `CANDLEY`).
1314Each TH1 is represented as one candle.
1315
1316Begin_Macro(source)
1317../../../tutorials/hist/hist052_Graphics_candle_plot_whiskers.C
1318End_Macro
1319
1320The candle reduces the information coming from a whole distribution into few values.
1321Independently from the number of entries or the significance of the underlying distribution
1322a candle will always look like a candle. So candle plots should be used carefully in
1323particular with unknown distributions. The definition of a candle is based on
1324__unbinned data__. Here, candles are created from binned data. Because of this, the
1325deviation is connected to the bin width used. The calculation of the quantiles
1326normally done on unbinned data also. Because data are binned, this will
1327only work the best possible way within the resolution of one bin
1328
1329Because of all these facts one should take care that:
1330
1331 - there are enough points per candle
1332 - the bin width is small enough (more bins will increase the maximum
1333 available resolution of the quantiles although there will be some
1334 bins with no entries)
1335 - never make a candle-plot if the underlying distribution is double-distributed
1336 - only create candles of distributions that are more-or-less gaussian (the
1337 MPV should be not too far away from the mean).
1338
1339#### What a candle is made of
1340
1341\since **ROOT version 6.07/05**
1342
1343##### The box
1344The box displays the position of the inter-quantile-range of the underlying
1345distribution. The box contains 25% of the distribution below the median
1346and 25% of the distribution above the median. If the underlying distribution is large
1347enough and gaussian shaped the end-points of the box represent \f$ 0.6745\times\sigma \f$
1348(Where \f$ \sigma \f$ is the standard deviation of the gaussian). The width and
1349the position of the box can be modified by SetBarWidth() and SetBarOffset().
1350The +-25% quantiles are calculated by the GetQuantiles() methods.
1351
1352\since **ROOT version 6.11/01**
1353
1354Using the static function TCandle::SetBoxRange(double) the box definition will be
1355overwritten. E.g. using a box range of 0.68 will redefine the area of the lower box edge
1356to the upper box edge in order to cover 68% of the distribution illustrated by that candle.
1357The static function will affect all candle-charts in the running program.
1358Default is 0.5.
1359
1360Using the static function TCandle::SetScaledCandle(bool) the width of the box (and the
1361whole candle) can be influenced. Deactivated, the width is constant (to be set by
1362SetBarWidth() ). Activated, the width of the boxes will be scaled to each other based on the
1363amount of data in the corresponding candle, the maximum width can be influenced by
1364SetBarWidth(). The static function will affect all candle-charts in the running program.
1365Default is false. Scaling between multiple candle-charts (using "same" or THStack) is not
1366supported, yet
1367
1368##### The Median
1369For a sorted list of numbers, the median is the value in the middle of the list.
1370E.g. if a sorted list is made of five numbers "1,2,3,6,7" 3 will be the median
1371because it is in the middle of the list. If the number of entries is even the
1372average of the two values in the middle will be used. As histograms are binned
1373data, the situation is a bit more complex. The following example shows this:
1374
1375~~~ {.cpp}
1376void quantiles() {
1377 auto h = new TH1I("h","h",10,0,10);
1378 //h->Fill(3);
1379 //h->Fill(3);
1380 h->Fill(4);
1381 h->Draw();
1382 double p = 0.;
1383 double q = 0.;
1384 h->GetQuantiles(1,&q,&p);
1385
1386 cout << "Median is: " << q << std::endl;
1387}
1388~~~
1389
1390Here the bin-width is 1.0. If the two Fill(3) are commented out, as there are currently,
1391the example will return a calculated median of 4.5, because that's the bin center
1392of the bin in which the value 4.0 has been dropped. If the two Fill(3) are not
1393commented out, it will return 3.75, because the algorithm tries to evenly distribute
1394the individual values of a bin with bin content > 0. It means the sorted list
1395would be "3.25, 3.75, 4.5".
1396
1397The consequence is a median of 3.75. This shows how important it is to use a
1398small enough bin-width when using candle-plots on binned data.
1399If the distribution is large enough and gaussian shaped the median will be exactly
1400equal to the mean.
1401The median can be shown as a line or as a circle or not shown at all.
1402
1403In order to show the significance of the median notched candle plots apply a "notch" or
1404narrowing of the box around the median. The significance is defined by
1405\f$ 1.57\times\frac{iqr}{N} \f$ and will be represented as the size of the notch
1406(where iqr is the size of the box and N is the number of entries of the whole
1407distribution). Candle plots like these are usually called "notched candle plots".
1408
1409In case the significance of the median is greater that the size of the box, the
1410box will have an unnatural shape. Usually it means the chart has not enough data,
1411or that representing this uncertainty is not useful
1412
1413##### The Mean
1414The mean can be drawn as a dashed line or as a circle or not drawn at all.
1415The mean is the arithmetic average of the values in the distribution.
1416It is calculated using GetMean(). Because histograms are
1417binned data, the mean value can differ from a calculation on the raw-data.
1418If the distribution is large enough and gaussian shaped the mean will be
1419exactly the median.
1420
1421##### The Whiskers
1422The whiskers represent the part of the distribution not covered by the box.
1423The upper 25% and the lower 25% of the distribution are located within the whiskers.
1424Two representations are available.
1425
1426 - A simple one (using w=1) defining the lower whisker from the lowest data value
1427 to the bottom of the box, and the upper whisker from the top of the box to the
1428 highest data value. In this representation the whisker-lines are dashed.
1429 - A more complex one having a further restriction. The whiskers are still connected
1430 to the box but their length cannot exceed \f$ 1.5\times iqr \f$. So it might
1431 be that the outermost part of the underlying distribution will not be covered
1432 by the whiskers. Usually these missing parts will be represented by the outliers
1433 (see points). Of course the upper and the lower whisker may differ in length.
1434 In this representation the whiskers are drawn as solid lines.
1435
1436\since **ROOT version 6.11/01**
1437
1438Using the static function TCandle::SetWhiskerRange(double) the whisker definition w=1
1439will be overwritten. E.g. using a whisker-range of 0.95 and w=1 will redefine the area of
1440the lower whisker to the upper whisker in order to cover 95% of the distribution inside
1441that candle. The static function will affect all candle-charts in the running program.
1442Default is 1.
1443
1444If the distribution is large enough and gaussian shaped, the maximum length of
1445the whisker will be located at \f$ \pm 2.698 \sigma \f$ (when using the
14461.5*iqr-definition (w=2), where \f$ \sigma \f$ is the standard deviation
1447(see picture above). In that case 99.3% of the total distribution will be covered
1448by the box and the whiskers, whereas 0.7% are represented by the outliers.
1449
1450##### The Anchors
1451The anchors have no special meaning in terms of statistical calculation. They mark
1452the end of the whiskers and they have the width of the box. Both representation
1453with and without anchors are common.
1454
1455##### The Points
1456Depending on the configuration the points can have different meanings:
1457 - If p=1 the points represent the outliers. If they are shown, it means
1458 some parts of the underlying distribution are not covered by the whiskers.
1459 This can only occur when the whiskers are set to option w=2. Here the whiskers
1460 can have a maximum length of \f$ 1.5 \times iqr \f$. So any points outside the
1461 whiskers will be drawn as outliers. The outliers will be represented by crosses.
1462 - If p=2 all points in the distribution will be painted as crosses. This is
1463 useful for small datasets only (up to 10 or 20 points per candle).
1464 The outliers are shown along the candle. Because the underlying distribution
1465 is binned, is frequently occurs that a bin contains more than one value.
1466 Because of this the points will be randomly scattered within their bin along
1467 the candle axis. If the bin content for a bin is exactly 1 (usually
1468 this happens for the outliers) if will be drawn in the middle of the bin along
1469 the candle axis. As the maximum number of points per candle is limited by kNMax/2
1470 on very large datasets scaling will be performed automatically. In that case one
1471 would loose all outliers because they have usually a bin content of 1 (and a
1472 bin content between 0 and 1 after the scaling). Because of this all bin contents
1473 between 0 and 1 - after the scaling - will be forced to be 1.
1474 - As the drawing of all values on large datasets can lead to big amounts of crosses,
1475 one can show all values as a scatter plot instead by choosing p=3. The points will be
1476 drawn as dots and will be scattered within the width of the candle. The color
1477 of the points will be the color of the candle-chart.
1478
1479##### Other Options
1480Is is possible to combine all options of candle and violin plots with each other. E.g. a box-plot
1481with a histogram.
1482
1483#### How to use the candle-plots drawing option
1484
1485There are six predefined candle-plot representations:
1486
1487 - "CANDLEX1": Standard candle (whiskers cover the whole distribution)
1488 - "CANDLEX2": Standard candle with better whisker definition + outliers.
1489 It is a good compromise
1490 - "CANDLEX3": Like candle2 but with a mean as a circle.
1491 It is easier to distinguish mean and median
1492 - "CANDLEX4": Like candle3 but showing the uncertainty of the median as well
1493 (notched candle plots).
1494 For bigger datasets per candle
1495 - "CANDLEX5": Like candle2 but showing all data points.
1496 For very small datasets
1497 - "CANDLEX6": Like candle2 but showing all datapoints scattered.
1498 For huge datasets
1499
1500
1501The following picture shows how the six predefined representations look.
1502
1503Begin_Macro
1504{
1505 auto c1 = new TCanvas("c1","c1",700,800);
1506 c1->Divide(2,3);
1507 gStyle->SetOptStat(kFALSE);
1508
1509 auto hcandle = new TH2F("hcandle"," ",10,-4,4,40,-20,20);
1510 float px, py;
1511 for (Int_t i = 0; i < 15000; i++) {
1512 gRandom->Rannor(px,py);
1513 hcandle->Fill(px,5*py);
1514 }
1515 hcandle->SetMarkerSize(0.5);
1516
1517 TH2F *h2;
1518 for (Int_t i=1; i<7; i++) {
1519 c1->cd(i);
1520 h2 = (TH2F*)hcandle->DrawClone(Form("CANDLE%d",i));
1521 h2->SetTitle(Form("CANDLE%d",i));
1522 }
1523}
1524End_Macro
1525
1526
1527#### Example 1
1528Box and improved whisker, no mean, no median, no anchor no outliers
1529
1530 h1->Draw("CANDLEX(2001)");
1531
1532#### Example 2
1533A Candle-definition like "CANDLEX2" (New standard candle with better whisker definition + outliers)
1534
1535 h1->Draw("CANDLEX(112111)");
1536
1537#### Example 3
1538The following example shows how several candle plots can be super-imposed using
1539the option SAME. Note that the bar-width and bar-offset are active on candle plots.
1540Also the color, the line width, the size of the points and so on can be changed by the
1541standard attribute setting methods such as SetLineColor() SetLineWidth().
1542
1543Begin_Macro(source)
1544../../../tutorials/hist/hist049_Graphics_candle_plot.C
1545End_Macro
1546
1547\anchor HP140b
1548#### The VIOLIN option
1549
1550<a href="http://en.wikipedia.org/wiki/Violin_plot">A violin plot</a> is a candle plot
1551that also encodes the pdf information at each point.
1552
1553
1554Quartiles and mean are also represented at each point, with a marker
1555and two lines.
1556
1557In this implementation a TH2 is considered as a collection of TH1 along
1558X (option `VIOLIN` or `VIOLINX`) or Y (option `VIOLINY`).
1559
1560#### What a violin is made of
1561
1562\since **ROOT version 6.09/02**
1563
1564##### The histogram
1565The histogram is typically drawn to both directions with respect to the middle-line of the
1566corresponding bin. This can be achieved by using h=3. It is possible to draw a histogram only to
1567one side (h=1, or h=2).
1568The maximum number of bins in the histogram is limited to 500, if the number of bins in the used
1569histogram is higher it will be rebinned automatically. The maximum height of the histogram can
1570be modified by using SetBarWidth() and the position can be changed with SetBarOffset().
1571A solid fill style is recommended.
1572
1573\since **ROOT version 6.11/01**
1574
1575Using the static function TCandle::SetScaledViolin(bool) the height of the histogram or the
1576violin can be influenced. Activated, the height of the bins of the individual violins will be
1577scaled with respect to each other, the maximum height can be influenced by SetBarWidth().
1578Deactivated, the height of the bin with the maximum content of each individual violin is
1579set to a constant value using SetBarWidth(). The static function will affect all violin-charts
1580in the running program. Default is true. Scaling between multiple violin-charts
1581(using "same" or THStack) is not supported, yet.
1582
1583##### The zero indicator line
1584Typical for violin charts is a line in the background over the whole histogram indicating
1585the bins with zero entries. The zero indicator line can be activated with z=1. The line color
1586will always be the same as the fill-color of the histogram.
1587
1588##### The Mean
1589The Mean is illustrated with the same mechanism as used for candle plots. Usually a circle is used.
1590
1591##### Whiskers
1592The whiskers are illustrated by the same mechanism as used for candle plots. There is only one
1593difference. When using the simple whisker definition (w=1) and the zero indicator line (z=1), then
1594the whiskers will be forced to be solid (usually hashed)
1595
1596##### Points
1597The points are illustrated by the same mechanism as used for candle plots. E.g. VIOLIN2 uses
1598better whisker definition (w=2) and outliers (p=1).
1599
1600##### Other options
1601It is possible to combine all options of candle or violin plots with each other. E.g. a violin plot
1602including a box-plot.
1603
1604#### How to use the violin-plots drawing option
1605
1606There are two predefined violin-plot representations:
1607 - "VIOLINX1": Standard violin (histogram, mean, whisker over full distribution,
1608 zero indicator line)
1609 - "VIOLINX2": Line VIOLINX1 both with better whisker definition + outliers.
1610
1611A solid fill style is recommended for this plot (as opposed to a hollow or
1612hashed style).
1613
1614Begin_Macro(source)
1615{
1616 auto c1 = new TCanvas("c1","c1",600,400);
1617 Int_t nx(6), ny(40);
1618 double xmin(0.0), xmax(+6.0), ymin(0.0), ymax(+4.0);
1619 auto hviolin = new TH2F("hviolin", "Option VIOLIN example", nx, xmin, xmax, ny, ymin, ymax);
1620 TF1 f1("f1", "gaus", +0,0 +4.0);
1621 double x,y;
1622 for (Int_t iBin=1; iBin<hviolin->GetNbinsX(); ++iBin) {
1623 double xc = hviolin->GetXaxis()->GetBinCenter(iBin);
1624 f1.SetParameters(1, 2.0+TMath::Sin(1.0+xc), 0.2+0.1*(xc-xmin)/xmax);
1625 for(Int_t i=0; i<10000; ++i){
1626 x = xc;
1627 y = f1.GetRandom();
1628 hviolin->Fill(x, y);
1629 }
1630 }
1631 hviolin->SetFillColor(kGray);
1632 hviolin->SetMarkerStyle(20);
1633 hviolin->SetMarkerSize(0.5);
1634 hviolin->Draw("VIOLIN");
1635 c1->Update();
1636}
1637End_Macro
1638
1639The next example illustrates a time development of a certain value:
1640
1641Begin_Macro(source)
1642../../../tutorials/hist/hist047_Graphics_candle_decay.C
1643End_Macro
1644
1645
1646\anchor HP15
1647### The TEXT and TEXTnn Option
1648
1649
1650For each bin the content is printed. The text attributes are:
1651
1652- text font = current TStyle font (`gStyle->SetTextFont()`).
1653- text size = 0.02*padheight*markersize (if `h` is the histogram drawn
1654 with the option `TEXT` the marker size can be changed with
1655 `h->SetMarkerSize(markersize)`).
1656- text color = marker color.
1657
1658By default the format `g` is used. This format can be redefined
1659by calling `gStyle->SetPaintTextFormat()`.
1660
1661It is also possible to use `TEXTnn` in order to draw the text with
1662the angle `nn` (`0 < nn <= 90`).
1663
1664For 2D histograms the text is plotted in the center of each non empty cells.
1665It is possible to plot empty cells by calling `gStyle->SetHistMinimumZero()`
1666or providing MIN0 draw option. For 1D histogram the text is plotted at a y
1667position equal to the bin content.
1668
1669For 2D histograms when the option "E" (errors) is combined with the option
1670text ("TEXTE"), the error for each bin is also printed.
1671
1672Begin_Macro(source)
1673{
1674 auto c01 = new TCanvas("c01","c01",700,400);
1675 c01->Divide(2,1);
1676 auto htext1 = new TH1F("htext1","Option TEXT on 1D histograms ",10,-4,4);
1677 auto htext2 = new TH2F("htext2","Option TEXT on 2D histograms ",10,-4,4,10,-20,20);
1678 float px, py;
1679 for (Int_t i = 0; i < 25000; i++) {
1680 gRandom->Rannor(px,py);
1681 htext1->Fill(px,0.1);
1682 htext2->Fill(px,5*py,0.1);
1683 }
1684 gStyle->SetPaintTextFormat("4.1f m");
1685 htext2->SetMarkerSize(1.8);
1686 c01->cd(1);
1687 htext2->Draw("TEXT45");
1688 c01->cd(2);
1689 htext1->Draw();
1690 htext1->Draw("HIST TEXT0 SAME");
1691}
1692End_Macro
1693
1694\since **ROOT version 6.07/07:**
1695
1696In case several histograms are drawn on top ot each other (using option `SAME`),
1697the text can be shifted using `SetBarOffset()`. It specifies an offset for the
1698text position in each cell, in percentage of the bin width.
1699
1700Begin_Macro(source)
1701{
1702 auto c03 = new TCanvas("c03","c03",700,400);
1703 gStyle->SetOptStat(0);
1704 auto htext3 = new TH2F("htext3","Several 2D histograms drawn with option TEXT",10,-4,4,10,-20,20);
1705 auto htext4 = new TH2F("htext4","htext4",10,-4,4,10,-20,20);
1706 auto htext5 = new TH2F("htext5","htext5",10,-4,4,10,-20,20);
1707 float px, py;
1708 for (Int_t i = 0; i < 25000; i++) {
1709 gRandom->Rannor(px,py);
1710 htext3->Fill(4*px,20*py,0.1);
1711 htext4->Fill(4*px,20*py,0.5);
1712 htext5->Fill(4*px,20*py,1.0);
1713 }
1714 htext4->SetMarkerSize(1.8);
1715 htext5->SetMarkerSize(1.8);
1716 htext5->SetMarkerColor(kRed);
1717 htext4->SetBarOffset(0.2);
1718 htext5->SetBarOffset(-0.2);
1719 htext3->Draw("COL");
1720 htext4->Draw("TEXT SAME");
1721 htext5->Draw("TEXT SAME");
1722}
1723End_Macro
1724
1725In the case of profile histograms it is possible to print the number
1726of entries instead of the bin content. It is enough to combine the
1727option "E" (for entries) with the option "TEXT".
1728
1729Begin_Macro(source)
1730{
1731 auto c02 = new TCanvas("c02","c02",700,400);
1732 c02->Divide(2,1);
1733 gStyle->SetPaintTextFormat("g");
1734
1735 auto profile = new TProfile("profile","profile",10,0,10);
1736 profile->SetMarkerSize(2.2);
1737 profile->Fill(0.5,1);
1738 profile->Fill(1.5,2);
1739 profile->Fill(2.5,3);
1740 profile->Fill(3.5,4);
1741 profile->Fill(4.5,5);
1742 profile->Fill(5.5,5);
1743 profile->Fill(6.5,4);
1744 profile->Fill(7.5,3);
1745 profile->Fill(8.5,2);
1746 profile->Fill(9.5,1);
1747 c02->cd(1); profile->Draw("HIST TEXT0");
1748 c02->cd(2); profile->Draw("HIST TEXT0E");
1749}
1750End_Macro
1751
1752\anchor HP16
1753### The CONTour options
1754
1755
1756The following contour options are supported:
1757
1758| Option | Description |
1759|----------|-----------------------------------------------------------------------------|
1760| "CONT" | Draw a contour plot (same as CONT0). |
1761| "CONT0" | Draw a contour plot using surface colors to distinguish contours. |
1762| "CONT1" | Draw a contour plot using the line colors to distinguish contours. |
1763| "CONT2" | Draw a contour plot using the line styles (1 to 5) to distinguish contours. |
1764| "CONT3" | Draw a contour plot using the same line style for all contours. |
1765| "CONT4" | Draw a contour plot using surface colors (`SURF` option at theta = 0). |
1766
1767
1768The following example shows a 2D histogram plotted with the option
1769`CONTZ`. The option `CONT` draws a contour plot using surface
1770colors to distinguish contours. Combined with the option `CONT` (or
1771`CONT0`), the option `Z` allows to display the color palette
1772defined by `gStyle->SetPalette()`.
1773
1774Begin_Macro(source)
1775{
1776 auto c1 = new TCanvas("c1","c1",600,400);
1777 auto hcontz = new TH2F("hcontz","Option CONTZ example ",40,-4,4,40,-20,20);
1778 float px, py;
1779 for (Int_t i = 0; i < 25000; i++) {
1780 gRandom->Rannor(px,py);
1781 hcontz->Fill(px-1,5*py);
1782 hcontz->Fill(2+0.5*px,2*py-10.,0.1);
1783 }
1784 hcontz->Draw("CONTZ");
1785}
1786End_Macro
1787
1788The following example shows a 2D histogram plotted with the option
1789`CONT1Z`. The option `CONT1` draws a contour plot using the
1790line colors to distinguish contours. Combined with the option `CONT1`,
1791the option `Z` allows to display the color palette defined by
1792`gStyle->SetPalette()`.
1793
1794Begin_Macro(source)
1795{
1796 auto c1 = new TCanvas("c1","c1",600,400);
1797 auto hcont1 = new TH2F("hcont1","Option CONT1Z example ",40,-4,4,40,-20,20);
1798 float px, py;
1799 for (Int_t i = 0; i < 25000; i++) {
1800 gRandom->Rannor(px,py);
1801 hcont1->Fill(px-1,5*py);
1802 hcont1->Fill(2+0.5*px,2*py-10.,0.1);
1803 }
1804 hcont1->Draw("CONT1Z");
1805}
1806End_Macro
1807
1808The following example shows a 2D histogram plotted with the option
1809`CONT2`. The option `CONT2` draws a contour plot using the
1810line styles (1 to 5) to distinguish contours.
1811
1812Begin_Macro(source)
1813{
1814 auto c1 = new TCanvas("c1","c1",600,400);
1815 auto hcont2 = new TH2F("hcont2","Option CONT2 example ",40,-4,4,40,-20,20);
1816 float px, py;
1817 for (Int_t i = 0; i < 25000; i++) {
1818 gRandom->Rannor(px,py);
1819 hcont2->Fill(px-1,5*py);
1820 hcont2->Fill(2+0.5*px,2*py-10.,0.1);
1821 }
1822 hcont2->Draw("CONT2");
1823}
1824End_Macro
1825
1826The following example shows a 2D histogram plotted with the option
1827`CONT3`. The option `CONT3` draws contour plot using the same line style for
1828all contours.
1829
1830Begin_Macro(source)
1831{
1832 auto c1 = new TCanvas("c1","c1",600,400);
1833 auto hcont3 = new TH2F("hcont3","Option CONT3 example ",40,-4,4,40,-20,20);
1834 float px, py;
1835 for (Int_t i = 0; i < 25000; i++) {
1836 gRandom->Rannor(px,py);
1837 hcont3->Fill(px-1,5*py);
1838 hcont3->Fill(2+0.5*px,2*py-10.,0.1);
1839 }
1840 hcont3->SetLineStyle(kDotted);
1841 hcont3->Draw("CONT3");
1842}
1843End_Macro
1844
1845The following example shows a 2D histogram plotted with the option
1846`CONT4`. The option `CONT4` draws a contour plot using surface
1847colors to distinguish contours (`SURF` option at theta = 0). Combined
1848with the option `CONT` (or `CONT0`), the option `Z`
1849allows to display the color palette defined by `gStyle->SetPalette()`.
1850
1851Begin_Macro(source)
1852{
1853 auto c1 = new TCanvas("c1","c1",600,400);
1854 auto hcont4 = new TH2F("hcont4","Option CONT4Z example ",40,-4,4,40,-20,20);
1855 float px, py;
1856 for (Int_t i = 0; i < 25000; i++) {
1857 gRandom->Rannor(px,py);
1858 hcont4->Fill(px-1,5*py);
1859 hcont4->Fill(2+0.5*px,2*py-10.,0.1);
1860 }
1861 hcont4->Draw("CONT4Z");
1862}
1863End_Macro
1864
1865The default number of contour levels is 20 equidistant levels and can be changed
1866with `TH1::SetContour()` or `TStyle::SetNumberContours()`.
1867
1868\anchor HP16a
1869#### The LIST option
1870
1871When option `LIST` is specified together with option
1872`CONT`, the points used to draw the contours are saved in
1873`TGraph` objects:
1874
1875 h->Draw("CONT LIST");
1876 gPad->Update();
1877
1878The contour are saved in `TGraph` objects once the pad is painted.
1879Therefore to use this functionality in a macro, `gPad->Update()`
1880should be performed after the histogram drawing. Once the list is
1881built, the contours are accessible in the following way:
1882
1883 TObjArray *contours = (TObjArray*)gROOT->GetListOfSpecials()->FindObject("contours");
1884 Int_t ncontours = contours->GetSize();
1885 TList *list = (TList*)contours->At(i);
1886
1887Where `i` is a contour number, and list contains a list of
1888`TGraph` objects.
1889For one given contour, more than one disjoint polyline may be generated.
1890The number of TGraphs per contour is given by:
1891
1892 list->GetSize();
1893
1894To access the first graph in the list one should do:
1895
1896 TGraph *gr1 = (TGraph*)list->First();
1897
1898
1899The following example (hist102_TH2_contour_list.C) shows how to use this functionality.
1900
1901Begin_Macro(source)
1902../../../tutorials/hist/hist102_TH2_contour_list.C
1903End_Macro
1904
1905\anchor HP16b
1906#### The AITOFF, MERCATOR, SINUSOIDAL and PARABOLIC options
1907
1908The following options select the `CONT4` option and are useful for
1909sky maps or exposure maps (earth.C).
1910
1911| Option | Description |
1912|--------------|---------------------------------------------------------------|
1913| "AITOFF" | Draw a contour via an AITOFF projection.|
1914| "MERCATOR" | Draw a contour via an Mercator projection.|
1915| "SINUSOIDAL" | Draw a contour via an Sinusoidal projection.|
1916| "PARABOLIC" | Draw a contour via an Parabolic projection.|
1917
1918Begin_Macro(source)
1919../../../tutorials/visualisation/graphics/earth.C
1920End_Macro
1921
1922
1923\anchor HP17
1924### The LEGO options
1925
1926
1927In a lego plot the cell contents are drawn as 3-d boxes. The height of each box
1928is proportional to the cell content. The lego aspect is control with the
1929following options:
1930
1931| Option | Description |
1932|----------|-------------------------------------------------------------------|
1933| "LEGO" | Draw a lego plot using the hidden lines removal technique.|
1934| "LEGO1" | Draw a lego plot using the hidden surface removal technique.|
1935| "LEGO2" | Draw a lego plot using colors to show the cell contents.|
1936| "LEGO3" | Draw a lego plot with hidden surface removal, like LEGO1 but the border lines of each lego-bar are not drawn.|
1937| "LEGO4" | Draw a lego plot with hidden surface removal, like LEGO1 but without the shadow effect on each lego-bar.|
1938| "0" | When used with any LEGO option, the empty bins are not drawn.|
1939
1940
1941See the limitations with [the option "SAME"](\ref HP060a).
1942
1943Line attributes can be used in lego plots to change the edges' style.
1944
1945The following example shows a 2D histogram plotted with the option
1946`LEGO`. The option `LEGO` draws a lego plot using the hidden
1947lines removal technique.
1948
1949Begin_Macro(source)
1950{
1951 auto c2 = new TCanvas("c2","c2",600,400);
1952 auto hlego = new TH2F("hlego","Option LEGO example ",40,-4,4,40,-20,20);
1953 float px, py;
1954 for (Int_t i = 0; i < 25000; i++) {
1955 gRandom->Rannor(px,py);
1956 hlego->Fill(px-1,5*py);
1957 hlego->Fill(2+0.5*px,2*py-10.,0.1);
1958 }
1959 hlego->Draw("LEGO");
1960}
1961End_Macro
1962
1963The following example shows a 2D histogram plotted with the option
1964`LEGO1`. The option `LEGO1` draws a lego plot using the
1965hidden surface removal technique. Combined with any `LEGOn` option, the
1966option `0` allows to not drawn the empty bins.
1967
1968Begin_Macro(source)
1969{
1970 auto c2 = new TCanvas("c2","c2",600,400);
1971 auto hlego1 = new TH2F("hlego1","Option LEGO1 example (with option 0) ",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 hlego1->Fill(px-1,5*py);
1976 hlego1->Fill(2+0.5*px,2*py-10.,0.1);
1977 }
1978 hlego1->SetFillColor(kYellow);
1979 hlego1->Draw("LEGO1 0");
1980}
1981End_Macro
1982
1983The following example shows a 2D histogram plotted with the option
1984`LEGO3`. Like the option `LEGO1`, the option `LEGO3`
1985draws a lego plot using the hidden surface removal technique but doesn't draw
1986the border lines of each individual lego-bar. This is very useful for histograms
1987having many bins. With such histograms the option `LEGO1` gives a black
1988image because of the border lines. This option also works with stacked legos.
1989
1990Begin_Macro(source)
1991{
1992 auto c2 = new TCanvas("c2","c2",600,400);
1993 auto hlego3 = new TH2F("hlego3","Option LEGO3 example",40,-4,4,40,-20,20);
1994 float px, py;
1995 for (Int_t i = 0; i < 25000; i++) {
1996 gRandom->Rannor(px,py);
1997 hlego3->Fill(px-1,5*py);
1998 hlego3->Fill(2+0.5*px,2*py-10.,0.1);
1999 }
2000 hlego3->SetFillColor(kRed);
2001 hlego3->Draw("LEGO3");
2002}
2003End_Macro
2004
2005The following example shows a 2D histogram plotted with the option
2006`LEGO2`. The option `LEGO2` draws a lego plot using colors to
2007show the cell contents. Combined with the option `LEGO2`, the option
2008`Z` allows to display the color palette defined by
2009`gStyle->SetPalette()`.
2010
2011Begin_Macro(source)
2012{
2013 auto c2 = new TCanvas("c2","c2",600,400);
2014 auto hlego2 = new TH2F("hlego2","Option LEGO2Z example ",40,-4,4,40,-20,20);
2015 float px, py;
2016 for (Int_t i = 0; i < 25000; i++) {
2017 gRandom->Rannor(px,py);
2018 hlego2->Fill(px-1,5*py);
2019 hlego2->Fill(2+0.5*px,2*py-10.,0.1);
2020 }
2021 hlego2->Draw("LEGO2Z");
2022}
2023End_Macro
2024
2025
2026
2027\anchor HP18
2028### The "SURFace" options
2029
2030
2031In a surface plot, cell contents are represented as a mesh.
2032The height of the mesh is proportional to the cell content.
2033
2034| Option | Description |
2035|----------|-------------------------------------------------------------------|
2036| "SURF" | Draw a surface plot using the hidden line removal technique.|
2037| "SURF1" | Draw a surface plot using the hidden surface removal technique.|
2038| "SURF2" | Draw a surface plot using colors to show the cell contents.|
2039| "SURF3" | Same as `SURF` with an additional filled contour plot on top.|
2040| "SURF4" | Draw a surface using the Gouraud shading technique.|
2041| "SURF5" | Used with one of the options CYL, PSR and CYL this option allows to draw a filled contour plot.|
2042| "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.|
2043| "SURF7" | Same as `SURF2` with an additional line contour plot on top.|
2044
2045
2046
2047See the limitations with [the option "SAME"](\ref HP060a).
2048
2049The following example shows a 2D histogram plotted with the option
2050`SURF`. The option `SURF` draws a lego plot using the hidden
2051lines removal technique.
2052
2053Begin_Macro(source)
2054{
2055 auto c2 = new TCanvas("c2","c2",600,400);
2056 auto hsurf = new TH2F("hsurf","Option SURF example ",30,-4,4,30,-20,20);
2057 float px, py;
2058 for (Int_t i = 0; i < 25000; i++) {
2059 gRandom->Rannor(px,py);
2060 hsurf->Fill(px-1,5*py);
2061 hsurf->Fill(2+0.5*px,2*py-10.,0.1);
2062 }
2063 hsurf->Draw("SURF");
2064}
2065End_Macro
2066
2067The following example shows a 2D histogram plotted with the option
2068`SURF1`. The option `SURF1` draws a surface plot using the
2069hidden surface removal technique. Combined with the option `SURF1`,
2070the option `Z` allows to display the color palette defined by
2071`gStyle->SetPalette()`.
2072
2073Begin_Macro(source)
2074{
2075 auto c2 = new TCanvas("c2","c2",600,400);
2076 auto hsurf1 = new TH2F("hsurf1","Option SURF1 example ",30,-4,4,30,-20,20);
2077 float px, py;
2078 for (Int_t i = 0; i < 25000; i++) {
2079 gRandom->Rannor(px,py);
2080 hsurf1->Fill(px-1,5*py);
2081 hsurf1->Fill(2+0.5*px,2*py-10.,0.1);
2082 }
2083 hsurf1->Draw("SURF1");
2084}
2085End_Macro
2086
2087The following example shows a 2D histogram plotted with the option
2088`SURF2`. The option `SURF2` draws a surface plot using colors
2089to show the cell contents. Combined with the option `SURF2`, the option
2090`Z` allows to display the color palette defined by
2091`gStyle->SetPalette()`.
2092
2093Begin_Macro(source)
2094{
2095 auto c2 = new TCanvas("c2","c2",600,400);
2096 auto hsurf2 = new TH2F("hsurf2","Option SURF2 example ",30,-4,4,30,-20,20);
2097 float px, py;
2098 for (Int_t i = 0; i < 25000; i++) {
2099 gRandom->Rannor(px,py);
2100 hsurf2->Fill(px-1,5*py);
2101 hsurf2->Fill(2+0.5*px,2*py-10.,0.1);
2102 }
2103 hsurf2->Draw("SURF2");
2104}
2105End_Macro
2106
2107The following example shows a 2D histogram plotted with the option
2108`SURF3`. The option `SURF3` draws a surface plot using the
2109hidden line removal technique with, in addition, a filled contour view drawn on the
2110top. Combined with the option `SURF3`, the option `Z` allows
2111to display the color palette defined by `gStyle->SetPalette()`.
2112
2113Begin_Macro(source)
2114{
2115 auto c2 = new TCanvas("c2","c2",600,400);
2116 auto hsurf3 = new TH2F("hsurf3","Option SURF3 example ",30,-4,4,30,-20,20);
2117 float px, py;
2118 for (Int_t i = 0; i < 25000; i++) {
2119 gRandom->Rannor(px,py);
2120 hsurf3->Fill(px-1,5*py);
2121 hsurf3->Fill(2+0.5*px,2*py-10.,0.1);
2122 }
2123 hsurf3->Draw("SURF3");
2124}
2125End_Macro
2126
2127The following example shows a 2D histogram plotted with the option
2128`SURF4`. The option `SURF4` draws a surface using the Gouraud
2129shading technique.
2130
2131Begin_Macro(source)
2132{
2133 auto c2 = new TCanvas("c2","c2",600,400);
2134 auto hsurf4 = new TH2F("hsurf4","Option SURF4 example ",30,-4,4,30,-20,20);
2135 float px, py;
2136 for (Int_t i = 0; i < 25000; i++) {
2137 gRandom->Rannor(px,py);
2138 hsurf4->Fill(px-1,5*py);
2139 hsurf4->Fill(2+0.5*px,2*py-10.,0.1);
2140 }
2141 hsurf4->SetFillColor(kOrange);
2142 hsurf4->Draw("SURF4");
2143}
2144End_Macro
2145
2146The following example shows a 2D histogram plotted with the option
2147`SURF5 CYL`. Combined with the option `SURF5`, the option
2148`Z` allows to display the color palette defined by `gStyle->SetPalette()`.
2149
2150Begin_Macro(source)
2151{
2152 auto c2 = new TCanvas("c2","c2",600,400);
2153 auto hsurf5 = new TH2F("hsurf4","Option SURF5 example ",30,-4,4,30,-20,20);
2154 float px, py;
2155 for (Int_t i = 0; i < 25000; i++) {
2156 gRandom->Rannor(px,py);
2157 hsurf5->Fill(px-1,5*py);
2158 hsurf5->Fill(2+0.5*px,2*py-10.,0.1);
2159 }
2160 hsurf5->Draw("SURF5 CYL");
2161}
2162End_Macro
2163
2164The following example shows a 2D histogram plotted with the option
2165`SURF7`. The option `SURF7` draws a surface plot using the
2166hidden surfaces removal technique with, in addition, a line contour view drawn on the
2167top. Combined with the option `SURF7`, the option `Z` allows
2168to display the color palette defined by `gStyle->SetPalette()`.
2169
2170Begin_Macro(source)
2171{
2172 auto c2 = new TCanvas("c2","c2",600,400);
2173 auto hsurf7 = new TH2F("hsurf3","Option SURF7 example ",30,-4,4,30,-20,20);
2174 float px, py;
2175 for (Int_t i = 0; i < 25000; i++) {
2176 gRandom->Rannor(px,py);
2177 hsurf7->Fill(px-1,5*py);
2178 hsurf7->Fill(2+0.5*px,2*py-10.,0.1);
2179 }
2180 hsurf7->Draw("SURF7");
2181}
2182End_Macro
2183
2184As shown in the following example, when a contour plot is painted on top of a
2185surface plot using the option `SAME`, the contours appear in 3D on the
2186surface.
2187
2188Begin_Macro(source)
2189{
2190 auto c20=new TCanvas("c20","c20",600,400);
2191 int NBins = 50;
2192 double d = 2;
2193 auto hsc = new TH2F("hsc", "Surface and contour with option SAME ", NBins, -d, d, NBins, -d, d);
2194 for (int bx = 1; bx <= NBins; ++bx) {
2195 for (int by = 1; by <= NBins; ++by) {
2196 double x = hsc->GetXaxis()->GetBinCenter(bx);
2197 double y = hsc->GetYaxis()->GetBinCenter(by);
2198 hsc->SetBinContent(bx, by, exp(-x*x)*exp(-y*y));
2199 }
2200 }
2201 hsc->Draw("surf2");
2202 hsc->Draw("CONT1 SAME");
2203}
2204End_Macro
2205
2206
2207\anchor HP19
2208### Cylindrical, Polar, Spherical and PseudoRapidity/Phi options
2209
2210
2211Legos and surfaces plots are represented by default in Cartesian coordinates.
2212Combined with any `LEGOn` or `SURFn` options the following
2213options allow to draw a lego or a surface in other coordinates systems.
2214
2215| Option | Description |
2216|----------|-------------------------------------------------------------------|
2217| "CYL" | Use Cylindrical coordinates. The X coordinate is mapped on the angle and the Y coordinate on the cylinder length.|
2218| "POL" | Use Polar coordinates. The X coordinate is mapped on the angle and the Y coordinate on the radius.|
2219| "SPH" | Use Spherical coordinates. The X coordinate is mapped on the latitude and the Y coordinate on the longitude.|
2220| "PSR" | Use PseudoRapidity/Phi coordinates. The X coordinate is mapped on Phi.|
2221
2222
2223
2224<b>WARNING:</b> Axis are not drawn with these options.
2225
2226The following example shows the same histogram as a lego plot is the four
2227different coordinates systems.
2228
2229Begin_Macro(source)
2230{
2231 auto c3 = new TCanvas("c3","c3",600,400);
2232 c3->Divide(2,2);
2233 auto hlcc = new TH2F("hlcc","Cylindrical coordinates",20,-4,4,20,-20,20);
2234 float px, py;
2235 for (Int_t i = 0; i < 25000; i++) {
2236 gRandom->Rannor(px,py);
2237 hlcc->Fill(px-1,5*py);
2238 hlcc->Fill(2+0.5*px,2*py-10.,0.1);
2239 }
2240 hlcc->SetFillColor(kYellow);
2241 c3->cd(1); hlcc->Draw("LEGO1 CYL");
2242 c3->cd(2); auto hlpc = (TH2F*) hlcc->DrawClone("LEGO1 POL");
2243 hlpc->SetTitle("Polar coordinates");
2244 c3->cd(3); auto hlsc = (TH2F*) hlcc->DrawClone("LEGO1 SPH");
2245 hlsc->SetTitle("Spherical coordinates");
2246 c3->cd(4); auto hlprpc = (TH2F*) hlcc->DrawClone("LEGO1 PSR");
2247 hlprpc->SetTitle("PseudoRapidity/Phi coordinates");
2248}
2249End_Macro
2250
2251The following example shows the same histogram as a surface plot is the four different coordinates systems.
2252
2253Begin_Macro(source)
2254{
2255 auto c4 = new TCanvas("c4","c4",600,400);
2256 c4->Divide(2,2);
2257 auto hscc = new TH2F("hscc","Cylindrical coordinates",20,-4,4,20,-20,20);
2258 float px, py;
2259 for (Int_t i = 0; i < 25000; i++) {
2260 gRandom->Rannor(px,py);
2261 hscc->Fill(px-1,5*py);
2262 hscc->Fill(2+0.5*px,2*py-10.,0.1);
2263 }
2264 c4->cd(1); hscc->Draw("SURF1 CYL");
2265 c4->cd(2); auto hspc = (TH2F*) hscc->DrawClone("SURF1 POL");
2266 hspc->SetTitle("Polar coordinates");
2267 c4->cd(3); auto hssc = (TH2F*) hscc->DrawClone("SURF1 SPH");
2268 hssc->SetTitle("Spherical coordinates");
2269 c4->cd(4); auto hsprpc = (TH2F*) hscc->DrawClone("SURF1 PSR");
2270 hsprpc->SetTitle("PseudoRapidity/Phi coordinates");
2271}
2272End_Macro
2273
2274
2275\anchor HP20
2276### Base line for bar-charts and lego plots
2277
2278
2279By default the base line used to draw the boxes for bar-charts and lego plots is
2280the histogram minimum. It is possible to force this base line to be 0, using MIN0 draw
2281option or with the command:
2282
2283 gStyle->SetHistMinimumZero();
2284
2285Begin_Macro(source)
2286{
2287 auto c5 = new TCanvas("c5","c5",700,400);
2288 c5->Divide(2,1);
2289 auto hz1 = new TH1F("hz1","Bar-chart drawn from 0",20,-3,3);
2290 auto hz2 = new TH2F("hz2","Lego plot drawn from 0",20,-3,3,20,-3,3);
2291 Int_t i;
2292 double x,y;
2293 hz1->SetFillColor(kBlue);
2294 hz2->SetFillColor(kBlue);
2295 for (i=0;i<10000;i++) {
2296 x = gRandom->Gaus(0,1);
2297 y = gRandom->Gaus(0,1);
2298 if (x>0) {
2299 hz1->Fill(x,1);
2300 hz2->Fill(x,y,1);
2301 } else {
2302 hz1->Fill(x,-1);
2303 hz2->Fill(x,y,-2);
2304 }
2305 }
2306 c5->cd(1); hz1->Draw("bar2 min0");
2307 c5->cd(2); hz2->Draw("lego1 min0");
2308}
2309End_Macro
2310
2311This option also works for horizontal plots. The example given in the section
2312["The bar chart option"](\ref HP100) appears as follow:
2313
2314Begin_Macro(source)
2315{
2316 int i;
2317 const Int_t nx = 8;
2318 string os_X[nx] = {"8","32","128","512","2048","8192","32768","131072"};
2319 float d_35_0[nx] = {0.75, -3.30, -0.92, 0.10, 0.08, -1.69, -1.29, -2.37};
2320 float d_35_1[nx] = {1.01, -3.02, -0.65, 0.37, 0.34, -1.42, -1.02, -2.10};
2321
2322 auto cbh = new TCanvas("cbh","cbh",400,600);
2323 cbh->SetGrid();
2324
2325 auto h1bh = new TH1F("h1bh","Option HBAR centered on 0",nx,0,nx);
2326 h1bh->SetFillColor(4);
2327 h1bh->SetBarWidth(0.4);
2328 h1bh->SetBarOffset(0.1);
2329 h1bh->SetStats(0);
2330 h1bh->SetMinimum(-5);
2331 h1bh->SetMaximum(5);
2332
2333 for (i=1; i<=nx; i++) {
2334 h1bh->Fill(os_X[i-1].c_str(), d_35_0[i-1]);
2335 h1bh->GetXaxis()->SetBinLabel(i,os_X[i-1].c_str());
2336 }
2337
2338 h1bh->Draw("hbar min0");
2339
2340 auto h2bh = new TH1F("h2bh","h2bh",nx,0,nx);
2341 h2bh->SetFillColor(38);
2342 h2bh->SetBarWidth(0.4);
2343 h2bh->SetBarOffset(0.5);
2344 h2bh->SetStats(0);
2345 for (i=1;i<=nx;i++) h2bh->Fill(os_X[i-1].c_str(), d_35_1[i-1]);
2346
2347 h2bh->Draw("hbar min0 same");
2348}
2349End_Macro
2350
2351
2352\anchor HP20a
2353### TH2Poly Drawing
2354
2355
2356The following options are supported:
2357
2358| Option | Description |
2359|----------|-------------------------------------------------------------------|
2360| "SCAT" | Draw a scatter plot (legacy draw option).|
2361| "COL" | Draw a color plot. All the bins are painted even the empty bins (default).|
2362| "COLZ" | Same as "COL". In addition the color palette is also drawn.|
2363| "0" | When used with any COL options, the empty bins are not drawn.|
2364| "TEXT" | Draw bin contents as text (format set via `gStyle->SetPaintTextFormat`).|
2365| "TEXTN" | Draw bin names as text.|
2366| "TEXTnn" | Draw bin contents as text at angle nn (0 < nn <= 90).|
2367| "L" | Draw the bins boundaries as lines. The lines attributes are the TGraphs ones.|
2368| "P" | Draw the bins boundaries as markers. The markers attributes are the TGraphs ones.|
2369| "F" | Draw the bins boundaries as filled polygons. The filled polygons attributes are the TGraphs ones.|
2370
2371
2372
2373`TH2Poly` can be drawn as a color plot (option COL). `TH2Poly` bins can have any
2374shapes. The bins are defined as graphs. The following macro is a very simple
2375example showing how to book a TH2Poly and draw it.
2376
2377Begin_Macro(source)
2378{
2379 auto ch2p1 = new TCanvas("ch2p1","ch2p1",600,400);
2380 auto h2p = new TH2Poly();
2381 h2p->SetName("h2poly_name");
2382 h2p->SetTitle("h2poly_title");
2383 double px1[] = {0, 5, 6};
2384 double py1[] = {0, 0, 5};
2385 double px2[] = {0, -1, -1, 0};
2386 double py2[] = {0, 0, -1, 3};
2387 double px3[] = {4, 3, 0, 1, 2.4};
2388 double py3[] = {4, 3.7, 1, 3.7, 2.5};
2389 h2p->AddBin(3, px1, py1);
2390 h2p->AddBin(4, px2, py2);
2391 h2p->AddBin(5, px3, py3);
2392 h2p->Fill(0.1, 0.01, 3);
2393 h2p->Fill(-0.5, -0.5, 7);
2394 h2p->Fill(-0.7, -0.5, 1);
2395 h2p->Fill(1, 3, 1.5);
2396 double fx[] = {0.1, -0.5, -0.7, 1};
2397 double fy[] = {0.01, -0.5, -0.5, 3};
2398 double fw[] = {3, 1, 1, 1.5};
2399 h2p->FillN(4, fx, fy, fw);
2400 h2p->Draw("col");
2401}
2402End_Macro
2403
2404Rectangular bins are a frequent case. The special version of
2405the `AddBin` method allows to define them more easily like
2406shown in the following example (hist037_TH2Poly_boxes.C).
2407
2408Begin_Macro(source)
2409../../../tutorials/hist/hist037_TH2Poly_boxes.C
2410End_Macro
2411
2412One `TH2Poly` bin can be a list of polygons. Such bins are defined
2413by calling `AddBin` with a `TMultiGraph`. The following example
2414shows a such case:
2415
2416Begin_Macro(source)
2417{
2418 auto ch2p2 = new TCanvas("ch2p2","ch2p2",600,400);
2419
2420 Int_t i, bin;
2421 const Int_t nx = 48;
2422 const char *states [nx] = {
2423 "alabama", "arizona", "arkansas", "california",
2424 "colorado", "connecticut", "delaware", "florida",
2425 "georgia", "idaho", "illinois", "indiana",
2426 "iowa", "kansas", "kentucky", "louisiana",
2427 "maine", "maryland", "massachusetts", "michigan",
2428 "minnesota", "mississippi", "missouri", "montana",
2429 "nebraska", "nevada", "new_hampshire", "new_jersey",
2430 "new_mexico", "new_york", "north_carolina", "north_dakota",
2431 "ohio", "oklahoma", "oregon", "pennsylvania",
2432 "rhode_island", "south_carolina", "south_dakota", "tennessee",
2433 "texas", "utah", "vermont", "virginia",
2434 "washington", "west_virginia", "wisconsin", "wyoming"
2435 };
2436 Double_t pop[nx] = {
2437 4708708, 6595778, 2889450, 36961664, 5024748, 3518288, 885122, 18537969,
2438 9829211, 1545801, 12910409, 6423113, 3007856, 2818747, 4314113, 4492076,
2439 1318301, 5699478, 6593587, 9969727, 5266214, 2951996, 5987580, 974989,
2440 1796619, 2643085, 1324575, 8707739, 2009671, 19541453, 9380884, 646844,
2441 11542645, 3687050, 3825657, 12604767, 1053209, 4561242, 812383, 6296254,
2442 24782302, 2784572, 621760, 7882590, 6664195, 1819777, 5654774, 544270
2443 };
2444
2445 Double_t lon1 = -130;
2446 Double_t lon2 = -65;
2447 Double_t lat1 = 24;
2448 Double_t lat2 = 50;
2449 auto p = new TH2Poly("USA","USA Population",lon1,lon2,lat1,lat2);
2450
2451 TFile::SetCacheFileDir(".");
2452 auto f = TFile::Open("http://root.cern/files/usa.root", "CACHEREAD");
2453
2454 TMultiGraph *mg;
2455 TKey *key;
2456 TIter nextkey(gDirectory->GetListOfKeys());
2457 while ((key = (TKey*)nextkey())) {
2458 TObject *obj = key->ReadObj();
2459 if (obj->InheritsFrom("TMultiGraph")) {
2460 mg = (TMultiGraph*)obj;
2461 bin = p->AddBin(mg);
2462 }
2463 }
2464
2465 for (i=0; i<nx; i++) p->Fill(states[i], pop[i]);
2466
2467 gStyle->SetOptStat(11);
2468 p->Draw("COLZ L");
2469}
2470End_Macro
2471
2472`TH2Poly` histograms can also be plotted using the GL interface using
2473the option "GLLEGO".
2474
2475\since **ROOT version 6.09/01**
2476
2477In some cases it can be useful to not draw the empty bins. the option "0"
2478combined with the option "COL" and "COLZ" allows to do that.
2479
2480Begin_Macro(source)
2481{
2482 auto chc = new TCanvas("chc","chc",600,400);
2483
2484 auto hc = new TH2Poly();
2485 hc->Honeycomb(0,0,.1,25,25);
2486 hc->SetName("hc");
2487 hc->SetTitle("Option COLZ 0");
2488 TRandom ran;
2489 for (int i = 0; i<300; i++) hc->Fill(ran.Gaus(2.,1), ran.Gaus(2.,1));
2490 hc->Draw("colz 0");
2491}
2492End_Macro
2493
2494\anchor HP21
2495### The SPEC option
2496
2497
2498This option allows to use the `TSpectrum2Painter` tools. See the full
2499documentation in `TSpectrum2Painter::PaintSpectrum`.
2500
2501
2502\anchor HP22
2503### Option "Z" : Adding the color palette on the right side of the pad
2504
2505
2506When this option is specified, a color palette with an axis indicating the value
2507of the corresponding color is drawn on the right side of the picture. In case,
2508not enough space is left, one can increase the size of the right margin by
2509calling `TPad::SetRightMargin()`. The attributes used to display the
2510palette axis values are taken from the Z axis of the object. For example, to
2511set the labels size on the palette axis do:
2512
2513 hist->GetZaxis()->SetLabelSize().
2514
2515<b>WARNING:</b> The palette axis is always drawn vertically.
2516
2517
2518\anchor HP23
2519### Setting the color palette
2520
2521
2522To change the color palette `TStyle::SetPalette` should be used, eg:
2523
2524 gStyle->SetPalette(ncolors,colors);
2525
2526For example the option `COL` draws a 2D histogram with cells
2527represented by a box filled with a color index which is a function
2528of the cell content.
2529If the cell content is N, the color index used will be the color number
2530in `colors[N]`, etc. If the maximum cell content is greater than
2531`ncolors`, all cell contents are scaled to `ncolors`.
2532
2533If ` ncolors <= 0`, a default palette (see below) of 50 colors is
2534defined. This palette is recommended for pads, labels ...
2535
2536`if ncolors == 1 && colors == 0`, then a Pretty Palette with a
2537Spectrum Violet->Red is created with 50 colors. That's the default rain bow
2538palette.
2539
2540Other pre-defined palettes with 255 colors are available when `colors == 0`.
2541The following value of `ncolors` give access to:
2542
2543
2544 if ncolors = 51 and colors=0, a Deep Sea palette is used.
2545 if ncolors = 52 and colors=0, a Grey Scale palette is used.
2546 if ncolors = 53 and colors=0, a Dark Body Radiator palette is used.
2547 if ncolors = 54 and colors=0, a two-color hue palette palette is used.(dark blue through neutral gray to bright
2548yellow) if ncolors = 55 and colors=0, a Rain Bow palette is used. if ncolors = 56 and colors=0, an inverted Dark Body
2549Radiator palette is used.
2550
2551
2552If `ncolors > 0 && colors == 0`, the default palette is used with a maximum of ncolors.
2553
2554The default palette defines:
2555
2556- index 0 to 9 : shades of grey
2557- index 10 to 19 : shades of brown
2558- index 20 to 29 : shades of blue
2559- index 30 to 39 : shades of red
2560- index 40 to 49 : basic colors
2561
2562The color numbers specified in the palette can be viewed by selecting
2563the item `colors` in the `VIEW` menu of the canvas tool bar.
2564The red, green, and blue components of a color can be changed thanks to
2565`TColor::SetRGB()`.
2566
2567\since **ROOT version 6.19/01**
2568
2569As default labels and ticks are drawn by `TGAxis` at equidistant (lin or log)
2570points as controlled by SetNdivisions.
2571If option "CJUST" is given labels and ticks are justified at the
2572color boundaries defined by the contour levels.
2573For more details see `TPaletteAxis`
2574
2575\anchor HP24
2576### Drawing a sub-range of a 2D histogram; the [cutg] option
2577
2578
2579Using a `TCutG` object, it is possible to draw a sub-range of a 2D
2580histogram. One must create a graphical cut (mouse or C++) and specify the name
2581of the cut between `[]` in the `Draw()` option.
2582For example (fit2a.C), with a `TCutG` named `cutg`, one can call:
2583
2584 myhist->Draw("surf1 [cutg]");
2585
2586To invert the cut, it is enough to put a `-` in front of its name:
2587
2588 myhist->Draw("surf1 [-cutg]");
2589
2590It is possible to apply several cuts (`,` means logical AND):
2591
2592 myhist->Draw("surf1 [cutg1,cutg2]");
2593
2594Begin_Macro(source)
2595../../../tutorials/fit/fit2a.C
2596End_Macro
2597
2598\anchor HP25
2599### Drawing options for 3D histograms
2600
2601
2602| Option | Description |
2603|----------|-------------------------------------------------------------------|
2604| "SCAT" | Draw a scatter plot (legacy draw option).|
2605| "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)`|
2606| "BOX" | Draw a for each cell with volume proportional to the content's absolute value. An hidden line removal algorithm is used|
2607| "BOX1" | Same as BOX but an hidden surface removal algorithm is used|
2608| "BOX2" | Same as "COL". The boxes' colors are picked in the current palette according to the bins' contents (default)|
2609| "BOX2Z" | Same as "BOX2". In addition the color palette is also drawn.|
2610| "BOX3" | Same as BOX1, but the border lines of each lego-bar are not drawn.|
2611
2612Note that instead of `BOX` one can also use `LEGO`.
2613
2614By default, 3D histograms are drawn as a colored box plots.
2615
2616The following example shows a 3D histogram plotted as a scatter plot.
2617
2618Begin_Macro(source)
2619{
2620 auto c06 = new TCanvas("c06","c06",600,400);
2621 gStyle->SetOptStat(kFALSE);
2622 auto h3scat = new TH3F("h3scat","Option SCAT",15,-2,2,15,-2,2,15,0,4);
2623 double x, y, z;
2624 for (Int_t i=0;i<10000;i++) {
2625 gRandom->Rannor(x, y);
2626 z = x*x + y*y;
2627 h3scat->Fill(x,y,z);
2628 }
2629 h3scat->Draw("SCAT"); // This a legacy draw option
2630}
2631End_Macro
2632
2633The following example shows a 3D histogram plotted with the option `BOX`.
2634
2635Begin_Macro(source)
2636{
2637 auto c16 = new TCanvas("c16","c16",600,400);
2638 gStyle->SetOptStat(kFALSE);
2639 auto h3box = new TH3F("h3box","Option BOX",15,-2,2,15,-2,2,15,0,4);
2640 double x, y, z;
2641 for (Int_t i=0;i<10000;i++) {
2642 gRandom->Rannor(x, y);
2643 z = x*x + y*y;
2644 h3box->Fill(x,y,z);
2645 }
2646 h3box->Draw("BOX");
2647}
2648End_Macro
2649
2650The following example shows a 3D histogram plotted with the option `BOX1`.
2651
2652Begin_Macro(source)
2653{
2654 auto c36 = new TCanvas("c36","c36",600,400);
2655 gStyle->SetOptStat(kFALSE);
2656 auto h3box = new TH3F("h3box","Option BOX1",10,-2.,2.,10,-2.,2.,10,-0.5,2.);
2657 double x, y, z;
2658 for (Int_t i=0;i<10000;i++) {
2659 gRandom->Rannor(x, y);
2660 z = abs(sin(x)/x + cos(y)*y);
2661 h3box->Fill(x,y,z);
2662 }
2663 h3box->SetFillColor(9);
2664 h3box->Draw("BOX1");
2665}
2666End_Macro
2667
2668The following example shows a 3D histogram plotted with the option `BOX2`.
2669
2670Begin_Macro(source)
2671{
2672 auto c56 = new TCanvas("c56","c56",600,400);
2673 gStyle->SetOptStat(kFALSE);
2674 auto h3box = new TH3F("h3box","Option BOX2 (default)",10,-2.,2.,10,-2.,2.,10,-0.5,2.);
2675 double x, y, z;
2676 for (Int_t i=0;i<10000;i++) {
2677 gRandom->Rannor(x, y);
2678 z = abs(sin(x)/x + cos(y)*y);
2679 h3box->Fill(x,y,z);
2680 }
2681 h3box->Draw("BOX2 Z");
2682}
2683End_Macro
2684
2685The following example shows a 3D histogram plotted with the option `BOX3`.
2686
2687Begin_Macro(source)
2688{
2689 auto c46 = new TCanvas("c46","c46",600,400);
2690 c46->SetFillColor(38);
2691 gStyle->SetOptStat(kFALSE);
2692 auto h3box = new TH3F("h3box","Option BOX3",15,-2,2,15,-2,2,15,0,4);
2693 double x, y, z;
2694 for (Int_t i=0;i<10000;i++) {
2695 gRandom->Rannor(x, y);
2696 z = x*x + y*y;
2697 h3box->Fill(x,y,z);
2698 }
2699 h3box->Draw("BOX3");
2700}
2701End_Macro
2702
2703For all the `BOX` options each bin is drawn as a 3D box with a volume proportional
2704to the absolute value of the bin content. The bins with a negative content are
2705drawn with a X on each face of the box as shown in the following example:
2706
2707Begin_Macro(source)
2708{
2709 auto c = new TCanvas("c","c",600,400);
2710 gStyle->SetOptStat(kFALSE);
2711 auto h3box = new TH3F("h3box","Option BOX1 with negative bins",3, 0., 4., 3, 0.,4., 3, 0., 4.);
2712 h3box->Fill(0., 2., 2., 10.);
2713 h3box->Fill(2., 2., 2., 5.);
2714 h3box->Fill(2., 2., .5, 2.);
2715 h3box->Fill(2., 2., 3., -1.);
2716 h3box->Fill(3., 2., 2., -10.);
2717 h3box->SetFillColor(8);
2718 h3box->Draw("box1");
2719}
2720End_Macro
2721
2722The following example shows a 3D histogram plotted with the option `ISO`.
2723
2724Begin_Macro(source)
2725{
2726 auto c26 = new TCanvas("c26","c26",600,400);
2727 gStyle->SetOptStat(kFALSE);
2728 auto h3iso = new TH3F("h3iso","Option ISO",15,-2,2,15,-2,2,15,0,4);
2729 double x, y, z;
2730 for (Int_t i=0;i<10000;i++) {
2731 gRandom->Rannor(x, y);
2732 z = x*x + y*y;
2733 h3iso->Fill(x,y,z);
2734 }
2735 h3iso->SetFillColor(kCyan);
2736 h3iso->Draw("ISO");
2737}
2738End_Macro
2739
2740
2741\anchor HP26
2742### Drawing option for histograms' stacks
2743
2744
2745Stacks of histograms are managed with the `THStack`. A `THStack`
2746is a collection of `TH1` (or derived) objects. For painting only the
2747`THStack` containing `TH1` only or
2748`THStack` containing `TH2` only will be considered.
2749
2750By default, histograms are shown stacked:
2751
27521. The first histogram is paint.
27532. The sum of the first and second, etc...
2754
2755If the option `NOSTACK` is specified, the histograms are all paint in
2756the same pad as if the option `SAME` had been specified. This allows to
2757compute X and Y scales common to all the histograms, like
2758`TMultiGraph` does for graphs.
2759
2760If the option `PADS` is specified, the current pad/canvas is subdivided into
2761a number of pads equal to the number of histograms and each histogram is paint
2762into a separate pad. With `PADSn`, the current pad/canvas is subdivided into
2763`n` columns, automatically calculating the number of rows.
2764
2765The following example shows various types of stacks (hist023_THStack_simple.C).
2766
2767Begin_Macro(source)
2768../../../tutorials/hist/hist023_THStack_simple.C
2769End_Macro
2770
2771The option `nostackb` allows to draw the histograms next to each
2772other as bar charts:
2773
2774Begin_Macro(source)
2775{
2776 auto cst0 = new TCanvas("cst0","cst0",600,400);
2777 auto hs = new THStack("hs","Stacked 1D histograms: option #font[82]{\"nostackb\"}");
2778
2779 auto h1 = new TH1F("h1","h1",10,-4,4);
2780 h1->FillRandom("gaus",20000);
2781 h1->SetFillColor(kRed);
2782 hs->Add(h1);
2783
2784 auto h2 = new TH1F("h2","h2",10,-4,4);
2785 h2->FillRandom("gaus",15000);
2786 h2->SetFillColor(kBlue);
2787 hs->Add(h2);
2788
2789 auto h3 = new TH1F("h3","h3",10,-4,4);
2790 h3->FillRandom("gaus",10000);
2791 h3->SetFillColor(kGreen);
2792 hs->Add(h3);
2793
2794 hs->Draw("nostackb");
2795 hs->GetXaxis()->SetNdivisions(-10);
2796 cst0->SetGridx();
2797}
2798End_Macro
2799
2800If at least one of the histograms in the stack has errors, the whole stack is
2801visualized by default with error bars. To visualize it without errors the
2802option `HIST` should be used.
2803
2804Begin_Macro(source)
2805{
2806 auto cst1 = new TCanvas("cst1","cst1",700,400);
2807 cst1->Divide(2,1);
2808
2809 auto hst11 = new TH1F("hst11", "", 20, -10, 10);
2810 hst11->Sumw2();
2811 hst11->FillRandom("gaus", 1000);
2812 hst11->SetFillColor(kViolet);
2813 hst11->SetLineColor(kViolet);
2814
2815 auto hst12 = new TH1F("hst12", "", 20, -10, 10);
2816 hst12->FillRandom("gaus", 500);
2817 hst12->SetFillColor(kBlue);
2818 hst12->SetLineColor(kBlue);
2819
2820 THStack st1("st1", "st1");
2821 st1.Add(hst11);
2822 st1.Add(hst12);
2823
2824 cst1->cd(1); st1.Draw();
2825 cst1->cd(2); st1.Draw("hist");
2826}
2827End_Macro
2828
2829\anchor HP27
2830### Drawing of 3D implicit functions
2831
2832
28333D implicit functions (`TF3`) can be drawn as iso-surfaces.
2834The implicit function f(x,y,z) = 0 is drawn in cartesian coordinates.
2835In the following example the options "FB" and "BB" suppress the
2836"Front Box" and "Back Box" around the plot.
2837
2838Begin_Macro(source)
2839{
2840 auto c2 = new TCanvas("c2","c2",600,400);
2841 auto f3 = new TF3("f3","sin(x*x+y*y+z*z-36)",-2,2,-2,2,-2,2);
2842 f3->SetClippingBoxOn(0,0,0);
2843 f3->SetFillColor(30);
2844 f3->SetLineColor(15);
2845 f3->Draw("FBBB");
2846}
2847End_Macro
2848
2849
2850\anchor HP28
2851### Associated functions drawing
2852
2853
2854An associated function is created by `TH1::Fit`. More than on fitted
2855function can be associated with one histogram (see `TH1::Fit`).
2856
2857A `TF1` object `f1` can be added to the list of associated
2858functions of an histogram `h` without calling `TH1::Fit`
2859simply doing:
2860
2861 h->GetListOfFunctions()->Add(f1);
2862
2863or
2864
2865 h->GetListOfFunctions()->Add(f1,someoption);
2866
2867To retrieve a function by name from this list, do:
2868
2869 TF1 *f1 = (TF1*)h->GetListOfFunctions()->FindObject(name);
2870
2871or
2872
2873 TF1 *f1 = h->GetFunction(name);
2874
2875Associated functions are automatically painted when an histogram is drawn.
2876To avoid the painting of the associated functions the option `HIST`
2877should be added to the list of the options used to paint the histogram.
2878
2879
2880\anchor HP29
2881### Drawing using OpenGL
2882
2883
2884The class `TGLHistPainter` allows to paint data set using the OpenGL 3D
2885graphics library. The plotting options start with `GL` keyword.
2886In addition, in order to inform canvases that OpenGL should be used to render
28873D representations, the following option should be set:
2888
2889 gStyle->SetCanvasPreferGL(true);
2890
2891
2892\anchor HP29a
2893#### General information: plot types and supported options
2894
2895The following types of plots are provided:
2896
2897For lego plots the supported options are:
2898
2899| Option | Description |
2900|----------|-------------------------------------------------------------------|
2901| "GLLEGO" | Draw a lego plot. It works also for `TH2Poly`.|
2902| "GLLEGO2"| Bins with color levels.|
2903| "GLLEGO3"| Cylindrical bars.|
2904
2905
2906
2907Lego painter in cartesian supports logarithmic scales for X, Y, Z.
2908In polar only Z axis can be logarithmic, in cylindrical only Y.
2909
2910For surface plots (`TF2` and `TH2`) the supported options are:
2911
2912| Option | Description |
2913|-----------|------------------------------------------------------------------|
2914| "GLSURF" | Draw a surface.|
2915| "GLSURF1" | Surface with color levels|
2916| "GLSURF2" | The same as "GLSURF1" but without polygon outlines.|
2917| "GLSURF3" | Color level projection on top of plot (works only in cartesian coordinate system).|
2918| "GLSURF4" | Same as "GLSURF" but without polygon outlines.|
2919
2920
2921
2922The surface painting in cartesian coordinates supports logarithmic scales along
2923X, Y, Z axis. In polar coordinates only the Z axis can be logarithmic,
2924in cylindrical coordinates only the Y axis.
2925
2926Additional options to SURF and LEGO - Coordinate systems:
2927
2928| Option | Description |
2929|----------|-------------------------------------------------------------------|
2930| " " | Default, cartesian coordinates system.|
2931| "POL" | Polar coordinates system.|
2932| "CYL" | Cylindrical coordinates system.|
2933| "SPH" | Spherical coordinates system.|
2934
2935
2936
2937\anchor HP290
2938#### TH3 as color boxes
2939
2940The supported option is:
2941
2942| Option | Description |
2943|----------|-------------------------------------------------------------------|
2944| "GLCOL" | H3 is drawn using semi-transparent colored boxes. See glvox1.C .|
2945
2946
2947
2948\anchor HP29b
2949#### TH3 as boxes (spheres)
2950
2951The supported options are:
2952
2953| Option | Description |
2954|----------|-------------------------------------------------------------------|
2955| "GLBOX" | TH3 as a set of boxes, size of box is proportional to bin content.|
2956| "GLBOX1" | The same as "glbox", but spheres are drawn instead of boxes.|
2957
2958
2959
2960\anchor HP29c
2961#### TH3 as iso-surface(s)
2962
2963The supported option is:
2964
2965| Option | Description |
2966|----------|-------------------------------------------------------------------|
2967| "GLISO" | TH3 is drawn using iso-surfaces.|
2968
2969
2970
2971\anchor HP29d
2972#### TF3 (implicit function)
2973
2974The supported option is:
2975
2976| Option | Description |
2977|----------|-------------------------------------------------------------------|
2978| "GL" | Draw a TF3.|
2979
2980
2981
2982\anchor HP29e
2983#### Parametric surfaces
2984
2985glparametric.C shows how to create parametric equations and visualize the surface.
2986
2987\anchor HP29f
2988#### Interaction with the plots
2989
2990All the interactions are implemented via standard methods
2991`DistancetoPrimitive()` and `ExecuteEvent()`. That's why all the
2992interactions with the OpenGL plots are possible only when the mouse cursor is
2993in the plot's area (the plot's area is the part of a the pad occupied by
2994gl-produced picture). If the mouse cursor is not above gl-picture, the standard
2995pad interaction is performed.
2996
2997\anchor HP29g
2998#### Selectable parts
2999
3000Different parts of the plot can be selected:
3001
3002- xoz, yoz, xoy back planes: When such a plane selected, it's highlighted in green
3003 if the dynamic slicing by this plane is supported, and it's highlighted in red,
3004 if the dynamic slicing is not supported.
3005- The plot itself:
3006 On surfaces, the selected surface is outlined in red. (TF3 and
3007 ISO are not outlined). On lego plots, the selected bin is
3008 highlighted. The bin number and content are displayed in pad's
3009 status bar. In box plots, the box or sphere is highlighted and
3010 the bin info is displayed in pad's status bar.
3011
3012
3013\anchor HP29h
3014#### Rotation and zooming
3015
3016
3017- Rotation:
3018 When the plot is selected, it can be rotated by pressing and
3019 holding the left mouse button and move the cursor.
3020- Zoom/Unzoom:
3021 Mouse wheel or 'j', 'J', 'k', 'K' keys.
3022
3023
3024\anchor HP29i
3025#### Panning
3026
3027The selected plot can be moved in a pad's area by pressing and
3028holding the left mouse button and the shift key.
3029
3030\anchor HP29j
3031#### Box cut
3032
3033Surface, iso, box, TF3 and parametric painters support box cut by
3034pressing the 'c' or 'C' key when the mouse cursor is in a plot's
3035area. That will display a transparent box, cutting away part of the
3036surface (or boxes) in order to show internal part of plot. This box
3037can be moved inside the plot's area (the full size of the box is
3038equal to the plot's surrounding box) by selecting one of the box
3039cut axes and pressing the left mouse button to move it.
3040
3041\anchor HP29k
3042#### Plot specific interactions (dynamic slicing etc.)
3043
3044Currently, all gl-plots support some form of slicing. When back plane
3045is selected (and if it's highlighted in green) you can press and hold
3046left mouse button and shift key and move this back plane inside
3047plot's area, creating the slice. During this "slicing" plot becomes
3048semi-transparent. To remove all slices (and projected curves for
3049surfaces) double click with left mouse button in a plot's area.
3050
3051\anchor HP29l
3052#### Surface with option "GLSURF"
3053
3054The surface profile is displayed on the slicing plane.
3055The profile projection is drawn on the back plane
3056by pressing `'p'` or `'P'` key.
3057
3058\anchor HP29m
3059#### TF3
3060
3061The contour plot is drawn on the slicing plane. For TF3 the color
3062scheme can be changed by pressing 's' or 'S'.
3063
3064\anchor HP29n
3065#### Box
3066
3067The contour plot corresponding to slice plane position is drawn in real time.
3068
3069\anchor HP29o
3070#### Iso
3071
3072Slicing is similar to "GLBOX" option.
3073
3074\anchor HP29p
3075#### Parametric plot
3076
3077No slicing. Additional keys: 's' or 'S' to change color scheme -
3078about 20 color schemes supported ('s' for "scheme"); 'l' or 'L' to
3079increase number of polygons ('l' for "level" of details), 'w' or 'W'
3080to show outlines ('w' for "wireframe").
3081
3082\anchor HP30
3083#### Highlight mode for histogram
3084
3085\since **ROOT version 6.15/01**
3086
3087\image html hlHisto3_top.gif "Highlight mode"
3088
3089Highlight mode is implemented for `TH1` (and for `TGraph`) class. When
3090highlight mode is on, mouse movement over the bin will be represented
3091graphically. Bin will be highlighted as "bin box" (presented by box
3092object). Moreover, any highlight (change of bin) emits signal
3093`TCanvas::Highlighted()` which allows the user to react and call their own
3094function. For a better understanding see also the tutorial `hist043` to `hist046`
3095located in `$ROOTSYS/tutorials/hist/`.
3096
3097Highlight mode is switched on/off by `TH1::SetHighlight()` function
3098or interactively from `TH1` context menu. `TH1::IsHighlight()` to verify
3099whether the highlight mode enabled or disabled, default it is disabled.
3100
3101~~~ {.cpp}
3102 root [0] .x $ROOTSYS/tutorials/hsimple.C
3103 root [1] hpx->SetHighlight(kTRUE) // or interactively from TH1 context menu
3104 root [2] hpx->IsHighlight()
3105 (bool) true
3106~~~
3107
3108\image html hlsimple_nofun.gif "Highlight mode for histogram"
3109
3110\anchor HP30a
3111#### Highlight mode and user function
3112
3113The user can use (connect) `TCanvas::Highlighted()` signal, which is always
3114emitted if there is a highlight bin and call user function via signal
3115and slot communication mechanism. `TCanvas::Highlighted()` is similar
3116`TCanvas::Picked()`
3117
3118- when selected object (histogram as a whole) is different from previous
3119then emit `Picked()` signal
3120- when selected (highlighted) bin from histogram is different from previous
3121then emit `Highlighted()` signal
3122
3123Any user function (or functions) has to be defined
3124`UserFunction(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)`.
3125In example (see below) has name `PrintInfo()`. All parameters of user
3126function are taken from
3127
3128 void TCanvas::Highlighted(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)
3129
3130- `pad` is pointer to pad with highlighted histogram
3131- `obj` is pointer to highlighted histogram
3132- `x` is highlighted x bin for 1D histogram
3133- `y` is highlighted y bin for 2D histogram (for 1D histogram not in use)
3134
3135Example how to create a connection from any `TCanvas` object to a user
3136`UserFunction()` slot (see also `TQObject::Connect()` for additional info)
3137
3138 TQObject::Connect("TCanvas", "Highlighted(TVirtualPad*,TObject*,Int_t,Int_t)",
3139 0, 0, "UserFunction(TVirtualPad*,TObject*,Int_t,Int_t)");
3140
3141or use non-static "simplified" function
3142`TCanvas::HighlightConnect(const char *slot)`
3143
3144 c1->HighlightConnect("UserFunction(TVirtualPad*,TObject*,Int_t,Int_t)");
3145
3146NOTE the signal and slot string must have a form
3147"(TVirtualPad*,TObject*,Int_t,Int_t)"
3148
3149 root [0] .x $ROOTSYS/tutorials/hsimple.C
3150 root [1] hpx->SetHighlight(kTRUE)
3151 root [2] .x hlprint.C
3152
3153file `hlprint.C`
3154~~~ {.cpp}
3155void PrintInfo(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)
3156{
3157 auto h = (TH1F *)obj;
3158 if (!h->IsHighlight()) // after highlight disabled
3159 h->SetTitle("highlight disable");
3160 else
3161 h->SetTitle(TString::Format("bin[%03d] (%5.2f) content %g", x,
3162 h->GetBinCenter(x), h->GetBinContent(x)));
3163 pad->Update();
3164}
3165
3166void hlprint()
3167{
3168 if (!gPad) return;
3169 gPad->GetCanvas()->HighlightConnect("PrintInfo(TVirtualPad*,TObject*,Int_t,Int_t)");
3170}
3171~~~
3172
3173\image html hlsimple.gif "Highlight mode and simple user function"
3174
3175For more complex demo please see for example tree200_temperature.C file.
3176
3177*/
3178
3180
3183
3184const Int_t kNMAX = 2000;
3185
3186const Int_t kMAXCONTOUR = 104;
3188
3189static std::unique_ptr<TBox> gXHighlightBox, gYHighlightBox; // highlight X and Y box
3190
3212
3213
3214////////////////////////////////////////////////////////////////////////////////
3215/// Default constructor.
3216
3218{
3219 fH = nullptr;
3220 fXaxis = nullptr;
3221 fYaxis = nullptr;
3222 fZaxis = nullptr;
3223 fFunctions = nullptr;
3224 fNcuts = 0;
3225 fStack = nullptr;
3226 fShowProjection = 0;
3227 fShowProjection2 = 0;
3228 fShowOption = "";
3229 for (int i=0; i<kMaxCuts; i++) {
3230 fCuts[i] = nullptr;
3231 fCutsOpt[i] = 0;
3232 }
3233 fXHighlightBin = -1;
3234 fYHighlightBin = -1;
3235 fCurrentF3 = nullptr;
3236
3237 gStringEntries = gEnv->GetValue("Hist.Stats.Entries", "Entries");
3238 gStringMean = gEnv->GetValue("Hist.Stats.Mean", "Mean");
3239 gStringMeanX = gEnv->GetValue("Hist.Stats.MeanX", "Mean x");
3240 gStringMeanY = gEnv->GetValue("Hist.Stats.MeanY", "Mean y");
3241 gStringMeanZ = gEnv->GetValue("Hist.Stats.MeanZ", "Mean z");
3242 gStringStdDev = gEnv->GetValue("Hist.Stats.StdDev", "Std Dev");
3243 gStringStdDevX = gEnv->GetValue("Hist.Stats.StdDevX", "Std Dev x");
3244 gStringStdDevY = gEnv->GetValue("Hist.Stats.StdDevY", "Std Dev y");
3245 gStringStdDevZ = gEnv->GetValue("Hist.Stats.StdDevZ", "Std Dev z");
3246 gStringUnderflow = gEnv->GetValue("Hist.Stats.Underflow", "Underflow");
3247 gStringOverflow = gEnv->GetValue("Hist.Stats.Overflow", "Overflow");
3248 gStringIntegral = gEnv->GetValue("Hist.Stats.Integral", "Integral");
3249 gStringIntegralBinWidth = gEnv->GetValue("Hist.Stats.IntegralBinWidth", "Integral(w)");
3250 gStringSkewness = gEnv->GetValue("Hist.Stats.Skewness", "Skewness");
3251 gStringSkewnessX = gEnv->GetValue("Hist.Stats.SkewnessX", "Skewness x");
3252 gStringSkewnessY = gEnv->GetValue("Hist.Stats.SkewnessY", "Skewness y");
3253 gStringSkewnessZ = gEnv->GetValue("Hist.Stats.SkewnessZ", "Skewness z");
3254 gStringKurtosis = gEnv->GetValue("Hist.Stats.Kurtosis", "Kurtosis");
3255 gStringKurtosisX = gEnv->GetValue("Hist.Stats.KurtosisX", "Kurtosis x");
3256 gStringKurtosisY = gEnv->GetValue("Hist.Stats.KurtosisY", "Kurtosis y");
3257 gStringKurtosisZ = gEnv->GetValue("Hist.Stats.KurtosisZ", "Kurtosis z");
3258}
3259
3260////////////////////////////////////////////////////////////////////////////////
3261/// destructor.
3262
3266
3267////////////////////////////////////////////////////////////////////////////////
3268/// Compute the distance from the point px,py to a line.
3269///
3270/// Compute the closest distance of approach from point px,py to elements of
3271/// an histogram. The distance is computed in pixels units.
3272///
3273/// Algorithm: Currently, this simple model computes the distance from the mouse
3274/// to the histogram contour only.
3275
3277{
3278
3279 Double_t defaultLabelSize = 0.04; // See TAttAxis.h for source of this value
3280
3281 const Int_t big = 9999;
3282 const Int_t kMaxDiff = 7;
3283
3284 if (fPie)
3285 return fPie->DistancetoPrimitive(px, py);
3286
3287 Double_t x = gPad->AbsPixeltoX(px);
3288 Double_t x1 = gPad->AbsPixeltoX(px+1);
3289
3290 Int_t puxmin = gPad->XtoAbsPixel(gPad->GetUxmin());
3291 Int_t puymin = gPad->YtoAbsPixel(gPad->GetUymin());
3292 Int_t puxmax = gPad->XtoAbsPixel(gPad->GetUxmax());
3293 Int_t puymax = gPad->YtoAbsPixel(gPad->GetUymax());
3294 Int_t curdist = big;
3296 Bool_t dsame;
3297 TObject *PadPointer = gPad->GetPadPointer();
3298 if (!PadPointer) return 0;
3299 TString doption = PadPointer->GetDrawOption();
3300 Double_t factor = 1;
3301 if (fH->GetNormFactor() != 0) {
3302 factor = fH->GetNormFactor()/fH->GetSumOfWeights();
3303 }
3304 // return if point is not in the histogram area
3305
3306 // If a 3D view exists, check distance to axis
3307 TView *view = gPad->GetView();
3308 Int_t d1,d2,d3;
3309 if (view && Hoption.Contour != 14) {
3310 Double_t ratio;
3311 d3 = view->GetDistancetoAxis(3, px, py, ratio);
3312 if (d3 <= kMaxDiff) {gPad->SetSelected(fZaxis); return 0;}
3313 d1 = view->GetDistancetoAxis(1, px, py, ratio);
3314 if (d1 <= kMaxDiff) {gPad->SetSelected(fXaxis); return 0;}
3315 d2 = view->GetDistancetoAxis(2, px, py, ratio);
3316 if (d2 <= kMaxDiff) {gPad->SetSelected(fYaxis); return 0;}
3317 if ( px > puxmin && px < puxmax && py > puymax && py < puymin) curdist = 1;
3318 goto FUNCTIONS;
3319 }
3320 // check if point is close to an axis
3321 doption.ToLower();
3322 dsame = kFALSE;
3323 if (doption.Contains("same")) dsame = kTRUE;
3324
3326 if (doption.Contains("y+")) {
3328 if (px <= xyaxis+dyaxis && px >= xyaxis && py >puymax && py < puymin) {
3329 if (!dsame) {
3330 if (gPad->IsVertical()) gPad->SetSelected(fYaxis);
3331 else gPad->SetSelected(fXaxis);
3332 return 0;
3333 }
3334 }
3335 } else {
3337 if (px >= xyaxis-dyaxis && px <= xyaxis && py >puymax && py < puymin) {
3338 if (!dsame) {
3339 if (gPad->IsVertical()) gPad->SetSelected(fYaxis);
3340 else gPad->SetSelected(fXaxis);
3341 return 0;
3342 }
3343 }
3344 }
3345
3347 if (doption.Contains("x+")) {
3349 if (py >= yxaxis-dxaxis && py <= yxaxis && px <puxmax && px > puxmin) {
3350 if (!dsame) {
3351 if (gPad->IsVertical()) gPad->SetSelected(fXaxis);
3352 else gPad->SetSelected(fYaxis);
3353 return 0;
3354 }
3355 }
3356 } else {
3358 if (yxaxis < puymin) yxaxis = puymin;
3360 if (!dsame) {
3361 if (gPad->IsVertical()) gPad->SetSelected(fXaxis);
3362 else gPad->SetSelected(fYaxis);
3363 return 0;
3364 }
3365 }
3366 }
3367
3368 if (fH->IsHighlight()) { // only if highlight is enable
3369 if ((px > puxmin) && (py < puymin) && (px < puxmax) && (py > puymax))
3370 HighlightBin(px, py);
3371 }
3372
3373 // if object is 2D or 3D return this object
3374 if (fH->GetDimension() == 2) {
3375 if (fH->InheritsFrom(TH2Poly::Class())) {
3376 TH2Poly *th2 = (TH2Poly*)fH;
3378 gPad->GetRangeAxis(xmin, ymin, xmax, ymax);
3379 Double_t pxu = gPad->AbsPixeltoX(px);
3380 Double_t pyu = gPad->AbsPixeltoY(py);
3381 if ((pxu>xmax) || (pxu < xmin) || (pyu>ymax) || (pyu < ymin)) {
3382 curdist = big;
3383 goto FUNCTIONS;
3384 } else {
3385 Int_t bin = th2->FindBin(pxu, pyu);
3386 if (bin>0) curdist = 1;
3387 else curdist = big;
3388 goto FUNCTIONS;
3389 }
3390 }
3391 Int_t delta2 = 5; //Give a margin of delta2 pixels to be in the 2-d area
3392 if ( px > puxmin + delta2
3393 && px < puxmax - delta2
3394 && py > puymax + delta2
3395 && py < puymin - delta2) {curdist =1; goto FUNCTIONS;}
3396 }
3397
3398 // point is inside histogram area. Find channel number
3399 if (gPad->IsVertical()) {
3400 Int_t bin = fXaxis->FindFixBin(gPad->PadtoX(x));
3401 Int_t binsup = fXaxis->FindFixBin(gPad->PadtoX(x1));
3402 Double_t binval = factor*fH->GetBinContent(bin);
3403 Int_t pybin = gPad->YtoAbsPixel(gPad->YtoPad(binval));
3404 if (binval == 0 && pybin < puymin) pybin = 10000;
3405 // special case if more than one bin for the pixel
3406 if (binsup-bin>1) {
3410 for (Int_t ibin=bin+1; ibin<binsup; ibin++) {
3414 }
3415 Int_t pybinmin = gPad->YtoAbsPixel(gPad->YtoPad(binvalmax));
3416 Int_t pybinmax = gPad->YtoAbsPixel(gPad->YtoPad(binvalmin));
3418 }
3419 if (bin != binsup) { // Mouse on bin border
3421 Int_t pybinsub = gPad->YtoAbsPixel(gPad->YtoPad(binsupval));
3422 if (py <= TMath::Max(pybinsub,pybin) && py >= TMath::Min(pybinsub,pybin) && pybin != 10000) return 0;
3423 }
3424 if (TMath::Abs(py - pybin) <= kMaxDiff) return TMath::Abs(py - pybin);
3425 } else {
3426 Double_t y = gPad->AbsPixeltoY(py);
3427 Double_t y1 = gPad->AbsPixeltoY(py+1);
3428 Int_t bin = fXaxis->FindFixBin(gPad->PadtoY(y));
3429 Int_t binsup = fXaxis->FindFixBin(gPad->PadtoY(y1));
3430 Double_t binval = factor*fH->GetBinContent(bin);
3431 Int_t pxbin = gPad->XtoAbsPixel(gPad->XtoPad(binval));
3432 if (binval == 0 && pxbin > puxmin) pxbin = 10000;
3433 // special case if more than one bin for the pixel
3434 if (binsup-bin>1) {
3438 for (Int_t ibin=bin+1; ibin<binsup; ibin++) {
3442 }
3443 Int_t pxbinmin = gPad->XtoAbsPixel(gPad->XtoPad(binvalmax));
3444 Int_t pxbinmax = gPad->XtoAbsPixel(gPad->XtoPad(binvalmin));
3446 }
3447 if (TMath::Abs(px - pxbin) <= kMaxDiff) return TMath::Abs(px - pxbin);
3448 }
3449 // Loop on the list of associated functions and user objects
3450FUNCTIONS:
3451 TObject *f;
3452 TIter next(fFunctions);
3453 while ((f = (TObject*) next())) {
3454 Int_t dist;
3455 if (f->InheritsFrom(TF1::Class())) dist = f->DistancetoPrimitive(-px,py);
3456 else dist = f->DistancetoPrimitive(px,py);
3457 if (dist < kMaxDiff) {gPad->SetSelected(f); return dist;}
3458 }
3459 return curdist;
3460}
3461
3462////////////////////////////////////////////////////////////////////////////////
3463/// Display a panel with all histogram drawing options.
3464
3466{
3467
3468 gCurrentHist = fH;
3469 if (!gPad) {
3470 Error("DrawPanel", "need to draw histogram first");
3471 return;
3472 }
3474 editor->Show();
3475 gROOT->ProcessLine(TString::Format("((TCanvas*)0x%zx)->Selected((TVirtualPad*)0x%zx,(TObject*)0x%zx,1)",
3476 (size_t)gPad->GetCanvas(), (size_t)gPad, (size_t)fH).Data());
3477}
3478
3480protected:
3481 Int_t px1 = 0, py1 = 0;
3482 Double_t fX1 = 0, fY1 = 0, fX2 = 0, fY2 = 0;
3483
3484public:
3486 {
3487 px1 = px;
3488 py1 = py;
3489 fX1 = fX2 = parent.PadtoX(parent.AbsPixeltoX(px));
3490 fY1 = fY2 = parent.PadtoY(parent.AbsPixeltoY(py));
3491 }
3492
3493 void MovePoint(TVirtualPad &parent, Int_t px, Int_t py)
3494 {
3495 if (TMath::Abs(px1 - px) > 5 && TMath::Abs(py1 - py) > 5) {
3496 fX2 = parent.PadtoX(parent.AbsPixeltoX(px));
3497 fY2 = parent.PadtoY(parent.AbsPixeltoY(py));
3498 const char *opt = parent.OpaqueMoving() ? "izoombox" : "ilzoombox";
3499 parent.PaintBox(fX1, fY1, fX2, fY2, opt);
3500 parent.UpdateAsync();
3501 }
3502 }
3503
3505 {
3506 Double_t x1 = TMath::Max(TMath::Min(fX1, fX2), xaxis->GetXmin());
3507 Double_t x2 = TMath::Min(TMath::Max(fX1, fX2), xaxis->GetXmax());
3508 Double_t y1 = TMath::Max(TMath::Min(fY1, fY2), yaxis->GetXmin());
3509 Double_t y2 = TMath::Min(TMath::Max(fY1, fY2), yaxis->GetXmax());
3510 if (x1 < x2 && y1 < y2) {
3511 xaxis->SetRangeUser(x1, x2);
3512 yaxis->SetRangeUser(y1, y2);
3513 }
3514 }
3515
3516};
3517
3519public:
3521 Double_t xlow = 0, xup = 1, y0 = 0, factor = 1.;
3522};
3523
3524////////////////////////////////////////////////////////////////////////////////
3525/// Execute the actions corresponding to `event`.
3526///
3527/// This function is called when a histogram is clicked with the locator at
3528/// the pixel position px,py.
3529
3531{
3532 if (!gPad || !gPad->IsEditable())
3533 return;
3534
3535 if (fPie) {
3536 fPie->ExecuteEvent(event, px, py);
3537 return;
3538 }
3539
3540 // come here if we have a lego/surface in the pad
3541 TView *view = gPad->GetView();
3542
3543 if (!fShowProjection && view && !view->TestBit(kCannotRotate)) {
3544 view->ExecuteRotateView(event, px, py);
3545 return;
3546 }
3547 Bool_t opaque = gPad->OpaqueMoving();
3548
3549 TAxis *xaxis = fH->GetXaxis();
3550 TAxis *yaxis = fH->GetYaxis();
3551 Int_t dimension = fH->GetDimension();
3552
3553 // In case of option SAME the axis must be the ones of the first drawn histogram
3554 TString IsSame = fH->GetDrawOption();
3555 IsSame.ToLower();
3556 if (IsSame.Index("same")>=0) {
3557 TIter next(gPad->GetListOfPrimitives());
3558 while (auto h1 = (TH1 *)next()) {
3559 if (h1->InheritsFrom(TH1::Class())) {
3560 xaxis = h1->GetXaxis();
3561 yaxis = h1->GetYaxis();
3562 break;
3563 }
3564 }
3565 }
3566
3567 auto zoombox = dynamic_cast<TZoomInteractive *> (gPad->Interactive(this));
3568 auto h1edit = dynamic_cast<TEditInteractive *> (gPad->Interactive(this));
3569
3570 switch (event) {
3571
3572 case kButton1Down:
3573
3574 if (dimension == 2) {
3575 zoombox = new TZoomInteractive(*gPad, px, py);
3576 gPad->Interactive(this, zoombox);
3577 // no need to paint while box is dummy
3578 }
3579 // No break !!!
3580
3581 case kMouseMotion:
3582
3583 if (fShowProjection) {
3584 ShowProjection3(px,py);
3585 break;
3586 }
3587
3588 gPad->SetCursor(kPointer);
3589 if ((dimension == 1) && gROOT->GetEditHistograms()) {
3590 h1edit = new TEditInteractive();
3591
3592 Double_t baroffset = Hoption.Bar ? fH->GetBarOffset() : 0;
3593 Double_t barwidth = Hoption.Bar ? fH->GetBarWidth() : 1;
3594 h1edit->bin = fXaxis->FindFixBin(gPad->PadtoX(gPad->AbsPixeltoX(px)));
3596 h1edit->xlow = fXaxis->GetBinLowEdge(h1edit->bin) + baroffset*binwidth;
3597 h1edit->xup = h1edit->xlow + barwidth*binwidth;
3598 h1edit->y0 = fH->GetBinContent(h1edit->bin);
3599 h1edit->factor = fH->GetNormFactor() / fH->GetSumOfWeights();
3600 if (!h1edit->factor)
3601 h1edit->factor = 1.;
3602
3603 gPad->Interactive(this, h1edit);
3604 gPad->SetCursor(kArrowVer);
3605 }
3606
3607 break;
3608
3609 case kButton1Motion:
3610
3611 if ((dimension == 1) && h1edit) {
3612 Double_t yup = gPad->PadtoY(gPad->AbsPixeltoY(py)) / h1edit->factor;
3613 fH->SetBinContent(h1edit->bin, yup);
3614
3615 if (!opaque) {
3616 gPad->PaintBox(gPad->XtoPad(h1edit->xlow), gPad->YtoPad(h1edit->y0), gPad->XtoPad(h1edit->xup), gPad->YtoPad(yup), "ilh1edit"); // Draw the new box
3617 gPad->UpdateAsync();
3618 } else
3619 gPad->Modified();
3620 }
3621
3622 if (zoombox && dimension == 2)
3623 zoombox->MovePoint(*gPad, px, py);
3624
3625 break;
3626
3627 case kWheelUp:
3628
3629 if (dimension == 2) {
3630 Int_t bin1 = TMath::Max(xaxis->GetFirst() + 1, 1);
3631 Int_t bin2 = TMath::Min(xaxis->GetLast() - 1, xaxis->GetNbins());
3632 if (bin2 > bin1)
3633 xaxis->SetRange(bin1, bin2);
3634 bin1 = TMath::Max(yaxis->GetFirst() + 1, 1);
3635 bin2 = TMath::Min(yaxis->GetLast() - 1, yaxis->GetNbins());
3636 if (bin2 > bin1)
3637 yaxis->SetRange(bin1,bin2);
3638 }
3639 gPad->Modified();
3640 gPad->Update();
3641
3642 break;
3643
3644 case kWheelDown:
3645
3646 if (dimension == 2) {
3647 Int_t bin1 = TMath::Max(xaxis->GetFirst() - 1, 1);
3648 Int_t bin2 = TMath::Min(xaxis->GetLast() + 1, xaxis->GetNbins());
3649 const bool resetXaxisRange = bin1 == 1 && xaxis->GetFirst() == 1 && bin2 == xaxis->GetNbins() && xaxis->GetLast() == xaxis->GetNbins();
3650 if (bin2 > bin1)
3651 xaxis->SetRange(bin1, bin2);
3652 if (resetXaxisRange)
3653 xaxis->ResetBit(TAxis::kAxisRange);
3654 bin1 = TMath::Max(yaxis->GetFirst() - 1, 1);
3655 bin2 = TMath::Min(yaxis->GetLast() + 1, yaxis->GetNbins());
3656 const bool resetYaxisRange = bin1 == 1 && yaxis->GetFirst() == 1 && bin2 == yaxis->GetNbins() && yaxis->GetLast() == yaxis->GetNbins();
3657 if (bin2 > bin1)
3658 yaxis->SetRange(bin1, bin2);
3659 if (resetYaxisRange)
3660 yaxis->ResetBit(TAxis::kAxisRange);
3661 }
3662 gPad->Modified();
3663 gPad->Update();
3664
3665 break;
3666
3667 case kButton1Up:
3668 if ((dimension == 1) && h1edit) {
3669 PaintInit(); // recalculate Hparam structure and recalculate range
3670 // might resize pad pixmap so should be called before any paint routine
3672 }
3673 if ((dimension == 2) && zoombox)
3674 zoombox->ChangeRange(xaxis, yaxis);
3675 gPad->Interactive(); // remove interactive object
3676 gPad->Modified();
3677
3678 break;
3679
3680 case kButton1Locate:
3681
3682 ExecuteEvent(kButton1Down, px, py);
3683
3684 while (true) {
3685 px = py = 0;
3686 event = gPad->GetCanvasImp()->RequestLocator(px, py);
3687
3689
3690 if (event != -1) { // button is released
3691 ExecuteEvent(kButton1Up, px, py);
3692 return;
3693 }
3694 }
3695 }
3696}
3697
3698////////////////////////////////////////////////////////////////////////////////
3699/// Get a contour (as a list of TGraphs) using the Delaunay triangulation.
3700
3702{
3703 // Check if fH contains a TGraphDelaunay2D
3705 TGraphDelaunay2D *dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
3706 // try with the old painter
3707 TGraphDelaunay *dtOld = nullptr;
3708 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
3709
3710 if (!dt && !dtOld) return nullptr;
3711
3712 gCurrentHist = fH;
3713
3714 if (!fGraph2DPainter)
3715 ((THistPainter*)this)->fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
3716
3717 return fGraph2DPainter->GetContourList(contour);
3718}
3719
3720////////////////////////////////////////////////////////////////////////////////
3721/// Display the histogram info (bin number, contents, integral up to bin
3722/// corresponding to cursor position px,py.
3723
3725{
3726
3727 if (!gPad) return (char*)"";
3728
3729 Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
3730 Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
3731 Double_t x1 = gPad->PadtoX(gPad->AbsPixeltoX(px+1));
3733 drawOption.ToLower();
3736 if (fH->GetDimension() == 2) {
3737 if (gPad->GetView() || drawOption.Index("cont") >= 0) {
3738 uxmin=gPad->GetUxmin();
3739 uxmax=gPad->GetUxmax();
3742 x = xmin +(xmax-xmin)*(x-uxmin)/(uxmax-uxmin);
3743 uymin=gPad->GetUymin();
3744 uymax=gPad->GetUymax();
3747 y = ymin +(ymax-ymin)*(y-uymin)/(uymax-uymin);
3748 }
3749 }
3751 if (gPad->IsVertical()) {
3752 binx = fXaxis->FindFixBin(x);
3753 if (drawOption.Index("same") >= 0) {
3754 TH1 *h1;
3755 TIter next(gPad->GetListOfPrimitives());
3756 while ((h1 = (TH1 *)next())) {
3757 if (!h1->InheritsFrom(TH1::Class())) continue;
3758 binmin = h1->GetXaxis()->GetFirst();
3759 break;
3760 }
3761 } else {
3762 binmin = fXaxis->GetFirst();
3763 }
3765 // special case if more than 1 bin in x per pixel
3766 if (binx1-binx>1 && fH->GetDimension() == 1) {
3769 for (Int_t ibin=binx+1; ibin<binx1; ibin++) {
3773 binnear=ibin;
3774 }
3775 }
3776 binx = binnear;
3777 }
3778 } else {
3779 x1 = gPad->PadtoY(gPad->AbsPixeltoY(py+1));
3780 binx = fXaxis->FindFixBin(y);
3781 if (drawOption.Index("same") >= 0) {
3782 TH1 *h1;
3783 TIter next(gPad->GetListOfPrimitives());
3784 while ((h1 = (TH1 *)next())) {
3785 if (!h1->InheritsFrom(TH1::Class())) continue;
3786 binmin = h1->GetXaxis()->GetFirst();
3787 break;
3788 }
3789 } else {
3790 binmin = fXaxis->GetFirst();
3791 }
3793 // special case if more than 1 bin in x per pixel
3794 if (binx1-binx>1 && fH->GetDimension() == 1) {
3797 for (Int_t ibin=binx+1; ibin<binx1; ibin++) {
3801 binnear=ibin;
3802 }
3803 }
3804 binx = binnear;
3805 }
3806 }
3807 if (fH->GetDimension() == 1) {
3809 TProfile *tp = (TProfile*)fH;
3810 fObjectInfo.Form("(x=%g, y=%g, binx=%d, binc=%g, bine=%g, binn=%d)",
3812 (Int_t) tp->GetBinEntries(binx));
3813 }
3814 else {
3815 Double_t integ = 0;
3816 for (Int_t bin=binmin;bin<=binx;bin++) {integ += fH->GetBinContent(bin);}
3817 fObjectInfo.Form("(x=%g, y=%g, binx=%d, binc=%g, Sum=%g)",
3819 }
3820 } else if (fH->GetDimension() == 2) {
3821 if (fH->InheritsFrom(TH2Poly::Class())) {
3822 TH2Poly *th2 = (TH2Poly*)fH;
3823 biny = th2->FindBin(x,y);
3824 fObjectInfo.Form("%s (x=%g, y=%g, bin=%d, binc=%g)",
3825 th2->GetBinTitle(biny),x,y,biny,th2->GetBinContent(biny));
3826 }
3827 else if (fH->InheritsFrom(TProfile2D::Class())) {
3829 biny = fYaxis->FindFixBin(y);
3830 Int_t bin = fH->GetBin(binx,biny);
3831 fObjectInfo.Form("(x=%g, y=%g, binx=%d, biny=%d, binc=%g, bine=%g, binn=%d)",
3832 x, y, binx, biny, fH->GetBinContent(bin),
3833 fH->GetBinError(bin), (Int_t) tp->GetBinEntries(bin));
3834 } else {
3835 biny = fYaxis->FindFixBin(y);
3836 fObjectInfo.Form("(x=%g, y=%g, binx=%d, biny=%d, binc=%g bine=%g)",
3839 }
3840 } else {
3841 // 3d case: retrieving the x,y,z bin is not yet implemented
3842 // print just the x,y info
3843 fObjectInfo.Form("(x=%g, y=%g)",x,y);
3844 }
3845
3846 return (char *)fObjectInfo.Data();
3847}
3848
3849////////////////////////////////////////////////////////////////////////////////
3850/// Set highlight (enable/disable) mode for fH
3851
3853{
3854 if (fH->IsHighlight()) return;
3855
3856 fXHighlightBin = -1;
3857 fYHighlightBin = -1;
3858 // delete previous highlight box
3859 if (gXHighlightBox) gXHighlightBox.reset();
3860 if (gYHighlightBox) gYHighlightBox.reset();
3861 // emit Highlighted() signal (user can check on disabled)
3862 if (gPad->GetCanvas()) gPad->GetCanvas()->Highlighted(gPad, fH, fXHighlightBin, fYHighlightBin);
3863}
3864
3865////////////////////////////////////////////////////////////////////////////////
3866/// Check on highlight bin
3867
3869{
3870 // call from DistancetoPrimitive (only if highlight is enable)
3871
3872 Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
3873 Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
3876 if (!gPad->IsVertical()) binx = fXaxis->FindFixBin(y);
3877
3879 if (binx != fXHighlightBin) {
3881 changedBin = kTRUE;
3882 } else if (fH->GetDimension() == 1) return;
3883 if (biny != fYHighlightBin) {
3885 changedBin = kTRUE;
3886 }
3887 if (!changedBin) return;
3888
3889 // Info("HighlightBin", "histo: %p '%s'\txbin: %d, ybin: %d",
3890 // (void *)fH, fH->GetName(), fXHighlightBin, fYHighlightBin);
3891
3892 // paint highlight bin as box (recursive calls PaintHighlightBin)
3893 gPad->Modified(kTRUE);
3894 gPad->Update();
3895
3896 // emit Highlighted() signal
3897 if (gPad->GetCanvas()) gPad->GetCanvas()->Highlighted(gPad, fH, fXHighlightBin, fYHighlightBin);
3898}
3899
3900////////////////////////////////////////////////////////////////////////////////
3901/// Paint highlight bin as TBox object
3902
3904{
3905 // call from PaintTitle
3906
3907 if (!fH->IsHighlight()) return;
3908
3909 Double_t uxmin = gPad->GetUxmin();
3910 Double_t uxmax = gPad->GetUxmax();
3911 Double_t uymin = gPad->GetUymin();
3912 Double_t uymax = gPad->GetUymax();
3913 if (gPad->GetLogx()) {
3914 uxmin = TMath::Power(10.0, uxmin);
3915 uxmax = TMath::Power(10.0, uxmax);
3916 }
3917 if (gPad->GetLogy()) {
3918 uymin = TMath::Power(10.0, uymin);
3919 uymax = TMath::Power(10.0, uymax);
3920 }
3921
3922 // testing specific possibility (after zoom, draw with "same", log, etc.)
3924 if (gPad->IsVertical()) {
3926 if ((hcenter < uxmin) || (hcenter > uxmax)) return;
3927 } else {
3929 if ((hcenter < uymin) || (hcenter > uymax)) return;
3930 }
3931 if (fH->GetDimension() == 2) {
3933 if ((hcenter < uymin) || (hcenter > uymax)) return;
3934 }
3935
3936 // paint X highlight bin (for 1D or 2D)
3938 if (gPad->IsVertical()) {
3941 hby1 = uymin;
3942 hby2 = uymax;
3943 } else {
3944 hbx1 = uxmin;
3945 hbx2 = uxmax;
3948 }
3949
3950 if (!gXHighlightBox) {
3951 gXHighlightBox = std::make_unique<TBox>(hbx1, hby1, hbx2, hby2);
3952 gXHighlightBox->SetBit(kCannotPick);
3953 gXHighlightBox->SetFillColor(TColor::GetColor("#9797ff"));
3954 if (!TCanvas::SupportAlpha()) gXHighlightBox->SetFillStyle(3001);
3955 else gROOT->GetColor(gXHighlightBox->GetFillColor())->SetAlpha(0.5);
3956 }
3957 gXHighlightBox->SetX1(hbx1);
3958 gXHighlightBox->SetX2(hbx2);
3959 gXHighlightBox->SetY1(hby1);
3960 gXHighlightBox->SetY2(hby2);
3961 gXHighlightBox->Paint();
3962
3963 // Info("PaintHighlightBin", "histo: %p '%s'\txbin: %d, ybin: %d",
3964 // (void *)fH, fH->GetName(), fXHighlightBin, fYHighlightBin);
3965
3966 // paint Y highlight bin (only for 2D)
3967 if (fH->GetDimension() != 2) return;
3968 hbx1 = uxmin;
3969 hbx2 = uxmax;
3972
3973 if (!gYHighlightBox) {
3974 gYHighlightBox = std::make_unique<TBox>(hbx1, hby1, hbx2, hby2);
3975 gYHighlightBox->SetBit(kCannotPick);
3976 gYHighlightBox->SetFillColor(gXHighlightBox->GetFillColor());
3977 gYHighlightBox->SetFillStyle(gXHighlightBox->GetFillStyle());
3978 }
3979 gYHighlightBox->SetX1(hbx1);
3980 gYHighlightBox->SetX2(hbx2);
3981 gYHighlightBox->SetY1(hby1);
3982 gYHighlightBox->SetY2(hby2);
3983 gYHighlightBox->Paint();
3984}
3985
3986////////////////////////////////////////////////////////////////////////////////
3987/// Return `kTRUE` if the cell `ix`, `iy` is inside one of the graphical cuts.
3988
3990{
3991
3992 for (Int_t i=0;i<fNcuts;i++) {
3995 if (fCutsOpt[i] > 0) {
3996 if (!fCuts[i]->IsInside(x,y)) return kFALSE;
3997 } else {
3998 if (fCuts[i]->IsInside(x,y)) return kFALSE;
3999 }
4000 }
4001 return kTRUE;
4002}
4003
4004////////////////////////////////////////////////////////////////////////////////
4005/// Return `kTRUE` if the point `x`, `y` is inside one of the graphical cuts.
4006
4008{
4009
4010 for (Int_t i=0;i<fNcuts;i++) {
4011 if (fCutsOpt[i] > 0) {
4012 if (!fCuts[i]->IsInside(x,y)) return kFALSE;
4013 } else {
4014 if (fCuts[i]->IsInside(x,y)) return kFALSE;
4015 }
4016 }
4017 return kTRUE;
4018}
4019
4020////////////////////////////////////////////////////////////////////////////////
4021/// Decode string `choptin` and fill Hoption structure.
4022
4024{
4025
4026 char *l;
4027 char chopt[128];
4029 strlcpy(chopt,choptin,128);
4032
4040 Hoption.Candle = 0;
4041 Hoption.Polar = 0;
4042
4043 // special 2D options
4044 Hoption.List = 0;
4045 Hoption.Zscale = 0;
4046 Hoption.FrontBox = 1;
4047 Hoption.BackBox = 1;
4049
4050 Hoption.Zero = 0;
4051
4053
4054 //check for graphical cuts
4055 MakeCuts(chopt);
4056
4057 for (Int_t i=0;i<nch;i++) chopt[i] = toupper(chopt[i]);
4058 if (hdim > 1) Hoption.Color = 1; // Default drawing option for 2D and 3D histograms
4059 if (!nch) Hoption.Hist = 1;
4060 if (fFunctions->First()) Hoption.Func = 1;
4061 if (fH->GetSumw2N() && hdim == 1) Hoption.Error = 2;
4062
4063 char *l1 = strstr(chopt,"PFC"); // Automatic Fill Color
4064 char *l2 = strstr(chopt,"PLC"); // Automatic Line Color
4065 char *l3 = strstr(chopt,"PMC"); // Automatic Marker Color
4066 if (l1 || l2 || l3) {
4067 Int_t i = gPad->NextPaletteColor();
4068 if (l1) {memcpy(l1," ",3); fH->SetFillColor(i);}
4069 if (l2) {memcpy(l2," ",3); fH->SetLineColor(i);}
4070 if (l3) {memcpy(l3," ",3); fH->SetMarkerColor(i);}
4071 Hoption.Hist = 1; // Make sure something is drawn in case there is no drawing option specified.
4072 }
4073
4074 l = strstr(chopt,"MIN0");
4075 if (l) {
4076 Hoption.MinimumZero = 1;
4077 memcpy(l," ",4);
4078 }
4079
4080 l = strstr(chopt,"SPEC");
4081 if (l) {
4082 Hoption.Color = 0;
4083 memcpy(l," ",4);
4084 Int_t bs=0;
4085 l = strstr(chopt,"BF(");
4086 if (l) {
4087 if (sscanf(&l[3],"%d",&bs) > 0) {
4088 Int_t i=0;
4089 while (l[i]!=')') {
4090 l[i] = ' ';
4091 i++;
4092 }
4093 l[i] = ' ';
4094 }
4095 }
4096 Hoption.Spec = TMath::Max(1600,bs);
4097 return 1;
4098 }
4099
4100 l = strstr(chopt,"GL");
4101 if (l) {
4102 memcpy(l," ",2);
4103 }
4104 l = strstr(chopt,"X+");
4105 if (l) {
4106 Hoption.AxisPos = 10;
4107 memcpy(l," ",2);
4108 }
4109 l = strstr(chopt,"Y+");
4110 if (l) {
4111 Hoption.AxisPos += 1;
4112 memcpy(l," ",2);
4113 }
4114 if ((Hoption.AxisPos == 10 || Hoption.AxisPos == 1) && (nch == 2)) Hoption.Hist = 1;
4115 if (Hoption.AxisPos == 11 && nch == 4) Hoption.Hist = 1;
4116
4117 l = strstr(chopt,"SAMES");
4118 if (l) {
4119 if (nch == 5) Hoption.Hist = 1;
4120 Hoption.Same = 2;
4121 memcpy(l," ",5);
4122 if (l[5] == '0') { Hoption.Same += 10; l[5] = ' '; }
4123 }
4124 l = strstr(chopt,"SAME");
4125 if (l) {
4126 if (nch == 4) Hoption.Hist = 1;
4127 Hoption.Same = 1;
4128 memcpy(l," ",4);
4129 if (l[4] == '0') { Hoption.Same += 10; l[4] = ' '; }
4130 }
4131
4132 l = strstr(chopt,"SCAT");
4133 if (l) {
4134 Warning("MakeChopt","option SCAT is deprecated.");
4135 Hoption.Scat = 1;
4136 memcpy(l," ",4);
4137 Hoption.Color = 0;
4138 }
4139
4140 l = strstr(chopt,"PIE");
4141 if (l) {
4142 Hoption.Pie = 1;
4143 memcpy(l," ",3);
4144 }
4145
4146
4147 l = strstr(chopt,"CANDLE");
4148 if (l) {
4150 Hoption.Candle = candle.ParseOption(l);
4151 Hoption.Color = 0;
4152 }
4153
4154 l = strstr(chopt,"VIOLIN");
4155 if (l) {
4157 Hoption.Candle = candle.ParseOption(l);
4158 Hoption.Color = 0;
4159 }
4160
4161 l = strstr(chopt,"LEGO");
4162 if (l) {
4163 Hoption.Color = 0;
4164 Hoption.Lego = 1; memcpy(l," ",4);
4165 if (l[4] == '1') { Hoption.Lego = 11; l[4] = ' '; }
4166 if (l[4] == '2') { Hoption.Lego = 12; l[4] = ' '; }
4167 if (l[4] == '3') { Hoption.Lego = 13; l[4] = ' '; }
4168 if (l[4] == '4') { Hoption.Lego = 14; l[4] = ' '; }
4169 if (l[4] == '9') { Hoption.Lego = 19; l[4] = ' '; }
4170 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4171 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4172 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4173 }
4174
4175 l = strstr(chopt,"SURF");
4176 if (l) {
4177 Hoption.Color = 0;
4178 Hoption.Surf = 1; memcpy(l," ",4);
4179 if (l[4] == '1') { Hoption.Surf = 11; l[4] = ' '; }
4180 if (l[4] == '2') { Hoption.Surf = 12; l[4] = ' '; }
4181 if (l[4] == '3') { Hoption.Surf = 13; l[4] = ' '; }
4182 if (l[4] == '4') { Hoption.Surf = 14; l[4] = ' '; }
4183 if (l[4] == '5') { Hoption.Surf = 15; l[4] = ' '; }
4184 if (l[4] == '6') { Hoption.Surf = 16; l[4] = ' '; }
4185 if (l[4] == '7') { Hoption.Surf = 17; l[4] = ' '; }
4186 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4187 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4188 }
4189
4190 l = strstr(chopt,"TF3");
4191 if (l) {
4192 memcpy(l," ",3);
4193 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4194 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4195 }
4196
4197 l = strstr(chopt,"ISO");
4198 if (l) {
4199 memcpy(l," ",3);
4200 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4201 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4202 Hoption.Color = 0;
4203 }
4204
4205 l = strstr(chopt,"LIST"); if (l) { Hoption.List = 1; memcpy(l," ",4);}
4206
4207 l = strstr(chopt,"CONT");
4208 if (l) {
4209 memcpy(l," ",4);
4210 if (hdim>1) {
4211 Hoption.Color = 0;
4212 Hoption.Contour = 1;
4213 if (l[4] == '1') { Hoption.Contour = 11; l[4] = ' '; }
4214 if (l[4] == '2') { Hoption.Contour = 12; l[4] = ' '; }
4215 if (l[4] == '3') { Hoption.Contour = 13; l[4] = ' '; }
4216 if (l[4] == '4') { Hoption.Contour = 14; l[4] = ' '; }
4217 if (l[4] == '5') { Hoption.Contour = 15; l[4] = ' '; }
4218 } else {
4219 Hoption.Hist = 1;
4220 }
4221 }
4222 l = strstr(chopt,"HBAR");
4223 if (l) {
4224 Hoption.Hist = 0;
4225 Hoption.Bar = 20; memcpy(l," ",4);
4226 if (l[4] == '1') { Hoption.Bar = 21; l[4] = ' '; }
4227 if (l[4] == '2') { Hoption.Bar = 22; l[4] = ' '; }
4228 if (l[4] == '3') { Hoption.Bar = 23; l[4] = ' '; }
4229 if (l[4] == '4') { Hoption.Bar = 24; l[4] = ' '; }
4230 }
4231 l = strstr(chopt,"BAR");
4232 if (l) {
4233 Hoption.Hist = 0;
4234 Hoption.Bar = 10; memcpy(l," ",3);
4235 if (l[3] == '1') { Hoption.Bar = 11; l[3] = ' '; }
4236 if (l[3] == '2') { Hoption.Bar = 12; l[3] = ' '; }
4237 if (l[3] == '3') { Hoption.Bar = 13; l[3] = ' '; }
4238 if (l[3] == '4') { Hoption.Bar = 14; l[3] = ' '; }
4239 }
4240
4241 l = strstr(chopt,"ARR" );
4242 if (l) {
4243 memcpy(l," ", 3);
4244 if (hdim>1) {
4245 Hoption.Arrow = 1;
4246 Hoption.Color = 0;
4247 l = strstr(chopt,"COL"); if (l) { Hoption.Arrow = 2; memcpy(l," ",3); }
4248 l = strstr(chopt,"Z"); if (l) { Hoption.Zscale = 1; memcpy(l," ",1); }
4249 } else {
4250 Hoption.Hist = 1;
4251 }
4252 }
4253 l = strstr(chopt,"BOX" );
4254 if (l) {
4255 memcpy(l," ", 3);
4256 if (hdim>1) {
4257 Hoption.Color = 0;
4258 Hoption.Box = 1;
4259 if (l[3] == '1') { Hoption.Box = 11; l[3] = ' '; }
4260 if (l[3] == '2') { Hoption.Box = 12; l[3] = ' '; }
4261 if (l[3] == '3') { Hoption.Box = 13; l[3] = ' '; }
4262 } else {
4263 Hoption.Hist = 1;
4264 }
4265 }
4266 l = strstr(chopt,"TEXT");
4267 if (l) {
4268 Int_t angle;
4269 if (sscanf(&l[4],"%d",&angle) > 0) {
4270 if (angle < 0) angle=0;
4271 if (angle > 90) angle=90;
4272 Hoption.Text = 1000+angle;
4273 } else {
4274 Hoption.Text = 1;
4275 }
4276 memcpy(l," ", 4);
4277 l = strstr(chopt,"N");
4278 if (l && fH->InheritsFrom(TH2Poly::Class())) Hoption.Text = 3000 + (Hoption.Text != 1 ? Hoption.Text : 0);
4279 Hoption.Color = 0;
4280 }
4281 l = strstr(chopt,"COLZ");
4282 if (l) {
4283 memcpy(l," ",4);
4284 if (hdim > 1) {
4286 Hoption.Color = 1;
4287 Hoption.Zscale = 1;
4288 if (l[4] == '2') { Hoption.Color = 3; l[4] = ' '; }
4289 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4290 l = strstr(chopt,"1"); if (l) { Hoption.Color = 2; memcpy(l," ",1); }
4291 } else {
4292 Hoption.Hist = 1;
4293 }
4294 }
4295 l = strstr(chopt,"COL" );
4296 if (l) {
4297 memcpy(l," ", 3);
4298 if (hdim > 1) {
4300 Hoption.Color = 1;
4301 if (l[3] == '2') { Hoption.Color = 3; l[3] = ' '; }
4302 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4303 l = strstr(chopt,"1"); if (l) { Hoption.Color = 2; memcpy(l," ",1); }
4304 } else {
4305 Hoption.Hist = 1;
4306 }
4307 }
4308 l = strstr(chopt,"FUNC"); if (l) { Hoption.Func = 2; memcpy(l," ",4); Hoption.Hist = 0; }
4309 l = strstr(chopt,"HIST"); if (l) { Hoption.Hist = 2; memcpy(l," ",4); Hoption.Func = 0; Hoption.Error = 0;}
4310 l = strstr(chopt,"AXIS"); if (l) { Hoption.Axis = 1; memcpy(l," ",4); }
4311 l = strstr(chopt,"AXIG"); if (l) { Hoption.Axis = 2; memcpy(l," ",4); }
4312 l = strstr(chopt,"SCAT"); if (l) { Hoption.Scat = 1; memcpy(l," ",4); }
4313 l = strstr(chopt,"POLN"); if (l) { Hoption.System = kPOLAR; Hoption.Polar = 3; memcpy(l," ",4); }
4314 l = strstr(chopt,"POLF"); if (l) { Hoption.System = kPOLAR; Hoption.Polar = 2; memcpy(l," ",4); }
4315 l = strstr(chopt,"POL"); if (l) { Hoption.System = kPOLAR; Hoption.Polar = 1; memcpy(l," ",3); }
4316 l = strstr(chopt,"CYL"); if (l) { Hoption.System = kCYLINDRICAL; memcpy(l," ",3); }
4317 l = strstr(chopt,"SPH"); if (l) { Hoption.System = kSPHERICAL; memcpy(l," ",3); }
4318 l = strstr(chopt,"PSR"); if (l) { Hoption.System = kRAPIDITY; memcpy(l," ",3); }
4319
4320 l = strstr(chopt,"TRI");
4321 if (l) {
4322 if (!explicitColor) Hoption.Color = 0;
4323 Hoption.Tri = 1; memcpy(l," ",3);
4324 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4325 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4326 l = strstr(chopt,"ERR"); if (l) memcpy(l," ",3);
4327 }
4328
4329 l = strstr(chopt,"AITOFF");
4330 if (l) {
4331 Hoption.Proj = 1; memcpy(l," ",6); //Aitoff projection
4332 }
4333 l = strstr(chopt,"MERCATOR");
4334 if (l) {
4335 Hoption.Proj = 2; memcpy(l," ",8); //Mercator projection
4336 }
4337 l = strstr(chopt,"SINUSOIDAL");
4338 if (l) {
4339 Hoption.Proj = 3; memcpy(l," ",10); //Sinusoidal projection
4340 }
4341 l = strstr(chopt,"PARABOLIC");
4342 if (l) {
4343 Hoption.Proj = 4; memcpy(l," ",9); //Parabolic projection
4344 }
4345 l = strstr(chopt,"MOLLWEIDE");
4346 if (l) {
4347 Hoption.Proj = 5; memcpy(l," ",9); //Mollweide projection
4348 }
4349 if (Hoption.Proj > 0) {
4350 if (!explicitColor) Hoption.Color = 0;
4351 Hoption.Contour = 14;
4352 }
4353
4354 if (strstr(chopt,"A")) Hoption.Axis = -1;
4355 if (strstr(chopt,"B")) Hoption.Bar = 1;
4356 if (strstr(chopt,"C") && !strstr(chopt,"CJUST")) { Hoption.Curve =1; Hoption.Hist = -1;}
4357 if (strstr(chopt,"F")) Hoption.Fill =1;
4358 if (strstr(chopt,"][")) {Hoption.Off =1; Hoption.Hist =1;}
4359 if (strstr(chopt,"F2")) Hoption.Fill =2;
4360 if (strstr(chopt,"L")) { Hoption.Line =1; Hoption.Hist = -1;}
4361 if (strstr(chopt,"P")) { Hoption.Mark =1; Hoption.Hist = -1;}
4362 if (strstr(chopt,"Z")) Hoption.Zscale =1;
4363 if (strstr(chopt,"*")) Hoption.Star =1;
4364 if (strstr(chopt,"H")) Hoption.Hist =2;
4365 if (strstr(chopt,"P0")) Hoption.Mark =10;
4366
4367 if (fH->InheritsFrom(TH2Poly::Class())) {
4369 }
4370
4371 if (strstr(chopt,"E")) {
4372 if (hdim == 1) {
4373 Hoption.Error = 1;
4374 if (strstr(chopt,"E1")) Hoption.Error = 11;
4375 if (strstr(chopt,"E2")) Hoption.Error = 12;
4376 if (strstr(chopt,"E3")) Hoption.Error = 13;
4377 if (strstr(chopt,"E4")) Hoption.Error = 14;
4378 if (strstr(chopt,"E5")) Hoption.Error = 15;
4379 if (strstr(chopt,"E6")) Hoption.Error = 16;
4380 if (strstr(chopt,"E0")) Hoption.Error += 40;
4381 if (strstr(chopt,"X0")) {
4382 if (Hoption.Error == 1) Hoption.Error += 20;
4383 Hoption.Error += 10;
4384 }
4386 Hoption.Text += 2000;
4387 Hoption.Error = 0;
4388 }
4389 } else {
4390 if (Hoption.Error == 0) {
4391 Hoption.Error = 100;
4392 if (!explicitColor) Hoption.Color = 0;
4393 }
4394 if (Hoption.Text) {
4395 Hoption.Text += 2000;
4396 Hoption.Error = 0;
4397 }
4398 }
4399 }
4400
4401 if (Hoption.Surf == 15) {
4403 Hoption.Surf = 13;
4404 Warning("MakeChopt","option SURF5 is not supported in Cartesian and Polar modes");
4405 }
4406 }
4407
4408 // Copy options from current style
4409 Hoption.Logx = gPad->GetLogx();
4410 Hoption.Logy = gPad->GetLogy();
4411 Hoption.Logz = gPad->GetLogz();
4412
4413 // Check options incompatibilities
4414 if (Hoption.Bar == 1) Hoption.Hist = -1;
4415 return 1;
4416}
4417
4418////////////////////////////////////////////////////////////////////////////////
4419/// Decode string `choptin` and fill Graphical cuts structure.
4420
4422{
4423
4424 fNcuts = 0;
4425 char *left = (char*)strchr(choptin,'[');
4426 if (!left) return 0;
4427 char *right = (char*)strchr(choptin,']');
4428 if (!right) return 0;
4429 Int_t nch = right-left;
4430 if (nch < 2) return 0;
4431 char *cuts = left+1;
4432 *right = 0;
4433 char *comma, *minus;
4434 Int_t i;
4435 while (true) {
4436 comma = strchr(cuts,',');
4437 if (comma) *comma = 0;
4438 minus = strchr(cuts,'-');
4439 if (minus) cuts = minus+1;
4440 while (*cuts == ' ') cuts++;
4441 Int_t nc = strlen(cuts);
4442 while (cuts[nc-1] == ' ') {cuts[nc-1] = 0; nc--;}
4443 TIter next(gROOT->GetListOfSpecials());
4444 TCutG *cut=nullptr;
4445 TObject *obj;
4446 while ((obj = next())) {
4447 if (!obj->InheritsFrom(TCutG::Class())) continue;
4448 if (strcmp(obj->GetName(),cuts)) continue;
4449 cut = (TCutG*)obj;
4450 break;
4451 }
4452 if (cut) {
4453 fCuts[fNcuts] = cut;
4454 fCutsOpt[fNcuts] = 1;
4455 if (minus) fCutsOpt[fNcuts] = -1;
4456 fNcuts++;
4457 }
4458 if (!comma) break;
4459 cuts = comma+1;
4460 }
4461 for (i=0;i<=nch;i++) left[i] = ' ';
4462 return fNcuts;
4463}
4464
4465////////////////////////////////////////////////////////////////////////////////
4466/// [Control routine to paint any kind of histograms](\ref HP00)
4467
4469{
4470
4471 if (fH->GetBuffer()) fH->BufferEmpty(-1);
4472
4473 //For iOS: put the histogram on the top of stack of pickable objects.
4475
4476 gPad->SetVertical(kTRUE);
4477
4479 gCurrentHist = fH;
4480 TH1 *hsave = fH;
4482
4483 if (!MakeChopt(option)) return; //check options and fill Hoption structure
4484
4485 // Paint using TSpectrum2Painter
4486 if (Hoption.Spec) {
4487 if (!TableInit()) return;
4488 if (!TClass::GetClass("TSpectrum2Painter")) gSystem->Load("libSpectrumPainter");
4489 gROOT->ProcessLineFast(TString::Format("TSpectrum2Painter::PaintSpectrum((TH2F*)0x%zx,\"%s\",%d)",
4490 (size_t)fH, option, Hoption.Spec).Data());
4491 return;
4492 }
4493
4494 // Deflate the labels in case of alphanumeric labels
4498
4499 if (Hoption.Pie) {
4500 if (fH->GetDimension() == 1) {
4501 if (!fPie)
4502 fPie = std::make_unique<TPie>(fH);
4503 fPie->Paint(option);
4504 } else {
4505 Error("Paint", "Option PIE is for 1D histograms only");
4506 }
4507 return;
4508 } else {
4509 fPie.reset();
4510 }
4511
4512 fXbuf.resize(kNMAX);
4513 fYbuf.resize(kNMAX);
4514 if (fH->GetDimension() > 2) {
4515 PaintH3(option);
4517 if (Hoption.Func) {
4522 Hoption = hoptsave;
4523 Hparam = hparsave;
4524 }
4526 fXbuf.clear();
4527 fYbuf.clear();
4528 return;
4529 }
4530 TView *view = gPad->GetView();
4531 if (view) {
4532 if (!Hoption.Lego && !Hoption.Surf && !Hoption.Tri) {
4533 delete view;
4534 gPad->SetView(nullptr);
4535 }
4536 }
4537 if (fH->GetDimension() > 1 || Hoption.Lego || Hoption.Surf) {
4538 // In case of 1D histogram, Z axis becomes Y axis.
4539 Int_t logysav=0, logzsav=0;
4540 if (fH->GetDimension() == 1) {
4543 Hoption.Logz = 0;
4544 if (Hoption.Logy) {
4545 Hoption.Logz = 1;
4546 Hoption.Logy = 0;
4547 }
4548 }
4550 if (Hoption.Func) {
4555 Hoption = hoptsave;
4556 Hparam = hparsave;
4557 }
4560 fXbuf.clear();
4561 fYbuf.clear();
4562 if (fH->GetDimension() == 1) {
4565 }
4566 return;
4567 }
4568
4569 if (Hoption.Bar >= 20) {
4571 fXbuf.clear();
4572 fYbuf.clear();
4573 return;
4574 }
4575
4576 gPad->RangeAxisChanged(); //emit RangeAxisChanged() signal to sync axes
4577 // fill Hparam structure with histo parameters
4578 if (!PaintInit()) {
4579 fXbuf.clear();
4580 fYbuf.clear();
4581 return;
4582 }
4583
4584 // Picture surround (if new page) and page number (if requested).
4585 // Histogram surround (if not option "Same").
4586 PaintFrame();
4587
4588 // Paint histogram axis only
4589 Bool_t gridx = gPad->GetGridx();
4590 Bool_t gridy = gPad->GetGridy();
4591 if (Hoption.Axis > 0) {
4592 if (Hoption.Axis > 1) PaintAxis(kTRUE); //axis with grid
4593 else {
4594 if (gridx) gPad->SetGridx(0);
4595 if (gridy) gPad->SetGridy(0);
4597 if (gridx) gPad->SetGridx(1);
4598 if (gridy) gPad->SetGridy(1);
4599 }
4600 if ((Hoption.Same%10) ==1) Hoption.Same += 1;
4601 goto paintstat;
4602 }
4603 if (gridx || gridy) PaintAxis(kTRUE); // Draw the grid only
4604
4605 // test for options BAR or HBAR
4606 if (Hoption.Bar >= 10) {
4608 }
4609
4610 // do not draw histogram if error bars required
4611 if (!Hoption.Error) {
4612 if (Hoption.Hist && Hoption.Bar<10) PaintHist(option);
4613 }
4614
4615 // test for error bars or option E
4616 if (Hoption.Error) {
4618 if (Hoption.Hist == 2) PaintHist(option);
4619 }
4620
4622
4623 // test for associated function
4624 if (Hoption.Func) {
4629 Hoption = hoptsave;
4630 Hparam = hparsave;
4631 }
4632
4633 if (gridx) gPad->SetGridx(0);
4634 if (gridy) gPad->SetGridy(0);
4636 if (gridx) gPad->SetGridx(1);
4637 if (gridy) gPad->SetGridy(1);
4638
4639 PaintTitle(); // Draw histogram title
4640
4641 // Draw box with histogram statistics and/or fit parameters
4642paintstat:
4643 if ((Hoption.Same%10) != 1 && !fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
4644 TIter next(fFunctions);
4645 TObject *obj = nullptr;
4646 while ((obj = next())) {
4647 if (obj->InheritsFrom(TF1::Class())) break;
4648 obj = nullptr;
4649 }
4650
4651 //Stat is painted twice (first, it will be in canvas' list of primitives),
4652 //second, it will be here, this is not required on iOS.
4653 //Condition is ALWAYS true on a platform different from iOS.
4654 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode())
4655 PaintStat(gStyle->GetOptStat(),(TF1*)obj);
4656 }
4659 fXbuf.clear();
4660 fYbuf.clear();
4661}
4662
4663////////////////////////////////////////////////////////////////////////////////
4664/// [Control function to draw a table as an arrow plot](\ref HP12)
4665
4667{
4669 Double_t dx, dy, x1, x2, y1, y2, xc, yc, dxn, dyn;
4672 Double_t xrg = gPad->GetUxmin();
4673 Double_t yrg = gPad->GetUymin();
4674 Double_t xln = gPad->GetUxmax() - xrg;
4675 Double_t yln = gPad->GetUymax() - yrg;
4676 Double_t cx = (xln/Double_t(ncx))/2.;
4677 Double_t cy = (yln/Double_t(ncy))/2.;
4678 Double_t dn = 1.E-30;
4679
4680 auto arrow = new TArrow();
4681 arrow->SetAngle(30);
4682 arrow->SetFillStyle(1001);
4683 arrow->SetFillColor(fH->GetLineColor());
4684 arrow->SetLineColor(fH->GetLineColor());
4685 arrow->SetLineWidth(fH->GetLineWidth());
4686
4687 // Initialize the levels on the Z axis
4688 Int_t ncolors=0, ndivz=0;
4689 Double_t scale=0.;
4690 if (Hoption.Arrow>1) {
4692 Int_t ndiv = fH->GetContour();
4693 if (ndiv == 0 ) {
4694 ndiv = gStyle->GetNumberContours();
4695 fH->SetContour(ndiv);
4696 }
4697 ndivz = TMath::Abs(ndiv);
4698 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
4700 }
4701
4702 for (Int_t id=1;id<=2;id++) {
4703 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
4706 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
4707 xk = fXaxis->GetBinLowEdge(i);
4708 xstep = fXaxis->GetBinWidth(i);
4709 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
4710 if (i == Hparam.xfirst) {
4711 dx = fH->GetBinContent(i+1, j) - fH->GetBinContent(i, j);
4712 } else if (i == Hparam.xlast) {
4713 dx = fH->GetBinContent(i, j) - fH->GetBinContent(i-1, j);
4714 } else {
4715 dx = 0.5*(fH->GetBinContent(i+1, j) - fH->GetBinContent(i-1, j));
4716 }
4717 if (j == Hparam.yfirst) {
4718 dy = fH->GetBinContent(i, j+1) - fH->GetBinContent(i, j);
4719 } else if (j == Hparam.ylast) {
4720 dy = fH->GetBinContent(i, j) - fH->GetBinContent(i, j-1);
4721 } else {
4722 dy = 0.5*(fH->GetBinContent(i, j+1) - fH->GetBinContent(i, j-1));
4723 }
4724 if (id == 1) {
4727 } else if (id == 2) {
4728 xc = xrg + xln*(Double_t(i - Hparam.xfirst+1)-0.5)/Double_t(ncx);
4729 dxn = cx*dx/dn;
4730 x1 = xc - dxn;
4731 x2 = xc + dxn;
4732 yc = yrg + yln*(Double_t(j - Hparam.yfirst+1)-0.5)/Double_t(ncy);
4733 dyn = cy*dy/dn;
4734 y1 = yc - dyn;
4735 y2 = yc + dyn;
4736 if (Hoption.Arrow>1) {
4737 int color = Int_t(0.01+(fH->GetBinContent(i, j)-fH->GetMinimum())*scale);
4738 Int_t theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
4739 if (theColor > ncolors-1) theColor = ncolors-1;
4740 arrow->SetFillColor(gStyle->GetColorPalette(theColor));
4741 arrow->SetLineColor(gStyle->GetColorPalette(theColor));
4742 }
4743 if (TMath::Abs(x2-x1) > 0. || TMath::Abs(y2-y1) > 0.) {
4744 arrow->PaintArrow(x1, y1, x2, y2, 0.015, "|>");
4745 } else {
4746 arrow->PaintArrow(x1, y1, x2, y2, 0.005, "|>");
4747 }
4748 }
4749 }
4750 }
4751 }
4752
4754}
4755
4756////////////////////////////////////////////////////////////////////////////////
4757/// Draw axis (2D case) of an histogram.
4758///
4759/// If `drawGridOnly` is `TRUE`, only the grid is painted (if needed). This allows
4760/// to draw the grid and the axis separately. In `THistPainter::Paint` this
4761/// feature is used to make sure that the grid is drawn in the background and
4762/// the axis tick marks in the foreground of the pad.
4763
4765{
4766
4767 //On iOS, grid should not be pickable and can not be highlighted.
4768 //Condition is never true on a platform different from iOS.
4769 if (drawGridOnly && (gPad->PadInHighlightMode() || gPad->PadInSelectionMode()))
4770 return;
4771
4772 if (Hoption.Axis == -1) return;
4773 if (Hoption.Same && Hoption.Axis <= 0) return;
4774
4775 // Repainting alphanumeric labels axis on a plot done with
4776 // the option HBAR (horizontal) needs some adjustments.
4777 TAxis *xaxis = nullptr;
4778 TAxis *yaxis = nullptr;
4779 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4780 if (fXaxis->GetLabels() || fYaxis->GetLabels()) { // One axis has alphanumeric labels
4781 TIter next(gPad->GetListOfPrimitives());
4782 TObject *obj;
4783 // Check if the first TH1 of THStack in the pad is drawn with the option HBAR
4784 while ((obj = next())) {
4785 if (!obj->InheritsFrom(TH1::Class()) &&
4786 !obj->InheritsFrom(THStack::Class())) continue;
4787 TString opt = obj->GetDrawOption();
4788 opt.ToLower();
4789 // if drawn with HBAR, the axis should be inverted and the pad set to horizontal
4790 if (strstr(opt,"hbar")) {
4791 gPad->SetVertical(kFALSE);
4792 xaxis = fXaxis;
4793 yaxis = fYaxis;
4794 if (!strcmp(xaxis->GetName(),"xaxis")) {
4795 fXaxis = yaxis;
4796 fYaxis = xaxis;
4797 }
4798 }
4799 break;
4800 }
4801 }
4802 }
4803
4804 static char chopt[10] = "";
4805 Double_t gridl = 0;
4806 Int_t ndiv, ndivx, ndivy, nx1, nx2, ndivsave;
4807 Int_t useHparam = 0;
4811
4812 Double_t axmin = gPad->GetUxmin();
4813 Double_t axmax = gPad->GetUxmax();
4814 Double_t aymin = gPad->GetUymin();
4815 Double_t aymax = gPad->GetUymax();
4816 char *cw = nullptr;
4817 TGaxis axis;
4818
4819 // In case of option 'cont4' or in case of option 'same' over a 'cont4 plot'
4820 // Hparam must be use for the axis limits.
4821 if (Hoption.Contour == 14) useHparam = 1;
4822 if (Hoption.Same) {
4823 TObject *obj;
4824 TIter next(gPad->GetListOfPrimitives());
4825 while ((obj=next())) {
4826 if (strstr(obj->GetDrawOption(),"cont4")) {
4827 useHparam = 1;
4828 break;
4829 }
4830 }
4831 }
4832
4833 // Paint X axis
4834
4835 //To make X-axis selectable on iOS device.
4836 if (gPad->PadInSelectionMode())
4837 gPad->PushSelectableObject(fXaxis);
4838
4839 //This condition is ALWAYS true, unless it works on iOS (can be false on iOS).
4840 if (gPad->PadInSelectionMode() || !gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && gPad->GetSelected() == fXaxis)) {
4842 if (ndivx > 1000) {
4843 nx2 = ndivx/100;
4844 nx1 = TMath::Max(1, ndivx%100);
4845 ndivx = 100*nx2 + Int_t(Float_t(nx1)*gPad->GetAbsWNDC());
4846 }
4847 axis.SetTextAngle(0);
4849
4850 chopt[0] = 0;
4851 strlcat(chopt, "SDH",10);
4852 if (ndivx < 0) strlcat(chopt, "N",10);
4853 if (gPad->GetGridx()) {
4854 gridl = (aymax-aymin)/(gPad->GetY2() - gPad->GetY1());
4855 strlcat(chopt, "W",10);
4856 }
4857
4858 // Define X-Axis limits
4859 if (Hoption.Logx) {
4860 strlcat(chopt, "G",10);
4861 ndiv = TMath::Abs(ndivx);
4862 if (useHparam) {
4865 } else {
4866 umin = TMath::Power(10,axmin);
4867 umax = TMath::Power(10,axmax);
4868 }
4869 } else {
4870 ndiv = TMath::Abs(ndivx);
4871 if (useHparam) {
4872 umin = Hparam.xmin;
4873 umax = Hparam.xmax;
4874 } else {
4875 umin = axmin;
4876 umax = axmax;
4877 }
4878 }
4879
4880 // Display axis as time
4881 if (fXaxis->GetTimeDisplay()) {
4882 strlcat(chopt,"t",10);
4883 if (strlen(fXaxis->GetTimeFormatOnly()) == 0) {
4885 }
4886 }
4887
4888 // The main X axis can be on the bottom or on the top of the pad
4890 if (xAxisPos == 1) {
4891 // Main X axis top
4892 xAxisYPos1 = aymax;
4893 xAxisYPos2 = aymin;
4894 } else {
4895 // Main X axis bottom
4896 xAxisYPos1 = aymin;
4897 xAxisYPos2 = aymax;
4898 }
4899
4900 // Paint the main X axis (always)
4901 uminsave = umin;
4902 umaxsave = umax;
4903 ndivsave = ndiv;
4904 axis.SetOption(chopt);
4905 if (xAxisPos) {
4906 strlcat(chopt, "-",10);
4907 gridl = -gridl;
4908 }
4909 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4910 axis.SetLabelSize(0.);
4911 axis.SetTitle("");
4912 }
4915 umin, umax, ndiv, chopt, gridl, drawGridOnly);
4916
4917 // Paint additional X axis (if needed)
4918 // On iOS, this additional X axis is neither pickable, nor highlighted.
4919 // Additional checks PadInSelectionMode etc. does not effect non-iOS platform.
4920 if (gPad->GetTickx() && !gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
4921 if (xAxisPos) {
4922 cw=strstr(chopt,"-");
4923 *cw='z';
4924 } else {
4925 strlcat(chopt, "-",10);
4926 }
4927 if (gPad->GetTickx() < 2) strlcat(chopt, "U",10);
4928 if ((cw=strstr(chopt,"W"))) *cw='z';
4929 axis.SetTitle("");
4933 }
4934 }//End of "if pad in selection mode etc".
4935
4936 // Paint Y axis
4937 //On iOS, Y axis must pushed into the stack of selectable objects.
4938 if (gPad->PadInSelectionMode())
4939 gPad->PushSelectableObject(fYaxis);
4940
4941 //This conditions is ALWAYS true on a platform, different from iOS (on iOS can be true, can be false).
4942 if (gPad->PadInSelectionMode() || !gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && gPad->GetSelected() == fYaxis)) {
4945
4946 chopt[0] = 0;
4947 strlcat(chopt, "SDH",10);
4948 if (ndivy < 0) strlcat(chopt, "N",10);
4949 if (gPad->GetGridy()) {
4950 gridl = (axmax-axmin)/(gPad->GetX2() - gPad->GetX1());
4951 strlcat(chopt, "W",10);
4952 }
4953
4954 // Define Y-Axis limits
4955 if (Hoption.Logy) {
4956 strlcat(chopt, "G",10);
4957 ndiv = TMath::Abs(ndivy);
4958 if (useHparam) {
4961 } else {
4962 umin = TMath::Power(10,aymin);
4963 umax = TMath::Power(10,aymax);
4964 }
4965 } else {
4966 ndiv = TMath::Abs(ndivy);
4967 if (useHparam) {
4968 umin = Hparam.ymin;
4969 umax = Hparam.ymax;
4970 } else {
4971 umin = aymin;
4972 umax = aymax;
4973 }
4974 }
4975
4976 // Display axis as time
4977 if (fYaxis->GetTimeDisplay()) {
4978 strlcat(chopt,"t",10);
4979 if (strlen(fYaxis->GetTimeFormatOnly()) == 0) {
4981 }
4982 }
4983
4984 // The main Y axis can be on the left or on the right of the pad
4986 if (yAxisPos == 1) {
4987 // Main Y axis left
4988 yAxisXPos1 = axmax;
4989 yAxisXPos2 = axmin;
4990 } else {
4991 // Main Y axis right
4992 yAxisXPos1 = axmin;
4993 yAxisXPos2 = axmax;
4994 }
4995
4996 // Paint the main Y axis (always)
4997 uminsave = umin;
4998 umaxsave = umax;
4999 ndivsave = ndiv;
5000 axis.SetOption(chopt);
5001 if (yAxisPos) {
5002 strlcat(chopt, "+L",10);
5003 gridl = -gridl;
5004 }
5005 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
5006 axis.SetLabelSize(0.);
5007 axis.SetTitle("");
5008 }
5011 umin, umax, ndiv, chopt, gridl, drawGridOnly);
5012
5013 // Paint the additional Y axis (if needed)
5014 // Additional checks for pad mode are required on iOS: this "second" axis is
5015 // neither pickable, nor highlighted. Additional checks have no effect on non-iOS platform.
5016 if (gPad->GetTicky() && !gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
5017 if (gPad->GetTicky() < 2) {
5018 strlcat(chopt, "U",10);
5020 } else {
5021 strlcat(chopt, "+L",10);
5022 }
5023 if ((cw=strstr(chopt,"W"))) *cw='z';
5024 axis.SetTitle("");
5028 }
5029 }//End of "if pad is in selection mode etc."
5030
5031 // Reset the axis if they have been inverted in case of option HBAR
5032 if (xaxis) {
5033 fXaxis = xaxis;
5034 fYaxis = yaxis;
5035 }
5036}
5037
5038////////////////////////////////////////////////////////////////////////////////
5039/// [Draw a bar-chart in a normal pad.](\ref HP10)
5040
5042{
5043
5044 Int_t bar = Hoption.Bar - 10;
5048 TBox box;
5050 if (hcolor == gPad->GetFrameFillColor()) ++hcolor;
5052 box.SetFillColor(hcolor);
5053 box.SetFillStyle(hstyle);
5054 box.SetLineStyle(fH->GetLineStyle());
5055 box.SetLineColor(fH->GetLineColor());
5056 box.SetLineWidth(fH->GetLineWidth());
5057 for (Int_t bin=fXaxis->GetFirst();bin<=fXaxis->GetLast();bin++) {
5058 y = fH->GetBinContent(bin);
5059 xmin = gPad->XtoPad(fXaxis->GetBinLowEdge(bin));
5060 xmax = gPad->XtoPad(fXaxis->GetBinUpEdge(bin));
5061 ymin = gPad->GetUymin();
5062 ymax = gPad->YtoPad(y);
5063 if (ymax < gPad->GetUymin()) continue;
5064 if (ymax > gPad->GetUymax()) ymax = gPad->GetUymax();
5065 if (ymin < gPad->GetUymin()) ymin = gPad->GetUymin();
5066 if (Hoption.MinimumZero && ymin < 0)
5067 ymin=TMath::Min(0.,gPad->GetUymax());
5068 w = (xmax-xmin)*width;
5069 xmin += offset*(xmax-xmin);
5070 xmax = xmin + w;
5071 if (bar < 1) {
5072 box.PaintBox(xmin,ymin,xmax,ymax);
5073 } else {
5074 umin = xmin + bar*(xmax-xmin)/10.;
5075 umax = xmax - bar*(xmax-xmin)/10.;
5076 box.SetFillColor(TColor::GetColorBright(hcolor)); //bright
5077 box.PaintBox(xmin,ymin,umin,ymax);
5078 box.SetFillColor(hcolor);
5079 box.PaintBox(umin,ymin,umax,ymax);
5080 box.SetFillColor(TColor::GetColorDark(hcolor)); //dark
5081 box.PaintBox(umax,ymin,xmax,ymax);
5082 }
5083 }
5084}
5085
5086////////////////////////////////////////////////////////////////////////////////
5087/// [Draw a bar char in a rotated pad (X vertical, Y horizontal)](\ref HP10)
5088
5090{
5091
5092 gPad->SetVertical(kFALSE);
5093
5094 PaintInitH();
5095
5096 TAxis *xaxis = fXaxis;
5097 TAxis *yaxis = fYaxis;
5098 if (!strcmp(xaxis->GetName(),"xaxis")) {
5099 fXaxis = yaxis;
5100 fYaxis = xaxis;
5101 }
5102
5103 PaintFrame();
5105
5106 Int_t bar = Hoption.Bar - 20;
5110 TBox box;
5112 if (hcolor == gPad->GetFrameFillColor()) ++hcolor;
5114 box.SetFillColor(hcolor);
5115 box.SetFillStyle(hstyle);
5116 box.SetLineStyle(fH->GetLineStyle());
5117 box.SetLineColor(fH->GetLineColor());
5118 box.SetLineWidth(fH->GetLineWidth());
5119 for (Int_t bin=fYaxis->GetFirst();bin<=fYaxis->GetLast();bin++) {
5120 ymin = gPad->YtoPad(fYaxis->GetBinLowEdge(bin));
5121 ymax = gPad->YtoPad(fYaxis->GetBinUpEdge(bin));
5122 xmin = gPad->GetUxmin();
5123 xmax = gPad->XtoPad(fH->GetBinContent(bin));
5124 if (xmax < gPad->GetUxmin()) continue;
5125 if (xmax > gPad->GetUxmax()) xmax = gPad->GetUxmax();
5126 if (xmin < gPad->GetUxmin()) xmin = gPad->GetUxmin();
5127 if (Hoption.MinimumZero && xmin < 0)
5128 xmin=TMath::Min(0.,gPad->GetUxmax());
5129 w = (ymax-ymin)*width;
5130 ymin += offset*(ymax-ymin);
5131 ymax = ymin + w;
5132 if (bar < 1) {
5133 box.PaintBox(xmin,ymin,xmax,ymax);
5134 } else {
5135 umin = ymin + bar*(ymax-ymin)/10.;
5136 umax = ymax - bar*(ymax-ymin)/10.;
5137 box.SetFillColor(TColor::GetColorDark(hcolor)); //dark
5138 box.PaintBox(xmin,ymin,xmax,umin);
5139 box.SetFillColor(hcolor);
5140 box.PaintBox(xmin,umin,xmax,umax);
5141 box.SetFillColor(TColor::GetColorBright(hcolor)); //bright
5142 box.PaintBox(xmin,umax,xmax,ymax);
5143 }
5144 }
5145
5146 PaintTitle();
5147
5148 // Draw box with histogram statistics and/or fit parameters
5149 if ((Hoption.Same%10) != 1 && !fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
5150 TIter next(fFunctions);
5151 TObject *obj = nullptr;
5152 while ((obj = next())) {
5153 if (obj->InheritsFrom(TF1::Class())) break;
5154 obj = nullptr;
5155 }
5156 PaintStat(gStyle->GetOptStat(),(TF1*)obj);
5157 }
5158
5159 fXaxis = xaxis;
5160 fYaxis = yaxis;
5161}
5162
5163////////////////////////////////////////////////////////////////////////////////
5164/// [Control function to draw a 2D histogram as a box plot](\ref HP13)
5165
5167{
5168
5171 if (fH->GetFillColor() == 0) fH->SetFillStyle(0);
5172 if (Hoption.Box == 11) fH->SetFillStyle(1001);
5173 fH->TAttLine::Modify();
5174 fH->TAttFill::Modify();
5175
5176 Double_t z, xk,xstep, yk, ystep, xcent, ycent, xlow, xup, ylow, yup;
5177 Double_t ux1 = gPad->PixeltoX(1);
5178 Double_t ux0 = gPad->PixeltoX(0);
5179 Double_t uy1 = gPad->PixeltoY(1);
5180 Double_t uy0 = gPad->PixeltoY(0);
5181 Double_t dxmin = 0.51*(gPad->PadtoX(ux1)-gPad->PadtoX(ux0));
5182 Double_t dymin = 0.51*(gPad->PadtoY(uy0)-gPad->PadtoY(uy1));
5183
5184 Double_t zmin = TMath::Max(fH->GetMinimum(),0.);
5187 Double_t zminlin = zmin, zmaxlin = zmax;
5188
5189 // In case of option SAME, zmin and zmax values are taken from the
5190 // first plotted 2D histogram.
5191 if (Hoption.Same > 0 && Hoption.Same < 10) {
5192 TH2 *h2;
5193 TIter next(gPad->GetListOfPrimitives());
5194 while ((h2 = (TH2 *)next())) {
5195 if (!h2->InheritsFrom(TH2::Class())) continue;
5196 zmin = TMath::Max(h2->GetMinimum(), 0.);
5197 zmax = TMath::Max(TMath::Abs(h2->GetMaximum()),
5198 TMath::Abs(h2->GetMinimum()));
5199 zminlin = zmin;
5200 zmaxlin = zmax;
5201 if (Hoption.Logz) {
5202 if (zmin <= 0) {
5203 zmin = TMath::Log10(zmax*0.001);
5204 } else {
5205 zmin = TMath::Log10(zmin);
5206 }
5207 zmax = TMath::Log10(zmax);
5208 }
5209 break;
5210 }
5211 } else {
5212 if (Hoption.Logz) {
5213 if (zmin > 0) {
5214 zmin = TMath::Log10(zmin);
5215 zmax = TMath::Log10(zmax);
5216 } else {
5217 return;
5218 }
5219 }
5220 }
5221
5222 Double_t zratio, dz = zmax - zmin;
5224 if (fH->GetMinimum()<0) kZminNeg = kTRUE;
5226
5227 // Define the dark and light colors the "button style" boxes.
5228 Color_t color = fH->GetFillColor();
5229 Color_t light=0, dark=0;
5230 if (Hoption.Box == 11) {
5232 dark = TColor::GetColorDark(color);
5233 }
5234
5235 // Loop over all the bins and draw the boxes
5236 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
5239 ycent = 0.5*ystep;
5240 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
5241 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
5242 xk = fXaxis->GetBinLowEdge(i);
5243 xstep = fXaxis->GetBinWidth(i);
5244 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
5245 xcent = 0.5*xstep;
5246 z = Hparam.factor*fH->GetBinContent(bin);
5247 kZNeg = kFALSE;
5248
5249 if (TMath::Abs(z) < zminlin) continue; // Can be the case with ...
5250 if (TMath::Abs(z) > zmaxlin) z = zmaxlin; // ... option Same
5251 if (kZminNeg && z==0) continue; // Do not draw empty bins if case of histo with negative bins.
5252
5253 if (z < 0) {
5254 if (Hoption.Logz) continue;
5255 z = -z;
5256 kZNeg = kTRUE;
5257 }
5258 if (Hoption.Logz) {
5259 if (z != 0) z = TMath::Log10(z);
5260 else z = zmin;
5261 }
5262
5263 if (dz == 0) continue;
5264 zratio = TMath::Sqrt((z-zmin)/dz);
5265 if (zratio == 0) continue;
5266
5267 xup = xcent*zratio + xk + xcent;
5268 xlow = 2*(xk + xcent) - xup;
5269 if (xup-xlow < dxmin) xup = xlow+dxmin;
5270 if (Hoption.Logx) {
5271 if (xup > 0) xup = TMath::Log10(xup);
5272 else continue;
5273 if (xlow > 0) xlow = TMath::Log10(xlow);
5274 else continue;
5275 }
5276
5277 yup = ycent*zratio + yk + ycent;
5278 ylow = 2*(yk + ycent) - yup;
5279 if (yup-ylow < dymin) yup = ylow+dymin;
5280 if (Hoption.Logy) {
5281 if (yup > 0) yup = TMath::Log10(yup);
5282 else continue;
5283 if (ylow > 0) ylow = TMath::Log10(ylow);
5284 else continue;
5285 }
5286
5287 xlow = TMath::Max(xlow, gPad->GetUxmin());
5288 ylow = TMath::Max(ylow, gPad->GetUymin());
5289 xup = TMath::Min(xup , gPad->GetUxmax());
5290 yup = TMath::Min(yup , gPad->GetUymax());
5291
5292 if (xlow >= xup) continue;
5293 if (ylow >= yup) continue;
5294
5295 if (Hoption.Box == 1) {
5296 fH->SetFillColor(color);
5297 fH->TAttFill::Modify();
5298 gPad->PaintBox(xlow, ylow, xup, yup);
5299 if (kZNeg) {
5300 gPad->PaintLine(xlow, ylow, xup, yup);
5301 gPad->PaintLine(xlow, yup, xup, ylow);
5302 }
5303 } else if (Hoption.Box == 11) {
5304 // Draw the center of the box
5305 fH->SetFillColor(color);
5306 fH->TAttFill::Modify();
5307 gPad->PaintBox(xlow, ylow, xup, yup);
5308
5309 // Draw top&left part of the box
5310 Double_t x[7], y[7];
5311 Double_t bwidth = 0.1;
5312 x[0] = xlow; y[0] = ylow;
5313 x[1] = xlow + bwidth*(xup-xlow); y[1] = ylow + bwidth*(yup-ylow);
5314 x[2] = x[1]; y[2] = yup - bwidth*(yup-ylow);
5315 x[3] = xup - bwidth*(xup-xlow); y[3] = y[2];
5316 x[4] = xup; y[4] = yup;
5317 x[5] = xlow; y[5] = yup;
5318 x[6] = xlow; y[6] = ylow;
5319 if (kZNeg) fH->SetFillColor(dark);
5320 else fH->SetFillColor(light);
5321 fH->TAttFill::Modify();
5322 gPad->PaintFillArea(7, x, y);
5323
5324 // Draw bottom&right part of the box
5325 x[0] = xlow; y[0] = ylow;
5326 x[1] = xlow + bwidth*(xup-xlow); y[1] = ylow + bwidth*(yup-ylow);
5327 x[2] = xup - bwidth*(xup-xlow); y[2] = y[1];
5328 x[3] = x[2]; y[3] = yup - bwidth*(yup-ylow);
5329 x[4] = xup; y[4] = yup;
5330 x[5] = xup; y[5] = ylow;
5331 x[6] = xlow; y[6] = ylow;
5332 if (kZNeg) fH->SetFillColor(light);
5333 else fH->SetFillColor(dark);
5334 fH->TAttFill::Modify();
5335 gPad->PaintFillArea(7, x, y);
5336 }
5337 }
5338 }
5339
5343 fH->TAttFill::Modify();
5344}
5345
5346
5347
5348////////////////////////////////////////////////////////////////////////////////
5349/// [Control function to draw a 2D histogram as a candle (box) plot or violin plot](\ref HP14)
5350
5352{
5353 TH1D *hproj = nullptr;
5354 TH2D *h2 = (TH2D*)fH;
5355
5358 myCandle.SetMarkerColor(fH->GetLineColor());
5359 myCandle.SetLineColor(fH->GetLineColor());
5360 myCandle.SetLineWidth(fH->GetLineWidth());
5361 myCandle.SetFillColor(fH->GetFillColor());
5362 myCandle.SetFillStyle(fH->GetFillStyle());
5363 myCandle.SetMarkerSize(fH->GetMarkerSize());
5364 myCandle.SetMarkerStyle(fH->GetMarkerStyle());
5366
5367 Bool_t swapXY = myCandle.IsHorizontal();
5368 const Double_t standardCandleWidth = 0.66;
5369 const Double_t standardHistoWidth = 0.8;
5370
5371 double allMaxContent = 0, allMaxIntegral = 0;
5372 if (myCandle.IsViolinScaled())
5374
5375 if (!swapXY) { // Vertical candle
5376 //Determining the slice with the maximum integral - if necessary
5377 if (myCandle.IsCandleScaled())
5378 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast; i++) {
5379 hproj = h2->ProjectionY("_px", i, i);
5380 if (hproj->Integral() > allMaxIntegral) allMaxIntegral = hproj->Integral();
5381 }
5382 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast; i++) {
5384 Double_t binWidth = fXaxis->GetBinWidth(i);
5385 hproj = h2->ProjectionY("_px", i, i);
5386 if (hproj->GetEntries() != 0) {
5388 Double_t offset = fH->GetBarOffset()*binWidth;
5389 double myMaxContent = hproj->GetBinContent(hproj->GetMaximumBin());
5390 double myIntegral = hproj->Integral();
5392 if (candleWidth > 0.999 && candleWidth < 1.001) {
5395 }
5396 if (Hoption.Logz && myMaxContent > 0) {
5398 if (myCandle.IsViolinScaled() && myMaxContent > 0 && allMaxContent > 0)
5400 } else if (myCandle.IsViolinScaled() && (allMaxContent > 0))
5402 if (myCandle.IsCandleScaled() && (allMaxIntegral > 0))
5404
5405 myCandle.SetAxisPosition(binPosX+binWidth/2. + offset);
5406 myCandle.SetCandleWidth(candleWidth*binWidth);
5407 myCandle.SetHistoWidth(histoWidth*binWidth);
5408 myCandle.SetHistogram(hproj);
5409 myCandle.Paint();
5410 }
5411 }
5412 } else { // Horizontal candle
5413 //Determining the slice with the maximum integral - if necessary
5414 if (myCandle.IsCandleScaled())
5415 for (Int_t i=Hparam.yfirst; i<=Hparam.ylast; i++) {
5416 hproj = h2->ProjectionX("_py", i, i);
5417 if (hproj->Integral() > allMaxIntegral) allMaxIntegral = hproj->Integral();
5418 }
5419 for (Int_t i=Hparam.yfirst; i<=Hparam.ylast; i++) {
5421 Double_t binWidth = fYaxis->GetBinWidth(i);
5422 hproj = h2->ProjectionX("_py", i, i);
5423 if (hproj->GetEntries() != 0) {
5425 Double_t offset = fH->GetBarOffset()*binWidth;
5426 double myMaxContent = hproj->GetBinContent(hproj->GetMaximumBin());
5427 double myIntegral = hproj->Integral();
5429 if (candleWidth > 0.999 && candleWidth < 1.001) {
5432 }
5433 if (Hoption.Logz && myMaxContent > 0) {
5435 if (myCandle.IsViolinScaled() && myMaxContent > 0 && allMaxContent > 0)
5437 } else if (myCandle.IsViolinScaled() && (allMaxContent > 0))
5439 if (myCandle.IsCandleScaled() && (allMaxIntegral > 0))
5441
5442 myCandle.SetAxisPosition(binPosY+binWidth/2. + offset);
5443 myCandle.SetCandleWidth(candleWidth*binWidth);
5444 myCandle.SetHistoWidth(histoWidth*binWidth);
5445 myCandle.SetHistogram(hproj);
5446 myCandle.Paint();
5447 }
5448 }
5449 }
5450 delete hproj;
5451}
5452
5453
5454
5455////////////////////////////////////////////////////////////////////////////////
5456/// Returns the rendering regions for an axis to use in the COL2 option
5457///
5458/// The algorithm analyses the size of the axis compared to the size of
5459/// the rendering region. It figures out the boundaries to use for each color
5460/// of the rendering region. Only one axis is computed here.
5461///
5462/// This allows for a single computation of the boundaries before iterating
5463/// through all of the bins.
5464///
5465/// \param pAxis the axis to consider
5466/// \param nPixels the number of pixels to render axis into
5467/// \param isLog whether the axis is log scale
5468
5469std::vector<THistRenderingRegion>
5471{
5472 std::vector<THistRenderingRegion> regions;
5473
5474 enum STRATEGY { Bins, Pixels } strategy;
5475
5476 Int_t nBins = (pAxis->GetLast() - pAxis->GetFirst() + 1);
5477
5478 if (nBins >= nPixels) {
5479 // more bins than pixels... we should loop over pixels and sample
5480 strategy = Pixels;
5481 } else {
5482 // fewer bins than pixels... we should loop over bins
5483 strategy = Bins;
5484 }
5485
5486 if (isLog) {
5487
5488 Double_t xMin = pAxis->GetBinLowEdge(pAxis->GetFirst());
5489 Int_t binOffset=0;
5490 while (xMin <= 0 && ((pAxis->GetFirst()+binOffset) != pAxis->GetLast()) ) {
5491 binOffset++;
5492 xMin = pAxis->GetBinLowEdge(pAxis->GetFirst()+binOffset);
5493 }
5494 if (xMin <= 0) {
5495 // this should cause an error if we have
5496 return regions;
5497 }
5498 Double_t xMax = pAxis->GetBinUpEdge(pAxis->GetLast());
5499
5500 if (strategy == Bins) {
5501 // logarithmic plot. we find the pixel for the bin
5502 // pixel = eta * log10(V) - alpha
5503 // where eta = nPixels/(log10(Vmax)-log10(Vmin))
5504 // and alpha = nPixels*log10(Vmin)/(log10(Vmax)-log10(Vmin))
5505 // and V is axis value
5506 Double_t eta = (nPixels-1.0)/(TMath::Log10(xMax) - TMath::Log10(xMin));
5507 Double_t offset = -1.0 * eta * TMath::Log10(xMin);
5508
5509 for (Int_t bin=pAxis->GetFirst()+binOffset; bin<=pAxis->GetLast(); bin++) {
5510
5511 // linear plot. we simply need to find the appropriate bin
5512 // for the
5513 Double_t xLowValue = pAxis->GetBinLowEdge(bin);
5514 Double_t xUpValue = pAxis->GetBinUpEdge(bin);
5517 THistRenderingRegion region = {std::make_pair(xPx0, xPx1),
5518 std::make_pair(bin, bin+1)};
5519 regions.push_back(region);
5520 }
5521
5522 } else {
5523
5524 // loop over pixels
5525
5526 Double_t beta = (TMath::Log10(xMax) - TMath::Log10(xMin))/(nPixels-1.0);
5527
5528 for (Int_t pixelIndex=0; pixelIndex<(nPixels-1); pixelIndex++) {
5529 // linear plot
5530 Int_t binLow = pAxis->FindBin(xMin*TMath::Power(10.0, beta*pixelIndex));
5531 Int_t binHigh = pAxis->FindBin(xMin*TMath::Power(10.0, beta*(pixelIndex+1)));
5532 THistRenderingRegion region = { std::make_pair(pixelIndex, pixelIndex+1),
5533 std::make_pair(binLow, binHigh)};
5534 regions.push_back(region);
5535 }
5536 }
5537 } else {
5538 // standard linear plot
5539
5540 if (strategy == Bins) {
5541 // loop over bins
5542 for (Int_t bin=pAxis->GetFirst(); bin<=pAxis->GetLast(); bin++) {
5543
5544 // linear plot. we simply need to find the appropriate bin
5545 // for the
5546 Int_t xPx0 = ((bin - pAxis->GetFirst()) * nPixels)/nBins;
5547 Int_t xPx1 = xPx0 + nPixels/nBins;
5548
5549 // make sure we don't compute beyond our bounds
5550 if (xPx1>= nPixels) xPx1 = nPixels-1;
5551
5552 THistRenderingRegion region = {std::make_pair(xPx0, xPx1),
5553 std::make_pair(bin, bin+1)};
5554 regions.push_back(region);
5555 }
5556 } else {
5557 // loop over pixels
5559 // linear plot
5560 Int_t binLow = (nBins*pixelIndex)/nPixels + pAxis->GetFirst();
5561 Int_t binHigh = binLow + nBins/nPixels;
5562 THistRenderingRegion region = { std::make_pair(pixelIndex, pixelIndex+1),
5563 std::make_pair(binLow, binHigh)};
5564 regions.push_back(region);
5565 }
5566 }
5567 }
5568
5569 return regions;
5570}
5571
5572////////////////////////////////////////////////////////////////////////////////
5573/// [Rendering scheme for the COL2 and COLZ2 options] (\ref HP14)
5574
5576{
5577
5578 if (Hoption.System != kCARTESIAN) {
5579 Error("THistPainter::PaintColorLevelsFast(Option_t*)",
5580 "Only cartesian coordinates supported by 'COL2' option. Using 'COL' option instead.");
5581 PaintColorLevels(nullptr);
5582 return;
5583 }
5584
5585 Double_t z;
5586
5587 // Use existing max or min values. If either is already set
5588 // the appropriate value to use.
5589 Double_t zmin = fH->GetMinimumStored();
5590 Double_t zmax = fH->GetMaximumStored();
5591 Double_t originalZMin = zmin;
5592 Double_t originalZMax = zmax;
5593 if ((zmin == -1111) && (zmax == -1111)) {
5594 fH->GetMinimumAndMaximum(zmin, zmax);
5595 fH->SetMinimum(zmin);
5596 fH->SetMaximum(zmax);
5597 } else if (zmin == -1111) {
5598 zmin = fH->GetMinimum();
5599 fH->SetMinimum(zmin);
5600 } else if (zmax == -1111) {
5601 zmax = fH->GetMaximum();
5602 fH->SetMaximum(zmax);
5603 }
5604
5605 Double_t dz = zmax - zmin;
5606 if (dz <= 0) { // Histogram filled with a constant value
5607 zmax += 0.1*TMath::Abs(zmax);
5608 zmin -= 0.1*TMath::Abs(zmin);
5609 dz = zmax - zmin;
5610 }
5611
5612 if (Hoption.Logz) {
5613 if (zmin > 0) {
5614 zmin = TMath::Log10(zmin);
5615 zmax = TMath::Log10(zmax);
5616 dz = zmax - zmin;
5617 } else {
5618 Error("THistPainter::PaintColorLevelsFast(Option_t*)",
5619 "Cannot plot logz because bin content is less than 0.");
5620 return;
5621 }
5622 }
5623
5624 // Initialize the levels on the Z axis
5625 Int_t ndiv = fH->GetContour();
5626 if (ndiv == 0 ) {
5627 ndiv = gStyle->GetNumberContours();
5628 fH->SetContour(ndiv);
5629 }
5630 std::vector<Double_t> colorBounds(ndiv);
5631 std::vector<Double_t> contours(ndiv, 0);
5632 if (!fH->TestBit(TH1::kUserContour)) {
5633 fH->SetContour(ndiv);
5634 } else {
5635 fH->GetContour(contours.data());
5636 }
5637
5638 Double_t step = 1.0/ndiv;
5639 for (Int_t i=0; i<ndiv; ++i) {
5640 colorBounds[i] = step*i;
5641 }
5642
5643 auto pFrame = gPad->GetFrame();
5644 Int_t px0 = gPad->XtoPixel(pFrame->GetX1());
5645 Int_t px1 = gPad->XtoPixel(pFrame->GetX2());
5646 Int_t py0 = gPad->YtoPixel(pFrame->GetY1());
5647 Int_t py1 = gPad->YtoPixel(pFrame->GetY2());
5648 Int_t nXPixels = px1-px0;
5649 Int_t nYPixels = py0-py1; // y=0 is at the top of the screen
5650
5651 std::vector<Double_t> buffer(nXPixels*nYPixels, 0);
5652
5655 if (xRegions.empty() || yRegions.empty()) {
5656 Error("THistPainter::PaintColorLevelFast(Option_t*)",
5657 "Encountered error while computing rendering regions.");
5658 return;
5659 }
5660
5663 Double_t minValue = 1.;
5664 Double_t maxValue = 0.;
5665 for (auto& yRegion : yRegions) {
5666 for (auto& xRegion : xRegions ) {
5667
5668 const auto& xBinRange = xRegion.fBinRange;
5669 const auto& yBinRange = yRegion.fBinRange;
5670
5671 // sample the range
5672 z = fH->GetBinContent(xBinRange.second-1, yBinRange.second-1);
5673
5674 if (Hoption.Logz) {
5675 if (z > 0) z = TMath::Log10(z);
5676 else z = zmin;
5677 }
5678
5679 // obey the user's max and min values if they were set
5680 if (z > zmax) z = zmax;
5681 if (z < zmin) z = zmin;
5682
5684 // contours are absolute values
5685 auto index = TMath::BinarySearch(contours.size(), contours.data(), z);
5686 z = colorBounds[index];
5687 } else {
5688 Int_t index = 0;
5689 if (dz != 0) {
5690 index = 0.001 + ((z - zmin)/dz)*ndiv;
5691 }
5692
5693 if (index == static_cast<Int_t>(colorBounds.size())) {
5694 index--;
5695 }
5696
5697 // Do a little bookkeeping to use later for getting libAfterImage to produce
5698 // the correct colors
5699 if (index == 0) {
5700 minExists = kTRUE;
5701 } else if (index == static_cast<Int_t>(colorBounds.size()-1)) {
5702 maxExists = kTRUE;
5703 }
5704
5705 z = colorBounds[index];
5706
5707 if (z < minValue) {
5708 minValue = z;
5709 }
5710 if (z > maxValue) {
5711 maxValue = z;
5712 }
5713 }
5714
5715 // fill in the actual pixels
5716 const auto& xPixelRange = xRegion.fPixelRange;
5717 const auto& yPixelRange = yRegion.fPixelRange;
5718 for (Int_t xPx = xPixelRange.first; xPx <= xPixelRange.second; ++xPx) {
5719 for (Int_t yPx = yPixelRange.first; yPx <= yPixelRange.second; ++yPx) {
5721 buffer[pixel] = z;
5722 }
5723 }
5724 } // end px loop
5725 } // end py loop
5726
5727 // This is a bit of a hack to ensure that we span the entire color range and
5728 // don't screw up the colors for a sparse histogram. No one will notice that I set a
5729 // single pixel on the edge of the image to a different color. This is even more
5730 // true because the chosen pixels will be covered by the axis.
5731 if (minValue != maxValue) {
5732 if ( !minExists) {
5733 buffer.front() = 0;
5734 }
5735
5736 if ( !maxExists) {
5737 buffer[buffer.size()-nXPixels] = 0.95;
5738 }
5739 }
5740
5741 // Generate the TImage
5744 pImage->SetImageQuality(TAttImage::kImgBest);
5745 pImage->SetImage(buffer.data(), nXPixels, nYPixels, pPalette);
5746 delete pPalette;
5747
5748 auto pp = gPad->GetPainter();
5749 if (pp)
5750 pp->DrawImage(pImage, px0, py1);
5751
5752 delete pImage;
5753
5754 if (Hoption.Zscale)
5755 PaintPalette();
5756
5757 // Reset the maximum and minimum values to their original values
5758 // when this function was called. If we don't do this, an initial
5759 // value of -1111 will be replaced with the true max or min values.
5762}
5763
5764////////////////////////////////////////////////////////////////////////////////
5765/// [Control function to draw a 2D histogram as a color plot.](\ref HP14)
5766
5768{
5769 Double_t z, e, zc, xk, xstep, yk, ystep, xlow, xup, ylow, yup;
5770
5771 Double_t zmin = fH->GetMinimum();
5772 Double_t zmax = fH->GetMaximum();
5773
5774 Double_t dz = zmax - zmin;
5775 if (dz <= 0) { // Histogram filled with a constant value
5776 zmax += 0.1*TMath::Abs(zmax);
5777 zmin -= 0.1*TMath::Abs(zmin);
5778 dz = zmax - zmin;
5779 }
5780
5781 // In case of option SAME, zmin and zmax values are taken from the
5782 // first plotted 2D histogram.
5783 if (Hoption.Same > 0 && Hoption.Same < 10) {
5784 TH2 *h2;
5785 TIter next(gPad->GetListOfPrimitives());
5786 while ((h2 = (TH2 *)next())) {
5787 if (!h2->InheritsFrom(TH2::Class())) continue;
5788 zmin = h2->GetMinimum();
5789 zmax = h2->GetMaximum();
5790 fH->SetMinimum(zmin);
5791 fH->SetMaximum(zmax);
5792 if (Hoption.Logz) {
5793 if (zmin <= 0) {
5794 zmin = TMath::Log10(zmax*0.001);
5795 } else {
5796 zmin = TMath::Log10(zmin);
5797 }
5798 zmax = TMath::Log10(zmax);
5799 }
5800 dz = zmax - zmin;
5801 break;
5802 }
5803 } else {
5804 if (Hoption.Logz) {
5805 if (zmin > 0) {
5806 zmin = TMath::Log10(zmin);
5807 zmax = TMath::Log10(zmax);
5808 dz = zmax - zmin;
5809 } else {
5810 return;
5811 }
5812 }
5813 }
5814
5817 fH->SetFillStyle(1001);
5818 fH->TAttFill::Modify();
5819
5820 // Initialize the levels on the Z axis
5822 Int_t ndiv = fH->GetContour();
5823 if (ndiv == 0) {
5824 ndiv = gStyle->GetNumberContours();
5825 fH->SetContour(ndiv);
5826 }
5827 Int_t ndivz = TMath::Abs(ndiv);
5828 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
5829 Double_t scale = (dz ? ndivz / dz : 1.0);
5830
5831 Double_t xmin = gPad->GetUxmin();
5832 Double_t xmax = gPad->GetUxmax();
5833 Double_t ymin = gPad->GetUymin();
5834 Double_t ymax = gPad->GetUymax();
5835
5836 // range used for polar coordinates
5837 Double_t pxmin = xmin, pxmax = xmax, pymin = ymin, pymax = ymax, pkr = 0.5;
5838 if ((Hoption.System == kPOLAR) && (Hoption.Polar == 2)) {
5839 pxmin = fXaxis->GetXmin();
5840 pxmax = fXaxis->GetXmax();
5841 if (Hoption.Logx) {
5842 if (pxmax <= 0)
5843 return;
5845 if (pxmin <= 0)
5846 pxmin = pxmax - 5;
5847 else
5849 }
5850 pkr = 0.45; // makes fixed range more pretty
5851 pymin = fYaxis->GetXmin();
5852 pymax = fYaxis->GetXmax();
5853 if (Hoption.Logy) {
5854 if (pymax <= 0)
5855 return;
5857 if (pymin <= 0)
5858 pymin = pymax - 5;
5859 else
5861 } else if ((pymax > 0) && (pymin > 0)) {
5862 // force minimal radius to 0 to display natural polar graphics
5863 pymin = 0;
5864 }
5865 }
5866
5867 if ((Hoption.System == kPOLAR) && (Hoption.Polar == 3)) {
5868 // do not touch boundaries when draw without axis histogram
5869 if (!Hoption.Same)
5870 pkr = 0.45;
5871 // for natural coordinates force minimal radius to 0
5872 if (!Hoption.Logy && (pymax > 0))
5873 pymin = 0;
5874 }
5875
5876 Int_t color;
5877 TProfile2D* prof2d = dynamic_cast<TProfile2D*>(fH);
5878 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
5881 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
5882 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
5883 xk = fXaxis->GetBinLowEdge(i);
5884 xstep = fXaxis->GetBinWidth(i);
5885 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
5886 z = fH->GetBinContent(bin);
5887 e = fH->GetBinError(bin);
5888 // if fH is a profile histogram do not draw empty bins
5889 if (prof2d) {
5890 const Double_t binEntries = prof2d->GetBinEntries(bin);
5891 if (binEntries == 0)
5892 continue;
5893 } else {
5894 // don't draw the empty bins for non-profile histograms
5895 // with positive content
5896 if (z == 0 && e == 0) {
5897 if (zmin >= 0 || Hoption.Logz) continue;
5898 if (Hoption.Color == 2) continue;
5899 }
5900 }
5901
5902 if (Hoption.Logz)
5903 z = z > 0 ? TMath::Log10(z) : zmin;
5904 if (z < zmin && !Hoption.Zero)
5905 continue;
5906 xup = xk + xstep;
5907 xlow = xk;
5908 if (Hoption.Logx) {
5909 if ((xup <= 0) || (xlow <= 0))
5910 continue;
5911 xup = TMath::Log10(xup);
5912 xlow = TMath::Log10(xlow);
5913 }
5914 yup = yk + ystep;
5915 ylow = yk;
5916 if (Hoption.Logy) {
5917 if ((yup <= 0) || (ylow <= 0))
5918 continue;
5919 yup = TMath::Log10(yup);
5920 ylow = TMath::Log10(ylow);
5921 }
5922 if ((xup < xmin) || (yup < ymin) || (xlow > xmax) || (ylow > ymax))
5923 continue;
5924 if (xlow < xmin)
5925 xlow = xmin;
5926 if (ylow < ymin)
5927 ylow = ymin;
5928 if (xup > xmax)
5929 xup = xmax;
5930 if (yup > ymax)
5931 yup = ymax;
5932
5934 zc = fH->GetContourLevelPad(0);
5935 if (z < zc) continue;
5936 color = -1;
5937 for (Int_t k=0; k<ndiv; k++) {
5938 zc = fH->GetContourLevelPad(k);
5939 if (z < zc) {
5940 continue;
5941 } else {
5942 color++;
5943 }
5944 }
5945 } else {
5946 color = Hoption.Zero ? Int_t(0.01+(std::max(z, zmin)-zmin)*scale) : Int_t(0.01+(z-zmin)*scale);
5947 }
5948
5949 Int_t theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
5950 if (theColor > ncolors-1)
5951 theColor = ncolors-1;
5953 if (Hoption.System != kPOLAR) {
5955 fH->TAttFill::Modify();
5956 gPad->PaintBox(xlow, ylow, xup, yup);
5957 } else {
5958 Double_t midx = (xmin + xmax) / 2;
5959 Double_t midy = (ymin + ymax) / 2;
5960 Double_t rx = xmax - xmin;
5961 Double_t ry = ymax - ymin;
5962 Double_t a1, a2;
5963
5964 if (Hoption.Polar == 3) {
5965 a1 = xlow / TMath::Pi() * 180;
5966 a2 = xup / TMath::Pi() * 180;
5967 } else {
5968 a1 = ((xlow - pxmin) / (pxmax - pxmin) - 0.5) * 360;
5969 a2 = ((xup - pxmin) / (pxmax - pxmin) - 0.5) * 360;
5970 }
5971 Double_t r1 = (ylow - pymin) / (pymax - pymin) * rx * pkr;
5972 Double_t r2 = (yup - pymin) / (pymax - pymin) * rx * pkr;
5973
5974 TCrown crown(midx, midy, r1, r2, a1, a2);
5975 crown.SetYXRatio(rx > 0 ? ry / rx : 1);
5976 crown.SetFillColor(fillColor);
5977 crown.SetLineColor(fH->GetLineColor());
5978 crown.SetLineWidth(fH->GetLineWidth());
5979 crown.SetLineStyle(fH->GetLineStyle());
5980 crown.Paint();
5981 }
5982 }
5983 }
5984
5986
5989 fH->TAttFill::Modify();
5990
5991}
5992
5993////////////////////////////////////////////////////////////////////////////////
5994/// [Control function to draw a 2D histogram as a contour plot.](\ref HP16)
5995
5997{
5998
5999 Int_t i, j, count, ncontour, icol, n, lj, m, ix, jx, ljfill;
6000 Int_t itars, mode, ir[4];
6001 Double_t xsave, ysave, thesave,phisave,x[4], y[4], zc[4];
6002
6003 if (Hoption.Contour == 14) {
6004 Hoption.Surf = 12;
6005 Hoption.Axis = 1;
6006 thesave = gPad->GetTheta();
6007 phisave = gPad->GetPhi();
6008 gPad->SetPhi(0.);
6009 gPad->SetTheta(90.);
6011 gPad->SetPhi(phisave);
6012 gPad->SetTheta(thesave);
6013 TView *view = gPad->GetView();
6014 if (view) view->SetBit(kCannotRotate); //tested in ExecuteEvent
6015 PaintAxis();
6016 return;
6017 }
6018
6019 if (Hoption.Same) {
6020 // If the contour is painted on a 3d plot, the contour lines are
6021 // paint in 3d too.
6022 TObject *obj;
6023 TIter next(gPad->GetListOfPrimitives());
6024 while ((obj=next())) {
6025 if (strstr(obj->GetDrawOption(),"surf") ||
6026 strstr(obj->GetDrawOption(),"lego") ||
6027 strstr(obj->GetDrawOption(),"tri")) {
6028 Hoption.Surf = 16;
6030 return;
6031 }
6032 }
6033 }
6034
6035 if (Hoption.Contour == 15) {
6036 TGraphDelaunay2D *dt = nullptr;
6037 TGraphDelaunay *dtOld = nullptr;
6039 dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
6040 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
6041 if (!dt && !dtOld) return;
6042 if (!fGraph2DPainter)
6043 fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
6044 fGraph2DPainter->Paint(option);
6045 return;
6046 }
6047
6048 gPad->SetBit(TGraph::kClipFrame);
6049
6050 std::vector<Double_t> levels(2*kMAXCONTOUR);
6051 std::vector<Double_t> xarr(2*kMAXCONTOUR);
6052 std::vector<Double_t> yarr(2*kMAXCONTOUR);
6053 std::vector<Int_t> itarr(2*kMAXCONTOUR);
6054
6055 Int_t npmax = 0;
6056 for (i=0;i<2*kMAXCONTOUR;i++) itarr[i] = 0;
6057
6058 ncontour = fH->GetContour();
6059 if (ncontour == 0) {
6062 }
6063 if (ncontour > kMAXCONTOUR) {
6064 Warning("PaintContour", "maximum number of contours is %d, asked for %d",
6067 }
6069
6070 for (i=0;i<ncontour;i++) levels[i] = fH->GetContourLevelPad(i);
6074 if (Hoption.Contour == 13) {
6075 fH->TAttLine::Modify();
6076 }
6077
6078 std::vector<std::unique_ptr<TPolyLine>> polys;
6079 TObjArray *contours = nullptr;
6080 TList *list = nullptr;
6081 TGraph *graph = nullptr;
6082 std::vector<Int_t> np;
6083 if (Hoption.Contour == 1 || (Hoption.List && (Hoption.Contour == 11 || Hoption.Contour == 12 || Hoption.Contour == 13))) {
6084 np.resize(ncontour);
6085 for (i=0;i<ncontour;i++)
6086 np[i] = 0;
6087 for (i=0;i<ncontour;i++)
6088 polys.emplace_back(std::make_unique<TPolyLine>(100));
6089 if (Hoption.List == 1) {
6090 contours = (TObjArray*)gROOT->GetListOfSpecials()->FindObject("contours");
6091 if (contours) {
6092 gROOT->GetListOfSpecials()->Remove(contours);
6093 count = contours->GetSize();
6094 for (i=0;i<count;i++) {
6095 list = (TList*)contours->At(i);
6096 if (list) list->Delete();
6097 }
6098 contours->Delete();
6099 delete contours;
6100 }
6102 contours->SetName("contours");
6103 gROOT->GetListOfSpecials()->Add(contours);
6104 for (i=0;i<ncontour;i++) {
6105 list = new TList();
6106 contours->Add(list);
6107 }
6108 }
6109 }
6113
6114 Int_t k,ipoly;
6115 for (j=Hparam.yfirst; j<Hparam.ylast; j++) {
6116 y[0] = fYaxis->GetBinCenter(j);
6117 y[1] = y[0];
6118 y[2] = fYaxis->GetBinCenter(j+1);
6119 y[3] = y[2];
6120 for (i=Hparam.xfirst; i<Hparam.xlast; i++) {
6121 zc[0] = fH->GetBinContent(i, j);
6122 zc[1] = fH->GetBinContent(i+1, j);
6123 zc[2] = fH->GetBinContent(i+1, j+1);
6124 zc[3] = fH->GetBinContent(i, j+1);
6125 if (!IsInside(fXaxis->GetBinCenter(i),fYaxis->GetBinCenter(j))) continue;
6126 if (Hoption.Logz) {
6127 if (zc[0] > 0) zc[0] = TMath::Log10(zc[0]);
6128 else zc[0] = Hparam.zmin;
6129 if (zc[1] > 0) zc[1] = TMath::Log10(zc[1]);
6130 else zc[1] = Hparam.zmin;
6131 if (zc[2] > 0) zc[2] = TMath::Log10(zc[2]);
6132 else zc[2] = Hparam.zmin;
6133 if (zc[3] > 0) zc[3] = TMath::Log10(zc[3]);
6134 else zc[3] = Hparam.zmin;
6135 }
6136 for (k=0;k<4;k++) {
6137 ir[k] = TMath::BinarySearch(ncontour, levels.data(), zc[k]);
6138 }
6139 if (ir[0] != ir[1] || ir[1] != ir[2] || ir[2] != ir[3] || ir[3] != ir[0]) {
6140 x[0] = fXaxis->GetBinCenter(i);
6141 x[3] = x[0];
6142 x[1] = fXaxis->GetBinCenter(i+1);
6143 x[2] = x[1];
6144 if (zc[0] <= zc[1]) n = 0; else n = 1;
6145 if (zc[2] <= zc[3]) m = 2; else m = 3;
6146 if (zc[n] > zc[m]) n = m;
6147 n++;
6148 lj=1;
6149 for (ix=1;ix<=4;ix++) {
6150 m = n%4 + 1;
6151 ljfill = PaintContourLine(zc[n-1],ir[n-1],x[n-1],y[n-1],zc[m-1],
6152 ir[m-1],x[m-1],y[m-1], xarr.data()+lj-1,yarr.data()+lj-1,itarr.data()+lj-1, levels.data());
6153 lj += 2*ljfill;
6154 n = m;
6155 }
6156
6157 if (zc[0] <= zc[1]) n = 0; else n = 1;
6158 if (zc[2] <= zc[3]) m = 2; else m = 3;
6159 if (zc[n] > zc[m]) n = m;
6160 n++;
6161 lj=2;
6162 for (ix=1;ix<=4;ix++) {
6163 if (n == 1) m = 4;
6164 else m = n-1;
6165 ljfill = PaintContourLine(zc[n-1],ir[n-1],x[n-1],y[n-1],zc[m-1],
6166 ir[m-1],x[m-1],y[m-1],xarr.data()+lj-1,yarr.data()+lj-1,itarr.data()+lj-1, levels.data());
6167 lj += 2*ljfill;
6168 n = m;
6169 }
6170
6171 // Re-order endpoints
6172
6173 count = 0;
6174 for (ix=1; ix<=lj-5; ix +=2) {
6175 //count = 0;
6176 while (itarr[ix-1] != itarr[ix]) {
6177 xsave = xarr[ix];
6178 ysave = yarr[ix];
6179 itars = itarr[ix];
6180 for (jx=ix; jx<=lj-5; jx +=2) {
6181 xarr[jx] = xarr[jx+2];
6182 yarr[jx] = yarr[jx+2];
6183 itarr[jx] = itarr[jx+2];
6184 }
6185 xarr[lj-3] = xsave;
6186 yarr[lj-3] = ysave;
6187 itarr[lj-3] = itars;
6188 if (count > 100) break;
6189 count++;
6190 }
6191 }
6192
6193 if (count > 100) continue;
6194 for (ix=1; ix<=lj-2; ix +=2) {
6195 theColor = Int_t((itarr[ix-1]+0.99)*Float_t(ncolors)/Float_t(ndivz));
6197 if (Hoption.Contour == 11) {
6199 }
6200 if (Hoption.Contour == 12) {
6201 mode = icol%5;
6202 if (mode == 0) mode = 5;
6204 }
6205 if (Hoption.Contour != 1) {
6206 fH->TAttLine::Modify();
6207 gPad->PaintPolyLine(2,xarr.data()+ix-1,yarr.data()+ix-1);
6208 if ((Hoption.Contour != 11 && Hoption.Contour != 12 && Hoption.Contour != 13) || !Hoption.List)
6209 continue;
6210 }
6211
6212 ipoly = itarr[ix-1];
6213 if (ipoly >=0 && ipoly <ncontour) {
6214 polys[ipoly]->SetPoint(np[ipoly] ,xarr[ix-1],yarr[ix-1]);
6215 polys[ipoly]->SetPoint(np[ipoly]+1,xarr[ix], yarr[ix]);
6216 np[ipoly] += 2;
6217 if (npmax < np[ipoly]) npmax = np[ipoly];
6218 }
6219 }
6220 } // end of if (ir[0]
6221 } //end of for (i
6222 } //end of for (j
6223
6225 std::vector<Double_t> xp, yp;
6227 Int_t istart;
6228 Int_t first = ncontour;
6229 std::vector<Int_t> polysort;
6231 if (Hoption.Contour != 1) {
6232 if (!Hoption.List || (Hoption.Contour != 11 && Hoption.Contour != 12 && Hoption.Contour != 13))
6233 goto theEND;
6234 }
6235
6236 //The 2 points line generated above are now sorted/merged to generate
6237 //a list of consecutive points.
6238 // If the option "List" has been specified, the list of points is saved
6239 // in the form of TGraph objects in the ROOT list of special objects.
6240 xmin = gPad->GetUxmin();
6241 ymin = gPad->GetUymin();
6242 xp.resize(2*npmax);
6243 yp.resize(2*npmax);
6244 polysort.resize(ncontour);
6245 //find first positive contour
6246 for (ipoly=0;ipoly<ncontour;ipoly++) {
6247 if (levels[ipoly] >= 0) {first = ipoly; break;}
6248 }
6249 //store negative contours from 0 to minimum, then all positive contours
6250 k = 0;
6251 for (ipoly=first-1;ipoly>=0;ipoly--) {polysort[k] = ipoly; k++;}
6252 for (ipoly=first;ipoly<ncontour;ipoly++) {polysort[k] = ipoly; k++;}
6253 // if Contour==1 we can now draw sorted contours, otherwise (11,12,13) just store
6254 contListNb = 0;
6255 if (Hoption.Contour == 1) fH->SetFillStyle(1001);
6256 for (k=0;k<ncontour;k++) {
6257 ipoly = polysort[k];
6258 if (Hoption.List) list = (TList*)contours->At(contListNb);
6259 contListNb++;
6260 if (np[ipoly] == 0)
6261 continue;
6262 Double_t *xx = polys[ipoly]->GetX();
6263 Double_t *yy = polys[ipoly]->GetY();
6264 istart = 0;
6265 while (true) {
6266 iminus = npmax;
6267 iplus = iminus+1;
6268 xp[iminus]= xx[istart]; yp[iminus] = yy[istart];
6269 xp[iplus] = xx[istart+1]; yp[iplus] = yy[istart+1];
6270 xx[istart] = xmin; yy[istart] = ymin;
6271 xx[istart+1] = xmin; yy[istart+1] = ymin;
6272 while (true) {
6273 nadd = 0;
6274 for (i=2;i<np[ipoly];i+=2) {
6275 if ((iplus < 2*npmax-1) && (xx[i] == xp[iplus]) && (yy[i] == yp[iplus])) {
6276 iplus++;
6277 xp[iplus] = xx[i+1]; yp[iplus] = yy[i+1];
6278 xx[i] = xmin; yy[i] = ymin;
6279 xx[i+1] = xmin; yy[i+1] = ymin;
6280 nadd++;
6281 }
6282 if ((iminus > 0) && (xx[i+1] == xp[iminus]) && (yy[i+1] == yp[iminus])) {
6283 iminus--;
6284 xp[iminus] = xx[i]; yp[iminus] = yy[i];
6285 xx[i] = xmin; yy[i] = ymin;
6286 xx[i+1] = xmin; yy[i+1] = ymin;
6287 nadd++;
6288 }
6289 }
6290 if (nadd == 0) break;
6291 }
6294 if (Hoption.Contour == 1) {
6295 if (ndivz > 1) fH->SetFillColor(icol);
6296 fH->TAttFill::Modify();
6297 gPad->PaintFillArea(iplus-iminus+1,xp.data()+iminus,yp.data()+iminus);
6298 }
6299 if (Hoption.List) {
6300 graph = new TGraph(iplus-iminus+1,xp.data()+iminus,yp.data()+iminus);
6301 if (Hoption.Contour == 1)
6302 graph->SetFillColor(icol);
6303 else if (Hoption.Contour == 11)
6304 graph->SetLineColor(icol);
6305 else if (Hoption.Contour == 12) {
6306 mode = icol%5;
6307 if (mode == 0) mode = 5;
6308 graph->SetLineStyle(mode);
6309 }
6310 graph->SetLineWidth(fH->GetLineWidth());
6311 list->Add(graph);
6312 }
6313 //check if more points are left
6314 istart = 0;
6315 for (i=2;i<np[ipoly];i+=2) {
6316 if (xx[i] != xmin && yy[i] != ymin) {
6317 istart = i;
6318 break;
6319 }
6320 }
6321 if (istart == 0) break;
6322 }
6323 }
6324
6325theEND:
6326 gPad->ResetBit(TGraph::kClipFrame);
6331}
6332
6333////////////////////////////////////////////////////////////////////////////////
6334/// Fill the matrix `xarr` and `yarr` for Contour Plot.
6335
6339{
6340
6341 Bool_t vert;
6343 Int_t n, i, icount;
6344
6345 if (x1 == x2) {
6346 vert = kTRUE;
6347 tlen = y2 - y1;
6348 } else {
6349 vert = kFALSE;
6350 tlen = x2 - x1;
6351 }
6352
6353 n = icont1 +1;
6354 tdif = elev2 - elev1;
6355 i = 0;
6356 icount = 0;
6357 while (n <= icont2 && i <= kMAXCONTOUR/2 -3) {
6358 //elev = fH->GetContourLevel(n);
6359 elev = levels[n];
6360 diff = elev - elev1;
6361 pdif = diff/tdif;
6362 xlen = tlen*pdif;
6363 if (vert) {
6364 if (Hoption.Logx)
6365 xarr[i] = TMath::Log10(x1);
6366 else
6367 xarr[i] = x1;
6368 if (Hoption.Logy)
6369 yarr[i] = TMath::Log10(y1 + xlen);
6370 else
6371 yarr[i] = y1 + xlen;
6372 } else {
6373 if (Hoption.Logx)
6374 xarr[i] = TMath::Log10(x1 + xlen);
6375 else
6376 xarr[i] = x1 + xlen;
6377 if (Hoption.Logy)
6378 yarr[i] = TMath::Log10(y1);
6379 else
6380 yarr[i] = y1;
6381 }
6382 itarr[i] = n;
6383 icount++;
6384 i +=2;
6385 n++;
6386 }
6387 return icount;
6388}
6389
6390////////////////////////////////////////////////////////////////////////////////
6391/// [Draw 1D histograms error bars.](\ref HP09)
6392
6394{
6395
6396 // On iOS, we do not highlight histogram, if it's not picked at the moment
6397 // (but part of histogram (axis or pavestat) was picked, that's why this code
6398 // is called at all. This conditional statement never executes on non-iOS platform.
6399 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH) return;
6400
6401 const Int_t kBASEMARKER=8;
6402 Double_t xp, yp, ex1, ex2, ey1, ey2;
6403 Double_t delta;
6405 Double_t xi1, xi2, xi3, xi4, yi1, yi2, yi3, yi4;
6407 Double_t logxmin = 0;
6408 Double_t logymin = 0;
6409 Double_t offset = 0.;
6410 Double_t width = 0.;
6411 Int_t i, k, npoints, first, last, fixbin;
6412 Int_t if1 = 0;
6413 Int_t if2 = 0;
6417 static Float_t cxx[30] = {1.0,1.0,0.5,0.5,1.0,1.0,0.5,0.6,1.0,0.5,0.5,1.0,0.5,0.6,1.0,1.0,1.0,1.0,1.0,1.0,0.0,0.0,1.0,1.0,1.0,1.0,0.5,0.5,0.5,1.0};
6418 static Float_t cyy[30] = {1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,0.5,0.5,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,0.0,0.0,1.0,1.0,1.0,1.0,0.5,0.5,0.5,1.0};
6419
6420 std::vector<Double_t> xline, yline, xsegm, ysegm, xmarker, ymarker;
6422 if (Hoption.Error >= 40) {Hoption.Error -=40; option0 = 1;}
6423 if (Int_t(Hoption.Error/10) == 2) {optionEX0 = 1; Hoption.Error -= 10;}
6424 if (Hoption.Error == 31) {optionEX0 = 1; Hoption.Error = 1;}
6425 if (Hoption.Error == 11) option1 = 1;
6426 if (Hoption.Error == 12) option2 = 1;
6427 if (Hoption.Error == 13) option3 = 1;
6428 if (Hoption.Error == 14) {option4 = 1; option3 = 1;}
6429 if (Hoption.Error == 15) {optionI0 = 1; option3 = 1;}
6430 if (Hoption.Error == 16) {optionI0 = 1; option4 = 1; option3 = 1;}
6431 if (option2+option3 == 0) optionE = 1;
6432 if (Hoption.Error == 0) optionE = 0;
6433 if (fXaxis->GetXbins()->fN) fixbin = 0;
6434 else fixbin = 1;
6435
6436 offset = fH->GetBarOffset();
6437 width = fH->GetBarWidth();
6438
6440 if (optionEX0) {
6441 xerror = 0;
6442 } else {
6443 xerror = gStyle->GetErrorX();
6444 }
6446 if (errormarker == 1) symbolsize = 0.01;
6448 if (errormarker >= 20 && errormarker <= 49) {
6449 sbasex *= cxx[errormarker-20];
6450 sbasey *= cyy[errormarker-20];
6451 }
6452 // set the graphics attributes
6453
6454 fH->TAttLine::Modify();
6455 fH->TAttFill::Modify();
6456 fH->TAttMarker::Modify();
6457
6458 // set the first and last bin
6459
6460 Double_t factor = Hparam.factor;
6461 first = Hparam.xfirst;
6462 last = Hparam.xlast;
6463 npoints = last - first +1;
6464 xmin = gPad->GetUxmin();
6465 xmax = gPad->GetUxmax();
6466 ymin = gPad->GetUymin();
6467 ymax = gPad->GetUymax();
6468
6469 xsegm.reserve(1024);
6470 ysegm.reserve(1024);
6471 if (!xsegm.capacity() || !ysegm.capacity()) {
6472 Error("PaintErrors", "out of memory for lines painting");
6473 return;
6474 }
6475
6476 auto flush_segmentes = [&]() {
6477 if (xsegm.size() > 0) {
6478 gPad->PaintSegments(xsegm.size()/2, xsegm.data(), ysegm.data());
6479 xsegm.clear();
6480 ysegm.clear();
6481 }
6482 };
6483
6485 xsegm.emplace_back(x1);
6486 xsegm.emplace_back(x2);
6487 ysegm.emplace_back(y1);
6488 ysegm.emplace_back(y2);
6489 if (xsegm.size() == xsegm.capacity())
6491 };
6492
6493 auto flush_markers = [&]() {
6494 if (xmarker.size() > 0) {
6495 gPad->PaintPolyMarker(xmarker.size(), xmarker.data(), ymarker.data());
6496 xmarker.clear();
6497 ymarker.clear();
6498 }
6499 };
6500
6501 auto add_marker = [&](Double_t x, Double_t y) {
6502 if (xmarker.capacity() == 0) {
6503 xmarker.reserve(256);
6504 ymarker.reserve(256);
6505 }
6506
6507 xmarker.emplace_back(x);
6508 ymarker.emplace_back(y);
6509 if (xmarker.size() == xmarker.capacity()) {
6511 flush_markers();
6512 }
6513 };
6514
6515
6516 if (option3) {
6517 xline.resize(2*npoints);
6518 yline.resize(2*npoints);
6519 if ((npoints > 0) && (xline.empty() || yline.empty())) {
6520 Error("PaintErrors", "too many points, out of memory");
6521 return;
6522 }
6523 if1 = 1;
6524 if2 = 2*npoints;
6525 }
6526
6527 // compute the offset of the error bars due to the symbol size
6528 s2x = gPad->PixeltoX(Int_t(0.5*sbasex)) - gPad->PixeltoX(0);
6529 s2y =-gPad->PixeltoY(Int_t(0.5*sbasey)) + gPad->PixeltoY(0);
6530
6531 // compute size of the lines at the end of the error bars
6533 bxsize = gPad->PixeltoX(dxend) - gPad->PixeltoX(0);
6534 bysize =-gPad->PixeltoY(dxend) + gPad->PixeltoY(0);
6535
6536
6537 if (fixbin) {
6539 else xp = Hparam.xmin + 0.5*Hparam.xbinsize;
6540 } else {
6541 delta = fH->GetBinWidth(first);
6542 xp = fH->GetBinLowEdge(first) + 0.5*delta;
6543 }
6544
6545 // if errormarker = 0 or symbolsize = 0. no symbol is drawn
6548
6549 // ---------------------- Loop over the points---------------------
6550 for (k=first; k<=last; k++) {
6551
6552 // get the data
6553 // xp = X position of the current point
6554 // yp = Y position of the current point
6555 // ex1 = Low X error
6556 // ex2 = Up X error
6557 // ey1 = Low Y error
6558 // ey2 = Up Y error
6559 // (xi,yi) = Error bars coordinates
6560
6561 // apply offset on errors for bar histograms
6562 Double_t xminTmp = gPad->XtoPad(fXaxis->GetBinLowEdge(k));
6563 Double_t xmaxTmp = gPad->XtoPad(fXaxis->GetBinUpEdge(k));
6564 if (Hoption.Logx) {
6567 }
6570 xmaxTmp = xminTmp + w;
6571 xp = (xminTmp+xmaxTmp)/2.;
6572
6573 if (Hoption.Logx) {
6574 if (xp <= 0) goto L30;
6575 if (xp < logxmin) goto L30;
6576 if (xp > TMath::Power(10,xmax)) break;
6577 } else {
6578 if (xp < xmin) goto L30;
6579 if (xp > xmax) break;
6580 }
6581 yp = factor*fH->GetBinContent(k);
6582 if (optionI0 && yp==0) goto L30;
6583 if (fixbin) {
6585 } else {
6586 delta = fH->GetBinWidth(k);
6587 ex1 = xerror*delta;
6588 }
6589 if (fH->GetBinErrorOption() == TH1::kNormal) {
6590 ey1 = factor*fH->GetBinError(k);
6591 ey2 = ey1;
6592 } else {
6593 ey1 = factor*fH->GetBinErrorLow(k);
6594 ey2 = factor*fH->GetBinErrorUp(k);
6595 }
6596 ex2 = ex1;
6597
6598 xi4 = xp;
6599 xi3 = xp;
6600 xi2 = xp + ex2;
6601 xi1 = xp - ex1;
6602
6603 yi1 = yp;
6604 yi2 = yp;
6605 yi3 = yp - ey1;
6606 yi4 = yp + ey2;
6607
6608 // take the LOG if necessary
6609 if (Hoption.Logx) {
6614 }
6615 if (Hoption.Logy) {
6620 }
6621
6622 // test if error bars are not outside the limits
6623 // otherwise they are truncated
6624
6629
6630 // test if the marker is on the frame limits. If "Yes", the
6631 // marker will not be drawn and the error bars will be readjusted.
6632
6633 drawmarker = kTRUE;
6634 if (!option0 && !option3) {
6635 if (Hoption.Logy && yp < logymin) goto L30;
6636 if (yi1 < ymin || yi1 > ymax) goto L30;
6637 if (Hoption.Error != 0 && yp == 0 && ey1 <= 0) drawmarker = kFALSE;
6638 }
6640
6641 // draw the error rectangles
6642 if (option2) {
6643 if ((yi3 >= ymax) || (yi4 <= ymin))
6644 goto L30;
6645 gPad->PaintBox(xi1,yi3,xi2,yi4);
6646 }
6647
6648 // keep points for fill area drawing
6649 if (option3) {
6650 xline[if1-1] = xi3;
6651 xline[if2-1] = xi3;
6652 yline[if1-1] = yi4;
6653 yline[if2-1] = yi3;
6654 if1++;
6655 if2--;
6656 }
6657
6658 // draw the error bars
6659 if (Hoption.Logy && yp < logymin)
6661 if (optionE && drawmarker) {
6662 if ((yi3 < yi1 - s2y) && (yi3 < ymax))
6664 if ((yi1 + s2y < yi4) && (yi4 > ymin))
6666 // don't duplicate the horizontal line
6667 if (Hoption.Hist != 2) {
6669 if (xi1 < xi3 - s2x)
6671 if (xi3 + s2x < xi2)
6673 }
6674 }
6675 }
6676 if (optionE && !drawmarker && (ey1 != 0 || ey2 !=0)) {
6677 if ((yi3 < yi1) && (yi3 < ymax))
6679 if ((yi1 < yi4) && (yi4 > ymin))
6681 // don't duplicate the horizontal line
6682 if (Hoption.Hist != 2) {
6684 if (xi1 < xi3)
6686 if (xi3 < xi2)
6688 }
6689 }
6690 }
6691
6692 // draw line at the end of the error bars
6693
6694 if (option1 && drawmarker) {
6695
6701 if (xi1 < xi3-s2x)
6703 if (xi2 > xi3+s2x)
6705 }
6706 }
6707
6708 // draw the marker
6709
6710 if (drawmarker)
6711 add_marker(xi3, yi1);
6712
6713L30:
6714 if (fixbin) xp += Hparam.xbinsize;
6715 else {
6716 if (k < last) {
6717 delta = fH->GetBinWidth(k+1);
6718 xp = fH->GetBinLowEdge(k+1) + 0.5*delta;
6719 }
6720 }
6721 } //end of for loop
6722
6724
6725 flush_markers();
6726
6727
6728 // draw the filled area
6729
6730 if (option3) {
6731 TGraph graph;
6732 graph.SetLineStyle(fH->GetLineStyle());
6733 graph.SetLineColor(fH->GetLineColor());
6734 graph.SetLineWidth(fH->GetLineWidth());
6735 graph.SetFillStyle(fH->GetFillStyle());
6736 graph.SetFillColor(fH->GetFillColor());
6737 Int_t logx = gPad->GetLogx();
6738 Int_t logy = gPad->GetLogy();
6739 gPad->SetLogx(0);
6740 gPad->SetLogy(0);
6741
6742 // In some cases the number of points in the fill area is smaller than
6743 // 2*npoints. In such cases the array xline and yline must be arranged
6744 // before being plotted. The next loop does that.
6745 if (if2 > npoints) {
6746 for (i=1; i<if1; i++) {
6747 xline[if1-2+i] = xline[if2-1+i];
6748 yline[if1-2+i] = yline[if2-1+i];
6749 }
6750 npoints = if1-1;
6751 }
6752 if (option4) graph.PaintGraph(2*npoints,xline.data(),yline.data(),"FC");
6753 else graph.PaintGraph(2*npoints,xline.data(),yline.data(),"F");
6754 gPad->SetLogx(logx);
6755 gPad->SetLogy(logy);
6756 }
6757}
6758
6759////////////////////////////////////////////////////////////////////////////////
6760/// Draw 2D histograms errors.
6761
6763{
6764
6765 fH->TAttMarker::Modify();
6766 fH->TAttLine::Modify();
6767
6768 // Define the 3D view
6769 fXbuf[0] = Hparam.xmin;
6770 fYbuf[0] = Hparam.xmax;
6771 fXbuf[1] = Hparam.ymin;
6772 fYbuf[1] = Hparam.ymax;
6773 fXbuf[2] = Hparam.zmin;
6774 fYbuf[2] = Hparam.zmax*(1. + gStyle->GetHistTopMargin());
6775 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
6776 TView *view = gPad ? gPad->GetView() : nullptr;
6777 if (!view) {
6778 Error("Paint2DErrors", "no TView in current pad");
6779 return;
6780 }
6781 Double_t thedeg = 90 - gPad->GetTheta();
6782 Double_t phideg = -90 - gPad->GetPhi();
6783 Double_t psideg = view->GetPsi();
6784 Int_t irep;
6785 view->SetView(phideg, thedeg, psideg, irep);
6786
6787 // Set color/style for back box
6788 fLego->SetFillStyle(gPad->GetFrameFillStyle());
6789 fLego->SetFillColor(gPad->GetFrameFillColor());
6790 fLego->TAttFill::Modify();
6791 Int_t backcolor = gPad->GetFrameFillColor();
6792 if (Hoption.System != kCARTESIAN) backcolor = 0;
6793 view->PadRange(backcolor);
6794 fLego->SetFillStyle(fH->GetFillStyle());
6795 fLego->SetFillColor(fH->GetFillColor());
6796 fLego->TAttFill::Modify();
6797
6798 // Paint the Back Box if needed
6799 if (Hoption.BackBox && !Hoption.Same && !Hoption.Lego && !Hoption.Surf) {
6800 fLego->InitMoveScreen(-1.1,1.1);
6801 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
6803 fLego->BackBox(90);
6804 }
6805
6806 // Paint the Errors
6807 Double_t x, ex, x1, x2;
6808 Double_t y, ey, y1, y2;
6809 Double_t z, ez1, ez2, z1, z2;
6810 Double_t temp1[3],temp2[3];
6812 if (Hoption.Error == 110) {
6813 xyerror = 0;
6814 } else {
6816 }
6817
6819 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
6820 y = fYaxis->GetBinCenter(j);
6822 y1 = y-ey;
6823 y2 = y+ey;
6824 if (Hoption.Logy) {
6825 if (y > 0) y = TMath::Log10(y);
6826 else continue;
6827 if (y1 > 0) y1 = TMath::Log10(y1);
6828 else y1 = Hparam.ymin;
6829 if (y2 > 0) y2 = TMath::Log10(y2);
6830 else y2 = Hparam.ymin;
6831 }
6834 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
6835 xk = fXaxis->GetBinLowEdge(i);
6836 xstep = fXaxis->GetBinWidth(i);
6837 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
6838 Int_t bin = fH->GetBin(i,j);
6839 x = fXaxis->GetBinCenter(i);
6841 x1 = x-ex;
6842 x2 = x+ex;
6843 if (Hoption.Logx) {
6844 if (x > 0) x = TMath::Log10(x);
6845 else continue;
6846 if (x1 > 0) x1 = TMath::Log10(x1);
6847 else x1 = Hparam.xmin;
6848 if (x2 > 0) x2 = TMath::Log10(x2);
6849 else x2 = Hparam.xmin;
6850 }
6851 z = fH->GetBinContent(bin);
6852 if (fH->GetBinErrorOption() == TH1::kNormal) {
6853 ez1 = fH->GetBinError(bin);
6854 ez2 = ez1;
6855 }
6856 else {
6857 ez1 = fH->GetBinErrorLow(bin);
6858 ez2 = fH->GetBinErrorUp(bin);
6859 }
6860 z1 = z - ez1;
6861 z2 = z + ez2;
6862 if (Hoption.Logz) {
6863 if (z > 0) z = TMath::Log10(z);
6864 else z = Hparam.zmin;
6865 if (z1 > 0) z1 = TMath::Log10(z1);
6866 else z1 = Hparam.zmin;
6867 if (z2 > 0) z2 = TMath::Log10(z2);
6868 else z2 = Hparam.zmin;
6869
6870 }
6871 if (z <= Hparam.zmin) continue;
6872 if (z > Hparam.zmax) z = Hparam.zmax;
6873
6874 temp1[0] = x1;
6875 temp1[1] = y;
6876 temp1[2] = z;
6877 temp2[0] = x2;
6878 temp2[1] = y;
6879 temp2[2] = z;
6880 gPad->PaintLine3D(temp1, temp2);
6881 temp1[0] = x;
6882 temp1[1] = y1;
6883 temp1[2] = z;
6884 temp2[0] = x;
6885 temp2[1] = y2;
6886 temp2[2] = z;
6887 gPad->PaintLine3D(temp1, temp2);
6888 temp1[0] = x;
6889 temp1[1] = y;
6890 temp1[2] = z1;
6891 temp2[0] = x;
6892 temp2[1] = y;
6893 temp2[2] = z2;
6894 gPad->PaintLine3D(temp1, temp2);
6895 temp1[0] = x;
6896 temp1[1] = y;
6897 temp1[2] = z;
6898 view->WCtoNDC(temp1, &temp2[0]);
6899 gPad->PaintPolyMarker(1, &temp2[0], &temp2[1]);
6900 }
6901 }
6902
6903 // Paint the Front Box if needed
6904 if (Hoption.FrontBox) {
6905 fLego->InitMoveScreen(-1.1,1.1);
6907 fLego->FrontBox(90);
6908 }
6909
6910 // Paint the Axis if needed
6911 if (!Hoption.Axis && !Hoption.Same && !Hoption.Lego && !Hoption.Surf) {
6912 TGaxis axis;
6913 PaintLegoAxis(&axis, 90);
6914 }
6915
6916 fLego.reset();
6917}
6918
6919////////////////////////////////////////////////////////////////////////////////
6920/// Calculate range and clear pad (canvas).
6921
6923{
6924
6925 if (Hoption.Same) return;
6926
6928
6929 if (Hoption.Lego || Hoption.Surf || Hoption.Tri ||
6930 Hoption.Contour == 14 || Hoption.Error >= 100) {
6931 TObject *frame = gPad->FindObject("TFrame");
6932 if (frame) gPad->Remove(frame);
6933 return;
6934 }
6935
6936 //The next statement is always executed on non-iOS platform,
6937 //on iOS depends on pad mode.
6938 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode())
6939 gPad->PaintPadFrame(Hparam.xmin,Hparam.ymin,Hparam.xmax,Hparam.ymax);
6940}
6941
6942////////////////////////////////////////////////////////////////////////////////
6943/// [Paint functions associated to an histogram.](\ref HP28")
6944
6946{
6947 auto lnk = fFunctions->FirstLink();
6948
6949 while (lnk) {
6950 auto obj = lnk->GetObject();
6952 if (obj->InheritsFrom(TF2::Class())) {
6953 if (!obj->TestBit(TF2::kNotDraw)) {
6954 if (Hoption.Lego || Hoption.Surf || Hoption.Error >= 100) {
6955 TF2 *f2 = (TF2*)obj;
6956 f2->SetMinimum(fH->GetMinimum());
6957 f2->SetMaximum(fH->GetMaximum());
6958 f2->SetRange(fH->GetXaxis()->GetXmin(), fH->GetYaxis()->GetXmin(), fH->GetXaxis()->GetXmax(), fH->GetYaxis()->GetXmax() );
6959 f2->Paint("surf same");
6960 } else {
6961 obj->Paint("cont3 same");
6962 }
6963 }
6964 } else if (obj->InheritsFrom(TF1::Class())) {
6965 if (!obj->TestBit(TF1::kNotDraw)) obj->Paint("lsame");
6966 } else {
6967 //Let's make this 'function' selectable on iOS device (for example, it can be TPaveStat).
6968 gPad->PushSelectableObject(obj);
6969
6970 //The next statement is ALWAYS executed on non-iOS platform, on iOS it depends on pad's mode
6971 //and picked object.
6972 if (!gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && obj == gPad->GetSelected()))
6973 obj->Paint(lnk->GetOption());
6974 }
6975 lnk = lnk->Next();
6976 }
6977}
6978
6979////////////////////////////////////////////////////////////////////////////////
6980/// [Control routine to draw 1D histograms](\ref HP01b)
6981
6983{
6984
6985 //On iOS: do not highlight hist, if part of it was selected.
6986 //Never executes on non-iOS platform.
6987 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
6988 return;
6989
6990 static char chopth[17];
6991
6993 Int_t i, j, first, last, nbins, fixbin;
6994 Double_t c1, yb;
6995 yb = 0;
6996
6997 strlcpy(chopth, " ",17);
6998
7001 Double_t baroffset = fH->GetBarOffset();
7002 Double_t barwidth = fH->GetBarWidth();
7005 gStyle->SetBarOffset(baroffset);
7006 gStyle->SetBarWidth(barwidth);
7007
7008 // Create "LIFE" structure to keep current histogram status
7009
7010 first = Hparam.xfirst;
7011 last = Hparam.xlast;
7012 nbins = last - first + 1;
7013
7014 std::vector<Double_t> keepx, keepy;
7015 if (fXaxis->GetXbins()->fN) fixbin = 0;
7016 else fixbin = 1;
7017 if (fixbin) keepx.resize(2);
7018 else keepx.resize(nbins+1);
7019 keepy.resize(nbins);
7020 Double_t logymin = 0;
7022
7023 // Loop on histogram bins
7024
7025 for (j=first; j<=last;j++) {
7027 if (TMath::Abs(ymax-ymin) > 0) {
7029 else yb = c1;
7030 }
7031 if (!Hoption.Line) {
7032 yb = TMath::Max(yb, ymin);
7033 yb = TMath::Min(yb, ymax);
7034 }
7035 keepy[j-first] = yb;
7036 }
7037
7038 // Draw histogram according to value of FillStyle and FillColor
7039
7040 if (fixbin) { keepx[0] = Hparam.xmin; keepx[1] = Hparam.xmax; }
7041 else {
7042 for (i=0; i<nbins; i++) keepx[i] = fXaxis->GetBinLowEdge(i+first);
7043 keepx[nbins] = fXaxis->GetBinUpEdge(nbins-1+first);
7044 }
7045
7046 // Prepare Fill area (systematic with option "Bar").
7047
7049 htype = oldhtype;
7050 if (Hoption.Bar) {
7051 if (htype == 0 || htype == 1000) htype = 1001;
7052 }
7053
7055
7056 // Code option for GrapHist
7057
7058 if (Hoption.Line) chopth[0] = 'L';
7059 if (Hoption.Star) chopth[1] = '*';
7060 if (Hoption.Mark) chopth[2] = 'P';
7061 if (Hoption.Mark == 10) chopth[3] = '0';
7063 if (Hoption.Curve) chopth[3] = 'C';
7064 if (Hoption.Hist > 0) chopth[4] = 'H';
7065 else if (Hoption.Bar) chopth[5] = 'B';
7066 if (Hoption.Logy) chopth[6] = '1';
7067 if (fH->GetFillColor() && htype) {
7068 if (Hoption.Hist > 0 || Hoption.Curve || Hoption.Line) {
7069 chopth[7] = 'F';
7070 }
7071 }
7072 }
7073 if (!fixbin && strlen(chopth)) {
7074 chopth[8] = 'N';
7075 }
7076
7077 if (Hoption.Fill == 2) chopth[13] = '2';
7078
7079 // Option LOGX
7080
7081 if (Hoption.Logx) {
7082 chopth[9] = 'G';
7083 chopth[10] = 'X';
7084 if (fixbin) {
7085 keepx[0] = TMath::Power(10,keepx[0]);
7086 keepx[1] = TMath::Power(10,keepx[1]);
7087 }
7088 }
7089
7090 if (Hoption.Off) {
7091 chopth[11] = ']';
7092 chopth[12] = '[';
7093 }
7094
7095 // Draw the histogram
7096
7097 TGraph graph;
7098 graph.SetLineWidth(lw);
7099 graph.SetLineStyle(fH->GetLineStyle());
7100 graph.SetLineColor(fH->GetLineColor());
7101 graph.SetFillStyle(htype);
7102 graph.SetFillColor(fH->GetFillColor());
7104 graph.SetMarkerSize(fH->GetMarkerSize());
7107
7108 graph.PaintGrapHist(nbins, keepx.data(), keepy.data() ,chopth);
7109
7112
7114}
7115
7116////////////////////////////////////////////////////////////////////////////////
7117/// [Control function to draw a 3D histograms.](\ref HP01d)
7118
7120{
7121
7122 TString cmd;
7123 TString opt = option;
7124 opt.ToLower();
7125 Int_t irep;
7126 Float_t NEntries = fH->GetEntries();
7127
7128 if (fCurrentF3 || strstr(opt,"tf3")) {
7129 PaintTF3();
7130 return;
7131 }
7132
7133 if (NEntries > 0) {
7134 if (Hoption.Box || Hoption.Lego || Hoption.Color) {
7135 if (Hoption.Box == 11 || Hoption.Lego == 11) {
7136 PaintH3Box(1);
7137 } else if (Hoption.Box == 12 || Hoption.Lego == 12 || Hoption.Color == 1) {
7138 PaintH3Box(2);
7139 } else if (Hoption.Box == 13 || Hoption.Lego == 13) {
7140 PaintH3Box(3);
7141 } else {
7143 }
7144 return;
7145 }
7146
7147 if (strstr(opt,"iso")) {
7148 PaintH3Iso();
7149 return;
7150 }
7151 }
7152
7153 TView *view = gPad ? gPad->GetView() : nullptr;
7154 if (!view) return;
7155
7156 if (strstr(opt,"fb")) Hoption.FrontBox = 0;
7157 if (strstr(opt,"bb")) Hoption.BackBox = 0;
7158
7159 Double_t thedeg = 90 - gPad->GetTheta();
7160 Double_t phideg = -90 - gPad->GetPhi();
7161 Double_t psideg = view->GetPsi();
7162 view->SetView(phideg, thedeg, psideg, irep);
7163
7164 if(NEntries > 0) { // Paint as 3D scatter plot
7165 cmd.Form("TPolyMarker3D::PaintH3((TH1 *)0x%zx,\"%s\");",(size_t)fH,option);
7166 gROOT->ProcessLine(cmd.Data());
7167 } else {
7168 TAxis* xAxis = fH->GetXaxis();
7169 TAxis* yAxis = fH->GetYaxis();
7170 TAxis* zAxis = fH->GetZaxis();
7171 Double_t xmin = xAxis->GetXmin();
7172 Double_t xmax = xAxis->GetXmax();
7173 Double_t ymin = yAxis->GetXmin();
7174 Double_t ymax = yAxis->GetXmax();
7175 Double_t zmin = zAxis->GetXmin();
7176 Double_t zmax = zAxis->GetXmax();
7177 view->SetRange(xmin, ymin, zmin, xmax, ymax, zmax); // Set the axis limits (Xmin, Ymin, Zmin, Xmax, Ymax, Zmax)
7178 }
7179
7180 if (Hoption.Same) return;
7181
7182 // Draw axis
7183 view->SetOutlineToCube();
7184 TSeqCollection *ol = view->GetOutline();
7185 if (ol && Hoption.BackBox && Hoption.FrontBox) ol->Paint(option);
7187
7188 if (!Hoption.Axis && !Hoption.Same) {
7189 TGaxis axis;
7190 PaintLegoAxis(&axis, 90);
7191 }
7192
7193 // Draw palette. In case of 4D plot with TTree::Draw() the palette should
7194 // be painted with the option colz.
7195 if (fH->GetDrawOption() && strstr(opt,"colz")) {
7196 Int_t ndiv = fH->GetContour();
7197 if (ndiv == 0 ) {
7198 ndiv = gStyle->GetNumberContours();
7199 fH->SetContour(ndiv);
7200 }
7201 PaintPalette();
7202 }
7203
7204 // Draw title
7205 PaintTitle();
7206
7207 //Draw stats and fit results
7208 TF1 *fit = nullptr;
7209 TIter next(fFunctions);
7210 while (auto obj = next()) {
7211 if (obj->InheritsFrom(TF1::Class())) {
7212 fit = (TF1*)obj;
7213 break;
7214 }
7215 }
7216 if ((Hoption.Same%10) != 1) {
7217 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7219 }
7220 }
7221
7222}
7223
7224////////////////////////////////////////////////////////////////////////////////
7225/// Compute histogram parameters used by the drawing routines.
7226
7228{
7229
7230 if (fH->GetDimension() > 1 || Hoption.Lego || Hoption.Surf) return 1;
7231
7232 Int_t i;
7233 static const char *where = "PaintInit";
7235 Int_t maximum = 0;
7236 Int_t minimum = 0;
7237 if (fH->GetMaximumStored() != -1111) maximum = 1;
7238 if (fH->GetMinimumStored() != -1111) minimum = 1;
7239
7240 // Compute X axis parameters
7241
7242 Int_t last = fXaxis->GetLast();
7243 Int_t first = fXaxis->GetFirst();
7246 Hparam.xlast = last;
7247 Hparam.xfirst = first;
7250
7251 // if log scale in X, replace xmin,max by the log
7252 if (Hoption.Logx) {
7253 if (Hparam.xmax<=0) {
7254 Error(where, "cannot set X axis to log scale");
7255 return 0;
7256 }
7257 if (Hparam.xlowedge <=0 ) {
7258 if (Hoption.Same) {
7259 TH1* h1 = nullptr;
7260 TObject *obj;
7261 TIter next(gPad->GetListOfPrimitives());
7262 while ((obj = (TObject *)next())) {
7263 if (obj->InheritsFrom(TH1::Class())) { h1 = (TH1*)(obj) ; break; }
7264 if (obj->InheritsFrom(THStack::Class())) { h1 = ((THStack*)(obj))->GetHistogram() ; break; }
7265 if (obj->InheritsFrom(TGraph::Class())) { h1 = ((TGraph*)(obj))->GetHistogram() ; break; }
7266 if (obj->InheritsFrom(TMultiGraph::Class())) { h1 = ((TMultiGraph*)(obj))->GetHistogram(); break; }
7267 if (obj->InheritsFrom(TGraph2D::Class())) { h1 = ((TGraph2D*)(obj))->GetHistogram(); break; }
7268 if (obj->InheritsFrom(TF1::Class())) { h1 = ((TF1*)(obj))->GetHistogram(); break; }
7269 }
7270 if (h1) {
7272 } else {
7273 Error(where, "undefined user's coordinates. Cannot use option SAME");
7274 return 0;
7275 }
7276 } else {
7277 for (i=first; i<=last; i++) {
7278 Double_t binLow = fXaxis->GetBinLowEdge(i);
7279 if (binLow>0) {
7280 Hparam.xlowedge = binLow;
7281 break;
7282 }
7283 if (binLow == 0 && fH->GetBinContent(i) !=0) {
7284 Hparam.xlowedge = fXaxis->GetBinUpEdge(i)*0.001;
7285 break;
7286 }
7287 }
7288 if (Hparam.xlowedge<=0) {
7289 Error(where, "cannot set X axis to log scale");
7290 return 0;
7291 }
7292 }
7294 }
7299 if (Hparam.xlast > last) Hparam.xlast = last;
7300 if (Hparam.xfirst < first) Hparam.xfirst = first;
7301 }
7302
7303 // Compute Y axis parameters
7304 Double_t bigp = TMath::Power(10,32);
7305 Double_t ymax = -bigp;
7306 Double_t ymin = bigp;
7307 Double_t c1, e1;
7308 Double_t xv[1];
7309 Double_t fval;
7310 TObject *f;
7311 TF1 *f1;
7312 Double_t allchan = 0;
7313 Int_t nonNullErrors = 0;
7314 TIter next(fFunctions);
7315 for (i=first; i<=last;i++) {
7316 c1 = fH->GetBinContent(i);
7317 if (std::isnan(c1) || std::isinf(c1))
7318 continue;
7320 if (Hoption.Logy) {
7321 if (c1 > 0) ymin = TMath::Min(ymin,c1);
7322 } else {
7324 }
7325 if (Hoption.Error) {
7327 e1 = fH->GetBinError(i);
7328 else
7329 e1 = fH->GetBinErrorUp(i);
7330 if (e1 > 0) nonNullErrors++;
7333 e1 = fH->GetBinErrorLow(i);
7334
7335 if (Hoption.Logy) {
7336 if (c1-e1>0.01*TMath::Abs(c1)) ymin = TMath::Min(ymin,c1-e1);
7337 } else {
7339 }
7340 }
7341 if (Hoption.Func) {
7342 xv[0] = fXaxis->GetBinCenter(i);
7343 while ((f = (TObject*) next())) {
7344 if (f->IsA() == TF1::Class()) {
7345 f1 = (TF1*)f;
7346 if (xv[0] < f1->GetXmin() || xv[0] > f1->GetXmax()) continue;
7347 fval = f1->Eval(xv[0],0,0);
7348 if (f1->GetMaximumStored() != -1111) fval = TMath::Min(f1->GetMaximumStored(), fval);
7350 if (Hoption.Logy) {
7351 if (c1 > 0 && fval > 0.3*c1) ymin = TMath::Min(ymin,fval);
7352 }
7353 }
7354 }
7355 next.Reset();
7356 }
7357 allchan += c1;
7358 }
7359 if (!nonNullErrors) {
7360 if (Hoption.Error) {
7361 if (!Hoption.Mark && !Hoption.Line && !Hoption.Star && !Hoption.Curve) Hoption.Hist = 2;
7362 Hoption.Error=0;
7363 }
7364 }
7365
7366
7367 // Take into account maximum , minimum
7368
7369 if (Hoption.Logy && ymin <= 0) {
7370 if (ymax >= 1) ymin = TMath::Max(.005,ymax*1e-10);
7371 else ymin = 0.001*ymax;
7372 }
7373
7374 Double_t xm = ymin;
7375 if (maximum) ymax = fH->GetMaximumStored();
7376 if (minimum) xm = fH->GetMinimumStored();
7377 if (Hoption.Logy && xm < 0) {
7378 Error(where, "log scale requested with a negative argument (%f)", xm);
7379 return 0;
7380 } else if (Hoption.Logy && xm>=0 && ymax==0) { // empty histogram in log scale
7381 ymin = 0.01;
7382 ymax = 10.;
7383 } else {
7384 ymin = xm;
7385 }
7386
7387 if (ymin >= ymax) {
7388 if (Hoption.Logy) {
7389 if (ymax > 0) ymin = 0.001*ymax;
7390 else {
7391 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", ymax);
7392 return 0;
7393 }
7394 }
7395 else {
7396 if (ymin > 0) {
7397 ymin = 0;
7398 ymax *= 2;
7399 } else if (ymin < 0) {
7400 ymax = 0;
7401 ymin *= 2;
7402 } else {
7403 ymin = 0;
7404 ymax = 1;
7405 }
7406 }
7407 }
7408
7409 // In some cases, mainly because of precision issues, ymin and ymax could almost equal.
7410 if (TMath::AreEqualRel(ymin,ymax,1E-15)) {
7411 ymin = ymin*(1-1E-14);
7412 ymax = ymax*(1+1E-14);
7413 }
7414
7415 // take into account normalization factor
7416 Hparam.allchan = allchan;
7417 Double_t factor = allchan;
7418 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
7419 if (allchan) factor /= allchan;
7420 if (factor == 0) factor = 1;
7421 Hparam.factor = factor;
7422 ymax = factor*ymax;
7423 ymin = factor*ymin;
7424 //just in case the norm factor is negative
7425 // this may happen with a positive norm factor and a negative integral !
7426 if (ymax < ymin) {
7427 Double_t temp = ymax;
7428 ymax = ymin;
7429 ymin = temp;
7430 }
7431
7432 // For log scales, histogram coordinates are LOG10(ymin) and
7433 // LOG10(ymax). Final adjustment (if not option "Same"
7434 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
7435 // Maximum and Minimum are not defined.
7436 if (Hoption.Logy) {
7437 if (ymin <=0 || ymax <=0) {
7438 Error(where, "Cannot set Y axis to log scale");
7439 return 0;
7440 }
7442 if (!minimum) ymin += TMath::Log10(0.5);
7444 if (!maximum) ymax += TMath::Log10(2*(0.9/0.95));
7445 if (!Hoption.Same) {
7446 Hparam.ymin = ymin;
7447 Hparam.ymax = ymax;
7448 }
7449 return 1;
7450 }
7451
7452 // final adjustment of ymin for linear scale.
7453 // if minimum is not set , then ymin is set to zero if >0
7454 // or to ymin - margin if <0.
7455 if (!minimum) {
7456 if (Hoption.MinimumZero) {
7457 if (ymin >= 0) ymin = 0;
7458 else ymin -= yMARGIN*(ymax-ymin);
7459 } else {
7461 if (ymin >= 0 && (ymin-dymin <= 0)) ymin = 0;
7462 else ymin -= dymin;
7463 }
7464 }
7465
7466 // final adjustment of YMAXI for linear scale (if not option "Same"):
7467 // decrease histogram height to MAX% of allowed height if HMAXIM
7468 // has not been called.
7469 if (!maximum) {
7470 ymax += yMARGIN*(ymax-ymin);
7471 }
7472
7473 Hparam.ymin = ymin;
7474 Hparam.ymax = ymax;
7475 return 1;
7476}
7477
7478////////////////////////////////////////////////////////////////////////////////
7479/// Compute histogram parameters used by the drawing routines for a rotated pad.
7480
7482{
7483
7484 static const char *where = "PaintInitH";
7486 Int_t maximum = 0;
7487 Int_t minimum = 0;
7488 if (fH->GetMaximumStored() != -1111) maximum = 1;
7489 if (fH->GetMinimumStored() != -1111) minimum = 1;
7490
7491 // Compute X axis parameters
7492
7493 Int_t last = fXaxis->GetLast();
7494 Int_t first = fXaxis->GetFirst();
7497 Hparam.xlast = last;
7498 Hparam.xfirst = first;
7501
7502 // if log scale in Y, replace ymin,max by the log
7503 if (Hoption.Logy) {
7504 if (Hparam.xlowedge <=0 ) {
7507 }
7508 if (Hparam.ymin <=0 || Hparam.ymax <=0) {
7509 Error(where, "cannot set Y axis to log scale");
7510 return 0;
7511 }
7516 if (Hparam.xlast > last) Hparam.xlast = last;
7517 }
7518
7519 // Compute Y axis parameters
7520 Double_t bigp = TMath::Power(10,32);
7521 Double_t xmax = -bigp;
7522 Double_t xmin = bigp;
7523 Double_t c1, e1;
7524 Double_t xv[1];
7525 Double_t fval;
7526 Int_t i;
7527 TObject *f;
7528 TF1 *f1;
7529 Double_t allchan = 0;
7530 TIter next(fFunctions);
7531 for (i=first; i<=last;i++) {
7532 c1 = fH->GetBinContent(i);
7535 if (Hoption.Error) {
7536 e1 = fH->GetBinError(i);
7539 }
7540 if (Hoption.Func) {
7541 xv[0] = fXaxis->GetBinCenter(i);
7542 while ((f = (TObject*) next())) {
7543 if (f->IsA() == TF1::Class()) {
7544 f1 = (TF1*)f;
7545 if (xv[0] < f1->GetXmin() || xv[0] > f1->GetXmax()) continue;
7546 fval = f1->Eval(xv[0],0,0);
7548 if (Hoption.Logy) {
7549 if (fval > 0.3*c1) xmin = TMath::Min(xmin,fval);
7550 }
7551 }
7552 }
7553 next.Reset();
7554 }
7555 allchan += c1;
7556 }
7557
7558 // Take into account maximum , minimum
7559
7560 if (Hoption.Logx && xmin <= 0) {
7561 if (xmax >= 1) xmin = TMath::Max(.5,xmax*1e-10);
7562 else xmin = 0.001*xmax;
7563 }
7564 Double_t xm = xmin;
7565 if (maximum) xmax = fH->GetMaximumStored();
7566 if (minimum) xm = fH->GetMinimumStored();
7567 if (Hoption.Logx && xm <= 0) {
7568 Error(where, "log scale requested with zero or negative argument (%f)", xm);
7569 return 0;
7570 }
7571 else xmin = xm;
7572 if (xmin >= xmax) {
7573 if (Hoption.Logx) {
7574 if (xmax > 0) xmin = 0.001*xmax;
7575 else {
7576 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", xmax);
7577 return 0;
7578 }
7579 }
7580 else {
7581 if (xmin > 0) {
7582 xmin = 0;
7583 xmax *= 2;
7584 } else if (xmin < 0) {
7585 xmax = 0;
7586 xmin *= 2;
7587 } else {
7588 xmin = 0;
7589 xmax = 1;
7590 }
7591 }
7592 }
7593
7594 // take into account normalization factor
7595 Hparam.allchan = allchan;
7596 Double_t factor = allchan;
7597 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
7598 if (allchan) factor /= allchan;
7599 if (factor == 0) factor = 1;
7600 Hparam.factor = factor;
7601 xmax = factor*xmax;
7602 xmin = factor*xmin;
7603
7604 // For log scales, histogram coordinates are LOG10(ymin) and
7605 // LOG10(ymax). Final adjustment (if not option "Same"
7606 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
7607 // Maximum and Minimum are not defined.
7608 if (Hoption.Logx) {
7609 if (xmin <=0 || xmax <=0) {
7610 Error(where, "Cannot set Y axis to log scale");
7611 return 0;
7612 }
7614 if (!minimum) xmin += TMath::Log10(0.5);
7616 if (!maximum) xmax += TMath::Log10(2*(0.9/0.95));
7617 if (!Hoption.Same) {
7618 Hparam.xmin = xmin;
7619 Hparam.xmax = xmax;
7620 }
7621 return 1;
7622 }
7623
7624 // final adjustment of ymin for linear scale.
7625 // if minimum is not set , then ymin is set to zero if >0
7626 // or to ymin - margin if <0.
7627 if (!minimum) {
7628 if (xmin >= 0) xmin = 0;
7629 else xmin -= yMARGIN*(xmax-xmin);
7630 }
7631
7632 // final adjustment of YMAXI for linear scale (if not option "Same"):
7633 // decrease histogram height to MAX% of allowed height if HMAXIM
7634 // has not been called.
7635 if (!maximum) {
7636 xmax += yMARGIN*(xmax-xmin);
7637 }
7638 Hparam.xmin = xmin;
7639 Hparam.xmax = xmax;
7640 return 1;
7641}
7642
7643////////////////////////////////////////////////////////////////////////////////
7644/// [Control function to draw a 3D histogram with boxes.](\ref HP25)
7645
7647{
7648 // Predefined box structure
7649 Double_t wxyz[8][3] = { {-1,-1,-1}, {1,-1,-1}, {1,1,-1}, {-1,1,-1},
7650 {-1,-1, 1}, {1,-1, 1}, {1,1, 1}, {-1,1, 1} };
7651 Int_t iface[6][4] = { {0,3,2,1}, {4,5,6,7},
7652 {0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7} };
7653
7654 // Define dimensions of world space
7655 TAxis *xaxis = fH->GetXaxis();
7656 TAxis *yaxis = fH->GetYaxis();
7657 TAxis *zaxis = fH->GetZaxis();
7658
7659 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7660 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7661 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7662 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7663 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7664 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7665
7666 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7667
7668 // Set view
7669 TView *view = gPad ? gPad->GetView() : nullptr;
7670 if (!view) {
7671 Error("PaintH3", "no TView in current pad");
7672 return;
7673 }
7674 Double_t thedeg = 90 - gPad->GetTheta();
7675 Double_t phideg = -90 - gPad->GetPhi();
7676 Double_t psideg = view->GetPsi();
7677 Int_t irep;
7678 view->SetView(phideg, thedeg, psideg, irep);
7679
7680 Int_t backcolor = gPad->GetFrameFillColor();
7681 view->PadRange(backcolor);
7682
7683 // Draw back surfaces of frame box
7684 fLego->InitMoveScreen(-1.1,1.1);
7685 if (Hoption.BackBox) {
7686 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
7688 fLego->BackBox(90);
7689 }
7690
7692
7693 // Define order of drawing
7694 Double_t *tnorm = view->GetTnorm();
7695 if (!tnorm) return;
7696 Int_t incrx = (tnorm[ 8] < 0.) ? -1 : +1;
7697 Int_t incry = (tnorm[ 9] < 0.) ? -1 : +1;
7698 Int_t incrz = (tnorm[10] < 0.) ? -1 : +1;
7699 Int_t ix1 = (incrx == +1) ? xaxis->GetFirst() : xaxis->GetLast();
7700 Int_t iy1 = (incry == +1) ? yaxis->GetFirst() : yaxis->GetLast();
7701 Int_t iz1 = (incrz == +1) ? zaxis->GetFirst() : zaxis->GetLast();
7702 Int_t ix2 = (incrx == +1) ? xaxis->GetLast() : xaxis->GetFirst();
7703 Int_t iy2 = (incry == +1) ? yaxis->GetLast() : yaxis->GetFirst();
7704 Int_t iz2 = (incrz == +1) ? zaxis->GetLast() : zaxis->GetFirst();
7705
7706 // Set graphic attributes (colour, style, etc.)
7711
7712 fH->SetFillStyle(1001);
7713 fH->TAttFill::Modify();
7714 fH->TAttLine::Modify();
7717
7718 // Create bin boxes and draw
7722
7723 Double_t pmin[3], pmax[3], sxyz[8][3];
7724 for (Int_t ix = ix1; ix !=ix2+incrx; ix += incrx) {
7725 pmin[0] = xaxis->GetBinLowEdge(ix);
7726 pmax[0] = xaxis->GetBinUpEdge(ix);
7727 for (Int_t iy = iy1; iy != iy2+incry; iy += incry) {
7728 pmin[1] = yaxis->GetBinLowEdge(iy);
7729 pmax[1] = yaxis->GetBinUpEdge(iy);
7730 for (Int_t iz = iz1; iz != iz2+incrz; iz += incrz) {
7731 pmin[2] = zaxis->GetBinLowEdge(iz);
7732 pmax[2] = zaxis->GetBinUpEdge(iz);
7733 Double_t w = fH->GetBinContent(fH->GetBin(ix,iy,iz));
7734 Bool_t neg = kFALSE;
7735 Int_t n = 5;
7736 if (w<0) {
7737 w = -w;
7738 neg = kTRUE;
7739 }
7740 if (w < wmin) continue;
7741 if (w > wmax) w = wmax;
7742 Double_t scale = (TMath::Power((w-wmin)/(wmax-wmin),1./3.))/2.;
7743 if (scale == 0) continue;
7744 for (Int_t i=0; i<3; ++i) {
7745 Double_t c = (pmax[i] + pmin[i])*0.5;
7746 Double_t d = (pmax[i] - pmin[i])*scale;
7747 for (Int_t k=0; k<8; ++k) { // set bin box vertices
7748 sxyz[k][i] = wxyz[k][i]*d + c;
7749 }
7750 }
7751 for (Int_t k=0; k<8; ++k) { // transform to normalized space
7752 view->WCtoNDC(&sxyz[k][0],&sxyz[k][0]);
7753 }
7754 Double_t x[8], y[8]; // draw bin box faces
7755 for (Int_t k=0; k<6; ++k) {
7756 for (Int_t i=0; i<4; ++i) {
7757 Int_t iv = iface[k][i];
7758 x[i] = sxyz[iv][0];
7759 y[i] = sxyz[iv][1];
7760 }
7761 x[4] = x[0] ; y[4] = y[0];
7762 if (neg) {
7763 x[5] = x[2] ; y[5] = y[2];
7764 x[6] = x[3] ; y[6] = y[3];
7765 x[7] = x[1] ; y[7] = y[1];
7766 n = 8;
7767 } else {
7768 n = 5;
7769 }
7770 Double_t z = (x[2]-x[0])*(y[3]-y[1]) - (y[2]-y[0])*(x[3]-x[1]);
7771 if (z <= 0.) continue;
7772 if (iopt == 2) {
7773 theColor = ncolors*((w-wmin)/(wmax-wmin)) -1;
7775 } else {
7776 if (k == 3 || k == 5) {
7778 } else if (k == 0 || k == 1) {
7780 } else {
7782 }
7783 }
7784 fH->TAttFill::Modify();
7785 gPad->PaintFillArea(4, x, y);
7786 if (iopt != 3)gPad->PaintPolyLine(n, x, y);
7787 }
7788 }
7789 }
7790 }
7791
7792 // Draw front surfaces of frame box
7793 if (Hoption.FrontBox) fLego->FrontBox(90);
7794
7795 // Draw axis and title
7796 if (!Hoption.Axis && !Hoption.Same) {
7797 TGaxis axis;
7798 PaintLegoAxis(&axis, 90);
7799 }
7800 PaintTitle();
7801
7802 // Draw palette. if needed.
7803 if (Hoption.Zscale) {
7804 Int_t ndiv = fH->GetContour();
7805 if (ndiv == 0 ) {
7806 ndiv = gStyle->GetNumberContours();
7807 fH->SetContour(ndiv);
7808 }
7809 PaintPalette();
7810 }
7811
7812 //Draw stats and fit results
7813 TF1 *fit = nullptr;
7814 TIter next(fFunctions);
7815 while (auto obj = next()) {
7816 if (obj->InheritsFrom(TF1::Class())) {
7817 fit = (TF1*)obj;
7818 break;
7819 }
7820 }
7821 if ((Hoption.Same%10) != 1) {
7822 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7824 }
7825 }
7826
7827 fLego.reset();
7828
7831 fH->TAttFill::Modify();
7832}
7833
7834////////////////////////////////////////////////////////////////////////////////
7835/// [Control function to draw a 3D histogram with boxes.](\ref HP25)
7836
7838{
7839 // Predefined box structure
7840 Double_t wxyz[8][3] = {
7841 {-1,-1,-1}, {1,-1,-1}, {1,1,-1}, {-1,1,-1}, // bottom vertices
7842 {-1,-1, 1}, {1,-1, 1}, {1,1, 1}, {-1,1, 1} // top vertices
7843 };
7844 Int_t iface[6][4] = {
7845 {0,3,2,1}, {4,5,6,7}, // bottom and top faces
7846 {0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7} // side faces
7847 };
7848 Double_t normal[6][3] = {
7849 {0,0,-1}, {0,0,1}, // Z-, Z+
7850 {0,-1,0}, {1,0,0}, {0,1,0}, {-1,0,0} // Y-, X+, Y+, X-
7851 };
7852
7853 // Define dimensions of world space
7854 TAxis *xaxis = fH->GetXaxis();
7855 TAxis *yaxis = fH->GetYaxis();
7856 TAxis *zaxis = fH->GetZaxis();
7857
7858 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7859 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7860 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7861 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7862 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7863 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7864
7865 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7866
7867 // Set view
7868 TView *view = gPad ? gPad->GetView() : nullptr;
7869 if (!view) {
7870 Error("PaintH3", "no TView in current pad");
7871 return;
7872 }
7873 Double_t thedeg = 90 - gPad->GetTheta();
7874 Double_t phideg = -90 - gPad->GetPhi();
7875 Double_t psideg = view->GetPsi();
7876 Int_t irep;
7877 view->SetView(phideg, thedeg, psideg, irep);
7878
7879 Int_t backcolor = gPad->GetFrameFillColor();
7880 view->PadRange(backcolor);
7881
7882 // Draw front surfaces of frame box
7883 if (Hoption.FrontBox) {
7884 fLego->InitMoveScreen(-1.1,1.1);
7886 }
7887
7888 // Initialize hidden line removal algorithm "raster screen"
7889 fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
7890
7891 // Define order of drawing
7892 Double_t *tnorm = view->GetTnorm();
7893 if (!tnorm) return;
7894 Int_t incrx = (tnorm[ 8] < 0.) ? +1 : -1;
7895 Int_t incry = (tnorm[ 9] < 0.) ? +1 : -1;
7896 Int_t incrz = (tnorm[10] < 0.) ? +1 : -1;
7897 Int_t ix1 = (incrx == +1) ? xaxis->GetFirst() : xaxis->GetLast();
7898 Int_t iy1 = (incry == +1) ? yaxis->GetFirst() : yaxis->GetLast();
7899 Int_t iz1 = (incrz == +1) ? zaxis->GetFirst() : zaxis->GetLast();
7900 Int_t ix2 = (incrx == +1) ? xaxis->GetLast() : xaxis->GetFirst();
7901 Int_t iy2 = (incry == +1) ? yaxis->GetLast() : yaxis->GetFirst();
7902 Int_t iz2 = (incrz == +1) ? zaxis->GetLast() : zaxis->GetFirst();
7903
7904 // Set line attributes (colour, style, etc.)
7905 fH->TAttLine::Modify();
7906
7907 // Create bin boxes and draw
7908 const Int_t NTMAX = 100;
7909 Double_t tt[NTMAX][2];
7913 Double_t pmin[3], pmax[3], sxyz[8][3], pp[4][2];
7914 for (Int_t ix = ix1; ix !=ix2+incrx; ix += incrx) {
7915 pmin[0] = xaxis->GetBinLowEdge(ix);
7916 pmax[0] = xaxis->GetBinUpEdge(ix);
7917 for (Int_t iy = iy1; iy != iy2+incry; iy += incry) {
7918 pmin[1] = yaxis->GetBinLowEdge(iy);
7919 pmax[1] = yaxis->GetBinUpEdge(iy);
7920 for (Int_t iz = iz1; iz != iz2+incrz; iz += incrz) {
7921 pmin[2] = zaxis->GetBinLowEdge(iz);
7922 pmax[2] = zaxis->GetBinUpEdge(iz);
7923 Double_t w = fH->GetBinContent(fH->GetBin(ix,iy,iz));
7924 Bool_t neg = kFALSE;
7925 if (w<0) {
7926 w = -w;
7927 neg = kTRUE;
7928 }
7929 if (w < wmin) continue;
7930 if (w > wmax) w = wmax;
7931 Double_t scale = (TMath::Power((w-wmin)/(wmax-wmin),1./3.))/2.;
7932 if (scale == 0) continue;
7933 for (Int_t i=0; i<3; ++i) {
7934 Double_t c = (pmax[i] + pmin[i])*0.5;
7935 Double_t d = (pmax[i] - pmin[i])*scale;
7936 for (Int_t k=0; k<8; ++k) { // set bin box vertices
7937 sxyz[k][i] = wxyz[k][i]*d + c;
7938 }
7939 }
7940 for (Int_t k=0; k<8; ++k) { // transform to normalized space
7941 view->WCtoNDC(&sxyz[k][0],&sxyz[k][0]);
7942 }
7943 for (Int_t k=0; k<6; ++k) { // draw box faces
7944 Double_t zn;
7945 view->FindNormal(normal[k][0], normal[k][1], normal[k][2], zn);
7946 if (zn <= 0) continue;
7947 for (Int_t i=0; i<4; ++i) {
7948 Int_t ip = iface[k][i];
7949 pp[i][0] = sxyz[ip][0];
7950 pp[i][1] = sxyz[ip][1];
7951 }
7952 for (Int_t i=0; i<4; ++i) {
7953 Int_t i1 = i;
7954 Int_t i2 = (i == 3) ? 0 : i + 1;
7955 Int_t nt;
7956 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7957 Double_t xdel = pp[i2][0] - pp[i1][0];
7958 Double_t ydel = pp[i2][1] - pp[i1][1];
7959 Double_t x[2], y[2];
7960 for (Int_t it = 0; it < nt; ++it) {
7961 x[0] = pp[i1][0] + xdel*tt[it][0];
7962 y[0] = pp[i1][1] + ydel*tt[it][0];
7963 x[1] = pp[i1][0] + xdel*tt[it][1];
7964 y[1] = pp[i1][1] + ydel*tt[it][1];
7965 gPad->PaintPolyLine(2, x, y);
7966 }
7967 }
7968 if (neg) {
7969 Int_t i1 = 0;
7970 Int_t i2 = 2;
7971 Int_t nt;
7972 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7973 Double_t xdel = pp[i2][0] - pp[i1][0];
7974 Double_t ydel = pp[i2][1] - pp[i1][1];
7975 Double_t x[2], y[2];
7976 for (Int_t it = 0; it < nt; ++it) {
7977 x[0] = pp[i1][0] + xdel*tt[it][0];
7978 y[0] = pp[i1][1] + ydel*tt[it][0];
7979 x[1] = pp[i1][0] + xdel*tt[it][1];
7980 y[1] = pp[i1][1] + ydel*tt[it][1];
7981 gPad->PaintPolyLine(2, x, y);
7982 }
7983 i1 = 1;
7984 i2 = 3;
7985 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7986 xdel = pp[i2][0] - pp[i1][0];
7987 ydel = pp[i2][1] - pp[i1][1];
7988 for (Int_t it = 0; it < nt; ++it) {
7989 x[0] = pp[i1][0] + xdel*tt[it][0];
7990 y[0] = pp[i1][1] + ydel*tt[it][0];
7991 x[1] = pp[i1][0] + xdel*tt[it][1];
7992 y[1] = pp[i1][1] + ydel*tt[it][1];
7993 gPad->PaintPolyLine(2, x, y);
7994 }
7995 }
7996 fLego->FillPolygonBorder(4, &pp[0][0]); // update raster screen
7997 }
7998 }
7999 }
8000 }
8001
8002 // Draw frame box
8003 if (Hoption.BackBox) {
8004 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
8006 fLego->BackBox(90);
8007 }
8008
8009 if (Hoption.FrontBox) fLego->FrontBox(90);
8010
8011 // Draw axis and title
8012 if (!Hoption.Axis && !Hoption.Same) {
8013 TGaxis axis;
8014 PaintLegoAxis(&axis, 90);
8015 }
8016 PaintTitle();
8017
8018 //Draw stats and fit results
8019 TF1 *fit = nullptr;
8020 TIter next(fFunctions);
8021 while (auto obj = next()) {
8022 if (obj->InheritsFrom(TF1::Class())) {
8023 fit = (TF1*)obj;
8024 break;
8025 }
8026 }
8027 if ((Hoption.Same%10) != 1) {
8028 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
8030 }
8031 }
8032
8033 fLego.reset();
8034}
8035
8036////////////////////////////////////////////////////////////////////////////////
8037/// [Control function to draw a 3D histogram with Iso Surfaces.](\ref HP25)
8038
8040{
8041
8042 const Double_t ydiff = 1;
8043 const Double_t yligh1 = 10;
8044 const Double_t qa = 0.15;
8045 const Double_t qd = 0.15;
8046 const Double_t qs = 0.8;
8048 Int_t i, irep;
8049 Int_t nbcol = 28;
8050 Int_t icol1 = 201;
8051 Int_t ic1 = icol1;
8052 Int_t ic2 = ic1+nbcol;
8053 Int_t ic3 = ic2+nbcol;
8054
8055 TAxis *xaxis = fH->GetXaxis();
8056 TAxis *yaxis = fH->GetYaxis();
8057 TAxis *zaxis = fH->GetZaxis();
8058
8059 Int_t nx = fH->GetNbinsX();
8060 Int_t ny = fH->GetNbinsY();
8061 Int_t nz = fH->GetNbinsZ();
8062
8063 std::vector<Double_t> x(nx);
8064 std::vector<Double_t> y(ny);
8065 std::vector<Double_t> z(nz);
8066
8067 for (i=0; i<nx; i++) x[i] = xaxis->GetBinCenter(i+1);
8068 for (i=0; i<ny; i++) y[i] = yaxis->GetBinCenter(i+1);
8069 for (i=0; i<nz; i++) z[i] = zaxis->GetBinCenter(i+1);
8070
8071 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
8072 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
8073 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
8074 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
8075 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
8076 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
8077
8078 Double_t s[3];
8079 s[0] = fH->GetSumOfWeights()/(fH->GetNbinsX()*fH->GetNbinsY()*fH->GetNbinsZ());
8080 s[1] = 0.5*s[0];
8081 s[2] = 1.5*s[0];
8082
8083 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
8084
8085 TView *view = gPad ? gPad->GetView() : nullptr;
8086 if (!view) {
8087 Error("PaintH3Iso", "no TView in current pad");
8088 return;
8089 }
8090 Double_t thedeg = 90 - gPad->GetTheta();
8091 Double_t phideg = -90 - gPad->GetPhi();
8092 Double_t psideg = view->GetPsi();
8093 view->SetView(phideg, thedeg, psideg, irep);
8094
8095 Int_t backcolor = gPad->GetFrameFillColor();
8096 if (Hoption.System != kCARTESIAN) backcolor = 0;
8097 view->PadRange(backcolor);
8098
8099 Double_t dcol = 0.5/Double_t(nbcol);
8100 TColor *colref = gROOT->GetColor(fH->GetFillColor());
8101 if (!colref) {
8102 return;
8103 }
8104 Float_t r, g, b, hue, light, satur;
8105 colref->GetRGB(r,g,b);
8107 TColor *acol;
8108 for (Int_t col=0;col<nbcol;col++) {
8109 acol = gROOT->GetColor(col+icol1);
8110 TColor::HLStoRGB(hue, .4+col*dcol, satur, r, g, b);
8111 if (acol) acol->SetRGB(r, g, b);
8112 }
8113
8114 fLego->InitMoveScreen(-1.1,1.1);
8115
8116 if (Hoption.BackBox) {
8117 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
8119 fLego->BackBox(90);
8120 }
8121
8122 fLego->LightSource(0, ydiff, 0, 0, 0, irep);
8123 fLego->LightSource(1, yligh1, 1, 1, 1, irep);
8124 fLego->SurfaceProperty(qa, qd, qs, 1, irep);
8125 fmin = ydiff*qa;
8126 fmax = ydiff*qa + (yligh1+0.1)*(qd+qs);
8127 fLego->SetIsoSurfaceParameters(fmin, fmax, nbcol, ic1, ic2, ic3);
8128
8129 fLego->IsoSurface(1, s, nx, ny, nz, x.data(), y.data(), z.data(), "BF");
8130
8131 if (Hoption.FrontBox) {
8132 fLego->InitMoveScreen(-1.1,1.1);
8134 fLego->FrontBox(90);
8135 }
8136 if (!Hoption.Axis && !Hoption.Same) {
8137 TGaxis axis;
8138 PaintLegoAxis(&axis, 90);
8139 }
8140
8141 PaintTitle();
8142
8143 //Draw stats and fit results
8144 TF1 *fit = nullptr;
8145 TIter next(fFunctions);
8146 while (auto obj = next()) {
8147 if (obj->InheritsFrom(TF1::Class())) {
8148 fit = (TF1*)obj;
8149 break;
8150 }
8151 }
8152 if ((Hoption.Same%10) != 1) {
8153 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
8155 }
8156 }
8157
8158 fLego.reset();
8159}
8160
8161////////////////////////////////////////////////////////////////////////////////
8162/// [Control function to draw a 2D histogram as a lego plot.](\ref HP17)
8163
8165{
8166
8167 Int_t raster = 1;
8168 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
8169 Int_t nx = Hparam.xlast - Hparam.xfirst + 1;
8170 Int_t ny = Hparam.ylast - Hparam.yfirst + 1;
8171 Double_t zmin = Hparam.zmin;
8172 Double_t zmax = Hparam.zmax;
8177 Double_t dangle = 10*3.141592/180; //Delta angle for Rapidity option
8178 Double_t deltaz = TMath::Abs(zmin);
8179 if (deltaz == 0) deltaz = 1;
8180 if (zmin >= zmax) {
8181 zmin -= 0.5*deltaz;
8182 zmax += 0.5*deltaz;
8183 }
8184 Double_t z1c = zmin;
8185 Double_t z2c = zmin + (zmax-zmin)*(1+gStyle->GetHistTopMargin());
8186
8187 // Compute the lego limits and instantiate a lego object
8188 fXbuf[0] = -1;
8189 fYbuf[0] = 1;
8190 fXbuf[1] = -1;
8191 fYbuf[1] = 1;
8192 if (Hoption.System == kPOLAR) {
8193 fXbuf[2] = z1c;
8194 fYbuf[2] = z2c;
8195 } else if (Hoption.System == kCYLINDRICAL) {
8196 if (Hoption.Logy) {
8197 if (ylab1 > 0) fXbuf[2] = TMath::Log10(ylab1);
8198 else fXbuf[2] = 0;
8199 if (ylab2 > 0) fYbuf[2] = TMath::Log10(ylab2);
8200 else fYbuf[2] = 0;
8201 } else {
8202 fXbuf[2] = ylab1;
8203 fYbuf[2] = ylab2;
8204 }
8205 z1c = 0; z2c = 1;
8206 } else if (Hoption.System == kSPHERICAL) {
8207 fXbuf[2] = -1;
8208 fYbuf[2] = 1;
8209 z1c = 0; z2c = 1;
8210 } else if (Hoption.System == kRAPIDITY) {
8211 fXbuf[2] = -1/TMath::Tan(dangle);
8212 fYbuf[2] = 1/TMath::Tan(dangle);
8213 } else {
8214 fXbuf[0] = xlab1;
8215 fYbuf[0] = xlab2;
8216 fXbuf[1] = ylab1;
8217 fYbuf[1] = ylab2;
8218 fXbuf[2] = z1c;
8219 fYbuf[2] = z2c;
8220 raster = 0;
8221 }
8222
8223 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data(), Hoption.System);
8224
8225 Int_t nids = -1;
8226 TH1 * hid = nullptr;
8227 Color_t colormain = -1, colordark = -1;
8229
8230 // LEGO3 is like LEGO1 except that the black lines around each lego are not drawn.
8231 if (Hoption.Lego == 13) {
8232 Hoption.Lego = 11;
8233 fLego->SetMesh(0);
8234 }
8235 // LEGO4 is like LEGO1 except no shadows are drawn.
8236 if (Hoption.Lego == 14) {
8237 Hoption.Lego = 11;
8239 }
8240
8241 // Initialize the levels on the Z axis
8242 Int_t ndiv = fH->GetContour();
8243 if (ndiv == 0 ) {
8244 ndiv = gStyle->GetNumberContours();
8245 fH->SetContour(ndiv);
8246 }
8247 Int_t ndivz = TMath::Abs(ndiv);
8248 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
8249
8250 // Initialize colors
8251 if (!fStack) {
8252 fLego->SetEdgeAtt(fH->GetLineColor(),fH->GetLineStyle(),fH->GetLineWidth(),0);
8253 } else {
8254 for (Int_t id=0;id<=fStack->GetSize();id++) {
8255 hid = (TH1*)fStack->At((id==0)?id:id-1);
8256 fLego->SetEdgeAtt(hid->GetLineColor(),hid->GetLineStyle(),hid->GetLineWidth(),id);
8257 }
8258 }
8259
8260 if (Hoption.Lego == 11) {
8261 nids = 1;
8262 if (fStack) nids = fStack->GetSize();
8263 hid = fH;
8264 for (Int_t id=0;id<=nids;id++) {
8265 if (id > 0 && fStack) hid = (TH1*)fStack->At(id-1);
8266 colormain = hid->GetFillColor();
8267 if (colormain == 1) colormain = 17; //avoid drawing with black
8269 else colordark = colormain;
8270 fLego->SetColorMain(colormain,id);
8271 fLego->SetColorDark(colordark,id);
8272 if (id <= 1) fLego->SetColorMain(colormain,-1); // Set Bottom color
8273 if (id == nids) fLego->SetColorMain(colormain,99); // Set Top color
8274 }
8275 }
8276
8277 // Now ready to draw the lego plot
8278 Int_t irep = 0;
8279
8280 TView *view = gPad ? gPad->GetView() : nullptr;
8281 if (!view) {
8282 Error("PaintLego", "no TView in current pad");
8283 return;
8284 }
8285
8286 Double_t thedeg = 90 - gPad->GetTheta();
8287 Double_t phideg = -90 - gPad->GetPhi();
8288 Double_t psideg = view->GetPsi();
8289 view->SetView(phideg, thedeg, psideg, irep);
8290
8291 fLego->SetLineColor(kBlack); // zgrid color for lego1 & lego2
8292 fLego->SetFillStyle(fH->GetFillStyle());
8293
8294 // Set color/style for back box
8295 fLego->SetFillStyle(gPad->GetFrameFillStyle());
8296 fLego->SetFillColor(gPad->GetFrameFillColor());
8297 fLego->TAttFill::Modify();
8298
8299 Int_t backcolor = gPad->GetFrameFillColor();
8300 if (Hoption.System != kCARTESIAN) backcolor = 0;
8301 view->PadRange(backcolor);
8302
8303 fLego->SetFillStyle(fH->GetFillStyle());
8304 fLego->SetFillColor(fH->GetFillColor());
8305 fLego->TAttFill::Modify();
8306
8307 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
8308
8309 if (raster) fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
8310 else fLego->InitMoveScreen(-1.1,1.1);
8311
8312 if (Hoption.Lego == 19) {
8314 if (Hoption.BackBox) fLego->BackBox(90);
8315 if (Hoption.FrontBox) fLego->FrontBox(90);
8316 if (!Hoption.Axis) { TGaxis axis; PaintLegoAxis(&axis, 90); }
8317 return;
8318 }
8319
8320 if (Hoption.Lego == 11 || Hoption.Lego == 12) {
8323 fLego->BackBox(90);
8324 }
8325 }
8326
8327 if (Hoption.Lego == 12) DefineColorLevels(ndivz);
8328
8329 fLego->SetLegoFunction(&TPainter3dAlgorithms::LegoFunction);
8331 if (Hoption.Lego == 11) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode3);
8332 if (Hoption.Lego == 12) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode2);
8333 if (Hoption.System == kPOLAR) {
8334 if (Hoption.Lego == 1) fLego->LegoPolar(1,nx,ny,"FB");
8335 if (Hoption.Lego == 11) fLego->LegoPolar(1,nx,ny,"BF");
8336 if (Hoption.Lego == 12) fLego->LegoPolar(1,nx,ny,"BF");
8337 } else if (Hoption.System == kCYLINDRICAL) {
8338 if (Hoption.Lego == 1) fLego->LegoCylindrical(1,nx,ny,"FB");
8339 if (Hoption.Lego == 11) fLego->LegoCylindrical(1,nx,ny,"BF");
8340 if (Hoption.Lego == 12) fLego->LegoCylindrical(1,nx,ny,"BF");
8341 } else if (Hoption.System == kSPHERICAL) {
8342 if (Hoption.Lego == 1) fLego->LegoSpherical(0,1,nx,ny,"FB");
8343 if (Hoption.Lego == 11) fLego->LegoSpherical(0,1,nx,ny,"BF");
8344 if (Hoption.Lego == 12) fLego->LegoSpherical(0,1,nx,ny,"BF");
8345 } else if (Hoption.System == kRAPIDITY) {
8346 if (Hoption.Lego == 1) fLego->LegoSpherical(1,1,nx,ny,"FB");
8347 if (Hoption.Lego == 11) fLego->LegoSpherical(1,1,nx,ny,"BF");
8348 if (Hoption.Lego == 12) fLego->LegoSpherical(1,1,nx,ny,"BF");
8349 } else {
8350 if (Hoption.Lego == 1) {
8352 fLego->LegoCartesian(90,nx,ny,"FB");}
8353 if (Hoption.Lego == 11) fLego->LegoCartesian(90,nx,ny,"BF");
8354 if (Hoption.Lego == 12) fLego->LegoCartesian(90,nx,ny,"BF");
8355 }
8356
8357 if (Hoption.Lego == 1 || Hoption.Lego == 11) {
8360 fLego->BackBox(90);
8361 }
8362 }
8363 if (Hoption.System == kCARTESIAN) {
8364 fLego->InitMoveScreen(-1.1,1.1);
8366 if (Hoption.FrontBox) fLego->FrontBox(90);
8367 }
8368 if (!Hoption.Axis && !Hoption.Same) {
8369 TGaxis axis;
8370 PaintLegoAxis(&axis, 90);
8371 }
8373 fLego.reset();
8374}
8375
8376////////////////////////////////////////////////////////////////////////////////
8377/// Draw the axis for legos and surface plots.
8378
8380{
8381
8382 static Double_t epsil = 0.001;
8383
8386 Double_t r[24] /* was [3][8] */;
8387 Int_t ndivx, ndivy, ndivz, i;
8388 Double_t x1[3], x2[3], y1[3], y2[3], z1[3], z2[3], av[24] /* was [3][8] */;
8389 static char chopax[8], chopay[8], chopaz[8];
8390 Int_t ix1, ix2, iy1, iy2, iz1, iz2;
8391 Double_t rad;
8392
8393 TView *view = gPad ? gPad->GetView() : nullptr;
8394 if (!view) {
8395 Error("PaintLegoAxis", "no TView in current pad");
8396 return;
8397 }
8398
8399 // In polar coordinates, draw a short line going from the external circle
8400 // corresponding to r = 1 up to r = 1.1
8401 if (Hoption.System == kPOLAR) {
8402 r[0] = 1;
8403 r[1] = 0;
8404 r[2] = 0;
8405 view->WCtoNDC(r, x1);
8406 r[0] = 1.1;
8407 r[1] = 0;
8408 r[2] = 0;
8409 view->WCtoNDC(r, x2);
8410 gPad->PaintLine(x1[0],x1[1],x2[0],x2[1]);
8411 return;
8412 }
8413
8414 if (Hoption.System != kCARTESIAN) return;
8415
8416 rad = TMath::ATan(1.) * 4. /180.;
8417 cosa = TMath::Cos(ang*rad);
8418 sina = TMath::Sin(ang*rad);
8419
8420 view->AxisVertex(ang, av, ix1, ix2, iy1, iy2, iz1, iz2);
8421 for (i = 1; i <= 8; ++i) {
8422 r[i*3 - 3] = av[i*3 - 3] + av[i*3 - 2]*cosa;
8423 r[i*3 - 2] = av[i*3 - 2]*sina;
8424 r[i*3 - 1] = av[i*3 - 1];
8425 }
8426
8427 view->WCtoNDC(&r[ix1*3 - 3], x1);
8428 view->WCtoNDC(&r[ix2*3 - 3], x2);
8429 view->WCtoNDC(&r[iy1*3 - 3], y1);
8430 view->WCtoNDC(&r[iy2*3 - 3], y2);
8431 view->WCtoNDC(&r[iz1*3 - 3], z1);
8432 view->WCtoNDC(&r[iz2*3 - 3], z2);
8433
8434 view->SetAxisNDC(x1, x2, y1, y2, z1, z2);
8435
8436 Double_t *rmin = view->GetRmin();
8437 Double_t *rmax = view->GetRmax();
8438 if (!rmin || !rmax) return;
8439
8440 // Initialize the axis options
8441 if (x1[0] > x2[0]) strlcpy(chopax, "SDH=+",8);
8442 else strlcpy(chopax, "SDH=-",8);
8443 if (y1[0] > y2[0]) strlcpy(chopay, "SDH=+",8);
8444 else strlcpy(chopay, "SDH=-",8);
8445 if (z2[1] > z1[1]) strlcpy(chopaz, "SDH=+",8);
8446 else strlcpy(chopaz, "SDH=-",8);
8447
8448 // Option LOG is required ?
8449 if (Hoption.Logx) strlcat(chopax,"G",8);
8450 if (Hoption.Logy) strlcat(chopay,"G",8);
8451 if (Hoption.Logz) strlcat(chopaz,"G",8);
8452
8453 // Initialize the number of divisions. If the
8454 // number of divisions is negative, option 'N' is required.
8458 if (ndivx < 0) {
8460 strlcat(chopax, "N",8);
8461 }
8462 if (ndivy < 0) {
8464 strlcat(chopay, "N",8);
8465 }
8466 if (ndivz < 0) {
8468 strlcat(chopaz, "N",8);
8469 }
8470
8471 // Set Axis attributes.
8472 // The variable SCALE rescales the VSIZ
8473 // in order to have the same label size for all angles.
8474
8475 axis->SetLineWidth(1);
8476
8477 // X axis drawing
8478 if (TMath::Abs(x1[0] - x2[0]) >= epsil || TMath::Abs(x1[1] - x2[1]) > epsil) {
8481 if (Hoption.Logx && !fH->InheritsFrom(TH3::Class())) {
8482 bmin = TMath::Power(10, rmin[0]);
8483 bmax = TMath::Power(10, rmax[0]);
8484 } else {
8485 bmin = rmin[0];
8486 bmax = rmax[0];
8487 }
8488 // Option time display is required ?
8489 if (fXaxis->GetTimeDisplay()) {
8490 strlcat(chopax,"t",8);
8491 if (strlen(fXaxis->GetTimeFormatOnly()) == 0) {
8493 } else {
8495 }
8496 }
8497 axis->SetOption(chopax);
8498 axis->PaintAxis(x1[0], x1[1], x2[0], x2[1], bmin, bmax, ndivx, chopax);
8499 }
8500
8501 // Y axis drawing
8502 if (TMath::Abs(y1[0] - y2[0]) >= epsil || TMath::Abs(y1[1] - y2[1]) > epsil) {
8505 if (fYaxis->GetTitleOffset() == 0) axis->SetTitleOffset(1.5);
8506
8507 if (fH->GetDimension() < 2) {
8508 strlcpy(chopay, "V=+UN",8);
8509 ndivy = 0;
8510 }
8511 if (TMath::Abs(y1[0] - y2[0]) < epsil) {
8512 y2[0] = y1[0];
8513 }
8514 if (Hoption.Logy && !fH->InheritsFrom(TH3::Class())) {
8515 bmin = TMath::Power(10, rmin[1]);
8516 bmax = TMath::Power(10, rmax[1]);
8517 } else {
8518 bmin = rmin[1];
8519 bmax = rmax[1];
8520 }
8521 // Option time display is required ?
8522 if (fYaxis->GetTimeDisplay()) {
8523 strlcat(chopay,"t",8);
8524 if (strlen(fYaxis->GetTimeFormatOnly()) == 0) {
8526 } else {
8528 }
8529 }
8530 axis->SetOption(chopay);
8531 axis->PaintAxis(y1[0], y1[1], y2[0], y2[1], bmin, bmax, ndivy, chopay);
8532 }
8533
8534 // Z axis drawing
8535 if (TMath::Abs(z1[0] - z2[0]) >= 100*epsil || TMath::Abs(z1[1] - z2[1]) > 100*epsil) {
8537 if (Hoption.Logz && !fH->InheritsFrom(TH3::Class())) {
8538 bmin = TMath::Power(10, rmin[2]);
8539 bmax = TMath::Power(10, rmax[2]);
8540 } else {
8541 bmin = rmin[2];
8542 bmax = rmax[2];
8543 }
8544 // Option time display is required ?
8545 if (fZaxis->GetTimeDisplay()) {
8546 strlcat(chopaz,"t",8);
8547 if (strlen(fZaxis->GetTimeFormatOnly()) == 0) {
8549 } else {
8551 }
8552 }
8553 axis->SetOption(chopaz);
8555 if (ztit.Index(";")>0) {
8556 ztit.Remove(ztit.Index(";"),ztit.Length());
8557 axis->SetTitle(ztit.Data());
8558 }
8559 axis->PaintAxis(z1[0], z1[1], z2[0], z2[1], bmin, bmax, ndivz, chopaz);
8560 }
8561
8562 //fH->SetLineStyle(1); /// otherwise fEdgeStyle[i] gets overwritten!
8563}
8564
8565////////////////////////////////////////////////////////////////////////////////
8566/// [Paint the color palette on the right side of the pad.](\ref HP22)
8567
8569{
8571 TView *view = gPad ? gPad->GetView() : nullptr;
8572 if (palette) {
8573 if (view) {
8574 if (!palette->TestBit(TPaletteAxis::kHasView)) {
8576 delete palette; palette = nullptr;
8577 }
8578 } else {
8579 if (palette->TestBit(TPaletteAxis::kHasView)) {
8581 delete palette; palette = nullptr;
8582 }
8583 }
8584 // make sure the histogram member of the palette is setup correctly. It may not be after a Clone()
8585 if (palette && !palette->GetHistogram()) palette->SetHistogram(fH);
8586 }
8587
8588 if (!palette) {
8589 Double_t xup = gPad->GetUxmax();
8590 Double_t x2 = gPad->PadtoX(gPad->GetX2());
8591 Double_t ymin = gPad->PadtoY(gPad->GetUymin());
8592 Double_t ymax = gPad->PadtoY(gPad->GetUymax());
8593 Double_t xr = 0.05*(gPad->GetX2() - gPad->GetX1());
8594 Double_t xmin = gPad->PadtoX(xup +0.1*xr);
8595 Double_t xmax = gPad->PadtoX(xup + xr);
8596 if (xmax > x2) xmax = gPad->PadtoX(gPad->GetX2()-0.01*xr);
8599 palette->Paint();
8600 }
8601}
8602
8603////////////////////////////////////////////////////////////////////////////////
8604/// [Control function to draw a 2D histogram as a scatter plot.](\ref HP11)
8605
8607{
8608
8609 fH->TAttMarker::Modify();
8610
8611 Int_t k, marker;
8612 Double_t dz, z, xk,xstep, yk, ystep;
8613 Double_t scale = 1;
8615 Double_t zmax = fH->GetMaximum();
8616 Double_t zmin = fH->GetMinimum();
8617 if (zmin == 0 && zmax == 0) return;
8618 if (zmin == zmax) {
8619 zmax += 0.1*TMath::Abs(zmax);
8620 zmin -= 0.1*TMath::Abs(zmin);
8621 }
8623 if (Hoption.Logz) {
8624 if (zmin > 0) zmin = TMath::Log10(zmin);
8625 else zmin = 0;
8626 if (zmax > 0) zmax = TMath::Log10(zmax);
8627 else zmax = 0;
8628 if (zmin == 0 && zmax == 0) return;
8629 dz = zmax - zmin;
8630 scale = 100/dz;
8631 if (ncells > 10000) scale /= 5;
8632 ltest = kTRUE;
8633 } else {
8634 dz = zmax - zmin;
8635 if (dz >= kNMAX || zmax < 1) {
8636 scale = (kNMAX-1)/dz;
8637 if (ncells > 10000) scale /= 5;
8638 ltest = kTRUE;
8639 }
8640 }
8641 if (fH->GetMinimumStored() == -1111) {
8643 if (Hoption.MinimumZero) {
8644 if (zmin >= 0) zmin = 0;
8645 else zmin -= yMARGIN*(zmax-zmin);
8646 } else {
8647 Double_t dzmin = yMARGIN*(zmax-zmin);
8648 if (zmin >= 0 && (zmin-dzmin <= 0)) zmin = 0;
8649 else zmin -= dzmin;
8650 }
8651 }
8652
8653 TString opt = option;
8654 opt.ToLower();
8655 if (opt.Contains("scat=")) {
8656 char optscat[100];
8657 strlcpy(optscat,opt.Data(),100);
8658 char *oscat = strstr(optscat,"scat=");
8659 char *blank = strstr(oscat," "); if (blank) *blank = 0;
8660 sscanf(oscat+5,"%lg",&scale);
8661 }
8662 // use an independent instance of a random generator
8663 // instead of gRandom to avoid conflicts and
8664 // to get same random numbers when drawing the same histogram
8666 marker=0;
8667 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
8670 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
8671 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
8672 xk = fXaxis->GetBinLowEdge(i);
8673 xstep = fXaxis->GetBinWidth(i);
8674 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
8675 z = fH->GetBinContent(bin);
8676 if (z < zmin) z = zmin;
8677 if (z > zmax) z = zmax;
8678 if (Hoption.Logz) {
8679 if (z > 0) z = TMath::Log10(z) - zmin;
8680 } else {
8681 z -= zmin;
8682 }
8683 if (z <= 0) continue;
8684 k = Int_t(z*scale);
8685 if (ltest) k++;
8686 if (k > 0) {
8687 for (Int_t loop=0; loop<k; loop++) {
8688 if (k+marker >= kNMAX) {
8689 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
8690 marker=0;
8691 }
8692 fXbuf[marker] = (random.Rndm()*xstep) + xk;
8693 fYbuf[marker] = (random.Rndm()*ystep) + yk;
8694 if (Hoption.Logx) {
8695 if (fXbuf[marker] > 0) fXbuf[marker] = TMath::Log10(fXbuf[marker]);
8696 else break;
8697 }
8698 if (Hoption.Logy) {
8699 if (fYbuf[marker] > 0) fYbuf[marker] = TMath::Log10(fYbuf[marker]);
8700 else break;
8701 }
8702 if (fXbuf[marker] < gPad->GetUxmin()) break;
8703 if (fYbuf[marker] < gPad->GetUymin()) break;
8704 if (fXbuf[marker] > gPad->GetUxmax()) break;
8705 if (fYbuf[marker] > gPad->GetUymax()) break;
8706 marker++;
8707 }
8708 }
8709 }
8710 }
8711 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
8712
8714}
8715
8716////////////////////////////////////////////////////////////////////////////////
8717/// Static function to paint special objects like vectors and matrices.
8718/// This function is called via `gROOT->ProcessLine` to paint these objects
8719/// without having a direct dependency of the graphics or histogramming
8720/// system.
8721
8723{
8724
8725 if (!obj) return;
8726 TDirectory::TContext ctx{nullptr}; // No self-registration to directories
8727
8728 if (obj->InheritsFrom(TMatrixFBase::Class())) {
8729 // case TMatrixF
8730 TH2F *R__TMatrixFBase = new TH2F((TMatrixFBase &)*obj);
8731 R__TMatrixFBase->SetBit(kCanDelete);
8732 R__TMatrixFBase->Draw(option);
8733
8734 } else if (obj->InheritsFrom(TMatrixDBase::Class())) {
8735 // case TMatrixD
8736 TH2D *R__TMatrixDBase = new TH2D((TMatrixDBase &)*obj);
8737 R__TMatrixDBase->SetBit(kCanDelete);
8738 R__TMatrixDBase->Draw(option);
8739
8740 } else if (obj->InheritsFrom(TVectorF::Class())) {
8741 //case TVectorF
8742 TH1F *R__TVectorF = new TH1F((TVectorF &)*obj);
8743 R__TVectorF->SetBit(kCanDelete);
8744 R__TVectorF->Draw(option);
8745
8746 } else if (obj->InheritsFrom(TVectorD::Class())) {
8747 //case TVectorD
8748 TH1D *R__TVectorD = new TH1D((TVectorD &)*obj);
8749 R__TVectorD->SetBit(kCanDelete);
8750 R__TVectorD->Draw(option);
8751 }
8752}
8753
8754////////////////////////////////////////////////////////////////////////////////
8755/// [Draw the statistics box for 1D and profile histograms.](\ref HP07)
8756
8758{
8759 TString tt, tf;
8760 Int_t dofit;
8761 TPaveStats *stats = nullptr;
8762 TIter next(fFunctions);
8763 while (auto obj = next()) {
8764 if (obj->InheritsFrom(TPaveStats::Class())) {
8765 stats = (TPaveStats*)obj;
8766 break;
8767 }
8768 }
8769
8770 if (stats && dostat) {
8771 dofit = stats->GetOptFit();
8772 dostat = stats->GetOptStat();
8773 } else {
8774 dofit = gStyle->GetOptFit();
8775 }
8776 if (!dofit) fit = nullptr;
8777 if (dofit == 1) dofit = 111;
8778 if (dostat == 1) dostat = 1111;
8779 Int_t print_name = dostat%10;
8780 Int_t print_entries = (dostat/10)%10;
8781 Int_t print_mean = (dostat/100)%10;
8782 Int_t print_stddev = (dostat/1000)%10;
8783 Int_t print_under = (dostat/10000)%10;
8784 Int_t print_over = (dostat/100000)%10;
8785 Int_t print_integral= (dostat/1000000)%10;
8786 Int_t print_skew = (dostat/10000000)%10;
8787 Int_t print_kurt = (dostat/100000000)%10;
8791 Int_t print_fval = dofit%10;
8792 Int_t print_ferrors = (dofit/10)%10;
8793 Int_t print_fchi2 = (dofit/100)%10;
8794 Int_t print_fprob = (dofit/1000)%10;
8796 if (fit) {
8797 if (print_fval < 2) nlinesf += fit->GetNumberFreeParameters();
8798 else nlinesf += fit->GetNpar();
8799 }
8801
8802 // Pavetext with statistics
8803 Bool_t done = kFALSE;
8804 if (!dostat && !fit) {
8805 if (stats) { fFunctions->Remove(stats); delete stats;}
8806 return;
8807 }
8809 if (fit) statw = 1.8*gStyle->GetStatW();
8811 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
8812 stath = 0.25*(nlines+nlinesf)*gStyle->GetStatH();
8813 }
8814 if (stats) {
8815 stats->Clear();
8816 done = kTRUE;
8817 } else {
8818 stats = new TPaveStats(
8821 gStyle->GetStatX(),
8822 gStyle->GetStatY(),"brNDC");
8823
8824 stats->SetParent(fH);
8825 stats->SetOptFit(dofit);
8826 stats->SetOptStat(dostat);
8827 stats->SetFillColor(gStyle->GetStatColor());
8828 stats->SetFillStyle(gStyle->GetStatStyle());
8830 stats->SetTextFont(gStyle->GetStatFont());
8831 if (gStyle->GetStatFont()%10 > 2)
8833 stats->SetFitFormat(gStyle->GetFitFormat());
8835 stats->SetName("stats");
8836
8838 stats->SetTextAlign(12);
8839 stats->SetBit(kCanDelete);
8840 stats->SetBit(kMustCleanup);
8841 }
8842 if (print_name) stats->AddText(fH->GetName());
8843 if (print_entries) {
8844 if (fH->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(fH->GetEntries()+0.5));
8845 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(fH->GetEntries()));
8846 stats->AddText(tt.Data());
8847 }
8848 if (print_mean) {
8849 if (print_mean == 1) {
8850 tf.Form("%s = %s%s",gStringMean.Data(),"%",stats->GetStatFormat());
8851 tt.Form(tf.Data(),fH->GetMean(1));
8852 } else {
8853 tf.Form("%s = %s%s #pm %s%s",gStringMean.Data(),"%",stats->GetStatFormat()
8854 ,"%",stats->GetStatFormat());
8855 tt.Form(tf.Data(),fH->GetMean(1),fH->GetMeanError(1));
8856 }
8857 stats->AddText(tt.Data());
8859 if (print_mean == 1) {
8860 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
8861 tt.Form(tf.Data(),fH->GetMean(2));
8862 } else {
8863 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
8864 ,"%",stats->GetStatFormat());
8865 tt.Form(tf.Data(),fH->GetMean(2),fH->GetMeanError(2));
8866 }
8867 stats->AddText(tt.Data());
8868 }
8869 }
8870 if (print_stddev) {
8871 if (print_stddev == 1) {
8872 tf.Form("%s = %s%s",gStringStdDev.Data(),"%",stats->GetStatFormat());
8873 tt.Form(tf.Data(),fH->GetStdDev(1));
8874 } else {
8875 tf.Form("%s = %s%s #pm %s%s",gStringStdDev.Data(),"%",stats->GetStatFormat()
8876 ,"%",stats->GetStatFormat());
8877 tt.Form(tf.Data(),fH->GetStdDev(1),fH->GetStdDevError(1));
8878 }
8879 stats->AddText(tt.Data());
8881 if (print_stddev == 1) {
8882 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
8883 tt.Form(tf.Data(),fH->GetStdDev(2));
8884 } else {
8885 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
8886 ,"%",stats->GetStatFormat());
8887 tt.Form(tf.Data(),fH->GetStdDev(2),fH->GetStdDevError(2));
8888 }
8889 stats->AddText(tt.Data());
8890 }
8891 }
8892 if (print_under) {
8893 tf.Form("%s = %s%s",gStringUnderflow.Data(),"%",stats->GetStatFormat());
8894 tt.Form(tf.Data(),fH->GetBinContent(0));
8895 stats->AddText(tt.Data());
8896 }
8897 if (print_over) {
8898 tf.Form("%s = %s%s",gStringOverflow.Data(),"%",stats->GetStatFormat());
8899 tt.Form(tf.Data(),fH->GetBinContent(fXaxis->GetNbins()+1));
8900 stats->AddText(tt.Data());
8901 }
8902 if (print_integral) {
8903 if (print_integral == 1) {
8904 tf.Form("%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
8905 tt.Form(tf.Data(),fH->Integral());
8906 } else {
8907 tf.Form("%s = %s%s",gStringIntegralBinWidth.Data(),"%",stats->GetStatFormat());
8908 tt.Form(tf.Data(),fH->Integral("width"));
8909 }
8910 stats->AddText(tt.Data());
8911 }
8912 if (print_skew) {
8913 if (print_skew == 1) {
8914 tf.Form("%s = %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat());
8915 tt.Form(tf.Data(),fH->GetSkewness(1));
8916 } else {
8917 tf.Form("%s = %s%s #pm %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat()
8918 ,"%",stats->GetStatFormat());
8919 tt.Form(tf.Data(),fH->GetSkewness(1),fH->GetSkewness(11));
8920 }
8921 stats->AddText(tt.Data());
8922 }
8923 if (print_kurt) {
8924 if (print_kurt == 1) {
8925 tf.Form("%s = %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat());
8926 tt.Form(tf.Data(),fH->GetKurtosis(1));
8927 } else {
8928 tf.Form("%s = %s%s #pm %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat()
8929 ,"%",stats->GetStatFormat());
8930 tt.Form(tf.Data(),fH->GetKurtosis(1),fH->GetKurtosis(11));
8931 }
8932 stats->AddText(tt.Data());
8933 }
8934
8935 // Draw Fit parameters
8936 if (fit) {
8937 Int_t ndf = fit->GetNDF();
8938 tf.Form("#chi^{2} / ndf = %s%s / %d","%",stats->GetFitFormat(),ndf);
8939 tt.Form(tf.Data(),fit->GetChisquare());
8940 if (print_fchi2) stats->AddText(tt.Data());
8941 if (print_fprob) {
8942 tf.Form("Prob = %s%s","%",stats->GetFitFormat());
8943 tt.Form(tf.Data(),TMath::Prob(fit->GetChisquare(),ndf));
8944 stats->AddText(tt.Data());
8945 }
8946 if (print_fval || print_ferrors) {
8948 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
8949 fit->GetParLimits(ipar,parmin,parmax);
8951 if (print_ferrors) {
8952 tf.Form("%-8s = %s%s #pm %s ", fit->GetParName(ipar), "%",stats->GetFitFormat(),
8953 GetBestFormat(fit->GetParameter(ipar), fit->GetParError(ipar), stats->GetFitFormat()));
8954 tt.Form(tf.Data(),fit->GetParameter(ipar)
8955 ,fit->GetParError(ipar));
8956 } else {
8957 tf.Form("%-8s = %s%s ",fit->GetParName(ipar), "%",stats->GetFitFormat());
8958 tt.Form(tf.Data(),fit->GetParameter(ipar));
8959 }
8960 stats->AddText(tt.Data());
8961 }
8962 }
8963 }
8964
8965 if (!done) fFunctions->Add(stats);
8966 stats->Paint(stats->GetOption());
8967}
8968
8969////////////////////////////////////////////////////////////////////////////////
8970/// [Draw the statistics box for 2D histograms.](\ref HP07)
8971
8973{
8974
8975 if (fH->GetDimension() != 2) return;
8976 TH2 *h2 = (TH2*)fH;
8977
8978 TString tt, tf;
8979 Int_t dofit;
8980 TPaveStats *stats = nullptr;
8981 TIter next(fFunctions);
8982 while (auto obj = next()) {
8983 if (obj->InheritsFrom(TPaveStats::Class())) {
8984 stats = (TPaveStats*)obj;
8985 break;
8986 }
8987 }
8988 if (stats && dostat) {
8989 dofit = stats->GetOptFit();
8990 dostat = stats->GetOptStat();
8991 } else {
8992 dofit = gStyle->GetOptFit();
8993 }
8994 if (dostat == 1) dostat = 1111;
8995 Int_t print_name = dostat%10;
8996 Int_t print_entries = (dostat/10)%10;
8997 Int_t print_mean = (dostat/100)%10;
8998 Int_t print_stddev = (dostat/1000)%10;
8999 Int_t print_under = (dostat/10000)%10;
9000 Int_t print_over = (dostat/100000)%10;
9001 Int_t print_integral= (dostat/1000000)%10;
9002 Int_t print_skew = (dostat/10000000)%10;
9003 Int_t print_kurt = (dostat/100000000)%10;
9005 if (print_under || print_over) nlines += 3;
9006
9007 // Pavetext with statistics
9008 if (!gStyle->GetOptFit()) fit = nullptr;
9009 Bool_t done = kFALSE;
9010 if (!dostat && !fit) {
9011 if (stats) { fFunctions->Remove(stats); delete stats;}
9012 return;
9013 }
9015 if (fit) statw = 1.8*gStyle->GetStatW();
9017 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
9018 stath = 0.25*nlines*gStyle->GetStatH();
9019 }
9020 if (fit) stath += gStyle->GetStatH();
9021 if (stats) {
9022 stats->Clear();
9023 done = kTRUE;
9024 } else {
9025 stats = new TPaveStats(
9028 gStyle->GetStatX(),
9029 gStyle->GetStatY(),"brNDC");
9030
9031 stats->SetParent(fH);
9032 stats->SetOptFit(dofit);
9033 stats->SetOptStat(dostat);
9034 stats->SetFillColor(gStyle->GetStatColor());
9035 stats->SetFillStyle(gStyle->GetStatStyle());
9037 stats->SetName("stats");
9038
9040 stats->SetTextAlign(12);
9041 stats->SetTextFont(gStyle->GetStatFont());
9042 if (gStyle->GetStatFont()%10 > 2)
9044 stats->SetFitFormat(gStyle->GetFitFormat());
9046 stats->SetBit(kCanDelete);
9047 stats->SetBit(kMustCleanup);
9048 }
9049 if (print_name) stats->AddText(h2->GetName());
9050 if (print_entries) {
9051 if (h2->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(h2->GetEntries()+0.5));
9052 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(h2->GetEntries()));
9053 stats->AddText(tt.Data());
9054 }
9055 if (print_mean) {
9056 if (print_mean == 1) {
9057 tf.Form("%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
9058 tt.Form(tf.Data(),h2->GetMean(1));
9059 stats->AddText(tt.Data());
9060 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
9061 tt.Form(tf.Data(),h2->GetMean(2));
9062 stats->AddText(tt.Data());
9063 } else {
9064 tf.Form("%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
9065 ,"%",stats->GetStatFormat());
9066 tt.Form(tf.Data(),h2->GetMean(1),h2->GetMeanError(1));
9067 stats->AddText(tt.Data());
9068 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
9069 ,"%",stats->GetStatFormat());
9070 tt.Form(tf.Data(),h2->GetMean(2),h2->GetMeanError(2));
9071 stats->AddText(tt.Data());
9072 }
9073 }
9074 if (print_stddev) {
9075 if (print_stddev == 1) {
9076 tf.Form("%s = %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat());
9077 tt.Form(tf.Data(),h2->GetStdDev(1));
9078 stats->AddText(tt.Data());
9079 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
9080 tt.Form(tf.Data(),h2->GetStdDev(2));
9081 stats->AddText(tt.Data());
9082 } else {
9083 tf.Form("%s = %s%s #pm %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat()
9084 ,"%",stats->GetStatFormat());
9085 tt.Form(tf.Data(),h2->GetStdDev(1),h2->GetStdDevError(1));
9086 stats->AddText(tt.Data());
9087 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
9088 ,"%",stats->GetStatFormat());
9089 tt.Form(tf.Data(),h2->GetStdDev(2),h2->GetStdDevError(2));
9090 stats->AddText(tt.Data());
9091 }
9092 }
9093 if (print_integral) {
9094 tf.Form("%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
9095 tt.Form(tf.Data(),fH->Integral());
9096 stats->AddText(tt.Data());
9097 }
9098 if (print_skew) {
9099 if (print_skew == 1) {
9100 tf.Form("%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
9101 tt.Form(tf.Data(),h2->GetSkewness(1));
9102 stats->AddText(tt.Data());
9103 tf.Form("%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
9104 tt.Form(tf.Data(),h2->GetSkewness(2));
9105 stats->AddText(tt.Data());
9106 } else {
9107 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
9108 ,"%",stats->GetStatFormat());
9109 tt.Form(tf.Data(),h2->GetSkewness(1),h2->GetSkewness(11));
9110 stats->AddText(tt.Data());
9111 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
9112 ,"%",stats->GetStatFormat());
9113 tt.Form(tf.Data(),h2->GetSkewness(2),h2->GetSkewness(12));
9114 stats->AddText(tt.Data());
9115 }
9116 }
9117 if (print_kurt) {
9118 if (print_kurt == 1) {
9119 tf.Form("%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
9120 tt.Form(tf.Data(),h2->GetKurtosis(1));
9121 stats->AddText(tt.Data());
9122 tf.Form("%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
9123 tt.Form(tf.Data(),h2->GetKurtosis(2));
9124 stats->AddText(tt.Data());
9125 } else {
9126 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
9127 ,"%",stats->GetStatFormat());
9128 tt.Form(tf.Data(),h2->GetKurtosis(1),h2->GetKurtosis(11));
9129 stats->AddText(tt.Data());
9130 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
9131 ,"%",stats->GetStatFormat());
9132 tt.Form(tf.Data(),h2->GetKurtosis(2),h2->GetKurtosis(12));
9133 stats->AddText(tt.Data());
9134 }
9135 }
9136 if (print_under || print_over) {
9137 //get 3*3 under/overflows for 2d hist
9138 Double_t unov[9];
9139
9140 Int_t cellsX = h2->GetXaxis()->GetNbins() + 1;
9141 Int_t cellsY = h2->GetYaxis()->GetNbins() + 1;
9142 Int_t firstX = std::max(1, h2->GetXaxis()->GetFirst());
9143 Int_t firstY = std::max(1, h2->GetYaxis()->GetFirst());
9144 Int_t lastX = std::min(h2->GetXaxis()->GetLast(), h2->GetXaxis()->GetNbins());
9145 Int_t lastY = std::min(h2->GetYaxis()->GetLast(), h2->GetYaxis()->GetNbins());
9146
9147 unov[0] = h2->Integral( 0, firstX-1, lastY+1, cellsY );
9148 unov[1] = h2->Integral(firstX , lastX , lastY+1, cellsY );
9149 unov[2] = h2->Integral(lastX+1, cellsX , lastY+1, cellsY );
9150 unov[3] = h2->Integral( 0, firstX-1, firstY , lastY );
9151 unov[4] = h2->Integral(firstX , lastX , firstY , lastY );
9152 unov[5] = h2->Integral(lastX+1, cellsX , firstY , lastY );
9153 unov[6] = h2->Integral( 0, firstX-1, 0, firstY-1);
9154 unov[7] = h2->Integral(firstX, lastX, 0, firstY-1);
9155 unov[8] = h2->Integral(lastX+1, cellsX , 0, firstY-1);
9156
9157 tt.Form("%g|%g|%g\n", unov[0], unov[1], unov[2]);
9158 stats->AddText(tt.Data());
9159 tt.Form("%g|%g|%g\n", unov[3], unov[4], unov[5]);
9160 stats->AddText(tt.Data());
9161 tt.Form("%g|%g|%g\n", unov[6], unov[7], unov[8]);
9162 stats->AddText(tt.Data());
9163 }
9164
9165 // Draw Fit parameters
9166 if (fit) {
9167 Int_t ndf = fit->GetNDF();
9168 tt.Form("#chi^{2} / ndf = %6.4g / %d",fit->GetChisquare(),ndf);
9169 stats->AddText(tt.Data());
9170 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
9171 tt.Form("%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
9172 ,fit->GetParameter(ipar)
9173 ,fit->GetParError(ipar));
9174 stats->AddText(tt.Data());
9175 }
9176 }
9177
9178 if (!done) fFunctions->Add(stats);
9179 stats->Paint(stats->GetOption());
9180}
9181
9182////////////////////////////////////////////////////////////////////////////////
9183/// [Draw the statistics box for 3D histograms.](\ref HP07)
9184
9186{
9187
9188 if (fH->GetDimension() != 3) return;
9189 TH3 *h3 = (TH3*)fH;
9190
9191 TString tt, tf;
9192 Int_t dofit;
9193 TPaveStats *stats = nullptr;
9194 TIter next(fFunctions);
9195 while (auto obj = next()) {
9196 if (obj->InheritsFrom(TPaveStats::Class())) {
9197 stats = (TPaveStats*)obj;
9198 break;
9199 }
9200 }
9201 if (stats && dostat) {
9202 dofit = stats->GetOptFit();
9203 dostat = stats->GetOptStat();
9204 } else {
9205 dofit = gStyle->GetOptFit();
9206 }
9207 if (dostat == 1) dostat = 1111;
9208 Int_t print_name = dostat%10;
9209 Int_t print_entries = (dostat/10)%10;
9210 Int_t print_mean = (dostat/100)%10;
9211 Int_t print_stddev = (dostat/1000)%10;
9212 Int_t print_under = (dostat/10000)%10;
9213 Int_t print_over = (dostat/100000)%10;
9214 Int_t print_integral= (dostat/1000000)%10;
9215 Int_t print_skew = (dostat/10000000)%10;
9216 Int_t print_kurt = (dostat/100000000)%10;
9218 if (print_under || print_over) nlines += 3;
9219
9220 // Pavetext with statistics
9221 if (!gStyle->GetOptFit()) fit = nullptr;
9222 Bool_t done = kFALSE;
9223 if (!dostat && !fit) {
9224 if (stats) { fFunctions->Remove(stats); delete stats;}
9225 return;
9226 }
9228 if (fit) statw = 1.8*gStyle->GetStatW();
9230 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
9231 stath = 0.25*nlines*gStyle->GetStatH();
9232 }
9233 if (fit) stath += gStyle->GetStatH();
9234 if (stats) {
9235 stats->Clear();
9236 done = kTRUE;
9237 } else {
9238 stats = new TPaveStats(
9241 gStyle->GetStatX(),
9242 gStyle->GetStatY(),"brNDC");
9243
9244 stats->SetParent(fH);
9245 stats->SetOptFit(dofit);
9246 stats->SetOptStat(dostat);
9247 stats->SetFillColor(gStyle->GetStatColor());
9248 stats->SetFillStyle(gStyle->GetStatStyle());
9250 stats->SetName("stats");
9251
9253 stats->SetTextAlign(12);
9254 stats->SetTextFont(gStyle->GetStatFont());
9255 stats->SetFitFormat(gStyle->GetFitFormat());
9257 stats->SetBit(kCanDelete);
9258 stats->SetBit(kMustCleanup);
9259 }
9260 if (print_name) stats->AddText(h3->GetName());
9261 if (print_entries) {
9262 if (h3->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(h3->GetEntries()+0.5));
9263 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(h3->GetEntries()+0.5));
9264 stats->AddText(tt.Data());
9265 }
9266 if (print_mean) {
9267 if (print_mean == 1) {
9268 tf.Form("%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
9269 tt.Form(tf.Data(),h3->GetMean(1));
9270 stats->AddText(tt.Data());
9271 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
9272 tt.Form(tf.Data(),h3->GetMean(2));
9273 stats->AddText(tt.Data());
9274 tf.Form("%s = %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat());
9275 tt.Form(tf.Data(),h3->GetMean(3));
9276 stats->AddText(tt.Data());
9277 } else {
9278 tf.Form("%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
9279 ,"%",stats->GetStatFormat());
9280 tt.Form(tf.Data(),h3->GetMean(1),h3->GetMeanError(1));
9281 stats->AddText(tt.Data());
9282 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
9283 ,"%",stats->GetStatFormat());
9284 tt.Form(tf.Data(),h3->GetMean(2),h3->GetMeanError(2));
9285 stats->AddText(tt.Data());
9286 tf.Form("%s = %s%s #pm %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat()
9287 ,"%",stats->GetStatFormat());
9288 tt.Form(tf.Data(),h3->GetMean(3),h3->GetMeanError(3));
9289 stats->AddText(tt.Data());
9290 }
9291 }
9292 if (print_stddev) {
9293 if (print_stddev == 1) {
9294 tf.Form("%s = %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat());
9295 tt.Form(tf.Data(),h3->GetStdDev(1));
9296 stats->AddText(tt.Data());
9297 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
9298 tt.Form(tf.Data(),h3->GetStdDev(2));
9299 stats->AddText(tt.Data());
9300 tf.Form("%s = %s%s",gStringStdDevZ.Data(),"%",stats->GetStatFormat());
9301 tt.Form(tf.Data(),h3->GetStdDev(3));
9302 stats->AddText(tt.Data());
9303 } else {
9304 tf.Form("%s = %s%s #pm %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat()
9305 ,"%",stats->GetStatFormat());
9306 tt.Form(tf.Data(),h3->GetStdDev(1),h3->GetStdDevError(1));
9307 stats->AddText(tt.Data());
9308 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
9309 ,"%",stats->GetStatFormat());
9310 tt.Form(tf.Data(),h3->GetStdDev(2),h3->GetStdDevError(2));
9311 stats->AddText(tt.Data());
9312 tf.Form("%s = %s%s #pm %s%s",gStringStdDevZ.Data(),"%",stats->GetStatFormat()
9313 ,"%",stats->GetStatFormat());
9314 tt.Form(tf.Data(),h3->GetStdDev(3),h3->GetStdDevError(3));
9315 stats->AddText(tt.Data());
9316 }
9317 }
9318 if (print_integral) {
9319 tt.Form("%s = %6.4g",gStringIntegral.Data(),h3->Integral());
9320 stats->AddText(tt.Data());
9321 }
9322 if (print_skew) {
9323 if (print_skew == 1) {
9324 tf.Form("%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
9325 tt.Form(tf.Data(),h3->GetSkewness(1));
9326 stats->AddText(tt.Data());
9327 tf.Form("%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
9328 tt.Form(tf.Data(),h3->GetSkewness(2));
9329 stats->AddText(tt.Data());
9330 tf.Form("%s = %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat());
9331 tt.Form(tf.Data(),h3->GetSkewness(3));
9332 stats->AddText(tt.Data());
9333 } else {
9334 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
9335 ,"%",stats->GetStatFormat());
9336 tt.Form(tf.Data(),h3->GetSkewness(1),h3->GetSkewness(11));
9337 stats->AddText(tt.Data());
9338 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
9339 ,"%",stats->GetStatFormat());
9340 tt.Form(tf.Data(),h3->GetSkewness(2),h3->GetSkewness(12));
9341 stats->AddText(tt.Data());
9342 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat()
9343 ,"%",stats->GetStatFormat());
9344 tt.Form(tf.Data(),h3->GetSkewness(3),h3->GetSkewness(13));
9345 stats->AddText(tt.Data());
9346 }
9347 }
9348 if (print_kurt) {
9349 if (print_kurt == 1) {
9350 tf.Form("%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
9351 tt.Form(tf.Data(),h3->GetKurtosis(1));
9352 stats->AddText(tt.Data());
9353 tf.Form("%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
9354 tt.Form(tf.Data(),h3->GetKurtosis(2));
9355 stats->AddText(tt.Data());
9356 tf.Form("%s = %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat());
9357 tt.Form(tf.Data(),h3->GetKurtosis(3));
9358 stats->AddText(tt.Data());
9359 } else {
9360 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
9361 ,"%",stats->GetStatFormat());
9362 tt.Form(tf.Data(),h3->GetKurtosis(1),h3->GetKurtosis(11));
9363 stats->AddText(tt.Data());
9364 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
9365 ,"%",stats->GetStatFormat());
9366 tt.Form(tf.Data(),h3->GetKurtosis(2),h3->GetKurtosis(12));
9367 stats->AddText(tt.Data());
9368 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat()
9369 ,"%",stats->GetStatFormat());
9370 tt.Form(tf.Data(),h3->GetKurtosis(3),h3->GetKurtosis(13));
9371 stats->AddText(tt.Data());
9372 }
9373 }
9374 if (print_under || print_over) {
9375 // no underflow - overflow printing for a 3D histogram
9376 // one would need a 3D table
9377 }
9378
9379 // Draw Fit parameters
9380 if (fit) {
9381 Int_t ndf = fit->GetNDF();
9382 tt.Form("#chi^{2} / ndf = %6.4g / %d",fit->GetChisquare(),ndf);
9383 stats->AddText(tt.Data());
9384 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
9385 tt.Form("%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
9386 ,fit->GetParameter(ipar)
9387 ,fit->GetParError(ipar));
9388 stats->AddText(tt.Data());
9389 }
9390 }
9391
9392 if (!done) fFunctions->Add(stats);
9393 stats->Paint(stats->GetOption());
9394}
9395
9396////////////////////////////////////////////////////////////////////////////////
9397/// [Control function to draw a 2D histogram as a surface plot.](\ref HP18)
9398
9400{
9401
9402 const Double_t ydiff = 1;
9403 const Double_t yligh1 = 10;
9404 const Double_t qa = 0.15;
9405 const Double_t qd = 0.15;
9406 const Double_t qs = 0.8;
9408 Int_t raster = 0;
9409 Int_t irep = 0;
9410
9411 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
9414 Double_t zmin = Hparam.zmin;
9415 Double_t zmax = Hparam.zmax;
9420 Double_t dangle = 10*3.141592/180; //Delta angle for Rapidity option
9421 Double_t deltaz = TMath::Abs(zmin);
9422 if (deltaz == 0) deltaz = 1;
9423 if (zmin >= zmax) {
9424 zmin -= 0.5*deltaz;
9425 zmax += 0.5*deltaz;
9426 }
9427 Double_t z1c = zmin;
9428 Double_t z2c = zmin + (zmax-zmin)*(1+gStyle->GetHistTopMargin());
9429 // Compute the lego limits and instantiate a lego object
9430 fXbuf[0] = -1;
9431 fYbuf[0] = 1;
9432 fXbuf[1] = -1;
9433 fYbuf[1] = 1;
9434 if (Hoption.System >= kPOLAR && (Hoption.Surf == 1 || Hoption.Surf == 13)) raster = 1;
9435 if (Hoption.System == kPOLAR) {
9436 fXbuf[2] = z1c;
9437 fYbuf[2] = z2c;
9438 } else if (Hoption.System == kCYLINDRICAL) {
9439 if (Hoption.Logy) {
9440 if (ylab1 > 0) fXbuf[2] = TMath::Log10(ylab1);
9441 else fXbuf[2] = 0;
9442 if (ylab2 > 0) fYbuf[2] = TMath::Log10(ylab2);
9443 else fYbuf[2] = 0;
9444 } else {
9445 fXbuf[2] = ylab1;
9446 fYbuf[2] = ylab2;
9447 }
9448 z1c = 0; z2c = 1;
9449 } else if (Hoption.System == kSPHERICAL) {
9450 fXbuf[2] = -1;
9451 fYbuf[2] = 1;
9452 z1c = 0; z2c = 1;
9453 } else if (Hoption.System == kRAPIDITY) {
9454 fXbuf[2] = -1/TMath::Tan(dangle);
9455 fYbuf[2] = 1/TMath::Tan(dangle);
9456 } else {
9457 fXbuf[0] = xlab1;
9458 fYbuf[0] = xlab2;
9459 fXbuf[1] = ylab1;
9460 fYbuf[1] = ylab2;
9461 fXbuf[2] = z1c;
9462 fYbuf[2] = z2c;
9463 }
9464
9465 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data(), Hoption.System);
9466 fLego->SetEdgeAtt(fH->GetLineColor(),fH->GetLineStyle(),fH->GetLineWidth(),0);
9467 fLego->SetFillColor(fH->GetFillColor());
9468
9469 // Initialize the levels on the Z axis
9470 Int_t ndiv = fH->GetContour();
9471 if (ndiv == 0 ) {
9472 ndiv = gStyle->GetNumberContours();
9473 fH->SetContour(ndiv);
9474 }
9475 Int_t ndivz = TMath::Abs(ndiv);
9476 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
9477
9478 if (Hoption.Surf == 13 || Hoption.Surf == 15) fLego->SetMesh(3);
9479 if (Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) fLego->SetMesh(0);
9480
9481 // Close the surface in case of non cartesian coordinates.
9482
9483 if (Hoption.System != kCARTESIAN) {nx++; ny++;}
9484
9485 // Now ready to draw the surface plot
9486
9487 TView *view = gPad ? gPad->GetView() : nullptr;
9488 if (!view) {
9489 Error("PaintSurface", "no TView in current pad");
9490 return;
9491 }
9492
9493 Double_t thedeg = 90 - gPad->GetTheta();
9494 Double_t phideg = -90 - gPad->GetPhi();
9495 Double_t psideg = view->GetPsi();
9496 view->SetView(phideg, thedeg, psideg, irep);
9497
9498 // Set color/style for back box
9499 if (Hoption.Same) {
9500 fLego->SetFillStyle(0);
9501 fLego->SetFillColor(1);
9502 } else {
9503 fLego->SetFillStyle(gPad->GetFrameFillStyle());
9504 fLego->SetFillColor(gPad->GetFrameFillColor());
9505 }
9506 fLego->TAttFill::Modify();
9507
9508 Int_t backcolor = gPad->GetFrameFillColor();
9509 if (Hoption.System != kCARTESIAN) backcolor = 0;
9510 view->PadRange(backcolor);
9511
9512 fLego->SetFillStyle(fH->GetFillStyle());
9513 fLego->SetFillColor(fH->GetFillColor());
9514 fLego->TAttFill::Modify();
9515
9516 // Draw the filled contour on top
9518
9520 if (Hoption.Surf == 13 || Hoption.Surf == 15) {
9522 Hoption.Surf = 23;
9523 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9525 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"BF");
9526 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9527 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9528 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9529 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"BF");
9531 fLego->SetMesh(1);
9532 }
9533
9534 if (raster) fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
9535 else fLego->InitMoveScreen(-1.1,1.1);
9536
9537 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) {
9538 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9541 fLego->BackBox(90);
9542 }
9543 }
9544
9545 // Gouraud Shading surface
9546 if (Hoption.Surf == 14) {
9547 // Set light sources
9548 fLego->LightSource(0, ydiff, 0,0,0,irep);
9549 fLego->LightSource(1, yligh1 ,1,1,1,irep);
9550 fLego->SurfaceProperty(qa, qd, qs, 1, irep);
9551 fmin = ydiff*qa;
9552 fmax = fmin + (yligh1+0.1)*(qd+qs);
9553 Int_t nbcol = 28;
9554 icol1 = 201;
9555 Double_t dcol = 0.5/Double_t(nbcol);
9556 TColor *colref = gROOT->GetColor(fH->GetFillColor());
9557 if (!colref) return;
9559 colref->GetRGB(r,g,b);
9561 TColor *acol;
9562 for (Int_t col=0;col<nbcol;col++) {
9563 acol = gROOT->GetColor(col+icol1);
9565 if (acol) acol->SetRGB(r,g,b);
9566 }
9567 fLego->Spectrum(nbcol, fmin, fmax, icol1, 1, irep);
9568 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::GouraudFunction);
9570 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"BF");
9571 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9572 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9573 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9574 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"BF");
9575 } else if (Hoption.Surf == 15) {
9576 // The surface is not drawn in this case.
9577 } else {
9578 // Draw the surface
9579 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 16 || Hoption.Surf == 17) {
9581 } else {
9582 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9583 }
9584 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9585 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceRaster1);
9586 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode2);
9587 if (Hoption.System == kPOLAR) {
9588 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfacePolar(1,nx,ny,"FB");
9589 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfacePolar(1,nx,ny,"BF");
9590 } else if (Hoption.System == kCYLINDRICAL) {
9591 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceCylindrical(1,nx,ny,"FB");
9592 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9593 } else if (Hoption.System == kSPHERICAL) {
9594 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceSpherical(0,1,nx,ny,"FB");
9595 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9596 } else if (Hoption.System == kRAPIDITY) {
9597 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceSpherical(1,1,nx,ny,"FB");
9598 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9599 } else {
9600 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove1);
9601 if (Hoption.Surf == 16) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove3);
9602 if (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16) fLego->SurfaceCartesian(90,nx,ny,"FB");
9603 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCartesian(90,nx,ny,"BF");
9604 }
9605 }
9606
9607 // Paint the line contour on top for option SURF7
9608 if (Hoption.Surf == 17) {
9609 fLego->InitMoveScreen(-1.1,1.1);
9610 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9611 Hoption.Surf = 23;
9612 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9614 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"FB");
9615 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"FB");
9616 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"FB");
9617 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"FB");
9618 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"FB");
9619 }
9620
9621 if ((!Hoption.Same) &&
9622 (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16)) {
9625 fLego->BackBox(90);
9626 }
9627 }
9628 if (Hoption.System == kCARTESIAN) {
9629 fLego->InitMoveScreen(-1.1,1.1);
9631 if (Hoption.FrontBox) fLego->FrontBox(90);
9632 }
9633 if (!Hoption.Axis && !Hoption.Same) {
9634 TGaxis axis;
9635 PaintLegoAxis(&axis, 90);
9636 }
9637
9639
9640 fLego.reset();
9641}
9642
9643////////////////////////////////////////////////////////////////////////////////
9644/// Control function to draw a table using Delaunay triangles.
9645
9647{
9648
9649 TGraphDelaunay2D *dt = nullptr;
9650 TGraphDelaunay *dtOld = nullptr;
9651
9652 // Check if fH contains a TGraphDelaunay2D
9654 dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
9655 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
9656 if (!dt && !dtOld) return;
9657
9658 // If needed, create a TGraph2DPainter
9659 if (!fGraph2DPainter)
9660 fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
9661
9662 // Define the 3D view
9663 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
9664 if (Hoption.Same) {
9665 TView *viewsame = gPad ? gPad->GetView() : nullptr;
9666 if (!viewsame) {
9667 Error("PaintTriangles", "no TView in current pad, do not use option SAME");
9668 return;
9669 }
9670 Double_t *rmin = viewsame->GetRmin();
9671 Double_t *rmax = viewsame->GetRmax();
9672 if (!rmin || !rmax) return;
9673 fXbuf[0] = rmin[0];
9674 fYbuf[0] = rmax[0];
9675 fXbuf[1] = rmin[1];
9676 fYbuf[1] = rmax[1];
9677 fXbuf[2] = rmin[2];
9678 fYbuf[2] = rmax[2];
9679 fH->SetMaximum(rmax[2]);
9680 fH->SetMinimum(rmin[2]);
9681 fH->GetXaxis()->SetRangeUser(rmin[0],rmax[0]);
9682 fH->GetYaxis()->SetRangeUser(rmin[1],rmax[1]);
9683 } else {
9684 fXbuf[0] = Hparam.xmin;
9685 fYbuf[0] = Hparam.xmax;
9686 fXbuf[1] = Hparam.ymin;
9687 fYbuf[1] = Hparam.ymax;
9688 fXbuf[2] = Hparam.zmin;
9689 fYbuf[2] = Hparam.zmax;
9690 }
9691
9692 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
9693 TView *view = gPad ? gPad->GetView() : nullptr;
9694 if (!view) {
9695 Error("PaintTriangles", "no TView in current pad");
9696 return;
9697 }
9698 Double_t thedeg = 90 - gPad->GetTheta();
9699 Double_t phideg = -90 - gPad->GetPhi();
9700 Double_t psideg = view->GetPsi();
9701 Int_t irep;
9702 view->SetView(phideg, thedeg, psideg, irep);
9703
9704 // Set color/style for back box
9705 fLego->SetFillStyle(gPad->GetFrameFillStyle());
9706 fLego->SetFillColor(gPad->GetFrameFillColor());
9707 fLego->TAttFill::Modify();
9708 Int_t backcolor = gPad->GetFrameFillColor();
9709 if (Hoption.System != kCARTESIAN) backcolor = 0;
9710 view->PadRange(backcolor);
9711 fLego->SetFillStyle(fH->GetFillStyle());
9712 fLego->SetFillColor(fH->GetFillColor());
9713 fLego->TAttFill::Modify();
9714
9715 // Paint the Back Box if needed
9716 if (Hoption.BackBox && !Hoption.Same) {
9717 fLego->InitMoveScreen(-1.1,1.1);
9718 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9720 fLego->BackBox(90);
9721 }
9722
9723 // Paint the triangles
9724 fGraph2DPainter->Paint(option);
9725
9726 // Paint the Front Box if needed
9727 if (Hoption.FrontBox) {
9728 fLego->InitMoveScreen(-1.1,1.1);
9730 fLego->FrontBox(90);
9731 }
9732
9733 // Paint the Axis if needed
9734 if (!Hoption.Axis && !Hoption.Same) {
9735 TGaxis axis;
9736 PaintLegoAxis(&axis, 90);
9737 }
9738
9740
9741 fLego.reset();
9742}
9743
9744////////////////////////////////////////////////////////////////////////////////
9745/// Define the color levels used to paint legos, surfaces etc..
9746
9748{
9749
9750 Int_t i, irep;
9751
9752 // Initialize the color levels
9753 if (ndivz >= 100) {
9754 Warning("PaintSurface", "too many color levels, %d >= 100, reset to 99", ndivz);
9755 ndivz = 99;
9756 }
9757 std::vector<Double_t> funlevel(ndivz+1);
9758 std::vector<Int_t> colorlevel(ndivz+1);
9761 for (i = 0; i < ndivz; ++i) {
9763 theColor = Int_t((i+0.99)*Float_t(ncolors)/Float_t(ndivz));
9765 }
9767 fLego->ColorFunction(ndivz, funlevel.data(), colorlevel.data(), irep);
9768}
9769
9770////////////////////////////////////////////////////////////////////////////////
9771/// [Control function to draw 2D/3D histograms (tables).](\ref HP01c)
9772
9774{
9775
9776 // Fill Hparam structure with histo parameters
9777 if (!TableInit()) return;
9778
9779 // Draw histogram frame
9780 PaintFrame();
9781
9782 // If palette option not specified, delete a possible existing palette
9783 if (!Hoption.Zscale) {
9784 TObject *palette = fFunctions->FindObject("palette");
9785 if (palette) { fFunctions->Remove(palette); delete palette;}
9786 }
9787
9788 // Do not draw the histogram. Only the attached functions will be drawn.
9789 if (Hoption.Func == 2) {
9790 if (Hoption.Zscale) {
9791 Int_t ndiv = fH->GetContour();
9792 if (ndiv == 0 ) {
9793 ndiv = gStyle->GetNumberContours();
9794 fH->SetContour(ndiv);
9795 }
9796 PaintPalette();
9797 }
9798
9799 // Draw the histogram according to the option
9800 } else {
9801 if (fH->InheritsFrom(TH2Poly::Class()) && Hoption.Axis<=0) {
9802 if (Hoption.Fill) PaintTH2PolyBins("f");
9806 if (Hoption.Line) PaintTH2PolyBins("l");
9807 if (Hoption.Mark) PaintTH2PolyBins("P");
9808 } else if (Hoption.Axis<=0) {
9812 if (Hoption.Color) {
9815 }
9818 if (Hoption.Error >= 100) Paint2DErrors(option);
9820 }
9824 }
9825
9826 // Draw histogram title
9827 PaintTitle();
9828
9829 // Draw the axes
9830 if (!Hoption.Lego && !Hoption.Surf &&
9831 !Hoption.Tri && !(Hoption.Error >= 100)) PaintAxis(kFALSE);
9832
9833 TF1 *fit = nullptr;
9834 TIter next(fFunctions);
9835 while (auto obj = next()) {
9836 if (obj->InheritsFrom(TF1::Class())) {
9837 fit = (TF1*)obj;
9838 break;
9839 }
9840 }
9841 if ((Hoption.Same%10) != 1) {
9842 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
9843 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
9844 //ALWAYS executed on non-iOS platform.
9845 //On iOS, depends on mode.
9847 }
9848 }
9849 }
9850}
9851
9852////////////////////////////////////////////////////////////////////////////////
9853/// Control function to draw a TH2Poly bins' contours.
9854///
9855/// - option = "F" draw the bins as filled areas.
9856/// - option = "L" draw the bins as line.
9857/// - option = "P" draw the bins as markers.
9858
9860{
9861
9862 //Do not highlight the histogram, if its part was picked.
9863 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH) return;
9864
9865 TString opt = option;
9866 opt.ToLower();
9867 Bool_t line = kFALSE;
9868 Bool_t fill = kFALSE;
9869 Bool_t mark = kFALSE;
9870 if (opt.Contains("l")) line = kTRUE;
9871 if (opt.Contains("f")) fill = kTRUE;
9872 if (opt.Contains("p")) mark = kTRUE;
9873
9874 TH2PolyBin *b;
9875 Double_t z;
9876
9877 TIter next(((TH2Poly*)fH)->GetBins());
9878 TObject *obj, *poly;
9879
9880 while ((obj=next())) {
9881 b = (TH2PolyBin*)obj;
9882 z = b->GetContent();
9883 if (z==0 && Hoption.Zero) continue; // Do not draw empty bins in case of option "COL0 L"
9884 poly = b->GetPolygon();
9885
9886 // Paint the TGraph bins.
9887 if (poly->IsA() == TGraph::Class()) {
9888 TGraph *g = (TGraph*)poly;
9889 g->TAttLine::Modify();
9890 g->TAttMarker::Modify();
9891 g->TAttFill::Modify();
9892 if (line) {
9893 Int_t fs = g->GetFillStyle();
9895 g->SetFillStyle(0);
9897 g->Paint("F");
9899 g->SetFillStyle(fs);
9900 }
9901 if (fill) g->Paint("F");
9902 if (mark) g->Paint("P");
9903 }
9904
9905 // Paint the TMultiGraph bins.
9906 if (poly->IsA() == TMultiGraph::Class()) {
9908 TList *gl = mg->GetListOfGraphs();
9909 if (!gl) return;
9910 TGraph *g;
9911 TIter nextg(gl);
9912 while ((g = (TGraph*) nextg())) {
9913 g->TAttLine::Modify();
9914 g->TAttMarker::Modify();
9915 g->TAttFill::Modify();
9916 if (line) {
9917 Int_t fs = g->GetFillStyle();
9919 g->SetFillStyle(0);
9921 g->Paint("F");
9923 g->SetFillStyle(fs);
9924 }
9925 if (fill) g->Paint("F");
9926 if (mark) g->Paint("P");
9927 }
9928 }
9929 }
9930}
9931
9932////////////////////////////////////////////////////////////////////////////////
9933/// [Control function to draw a TH2Poly as a color plot.](\ref HP20a)
9934
9936{
9937
9938 //Do not highlight the histogram, if its part was picked.
9939 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
9940 return;
9941
9942 Int_t ncolors, color, theColor;
9943 Double_t z, zc;
9944 Double_t zmin = fH->GetMinimum();
9945 Double_t zmax = fH->GetMaximum();
9946 if (Hoption.Logz) {
9947 if (zmax > 0) {
9948 if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
9949 zmin = TMath::Log10(zmin);
9950 zmax = TMath::Log10(zmax);
9951 } else {
9952 return;
9953 }
9954 }
9955 Double_t dz = zmax - zmin;
9956
9957 // Initialize the levels on the Z axis
9959 Int_t ndiv = fH->GetContour();
9960 if (ndiv == 0 ) {
9961 ndiv = gStyle->GetNumberContours();
9962 fH->SetContour(ndiv);
9963 }
9964 Int_t ndivz = TMath::Abs(ndiv);
9965 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
9967
9968 TIter next(((TH2Poly*)fH)->GetBins());
9969
9970 while (auto obj = next()) {
9971 TH2PolyBin *b = (TH2PolyBin*)obj;
9972 TObject *poly = b->GetPolygon();
9973
9974 z = b->GetContent();
9975 if (z==0 && Hoption.Zero) continue;
9976 if (Hoption.Logz) {
9977 if (z > 0) z = TMath::Log10(z);
9978 else z = zmin;
9979 }
9980 if (z < zmin) continue;
9981
9982 // Define the bin color.
9984 zc = fH->GetContourLevelPad(0);
9985 if (z < zc) continue;
9986 color = -1;
9987 for (Int_t k=0; k<ndiv; k++) {
9988 zc = fH->GetContourLevelPad(k);
9989 if (z < zc) {
9990 continue;
9991 } else {
9992 color++;
9993 }
9994 }
9995 } else {
9996 color = Int_t(0.01+(z-zmin)*scale);
9997 }
9998 theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
9999 if (theColor > ncolors-1) theColor = ncolors-1;
10000
10002
10003 // Paint the TGraph bins.
10004 if (poly->IsA() == TGraph::Class()) {
10005 TGraph *g = (TGraph*)poly;
10006 auto origin = g->GetFillColor();
10007 g->SetFillColor(rootColor);
10008 g->TAttFill::Modify();
10009 g->Paint("F");
10010 g->SetFillColor(origin);
10011 }
10012
10013 // Paint the TMultiGraph bins.
10014 if (poly->IsA() == TMultiGraph::Class()) {
10017 while (auto g = (TGraph*) nextg()) {
10018 auto origin = g->GetFillColor();
10019 g->SetFillColor(rootColor);
10020 g->TAttFill::Modify();
10021 g->Paint("F");
10022 g->SetFillColor(origin);
10023 }
10024 }
10025 }
10027}
10028
10029////////////////////////////////////////////////////////////////////////////////
10030/// [Control function to draw a TH2Poly as a scatter plot.](\ref HP20a)
10031
10033{
10034
10035 //Do not highlight the histogram, if its part was selected.
10036 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
10037 return;
10038
10039 Int_t k, loop, marker=0;
10040 Double_t z, xk,xstep, yk, ystep, xp, yp;
10041 Double_t scale = 1;
10042 Double_t zmin = fH->GetMinimum();
10043 Double_t zmax = fH->GetMaximum();
10044 if (Hoption.Logz) {
10045 if (zmax > 0) {
10046 if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
10047 zmin = TMath::Log10(zmin);
10048 zmax = TMath::Log10(zmax);
10049 } else {
10050 return;
10051 }
10052 }
10053 Double_t dz = zmax - zmin;
10054 scale = (kNMAX-1)/dz;
10055
10056
10057 // use an independent instance of a random generator
10058 // instead of gRandom to avoid conflicts and
10059 // to get same random numbers when drawing the same histogram
10061
10062 TH2PolyBin *b;
10063
10064 TIter next(((TH2Poly*)fH)->GetBins());
10065 TObject *obj, *poly;
10066
10067 Double_t maxarea = 0, a;
10068 while ((obj=next())) {
10069 b = (TH2PolyBin*)obj;
10070 a = b->GetArea();
10071 if (a>maxarea) maxarea = a;
10072 }
10073
10074 next.Reset();
10075
10076 while ((obj=next())) {
10077 b = (TH2PolyBin*)obj;
10078 poly = b->GetPolygon();
10079 z = b->GetContent();
10080 if (z < zmin) z = zmin;
10081 if (z > zmax) z = zmax;
10082 if (Hoption.Logz) {
10083 if (z > 0) z = TMath::Log10(z) - zmin;
10084 } else {
10085 z -= zmin;
10086 }
10087 k = Int_t((z*scale)*(b->GetArea()/maxarea));
10088 xk = b->GetXMin();
10089 yk = b->GetYMin();
10090 xstep = b->GetXMax()-xk;
10091 ystep = b->GetYMax()-yk;
10092
10093 // Paint the TGraph bins.
10094 if (poly->IsA() == TGraph::Class()) {
10095 TGraph *g = (TGraph*)poly;
10096 if (k <= 0 || z <= 0) continue;
10097 loop = 0;
10098 while (loop<k) {
10099 if (k+marker >= kNMAX) {
10100 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10101 marker=0;
10102 }
10103 xp = (random.Rndm()*xstep) + xk;
10104 yp = (random.Rndm()*ystep) + yk;
10105 if (g->IsInside(xp,yp)) {
10106 fXbuf[marker] = xp;
10107 fYbuf[marker] = yp;
10108 marker++;
10109 loop++;
10110 }
10111 }
10112 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10113 }
10114
10115 // Paint the TMultiGraph bins.
10116 if (poly->IsA() == TMultiGraph::Class()) {
10118 TList *gl = mg->GetListOfGraphs();
10119 if (!gl) return;
10120 if (k <= 0 || z <= 0) continue;
10121 loop = 0;
10122 while (loop<k) {
10123 if (k+marker >= kNMAX) {
10124 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10125 marker=0;
10126 }
10127 xp = (random.Rndm()*xstep) + xk;
10128 yp = (random.Rndm()*ystep) + yk;
10129 if (mg->IsInside(xp,yp)) {
10130 fXbuf[marker] = xp;
10131 fYbuf[marker] = yp;
10132 marker++;
10133 loop++;
10134 }
10135 }
10136 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10137 }
10138 }
10139 PaintTH2PolyBins("l");
10140}
10141
10142////////////////////////////////////////////////////////////////////////////////
10143/// [Control function to draw a TH2Poly as a text plot.](\ref HP20a)
10144
10146{
10147
10148 TLatex text;
10149 text.SetTextFont(gStyle->GetTextFont());
10150 text.SetTextColor(fH->GetMarkerColor());
10151 text.SetTextSize(0.02*fH->GetMarkerSize());
10152
10153 Double_t x, y, z, e, angle = 0;
10154 TString tt, tf;
10155 tf.Form("%s%s","%",gStyle->GetPaintTextFormat());
10156 if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
10157 Int_t opt = (Int_t)Hoption.Text/1000;
10158
10159 text.SetTextAlign(22);
10160 if (Hoption.Text == 1) angle = 0;
10161 text.SetTextAngle(angle);
10162 text.TAttText::Modify();
10163
10164 TH2PolyBin *b;
10165
10166 TIter next(((TH2Poly*)fH)->GetBins());
10167 TObject *obj, *p;
10168
10169 while ((obj=next())) {
10170 b = (TH2PolyBin*)obj;
10171 p = b->GetPolygon();
10172 x = (b->GetXMin()+b->GetXMax())/2;
10173 if (Hoption.Logx) {
10174 if (x > 0) x = TMath::Log10(x);
10175 else continue;
10176 }
10177 y = (b->GetYMin()+b->GetYMax())/2;
10178 if (Hoption.Logy) {
10179 if (y > 0) y = TMath::Log10(y);
10180 else continue;
10181 }
10182 z = b->GetContent();
10183 if (z < fH->GetMinimum() || (z == 0 && !Hoption.MinimumZero)) continue;
10184 if (opt==2) {
10185 e = fH->GetBinError(b->GetBinNumber());
10186 tf.Form("#splitline{%s%s}{#pm %s%s}",
10188 "%",gStyle->GetPaintTextFormat());
10189 tt.Form(tf.Data(),z,e);
10190 } else {
10191 tt.Form(tf.Data(),z);
10192 }
10193 if (opt==3) text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),p->GetName());
10194 else text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),tt.Data());
10195 }
10196
10197 PaintTH2PolyBins("l");
10198}
10199
10200////////////////////////////////////////////////////////////////////////////////
10201/// [Control function to draw a 1D/2D histograms with the bin values.](\ref HP15)
10202
10204{
10205
10206 TLatex text;
10207 text.SetTextFont(((int)gStyle->GetTextFont()/10)*10+2); // font precision must be 2
10208 text.SetTextColor(fH->GetMarkerColor());
10209 text.SetTextSize(0.02*fH->GetMarkerSize());
10210
10211 Double_t x, y, z, e, angle = 0;
10212 TString tt, tf;
10213 tf.Form("%s%s","%",gStyle->GetPaintTextFormat());
10214 if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
10215
10216 // 1D histograms
10217 if (fH->GetDimension() == 1) {
10219 Double_t yt;
10220 TProfile *hp = (TProfile*)fH;
10221 if (Hoption.Text>2000 && fH->InheritsFrom(TProfile::Class())) {
10222 Hoption.Text = Hoption.Text-2000;
10223 getentries = kTRUE;
10224 }
10225 if (Hoption.Text == 1) angle = 90;
10226 text.SetTextAlign(11);
10227 if (angle == 90) text.SetTextAlign(12);
10228 if (angle == 0) text.SetTextAlign(21);
10229 text.TAttText::Modify();
10230 Double_t dt = 0.02*(gPad->GetY2()-gPad->GetY1());
10231 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10232 if (Hoption.Bar) {
10233 x = fH->GetXaxis()->GetBinLowEdge(i)+
10234 fH->GetXaxis()->GetBinWidth(i)*
10235 (fH->GetBarOffset()+0.5*fH->GetBarWidth());
10236 } else {
10237 x = fH->GetXaxis()->GetBinCenter(i);
10238 }
10239 y = fH->GetBinContent(i);
10240 yt = y;
10241 if (Hoption.MinimumZero && y<0) y = 0;
10242 if (getentries) yt = hp->GetBinEntries(i);
10243 if (yt == 0.) continue;
10244 tt.Form(tf.Data(),yt);
10245 if (Hoption.Logx) {
10246 if (x > 0) x = TMath::Log10(x);
10247 else continue;
10248 }
10249 if (Hoption.Logy) {
10250 if (y > 0) y = TMath::Log10(y);
10251 else continue;
10252 }
10253 if (y >= gPad->GetY2()) continue;
10254 if (y <= gPad->GetY1()) continue;
10255 text.PaintLatex(x,y+0.2*dt,angle,0.02*fH->GetMarkerSize(),tt.Data());
10256 }
10257
10258 // 2D histograms
10259 } else {
10260 Double_t zmin = Hparam.zmin;
10261 if (Hoption.Logz) zmin = TMath::Power(10,Hparam.zmin);
10262
10263 text.SetTextAlign(22);
10264 if (Hoption.Text == 1) angle = 0;
10265 text.SetTextAngle(angle);
10266 text.TAttText::Modify();
10267 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
10268 y = fYaxis->GetBinCenter(j);
10269 if (Hoption.Logy) {
10270 if (y > 0) y = TMath::Log10(y);
10271 else continue;
10272 }
10273 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10274 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
10275 x = fXaxis->GetBinCenter(i);
10276 if (Hoption.Logx) {
10277 if (x > 0) x = TMath::Log10(x);
10278 else continue;
10279 }
10280 if (!IsInside(x,y)) continue;
10281 z = fH->GetBinContent(bin);
10282 if (z < zmin || (z == 0 && !Hoption.MinimumZero)) continue;
10283 if (Hoption.Text>2000) {
10284 e = fH->GetBinError(bin);
10285 tf.Form("#splitline{%s%s}{#pm %s%s}",
10287 "%",gStyle->GetPaintTextFormat());
10288 tt.Form(tf.Data(),z,e);
10289 } else {
10290 tt.Form(tf.Data(),z);
10291 }
10292 text.PaintLatex(x,y+fH->GetBarOffset()*fYaxis->GetBinWidth(j),
10293 angle,0.02*fH->GetMarkerSize(),tt.Data());
10294 }
10295 }
10296 }
10297}
10298
10299////////////////////////////////////////////////////////////////////////////////
10300/// [Control function to draw a 3D implicit functions.](\ref HP27)
10301
10303{
10304
10305 Int_t irep;
10306
10307 TAxis *xaxis = fH->GetXaxis();
10308 TAxis *yaxis = fH->GetYaxis();
10309 TAxis *zaxis = fH->GetZaxis();
10310
10311 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
10312 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
10313 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
10314 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
10315 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
10316 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
10317
10318 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
10319
10320 TView *view = gPad ? gPad->GetView() : nullptr;
10321 if (!view) {
10322 Error("PaintTF3", "no TView in current pad");
10323 return;
10324 }
10325 Double_t thedeg = 90 - gPad->GetTheta();
10326 Double_t phideg = -90 - gPad->GetPhi();
10327 Double_t psideg = view->GetPsi();
10328 view->SetView(phideg, thedeg, psideg, irep);
10329
10330 fLego->InitMoveScreen(-1.1,1.1);
10331
10332 if (Hoption.BackBox) {
10333 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
10335 fLego->BackBox(90);
10336 }
10337
10339
10340 fLego->ImplicitFunction(fCurrentF3, fXbuf.data(), fYbuf.data(), fH->GetNbinsX(),
10341 fH->GetNbinsY(),
10342 fH->GetNbinsZ(), "BF");
10343
10344 if (Hoption.FrontBox) {
10345 fLego->InitMoveScreen(-1.1,1.1);
10347 fLego->FrontBox(90);
10348 }
10349 if (!Hoption.Axis && !Hoption.Same) {
10350 TGaxis axis;
10351 PaintLegoAxis(&axis, 90);
10352 }
10353
10354 PaintTitle();
10355
10356 fLego.reset();
10357}
10358
10359/////////////////////////////////////////////////////////////new TGaxis///////////////////
10360/// Draw the histogram title
10361///
10362/// The title is drawn according to the title alignment returned by
10363/// `GetTitleAlign()`. It is a 2 digits integer): hv
10364///
10365/// where `h` is the horizontal alignment and `v` is the
10366/// vertical alignment.
10367///
10368/// - `h` can get the values 1 2 3 for left, center, and right
10369/// - `v` can get the values 1 2 3 for bottom, middle and top
10370///
10371/// for instance the default alignment is: 13 (left top)
10372
10374{
10375 // probably best place for calls PaintHighlightBin
10376 // calls after paint histo (1D or 2D) and before paint title and stats
10377 if (!gPad->GetView()) PaintHighlightBin();
10378
10379 if (Hoption.Same) return;
10380 if (fH->TestBit(TH1::kNoTitle)) return;
10381 Int_t nt = strlen(fH->GetTitle());
10382 TPaveText *title = nullptr;
10383 TObject *obj;
10384 TIter next(gPad->GetListOfPrimitives());
10385 while ((obj = next())) {
10386 if (!obj->InheritsFrom(TPaveText::Class())) continue;
10387 title = (TPaveText*)obj;
10388 if (strcmp(title->GetName(),"title")) {title = nullptr; continue;}
10389 break;
10390 }
10391 if (nt == 0 || gStyle->GetOptTitle() <= 0) {
10392 if (title) delete title;
10393 return;
10394 }
10397
10398 if (ht <= 0) {
10399 if (gStyle->GetTitleFont("")%10 == 3) {
10400 Double_t hw = (Double_t) TMath::Max(gPad->GetPadWidth(), gPad->GetPadHeight());
10401 if (hw > 0)
10402 ht = 1.1 * (gStyle->GetTitleSize("")/hw);
10403 } else {
10404 ht = 1.1*gStyle->GetTitleFontSize();
10405 }
10406 }
10407 if (ht <= 0) ht = 0.05;
10408 if (wt <= 0) {
10409 TLatex l;
10410 l.SetTextSize(ht);
10411 l.SetTitle(fH->GetTitle());
10412 // adjustment in case the title has several lines (#splitline)
10413 ht = TMath::Max(ht, 1.2*l.GetYsize()/(gPad->GetY2() - gPad->GetY1()));
10414 Double_t wndc = l.GetXsize()/(gPad->GetX2() - gPad->GetX1());
10415 wt = TMath::Min(0.7, 0.02+wndc);
10416 }
10417 if (title) {
10418 TText *t0 = (TText*)title->GetLine(0);
10419 if (t0) {
10420 if (!strcmp(t0->GetTitle(),fH->GetTitle())) return;
10421 t0->SetTitle(fH->GetTitle());
10422 if (wt > 0) title->SetX2NDC(title->GetX1NDC()+wt);
10423 }
10424 return;
10425 }
10426
10428 if (talh < 1) talh = 1; else if (talh > 3) talh = 3;
10430 if (talv < 1) talv = 1; else if (talv > 3) talv = 3;
10432 xpos = gStyle->GetTitleX();
10433 ypos = gStyle->GetTitleY();
10434 if (talh == 2) xpos = xpos-wt/2.;
10435 if (talh == 3) xpos = xpos-wt;
10436 if (talv == 2) ypos = ypos+ht/2.;
10437 if (talv == 1) ypos = ypos+ht;
10438
10439 TPaveText *ptitle = new TPaveText(xpos, ypos-ht, xpos+wt, ypos,"blNDC");
10440
10441 // box with the histogram title
10442 ptitle->SetFillColor(gStyle->GetTitleFillColor());
10443 ptitle->SetFillStyle(gStyle->GetTitleStyle());
10444 ptitle->SetName("title");
10445 ptitle->SetBorderSize(gStyle->GetTitleBorderSize());
10446 ptitle->SetTextColor(gStyle->GetTitleTextColor());
10447 ptitle->SetTextFont(gStyle->GetTitleFont(""));
10448 if (gStyle->GetTitleFont("")%10 > 2)
10449 ptitle->SetTextSize(gStyle->GetTitleFontSize());
10450 ptitle->AddText(fH->GetTitle());
10451 ptitle->SetBit(kCanDelete);
10452 ptitle->Draw();
10453 ptitle->Paint("blNDC");
10454
10455 if(!gPad->IsEditable()) delete ptitle;
10456}
10457
10458////////////////////////////////////////////////////////////////////////////////
10459/// Process message `mess`.
10460
10461void THistPainter::ProcessMessage(const char *mess, const TObject *obj)
10462{
10463 if (!strcmp(mess,"SetF3")) {
10464 fCurrentF3 = (TF3 *)obj;
10465 }
10466}
10467
10468////////////////////////////////////////////////////////////////////////////////
10469/// Static function.
10470///
10471/// Convert Right Ascension, Declination to X,Y using an AITOFF projection.
10472/// This procedure can be used to create an all-sky map in Galactic
10473/// coordinates with an equal-area Aitoff projection. Output map
10474/// coordinates are zero longitude centered.
10475/// Also called Hammer-Aitoff projection (first presented by Ernst von Hammer in 1892)
10476///
10477/// source: GMT
10478///
10479/// code from Ernst-Jan Buis
10480
10482{
10483
10484 Double_t x, y;
10485
10487 Double_t delta = b*TMath::DegToRad();
10488 Double_t r2 = TMath::Sqrt(2.);
10489 Double_t f = 2*r2/TMath::Pi();
10490 Double_t cdec = TMath::Cos(delta);
10493 y = TMath::Sin(delta)*r2/denom;
10494 x *= TMath::RadToDeg()/f;
10495 y *= TMath::RadToDeg()/f;
10496 // x *= -1.; // for a skymap swap left<->right
10497 Al = x;
10498 Ab = y;
10499
10500 return 0;
10501}
10502
10503////////////////////////////////////////////////////////////////////////////////
10504/// Static function
10505///
10506/// Probably the most famous of the various map projections, the Mercator projection
10507/// takes its name from Mercator who presented it in 1569. It is a cylindrical, conformal projection
10508/// with no distortion along the equator.
10509/// The Mercator projection has been used extensively for world maps in which the distortion towards
10510/// the polar regions grows rather large, thus incorrectly giving the impression that, for example,
10511/// Greenland is larger than South America. In reality, the latter is about eight times the size of
10512/// Greenland. Also, the Former Soviet Union looks much bigger than Africa or South America. One may wonder
10513/// whether this illusion has had any influence on U.S. foreign policy.' (Source: GMT)
10514/// code from Ernst-Jan Buis
10515
10517{
10518
10519 Al = l;
10521 Ab = TMath::Log(aid);
10522 return 0;
10523}
10524
10525////////////////////////////////////////////////////////////////////////////////
10526/// Static function code for sinusoidal projection
10527/// from Ernst-Jan Buis
10528/// Source https://en.wikipedia.org/wiki/Sinusoidal_projection
10529
10531{
10532
10533 Al = l*cos(b*TMath::DegToRad());
10534 Ab = b;
10535 return 0;
10536}
10537
10538////////////////////////////////////////////////////////////////////////////////
10539/// Static function code for parabolic projection
10540/// from Ernst-Jan Buis
10541
10543{
10544
10545 Al = l*(2.*TMath::Cos(2*b*TMath::DegToRad()/3) - 1);
10546 Ab = 180*TMath::Sin(b*TMath::DegToRad()/3);
10547 return 0;
10548}
10549
10550////////////////////////////////////////////////////////////////////////////////
10551/// Static function.
10552///
10553/// Convert Right Ascension, Declination to X,Y using an MOLLWEIDE projection.
10554/// This procedure can be used to create an all-sky map in Galactic
10555/// coordinates with an equal-area Mollweide projection. Output map
10556/// coordinates are zero longitude centered.
10557/// It is also known as the Babinet projection, homalographic projection, homolographic projection, and elliptical projection.
10558/// Source: https://en.wikipedia.org/wiki/Mollweide_projection
10559///
10560/// code from Marco Meyer-Conde
10561
10563{
10564
10565 Double_t theta0 = b * TMath::DegToRad(), theta = theta0;
10566
10567 for (int i = 0; i < 100; i++) {
10568 Double_t num = 2 * theta + TMath::Sin(2 * theta) - TMath::Pi() * TMath::Sin(theta0);
10569 Double_t den = 4 * TMath::Power(TMath::Cos(theta), 2);
10570
10571 if (den < 1e-20) {
10572 theta = theta0;
10573 break;
10574 }
10575
10576 theta -= num / den;
10577
10578 if (TMath::Abs(num / den) < 1e-4) break;
10579 }
10580
10581 Al = l * TMath::Cos(theta);
10582 Ab = 90 * TMath::Sin(theta);
10583
10584 return 0;
10585}
10586
10587////////////////////////////////////////////////////////////////////////////////
10588/// Recompute the histogram range following graphics operations.
10589
10591{
10592
10593 if (Hoption.Same) return;
10594
10595 // Compute x,y range
10597 xmax = Hparam.xmax,
10598 ymin = Hparam.ymin,
10599 ymax = Hparam.ymax,
10600 xscale = 1;
10601
10602 std::function<Int_t(Double_t,Double_t,Double_t&,Double_t&)> func;
10603
10604 if (Hoption.Proj == 1) {
10605 func = ProjectAitoff2xy;
10606 xscale = 0.9999;
10607 } else if (Hoption.Proj == 2) {
10608 if (Hparam.ymin <= -90 || Hparam.ymax >= 90) {
10609 Warning("Mercator Projection", "Latitude out of range %f or %f", Hparam.ymin, Hparam.ymax);
10610 Hoption.Proj = 0;
10611 } else {
10614 }
10615 } else if (Hoption.Proj == 3) {
10616 func = ProjectSinusoidal2xy;
10617 } else if (Hoption.Proj == 4) {
10618 func = ProjectParabolic2xy;
10619 } else if (Hoption.Proj == 5) {
10620 func = ProjectMollweide2xy;
10621 }
10622
10623 if (func) {
10625
10629 func(Hparam.xmax, Hparam.ymin, xmax, ymin);
10630
10631 if (xmin > xmin_aid) xmin = xmin_aid;
10632 if (ymin > ymin_aid) ymin = ymin_aid;
10633 if (xmax < xmax_aid) xmax = xmax_aid;
10634 if (ymax < ymax_aid) ymax = ymax_aid;
10635 if (Hparam.ymin < 0 && Hparam.ymax > 0) {
10636 // there is an 'equator', check its range in the plot..
10637 func(Hparam.xmin*xscale, 0, xmin_aid, ymin_aid);
10638 func(Hparam.xmax*xscale, 0, xmax_aid, ymin_aid);
10639 if (xmin > xmin_aid) xmin = xmin_aid;
10640 if (xmax < xmax_aid) xmax = xmax_aid;
10641 }
10642 if (Hparam.xmin < 0 && Hparam.xmax > 0) {
10643 func(0, Hparam.ymin, xmin_aid, ymin_aid);
10644 func(0, Hparam.ymax, xmax_aid, ymax_aid);
10645 if (ymin > ymin_aid) ymin = ymin_aid;
10646 if (ymax < ymax_aid) ymax = ymax_aid;
10647 }
10648 }
10649
10650 Hparam.xmin = xmin;
10651 Hparam.xmax = xmax;
10652 Hparam.ymin = ymin;
10653 Hparam.ymax = ymax;
10654
10655 Double_t dx = xmax-xmin;
10656 Double_t dy = ymax-ymin;
10657 Double_t dxr = dx/(1 - gPad->GetLeftMargin() - gPad->GetRightMargin());
10658 Double_t dyr = dy/(1 - gPad->GetBottomMargin() - gPad->GetTopMargin());
10659
10660 // Range() could change the size of the pad pixmap and therefore should
10661 // be called before the other paint routines
10662 gPad->Range(xmin - dxr*gPad->GetLeftMargin(),
10663 ymin - dyr*gPad->GetBottomMargin(),
10664 xmax + dxr*gPad->GetRightMargin(),
10665 ymax + dyr*gPad->GetTopMargin());
10666 gPad->RangeAxis(xmin, ymin, xmax, ymax);
10667}
10668
10669////////////////////////////////////////////////////////////////////////////////
10670/// Set current histogram to `h`
10671
10673{
10674
10675 if (h == nullptr) return;
10676 fH = h;
10677 fXaxis = h->GetXaxis();
10678 fYaxis = h->GetYaxis();
10679 fZaxis = h->GetZaxis();
10681}
10682
10683////////////////////////////////////////////////////////////////////////////////
10684/// Initialize various options to draw 2D histograms.
10685
10687{
10688
10689 static const char *where = "TableInit";
10690
10691 Int_t first, last;
10693 Double_t zmin, zmax;
10694 Int_t maximum = 0;
10695 Int_t minimum = 0;
10696 if (fH->GetMaximumStored() != -1111) maximum = 1;
10697 if (fH->GetMinimumStored() != -1111) minimum = 1;
10698
10699 // ----------------- Compute X axis parameters
10700 first = fXaxis->GetFirst();
10701 last = fXaxis->GetLast();
10702 Hparam.xlast = last;
10703 Hparam.xfirst = first;
10708
10709 // if log scale in X, replace xmin,max by the log
10710 if (Hoption.Logx) {
10711 // find the first edge of a bin that is > 0
10712 if (Hparam.xlowedge <=0 ) {
10715 }
10716 if (Hparam.xmin <=0 || Hparam.xmax <=0) {
10717 Error(where, "cannot set X axis to log scale");
10718 return 0;
10719 }
10721 if (Hparam.xfirst < first) Hparam.xfirst = first;
10723 if (Hparam.xlast > last) Hparam.xlast = last;
10726 }
10727
10728 // ----------------- Compute Y axis parameters
10729 first = fYaxis->GetFirst();
10730 last = fYaxis->GetLast();
10731 Hparam.ylast = last;
10732 Hparam.yfirst = first;
10735 if (!Hparam.ybinsize) Hparam.ybinsize = 1;
10738
10739 // if log scale in Y, replace ymin,max by the log
10740 if (Hoption.Logy) {
10741 if (Hparam.ylowedge <=0 ) {
10744 }
10745 if (Hparam.ymin <=0 || Hparam.ymax <=0) {
10746 Error(where, "cannot set Y axis to log scale");
10747 return 0;
10748 }
10750 if (Hparam.yfirst < first) Hparam.yfirst = first;
10752 if (Hparam.ylast > last) Hparam.ylast = last;
10755 }
10756
10757
10758 // ----------------- Compute Z axis parameters
10759 Double_t bigp = TMath::Power(10,32);
10760 zmax = -bigp;
10761 zmin = bigp;
10762 Double_t c1, e1;
10763 Double_t allchan = 0;
10764 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
10765 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10766 c1 = fH->GetBinContent(i,j);
10767 zmax = TMath::Max(zmax,c1);
10768 if (Hoption.Error) {
10769 e1 = fH->GetBinError(i,j);
10770 zmax = TMath::Max(zmax,c1+e1);
10771 }
10772 zmin = TMath::Min(zmin,c1);
10773 allchan += c1;
10774 }
10775 }
10776
10777 // Take into account maximum , minimum
10778
10779 if (maximum) zmax = fH->GetMaximumStored();
10780 if (minimum) zmin = fH->GetMinimumStored();
10781 if (Hoption.Logz && zmax < 0) {
10782 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10783 return 0;
10784 } else if (Hoption.Logz && zmin>=0 && zmax==0) { // empty histogram in log scale
10785 zmin = 0.01;
10786 zmax = 10.;
10787 }
10788 if (zmin >= zmax) {
10789 if (Hoption.Logz) {
10790 if (zmax > 0) zmin = 0.001*zmax;
10791 else {
10792 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10793 return 0;
10794 }
10795 }
10796 }
10797
10798 // take into account normalization factor
10799 Hparam.allchan = allchan;
10800 Double_t factor = allchan;
10801 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
10802 if (allchan) factor /= allchan;
10803 if (factor == 0) factor = 1;
10804 Hparam.factor = factor;
10805 zmax = factor*zmax;
10806 zmin = factor*zmin;
10807 c1 = zmax;
10808 if (TMath::Abs(zmin) > TMath::Abs(c1)) c1 = zmin;
10809
10810 // For log scales, histogram coordinates are log10(ymin) and
10811 // log10(ymax). Final adjustment (if not option "Same")
10812 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
10813 // Maximum and Minimum are not defined.
10814 if (Hoption.Logz) {
10815 if (zmin <= 0) {
10816 zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
10817 fH->SetMinimum(zmin);
10818 }
10819 zmin = TMath::Log10(zmin);
10820 if (!minimum) zmin += TMath::Log10(0.5);
10821 zmax = TMath::Log10(zmax);
10822 if (!maximum) zmax += TMath::Log10(2*(0.9/0.95));
10823 goto LZMIN;
10824 }
10825
10826 // final adjustment of YMAXI for linear scale (if not option "Same"):
10827 // decrease histogram height to MAX% of allowed height if HMAXIM
10828 // has not been called.
10829 // MAX% is the value in percent which has been set in HPLSET
10830 // (default is 90%).
10831 if (!maximum) {
10832 zmax += yMARGIN*(zmax-zmin);
10833 }
10834
10835 // final adjustment of ymin for linear scale.
10836 // if minimum is not set , then ymin is set to zero if >0
10837 // or to ymin - yMARGIN if <0.
10838 if (!minimum) {
10839 if (Hoption.MinimumZero) {
10840 if (zmin >= 0) zmin = 0;
10841 else zmin -= yMARGIN*(zmax-zmin);
10842 } else {
10843 Double_t dzmin = yMARGIN*(zmax-zmin);
10844 if (zmin >= 0 && (zmin-dzmin <= 0)) zmin = 0;
10845 else zmin -= dzmin;
10846 }
10847 }
10848
10849LZMIN:
10850 Hparam.zmin = zmin;
10851 Hparam.zmax = zmax;
10852
10853 // Set bar offset and width
10856
10857 return 1;
10858}
10859
10860////////////////////////////////////////////////////////////////////////////////
10861/// This function returns the best format to print the error value (e)
10862/// knowing the parameter value (v) and the format (f) used to print it.
10863
10865{
10866
10867 static TString ef;
10868 TString tf, tv;
10869
10870 // print v with the format f in tv.
10871 tf.Form("%s%s","%",f);
10872 tv.Form(tf.Data(),v);
10873
10874 // Analyse tv.
10875 int ie = tv.Index("e");
10876 int iE = tv.Index("E");
10877 int id = tv.Index(".");
10878
10879 // v has been printed with the exponent notation.
10880 // There is 2 cases, the exponent is positive or negative
10881 if (ie >= 0 || iE >= 0) {
10882 if (tv.Index("+") >= 0) {
10883 if (e < 1) {
10884 ef.Form("%s.1f","%");
10885 } else {
10886 if (ie >= 0) {
10887 ef.Form("%s.%de","%",ie-id-1);
10888 } else {
10889 ef.Form("%s.%dE","%",iE-id-1);
10890 }
10891 }
10892 } else {
10893 if (ie >= 0) {
10894 ef.Form("%s.%de","%",ie-id-1);
10895 } else {
10896 ef.Form("%s.%dE","%",iE-id-1);
10897 }
10898 }
10899
10900 // There is not '.' in tv. e will be printed with one decimal digit.
10901 } else if (id < 0) {
10902 ef.Form("%s.1f","%");
10903
10904 // There is a '.' in tv and no exponent notation. e's decimal part will
10905 // have the same number of digits as v's one.
10906 } else {
10907 ef.Form("%s.%df","%",tv.Length()-id-1);
10908 }
10909
10910 return ef.Data();
10911}
10912
10913
10914////////////////////////////////////////////////////////////////////////////////
10915/// Return projection kind from option string
10916
10918{
10919 TString opt = option;
10920 opt.ToLower();
10921 Int_t projection = 0;
10922 if (opt.BeginsWith("xy"))
10923 projection = 4;
10924 else if (opt.BeginsWith("yx"))
10925 projection = 5;
10926 else if (opt.BeginsWith("xz"))
10927 projection = 6;
10928 else if (opt.BeginsWith("zx"))
10929 projection = 7;
10930 else if (opt.BeginsWith("yz"))
10931 projection = 8;
10932 else if (opt.BeginsWith("zy"))
10933 projection = 9;
10934 else if (opt.BeginsWith("x"))
10935 projection = 1;
10936 else if (opt.BeginsWith("y"))
10937 projection = 2;
10938 else if (opt.BeginsWith("z"))
10939 projection = 3;
10940 return projection;
10941}
10942
10943
10944////////////////////////////////////////////////////////////////////////////////
10945/// Set projection.
10946
10948{
10949 if (fShowProjection2) {
10950 auto name2 = TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2);
10951 auto c2 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name2.Data()));
10952 if (c2) c2->Close();
10953 fShowProjection2 = 0;
10954 }
10955 if (fShowProjection) {
10956 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10957 auto c1 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name1.Data()));
10958 if (c1) c1->Close();
10959 fShowProjection = 0;
10960 }
10961
10962 if (nbins <= 0)
10963 return;
10964
10965 if ((fH->GetDimension() == 3) && (gPad->GetGLDevice() != -1)) {
10966 Error("SetShowProjection", "TH3 projections do not work in GL mode");
10967 return;
10968 }
10969
10971 if (projection == 0)
10972 return;
10973
10974 // exclude x or xy from option, rest use as histogram draw option
10975 fShowOption = option + (projection < 4 ? 1 : 2);
10977 fShowProjection2 = 0;
10978
10979 gROOT->MakeDefCanvas();
10980 gPad->SetName(TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection).Data());
10981 gPad->SetGrid();
10982}
10983
10984////////////////////////////////////////////////////////////////////////////////
10985/// Set projection XY.
10986
10988{
10989 if (fShowProjection2) {
10990 auto name2 = TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2);
10991 auto c2 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name2.Data()));
10992 if (c2) c2->Close();
10993 fShowProjection2 = 0;
10994 }
10995 if (fShowProjection) {
10996 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10997 auto c1 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name1.Data()));
10998 if (c1) c1->Close();
10999 fShowProjection = 0;
11000 }
11001
11002 if ((nbinsX <= 0) || (nbinsY <= 0))
11003 return;
11004
11005 if ((fH->GetDimension() == 3) && (gPad->GetGLDevice() != -1)) {
11006 Error("SetShowProjectionXY", "TH3 projections do not work in GL mode");
11007 return;
11008 }
11009
11011 if (projection == 0)
11012 return;
11013
11014 // exclude x or xy from option, rest use as histogram draw option
11015 fShowOption = option + (projection < 4 ? 1 : 2);
11018
11019 gROOT->MakeDefCanvas();
11020 gPad->SetName(TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection).Data());
11021 gPad->SetGrid();
11022 gROOT->MakeDefCanvas();
11023 gPad->SetName(TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2).Data());
11024 gPad->SetGrid();
11025}
11026
11027
11028////////////////////////////////////////////////////////////////////////////////
11029/// Show projection onto X.
11030
11032{
11033 if (!gPad)
11034 return;
11035
11037
11038 // Erase old position and draw a line at current position
11039 Double_t uxmin = gPad->GetUxmin();
11040 Double_t uxmax = gPad->GetUxmax();
11041 Float_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
11042 Int_t biny1 = fH->GetYaxis()->FindBin(y);
11044 Double_t py1 = gPad->YtoPad(fH->GetYaxis()->GetBinLowEdge(biny1));
11045 Double_t py2 = gPad->YtoPad(fH->GetYaxis()->GetBinUpEdge(biny2));
11046
11047 gPad->PaintBox(uxmin,py1,uxmax,py2,"iprojX");
11048 gPad->UpdateAsync();
11049
11050 // Create or set the new canvas proj x
11052 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
11053 auto c = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name1.Data()));
11054 if (!c) {
11056 return;
11057 }
11058
11059 c->Clear();
11060 c->cd();
11061 c->SetLogy(ctxt.GetSaved()->GetLogz());
11062 c->SetLogx(ctxt.GetSaved()->GetLogx());
11063
11064 // Draw slice corresponding to mouse position
11065 TString prjName = TString::Format("slice_px_of_%s",fH->GetName());
11066 if (auto hp = ((TH2*)fH)->ProjectionX(prjName, biny1, biny2)) {
11067 hp->SetFillColor(38);
11068 // apply a patch from Oliver Freyermuth to set the title in the projection
11069 // using the range of the projected Y values
11070 if (biny1 == biny2) {
11073 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11075 if (fH->GetYaxis()->GetLabels() != nullptr) {
11076 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf] %s", biny1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetYaxis()->GetBinLabel(biny1)));
11077 } else {
11078 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf]", biny1, valuePrecision, valueFrom, valuePrecision, valueTo));
11079 }
11080 } else {
11083 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11084 // biny1 is used here to get equal precision no matter how large the binrange is,
11085 // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
11087 if (fH->GetYaxis()->GetLabels() != nullptr) {
11088 hp->SetTitle(TString::Format("ProjectionX of biny=[%d,%d] [y=%.*lf..%.*lf] [%s..%s]", biny1, biny2, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetYaxis()->GetBinLabel(biny1), fH->GetYaxis()->GetBinLabel(biny2)));
11089 } else {
11090 hp->SetTitle(TString::Format("ProjectionX of biny=[%d,%d] [y=%.*lf..%.*lf]", biny1, biny2, valuePrecision, valueFrom, valuePrecision, valueTo));
11091 }
11092 }
11093 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11094 hp->SetYTitle(((TH2*)fH)->GetZaxis()->GetTitle() ? ((TH2*)fH)->GetZaxis()->GetTitle() : "Number of Entries");
11095 c->Add(hp, fShowOption);
11096 c->UpdateAsync();
11097 }
11098}
11099
11100////////////////////////////////////////////////////////////////////////////////
11101/// Show projection onto Y.
11102
11104{
11105 if (!gPad)
11106 return;
11107
11109 if (fShowProjection2)
11111
11112 Double_t uymin = gPad->GetUymin();
11113 Double_t uymax = gPad->GetUymax();
11114 Float_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
11115 Int_t binx1 = fH->GetXaxis()->FindBin(x);
11117 Double_t px1 = gPad->XtoPad(fH->GetXaxis()->GetBinLowEdge(binx1));
11118 Double_t px2 = gPad->XtoPad(fH->GetXaxis()->GetBinUpEdge(binx2));
11119
11120 gPad->PaintBox(px1, uymin, px2, uymax, "iprojY");
11121 gPad->UpdateAsync();
11122
11123 // Create or set the new canvas proj y
11125
11126 TString name2 = fShowProjection2 ? TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2)
11127 : TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
11128
11129 auto c = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name2.Data()));
11130 if (!c) {
11132 return;
11133 }
11134
11135 c->Clear();
11136 c->cd();
11137 c->SetLogy(ctxt.GetSaved()->GetLogz());
11138 c->SetLogx(ctxt.GetSaved()->GetLogy());
11139
11140 // Draw slice corresponding to mouse position
11141 TString prjName = TString::Format("slice_py_of_%s",fH->GetName());
11142 if (auto hp = ((TH2*)fH)->ProjectionY(prjName, binx1, binx2)) {
11143 hp->SetFillColor(38);
11144 // apply a patch from Oliver Freyermuth to set the title in the projection
11145 // using the range of the projected X values
11146 if (binx1 == binx2) {
11149 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11151 if (fH->GetXaxis()->GetLabels()) {
11152 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf] [%s]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetXaxis()->GetBinLabel(binx1)));
11153 } else {
11154 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo));
11155 }
11156 } else {
11159 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11160 // binx1 is used here to get equal precision no matter how large the binrange is,
11161 // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
11163 if (fH->GetXaxis()->GetLabels()) {
11164 hp->SetTitle(TString::Format("ProjectionY of binx=[%d,%d] [x=%.*lf..%.*lf] [%s..%s]", binx1, binx2, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetXaxis()->GetBinLabel(binx1), fH->GetXaxis()->GetBinLabel(binx2)));
11165 } else {
11166 hp->SetTitle(TString::Format("ProjectionY of binx=[%d,%d] [x=%.*lf..%.*lf]", binx1, binx2, valuePrecision, valueFrom, valuePrecision, valueTo));
11167 }
11168 }
11169 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11170 hp->SetYTitle(((TH2*)fH)->GetZaxis()->GetTitle() ? ((TH2*)fH)->GetZaxis()->GetTitle() : "Number of Entries");
11171 c->Add(hp, fShowProjection2 ? "hbar" + fShowOption : fShowOption);
11172 c->UpdateAsync();
11173 }
11174}
11175
11176////////////////////////////////////////////////////////////////////////////////
11177/// Show projection (specified by `fShowProjection`) of a `TH3`.
11178/// The drawing option for the projection is in `fShowOption`.
11179///
11180/// First implementation: R.Brun
11181///
11182/// Full implementation: Tim Tran (timtran@jlab.org) April 2006
11183///
11184/// Redesign: S. Linev September 2026
11185
11187{
11188 Int_t nbins = fShowProjection / 100; //decode nbins
11189 Int_t kind = fShowProjection % 100; // projection kinds
11190
11191 if (fH->GetDimension() < 3) {
11192 if (fShowProjection2 % 100 == 1) {
11193 ShowProjectionY(px, py);
11194 }
11195 if (fShowProjection % 100 == 1) {
11196 ShowProjectionX(px, py);
11197 return;
11198 }
11199 if (fShowProjection % 100 == 2) {
11200 ShowProjectionY(px, py);
11201 return;
11202 }
11203 }
11204
11205 auto &parent = *gPad;
11206
11207 // 3D protection does not work with GL painters
11208 if (parent.GetGLDevice() != -1)
11209 return;
11210
11211 auto view = parent.GetView();
11212 if (!view)
11213 return;
11214
11215 // check that ranges are set
11216 if ((parent.GetUxmin() == parent.GetUxmax()) || (parent.GetUymin() == parent.GetUymax()))
11217 return;
11218
11219 // calculated vertices
11220 Double_t rect1x[5] = {0,0,0,0,0}, rect1y[5] = {0,0,0,0,0}, rect2x[5] = {0,0,0,0,0}, rect2y[5] = {0,0,0,0,0};
11221
11222 auto cname = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
11223 auto c = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(cname));
11224 auto h3 = dynamic_cast<TH3 *>(fH);
11225
11226 if (!c || !h3) {
11227 fShowProjection = 0;
11228 return;
11229 }
11230
11231 TAxis *xaxis = fH->GetXaxis();
11232 TAxis *yaxis = fH->GetYaxis();
11233 TAxis *zaxis = fH->GetZaxis();
11234
11235 static constexpr Int_t iMin = -111;
11236 static constexpr Int_t iMax = -11;
11237 static constexpr Int_t kMaxDist = 50; // maximal distance to detect bin
11238
11239 auto getx = [](TAxis *axis, Int_t indx) {
11240 return indx == iMin ? axis->GetBinLowEdge(axis->GetFirst())
11241 : (indx == iMax ? axis->GetBinUpEdge(axis->GetLast()) : axis->GetBinCenter(indx));
11242 };
11243
11244 auto findAxis = [&parent, px, py, xaxis, yaxis, zaxis, view, getx](Int_t &besti1, Int_t &besti2, char name) {
11245
11246 TAxis *axis1 = nullptr, *axis2 = nullptr;
11247 Int_t xindx = 0, yindx = 0, zindx = 0;
11248
11249 switch(name) {
11250 case 'x':
11251 axis1 = yaxis;
11252 axis2 = zaxis;
11253 xindx = TMath::Cos(view->GetLongitude() / 180. * TMath::Pi()) < 0 ? iMin : iMax;
11254 break;
11255 case 'y':
11256 axis1 = xaxis;
11257 axis2 = zaxis;
11258 yindx = TMath::Sin(view->GetLongitude() / 180. * TMath::Pi()) < 0 ? iMin : iMax;
11259 break;
11260 default:
11261 axis1 = xaxis;
11262 axis2 = yaxis;
11263 zindx = TMath::Cos(view->GetLatitude() / 180. * TMath::Pi()) > 0 ? iMax : iMin;
11264 break;
11265 }
11266
11268
11269 for (Int_t i1 = axis1->GetFirst(); i1 <= axis1->GetLast(); ++i1)
11270 for (Int_t i2 = axis2->GetFirst(); i2 <= axis2->GetLast(); ++i2) {
11271 switch(name) {
11272 case 'x': yindx = i1; zindx = i2; break;
11273 case 'y': xindx = i1; zindx = i2; break;
11274 default: xindx = i1; yindx = i2; break;
11275 }
11277 Double_t ndc[3];
11278 view->WCtoNDC(v, ndc);
11279 Int_t px1 = parent.XtoAbsPixel(ndc[0]);
11280 Int_t py1 = parent.YtoAbsPixel(ndc[1]);
11281 Double_t distance = TMath::Sqrt(1. * (px1 - px) * (px1 - px) + 1. * (py1 - py) * (py1 - py));
11282 if (distance < best_dist) {
11284 besti1 = i1;
11285 besti2 = i2;
11286 }
11287 }
11288
11289 return best_dist < kMaxDist;
11290 };
11291
11292 auto convert = [view, getx, xaxis, yaxis, zaxis](Int_t ix, Int_t iy, Int_t iz,
11294 Double_t vvv[3] = {getx(xaxis, ix), getx(yaxis, iy), getx(zaxis, iz)};
11295 Double_t uu[3];
11296 view->WCtoNDC(vvv, uu);
11297 resx = uu[0];
11298 resy = uu[1];
11299 };
11300
11301 auto draw_rects = [&parent, nbins, kind, &rect1x, &rect2x, &rect1y, &rect2y]() {
11302 rect1x[4] = rect1x[0];
11303 rect1y[4] = rect1y[0];
11304 rect2x[4] = rect2x[0];
11305 rect2y[4] = rect2y[0];
11306 if (kind > 3) {
11307 parent.PaintPolyLine(5, rect1x, rect1y, "iproj3_rect1");
11308 if (nbins > 1)
11309 parent.PaintPolyLine(5, rect2x, rect2y, "iproj3_rect2");
11310 } else {
11311 parent.PaintPolyLine(nbins > 1 ? 5 : 2, rect1x, rect1y, "iproj3_rect1");
11312 if (nbins > 1) {
11313 parent.PaintPolyLine(5, rect2x, rect2y, "iproj3_rect2");
11314 for (Int_t n = 0; n < 4; ++n) {
11315 Double_t xx[2] = {rect1x[n], rect2x[n]};
11316 Double_t yy[2] = {rect1y[n], rect2y[n]};
11317 parent.PaintPolyLine(2, xx, yy, TString::Format("iproj3_line%d", n).Data());
11318 }
11319 }
11320 }
11321 parent.UpdateAsync();
11322 };
11323
11324 Int_t binx = -1, biny = -1, binz = -1, binx2 = -1, biny2 = -1, binz2 = -1, dummy = -1;
11325
11326 auto extend_bin = [nbins](TAxis *axis, Int_t &bin) {
11327 Int_t bin2 = bin;
11328 if (nbins > 1) {
11329 bin2 = TMath::Min(bin + nbins / 2, axis->GetLast());
11330 bin = TMath::Max(bin2 - nbins + 1, axis->GetFirst());
11331 }
11332 return bin2;
11333 };
11334
11335 auto make_proj = [h3, &binx, &biny, &binz, &binx2, &biny2, &binz2, xaxis, yaxis, zaxis](const char *proj_kind) {
11336 Int_t firstX = xaxis->GetFirst();
11337 Int_t lastX = xaxis->GetLast();
11338 Int_t firstY = yaxis->GetFirst();
11339 Int_t lastY = yaxis->GetLast();
11340 Int_t firstZ = zaxis->GetFirst();
11341 Int_t lastZ = zaxis->GetLast();
11342 if (binx >= 0)
11343 xaxis->SetRange(binx, binx2);
11344 if (biny >= 0)
11345 yaxis->SetRange(biny, biny2);
11346 if (binz >= 0)
11347 zaxis->SetRange(binz, binz2);
11348 auto hp = h3->Project3D(proj_kind);
11349 if (binx >= 0)
11350 xaxis->SetRange(firstX,lastX);
11351 if (biny >= 0)
11352 yaxis->SetRange(firstY, lastY);
11353 if (binz >= 0)
11354 zaxis->SetRange(firstZ,lastZ);
11355 return hp;
11356 };
11357
11359
11360 switch (kind) {
11361 case 1: { // "x"
11362 if (!findAxis(biny, binz, 'x'))
11363 break;
11364
11367
11368 convert(iMin, biny, binz, rect1x[0], rect1y[0]);
11369 convert(iMax, biny, binz, rect1x[1], rect1y[1]);
11370 convert(iMax, biny, binz2, rect1x[2], rect1y[2]);
11371 convert(iMin, biny, binz2, rect1x[3], rect1y[3]);
11372 convert(iMin, biny2, binz, rect2x[0], rect2y[0]);
11373 convert(iMax, biny2, binz, rect2x[1], rect2y[1]);
11374 convert(iMax, biny2, binz2, rect2x[2], rect2y[2]);
11375 convert(iMin, biny2, binz2, rect2x[3], rect2y[3]);
11376
11377 draw_rects();
11378
11379 c->Clear();
11380
11381 if (auto hp = make_proj("x")) {
11382 hp->SetFillColor(38);
11383 if ((biny == biny2) && (binz == binz2))
11384 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny),
11385 binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
11386 else
11387 hp->SetTitle(TString::Format("ProjectionX, biny=[%d,%d] [y=%.1f..%.1f], binz=[%d,%d] [z=%.1f..%.1f]", biny, biny2, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny2),
11388 binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
11389 hp->SetXTitle(xaxis->GetTitle());
11390 hp->SetYTitle("Number of Entries");
11391 c->Add(hp, fShowOption);
11392 }
11393 break;
11394 }
11395
11396 case 2: { // "y"
11397 if (!findAxis(binx, binz, 'y'))
11398 break;
11399
11402
11403 convert(binx, iMin, binz, rect1x[0], rect1y[0]);
11404 convert(binx, iMax, binz, rect1x[1], rect1y[1]);
11405 convert(binx, iMax, binz2, rect1x[2], rect1y[2]);
11406 convert(binx, iMin, binz2, rect1x[3], rect1y[3]);
11407 convert(binx2, iMin, binz, rect2x[0], rect2y[0]);
11408 convert(binx2, iMax, binz, rect2x[1], rect2y[1]);
11409 convert(binx2, iMax, binz2, rect2x[2], rect2y[2]);
11410 convert(binx2, iMin, binz2, rect2x[3], rect2y[3]);
11411
11412 draw_rects();
11413
11414 c->Clear();
11415 if (auto hp = make_proj("y")) {
11416 hp->SetFillColor(38);
11417 if ((binx == binx2) && (binz == binz2))
11418 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
11419 binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
11420 else
11421 hp->SetTitle(TString::Format("ProjectionY, binx=[%d,%d] [x=%.1f..%.1f], binz=[%d,%d] [z=%.1f..%.1f]", binx, binx2, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx2),
11422 binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
11423 hp->SetXTitle(yaxis->GetTitle());
11424 hp->SetYTitle("Number of Entries");
11425 c->Add(hp, fShowOption);
11426 }
11427 break;
11428 }
11429
11430 case 3: { // "z"
11431 if (!findAxis(binx, biny, 'z'))
11432 break;
11435
11436 convert(binx, biny, iMin, rect1x[0], rect1y[0]);
11437 convert(binx, biny, iMax, rect1x[1], rect1y[1]);
11438 convert(binx, biny2, iMax, rect1x[2], rect1y[2]);
11439 convert(binx, biny2, iMin, rect1x[3], rect1y[3]);
11440 convert(binx2, biny, iMin, rect2x[0], rect2y[0]);
11441 convert(binx2, biny, iMax, rect2x[1], rect2y[1]);
11442 convert(binx2, biny2, iMax, rect2x[2], rect2y[2]);
11443 convert(binx2, biny2, iMin, rect2x[3], rect2y[3]);
11444
11445 draw_rects();
11446
11447 c->Clear();
11448 if (auto hp = make_proj("z")) {
11449 hp->SetFillColor(38);
11450 if ((binx == binx2) && (biny == biny2))
11451 hp->SetTitle(TString::Format("ProjectionZ of binx=%d [x=%.1f..%.1f] biny=%d [y=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
11452 biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny)));
11453 else
11454 hp->SetTitle(TString::Format("ProjectionZ, binx=[%d,%d] [x=%.1f..%.1f], biny=[%d,%d] [y=%.1f..%.1f]", binx, binx2, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx2),
11455 biny, biny2, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny2) ) );
11456 hp->SetXTitle(zaxis->GetTitle());
11457 hp->SetYTitle("Number of Entries");
11458 c->Add(hp, fShowOption);
11459 }
11460 break;
11461 }
11462
11463 case 4: // "xy"
11464 case 5: { // "yx"
11465 if (!findAxis(dummy, binz, 'x') && !findAxis(dummy, binz, 'y'))
11466 break;
11468
11469 convert(iMin, iMax, binz, rect1x[0], rect1y[0]);
11470 convert(iMax, iMax, binz, rect1x[1], rect1y[1]);
11471 convert(iMax, iMin, binz, rect1x[2], rect1y[2]);
11472 convert(iMin, iMin, binz, rect1x[3], rect1y[3]);
11473 if (binz != binz2) {
11474 convert(iMin, iMax, binz2, rect2x[0], rect2y[0]);
11475 convert(iMax, iMax, binz2, rect2x[1], rect2y[1]);
11476 convert(iMax, iMin, binz2, rect2x[2], rect2y[2]);
11477 convert(iMin, iMin, binz2, rect2x[3], rect2y[3]);
11478 }
11479
11480 draw_rects();
11481
11482 c->Clear();
11483
11484 if (auto hp = make_proj(kind == 4 ? "xy" : "yx")) {
11485 hp->SetFillColor(38);
11486 TString sbins = (binz == binz2) ? TString::Format("%d", binz) : TString::Format("[%d,%d]", binz, binz2);
11487 hp->SetTitle(TString::Format("Projection%s, binz=%s [z=%.1f..%.1f]", kind == 4 ? "XY" : "YX", sbins.Data(),
11488 zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2)));
11489 if (kind == 4) {
11490 hp->SetXTitle(yaxis->GetTitle());
11491 hp->SetYTitle(xaxis->GetTitle());
11492 } else {
11493 hp->SetXTitle(xaxis->GetTitle());
11494 hp->SetYTitle(yaxis->GetTitle());
11495 }
11496 hp->SetZTitle("Number of Entries");
11497 c->Add(hp, fShowOption);
11498 }
11499 break;
11500 }
11501
11502 case 6: // "xz"
11503 case 7: { // "zx"
11504 if (!findAxis(biny, dummy, 'x') && !findAxis(dummy, biny, 'z'))
11505 break;
11506
11508
11509 convert(iMin, biny, iMax, rect1x[0], rect1y[0]);
11510 convert(iMax, biny, iMax, rect1x[1], rect1y[1]);
11511 convert(iMax, biny, iMin, rect1x[2], rect1y[2]);
11512 convert(iMin, biny, iMin, rect1x[3], rect1y[3]);
11513
11514 if (biny != biny2) {
11515 convert(iMin, biny2, iMax, rect2x[0], rect2y[0]);
11516 convert(iMax, biny2, iMax, rect2x[1], rect2y[1]);
11517 convert(iMax, biny2, iMin, rect2x[2], rect2y[2]);
11518 convert(iMin, biny2, iMin, rect2x[3], rect2y[3]);
11519 }
11520
11521 draw_rects();
11522
11523 c->Clear();
11524
11525 if (auto hp = make_proj(kind == 6 ? "xz" : "zx")) {
11526 hp->SetFillColor(38);
11527 TString sbins = (biny == biny2) ? TString::Format("%d", biny) : TString::Format("[%d,%d]", biny, biny2);
11528 hp->SetTitle(TString::Format("Projection%s, biny=%s [y=%.1f..%.1f]", kind == 6 ? "XZ" : "ZX", sbins.Data(),
11529 yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny2)));
11530 if (kind == 6) {
11531 hp->SetXTitle(zaxis->GetTitle());
11532 hp->SetYTitle(xaxis->GetTitle());
11533 } else {
11534 hp->SetXTitle(xaxis->GetTitle());
11535 hp->SetYTitle(zaxis->GetTitle());
11536 }
11537 hp->SetZTitle("Number of Entries");
11538 c->Add(hp, fShowOption);
11539 }
11540 break;
11541 }
11542
11543 case 8: // "yz"
11544 case 9: { // "zy"
11545 if (!findAxis(binx, dummy, 'y') && !findAxis(binx, dummy, 'z'))
11546 break;
11547
11549
11550 convert(binx, iMax, iMin, rect1x[0], rect1y[0]);
11551 convert(binx, iMax, iMax, rect1x[1], rect1y[1]);
11552 convert(binx, iMin, iMax, rect1x[2], rect1y[2]);
11553 convert(binx, iMin, iMin, rect1x[3], rect1y[3]);
11554 if (binx != binx2) {
11555 convert(binx2, iMax, iMin, rect2x[0], rect2y[0]);
11556 convert(binx2, iMax, iMax, rect2x[1], rect2y[1]);
11557 convert(binx2, iMin, iMax, rect2x[2], rect2y[2]);
11558 convert(binx2, iMin, iMin, rect2x[3], rect2y[3]);
11559 }
11560
11561 draw_rects();
11562
11563 c->Clear();
11564 if (auto hp = make_proj(kind == 8 ? "yz" : "zy")) {
11565 hp->SetFillColor(38);
11566 TString sbins = (binx == binx2) ? TString::Format("%d", binx) : TString::Format("[%d,%d]", binx, binx2);
11567 hp->SetTitle(TString::Format("Projection%s of binx=%s [x=%.1f..%.f]", kind == 8 ? "YZ" : "ZY", sbins.Data(),
11568 xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx2)));
11569 if (kind == 8) {
11570 hp->SetXTitle(zaxis->GetTitle());
11571 hp->SetYTitle(yaxis->GetTitle());
11572 } else {
11573 hp->SetXTitle(yaxis->GetTitle());
11574 hp->SetYTitle(zaxis->GetTitle());
11575 }
11576 hp->SetZTitle("Number of Entries");
11577 c->Add(hp, fShowOption);
11578 }
11579 break;
11580 }
11581 }
11582 c->Update();
11583}
@ kMouseMotion
Definition Buttons.h:23
@ kWheelUp
Definition Buttons.h:18
@ kButton1Motion
Definition Buttons.h:20
@ kButton1Up
Definition Buttons.h:19
@ kWheelDown
Definition Buttons.h:18
@ kButton1Down
Definition Buttons.h:17
@ kButton1Locate
Definition Buttons.h:22
@ kArrowVer
Definition GuiTypes.h:375
@ kPointer
Definition GuiTypes.h:376
#define d(i)
Definition RSha256.hxx:102
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
#define c(i)
Definition RSha256.hxx:101
#define g(i)
Definition RSha256.hxx:105
#define a(i)
Definition RSha256.hxx:99
#define h(i)
Definition RSha256.hxx:106
#define e(i)
Definition RSha256.hxx:103
cudaEvent_t event
short Style_t
Style number (short)
Definition RtypesCore.h:97
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:60
short Color_t
Color number (short)
Definition RtypesCore.h:100
unsigned int UInt_t
Unsigned integer 4 bytes (unsigned int)
Definition RtypesCore.h:61
short Width_t
Line width (short)
Definition RtypesCore.h:99
float Float_t
Float 4 bytes (float)
Definition RtypesCore.h:72
short Short_t
Signed Short integer 2 bytes (short)
Definition RtypesCore.h:54
constexpr Bool_t kFALSE
Definition RtypesCore.h:109
double Double_t
Double 8 bytes.
Definition RtypesCore.h:74
constexpr Bool_t kTRUE
Definition RtypesCore.h:108
const char Option_t
Option string (const char)
Definition RtypesCore.h:81
#define BIT(n)
Definition Rtypes.h:90
@ kBlack
Definition Rtypes.h:65
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
R__EXTERN TEnv * gEnv
Definition TEnv.h:126
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t option
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void pixel
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t wmin
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t np
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize id
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char cname
Option_t Option_t TPoint TPoint const char x2
Option_t Option_t TPoint TPoint const char x1
Option_t Option_t TPoint TPoint angle
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void xpos
Option_t Option_t TPoint TPoint const char mode
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char backcolor
Option_t Option_t TPoint TPoint const char y2
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void ypos
Option_t Option_t width
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize fs
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t wmax
Option_t Option_t TPoint TPoint const char text
Option_t Option_t TPoint TPoint const char y1
char name[80]
Definition TGX11.cxx:142
R__EXTERN TH1 * gCurrentHist
R__EXTERN Hoption_t Hoption
float xmin
int ncx
float ymin
int ncy
float xmax
float ymax
static TString gStringStdDevZ
static TString gStringStdDevX
static TString gStringIntegralBinWidth
const UInt_t kCannotRotate
static TString gStringStdDev
const Int_t kNMAX
Hparam_t Hparam
const Int_t kMAXCONTOUR
static TString gStringOverflow
static TString gStringUnderflow
static TString gStringSkewnessY
static TString gStringMean
static TString gStringKurtosis
Hoption_t Hoption
static TString gStringMeanX
static TString gStringEntries
static TString gStringIntegral
static TString gStringKurtosisY
static TString gStringStdDevY
static TString gStringMeanY
static TString gStringSkewnessX
static TString gStringKurtosisX
static std::unique_ptr< TBox > gXHighlightBox
static std::unique_ptr< TBox > gYHighlightBox
static TString gStringSkewnessZ
TH1 * gCurrentHist
static TString gStringMeanZ
static TString gStringSkewness
static TString gStringKurtosisZ
const Int_t kMaxCuts
const Int_t kCYLINDRICAL
const Int_t kSPHERICAL
const Int_t kRAPIDITY
#define gROOT
Definition TROOT.h:417
R__EXTERN TStyle * gStyle
Definition TStyle.h:442
R__EXTERN TSystem * gSystem
Definition TSystem.h:582
const Int_t kCARTESIAN
Definition TView3D.cxx:32
const Int_t kPOLAR
Definition TView3D.cxx:33
#define gPad
Draw all kinds of Arrows.
Definition TArrow.h:29
virtual Int_t GetNdivisions() const
Definition TAttAxis.h:37
virtual Float_t GetLabelOffset() const
Definition TAttAxis.h:41
virtual Float_t GetLabelSize() const
Definition TAttAxis.h:42
virtual Float_t GetTickLength() const
Definition TAttAxis.h:46
virtual Float_t GetTitleOffset() const
Definition TAttAxis.h:44
virtual Color_t GetFillColor() const
Return the fill area color.
Definition TAttFill.h:32
virtual Style_t GetFillStyle() const
Return the fill area style.
Definition TAttFill.h:33
virtual void SetFillColor(Color_t fcolor)
Set the fill area color.
Definition TAttFill.h:40
virtual void SetFillStyle(Style_t fstyle)
Set the fill area style.
Definition TAttFill.h:42
virtual Color_t GetLineColor() const
Return the line color.
Definition TAttLine.h:36
virtual void SetLineStyle(Style_t lstyle)
Set the line style.
Definition TAttLine.h:46
virtual Width_t GetLineWidth() const
Return the line width.
Definition TAttLine.h:38
virtual void SetLineWidth(Width_t lwidth)
Set the line width.
Definition TAttLine.h:47
virtual void SetLineColor(Color_t lcolor)
Set the line color.
Definition TAttLine.h:44
virtual Style_t GetLineStyle() const
Return the line style.
Definition TAttLine.h:37
virtual Style_t GetMarkerStyle() const
Return the marker style.
Definition TAttMarker.h:35
virtual Color_t GetMarkerColor() const
Return the marker color.
Definition TAttMarker.h:34
virtual Size_t GetMarkerSize() const
Return the marker size.
Definition TAttMarker.h:36
virtual void SetMarkerStyle(Style_t mstyle=1)
Set the marker style.
virtual void SetMarkerSize(Size_t msize=1)
Set the marker size.
virtual void SetMarkerColor(Color_t mcolor=1)
Set the marker color.
static Style_t GetMarkerStyleBase(Style_t style)
Internal helper function that returns the corresponding marker style with line width 1 for the given ...
virtual void SetTextAlign(Short_t align=11)
Set the text alignment.
Definition TAttText.h:48
virtual Font_t GetTextFont() const
Return the text font.
Definition TAttText.h:38
virtual void SetTextAngle(Float_t tangle=0)
Set the text angle.
Definition TAttText.h:49
virtual void SetTextColor(Color_t tcolor=1)
Set the text color.
Definition TAttText.h:50
virtual void SetTextFont(Font_t tfont=62)
Set the text font.
Definition TAttText.h:52
virtual void SetTextSize(Float_t tsize=1)
Set the text size.
Definition TAttText.h:53
Class to manage histogram axis.
Definition TAxis.h:32
virtual Bool_t GetTimeDisplay() const
Definition TAxis.h:133
Bool_t IsAlphanumeric() const
Definition TAxis.h:90
const char * GetTitle() const override
Returns title of object.
Definition TAxis.h:137
virtual Double_t GetBinCenter(Int_t bin) const
Return center of bin.
Definition TAxis.cxx:482
Bool_t CanExtend() const
Definition TAxis.h:88
const TArrayD * GetXbins() const
Definition TAxis.h:138
Double_t GetXmax() const
Definition TAxis.h:142
@ kAxisRange
Definition TAxis.h:66
const char * GetBinLabel(Int_t bin) const
Return label for bin.
Definition TAxis.cxx:444
virtual Int_t FindBin(Double_t x)
Find bin number corresponding to abscissa x.
Definition TAxis.cxx:293
virtual Double_t GetBinLowEdge(Int_t bin) const
Return low edge of bin.
Definition TAxis.cxx:522
virtual Int_t FindFixBin(Double_t x) const
Find bin number corresponding to abscissa x
Definition TAxis.cxx:422
const char * ChooseTimeFormat(Double_t axislength=0)
Choose a reasonable time format from the coordinates in the active pad and the number of divisions in...
Definition TAxis.cxx:127
Int_t GetLast() const
Return last bin on the axis i.e.
Definition TAxis.cxx:473
virtual const char * GetTimeFormatOnly() const
Return only the time format from the string fTimeFormat.
Definition TAxis.cxx:604
Double_t GetXmin() const
Definition TAxis.h:141
Int_t GetNbins() const
Definition TAxis.h:127
virtual void SetRangeUser(Double_t ufirst, Double_t ulast)
Set the viewing range for the axis from ufirst to ulast (in user coordinates, that is,...
Definition TAxis.cxx:1090
virtual const char * GetTimeFormat() const
Definition TAxis.h:134
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width.
Definition TAxis.cxx:546
virtual Double_t GetBinUpEdge(Int_t bin) const
Return up edge of bin.
Definition TAxis.cxx:532
Int_t GetFirst() const
Return first bin on the axis i.e.
Definition TAxis.cxx:462
THashList * GetLabels() const
Definition TAxis.h:123
Create a Box.
Definition TBox.h:22
The candle plot painter class.
Definition TCandle.h:27
CandleOption
Definition TCandle.h:30
static Bool_t SupportAlpha()
Static function returning "true" if transparency is supported.
Definition TCanvas.cxx:2505
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition TClass.cxx:2999
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
The color creation and management class.
Definition TColor.h:22
static void RGBtoHLS(Float_t r, Float_t g, Float_t b, Float_t &h, Float_t &l, Float_t &s)
Definition TColor.h:83
static Int_t GetColor(const char *hexcolor)
Static method returning color number for color specified by hex color string of form: "#rrggbb",...
Definition TColor.cxx:1939
static Int_t GetColorBright(Int_t color)
Static function: Returns the bright color number corresponding to n If the TColor object does not exi...
Definition TColor.cxx:2108
static Int_t GetColorDark(Int_t color)
Static function: Returns the dark color number corresponding to n If the TColor object does not exist...
Definition TColor.cxx:2151
static void HLStoRGB(Float_t h, Float_t l, Float_t s, Float_t &r, Float_t &g, Float_t &b)
Definition TColor.h:78
To draw a Crown.
Definition TCrown.h:19
Graphical cut class.
Definition TCutG.h:20
static TClass * Class()
TDirectory::TContext keeps track and restore the current directory.
Definition TDirectory.h:89
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition TEnv.cxx:511
1-Dim function class
Definition TF1.h:182
virtual Double_t GetXmax() const
Definition TF1.h:525
virtual Int_t GetNDF() const
Return the number of degrees of freedom in the fit the fNDF parameter has been previously computed du...
Definition TF1.cxx:1940
virtual void GetParLimits(Int_t ipar, Double_t &parmin, Double_t &parmax) const
Return limits for parameter ipar.
Definition TF1.cxx:1991
virtual Double_t GetParError(Int_t ipar) const
Return value of parameter number ipar.
Definition TF1.cxx:1981
static TClass * Class()
Double_t GetChisquare() const
Return the Chisquare after fitting. See ROOT::Fit::FitResult::Chi2()
Definition TF1.h:409
virtual void SetMaximum(Double_t maximum=-1111)
Set the maximum value along Y for this function In case the function is already drawn,...
Definition TF1.cxx:3450
virtual Double_t GetMaximumStored() const
Definition TF1.h:438
virtual Int_t GetNpar() const
Definition TF1.h:446
virtual Int_t GetNumberFreeParameters() const
Return the number of free parameters.
Definition TF1.cxx:1951
@ kNotDraw
Definition TF1.h:297
virtual void SetMinimum(Double_t minimum=-1111)
Set the minimum value along Y for this function In case the function is already drawn,...
Definition TF1.cxx:3463
virtual const char * GetParName(Int_t ipar) const
Definition TF1.h:494
virtual Double_t Eval(Double_t x, Double_t y=0, Double_t z=0, Double_t t=0) const
Evaluate this function.
Definition TF1.cxx:1447
virtual Double_t GetXmin() const
Definition TF1.h:521
virtual Double_t GetParameter(Int_t ipar) const
Definition TF1.h:477
A 2-Dim function with parameters.
Definition TF2.h:29
void Paint(Option_t *option="") override
Paint this 2-D function with its current attributes.
Definition TF2.cxx:806
void SetRange(Double_t xmin, Double_t xmax) override
Initialize the upper and lower bounds to draw the function.
Definition TF2.h:133
static TClass * Class()
TF3 defines a 3D Function with Parameters.
Definition TF3.h:28
The axis painter class.
Definition TGaxis.h:26
void SetTimeFormat(const char *tformat)
Change the format used for time plotting.
Definition TGaxis.cxx:2937
virtual void PaintAxis(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax, Double_t &wmin, Double_t &wmax, Int_t &ndiv, Option_t *chopt="", Double_t gridlength=0, Bool_t drawGridOnly=kFALSE)
Control function to draw an axis.
Definition TGaxis.cxx:1006
void SetTitleOffset(Float_t titleoffset=1)
Definition TGaxis.h:130
virtual void SetTitle(const char *title="")
Change the title of the axis.
Definition TGaxis.cxx:2910
void SetLabelOffset(Float_t labeloffset)
Definition TGaxis.h:108
virtual void ImportAxisAttributes(TAxis *axis)
Internal method to import TAxis attributes to this TGaxis.
Definition TGaxis.cxx:953
void SetTickSize(Float_t ticksize)
Definition TGaxis.h:124
void SetLabelSize(Float_t labelsize)
Definition TGaxis.h:109
void SetOption(Option_t *option="")
To set axis options.
Definition TGaxis.cxx:2902
Graphics object made of three arrays X, Y and Z with the same number of points each.
Definition TGraph2D.h:41
static TClass * Class()
TGraphDelaunay2D generates a Delaunay triangulation of a TGraph2D.
TGraphDelaunay generates a Delaunay triangulation of a TGraph2D.
A TGraph is an object made of two arrays X and Y with npoints each.
Definition TGraph.h:41
static TClass * Class()
@ kClipFrame
Clip to the frame boundary.
Definition TGraph.h:75
void PaintGraph(Int_t npoints, const Double_t *x, const Double_t *y, Option_t *chopt)
Draw the (x,y) as a graph.
Definition TGraph.cxx:2015
void PaintGrapHist(Int_t npoints, const Double_t *x, const Double_t *y, Option_t *chopt)
Draw the (x,y) as a histogram.
Definition TGraph.cxx:2024
1-D histogram with a double per channel (see TH1 documentation)
Definition TH1.h:926
1-D histogram with a float per channel (see TH1 documentation)
Definition TH1.h:878
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:109
TAxis * GetZaxis()
Definition TH1.h:573
virtual EBinErrorOpt GetBinErrorOption() const
Definition TH1.h:517
virtual Float_t GetBarWidth() const
Definition TH1.h:501
virtual Double_t GetMinimumStored() const
Definition TH1.h:537
virtual Float_t GetBarOffset() const
Definition TH1.h:500
static TClass * Class()
virtual Double_t GetStdDev(Int_t axis=1) const
Returns the Standard Deviation (Sigma).
Definition TH1.cxx:7816
virtual Int_t GetNbinsY() const
Definition TH1.h:542
virtual Double_t GetBinError(Int_t bin) const
Return value of error associated to bin number bin.
Definition TH1.cxx:9293
virtual Int_t GetNbinsZ() const
Definition TH1.h:543
virtual Double_t GetNormFactor() const
Definition TH1.h:545
virtual Double_t GetMean(Int_t axis=1) const
For axis = 1,2 or 3 returns the mean value of the histogram along X,Y or Z axis.
Definition TH1.cxx:7744
virtual Double_t GetSkewness(Int_t axis=1) const
Definition TH1.cxx:7880
virtual Double_t GetContourLevelPad(Int_t level) const
Return the value of contour number "level" in Pad coordinates.
Definition TH1.cxx:8669
virtual Int_t GetDimension() const
Definition TH1.h:527
@ kNoTitle
Don't draw the histogram title.
Definition TH1.h:408
@ kUserContour
User specified contour levels.
Definition TH1.h:404
@ kNoStats
Don't draw stats box.
Definition TH1.h:403
TAxis * GetXaxis()
Definition TH1.h:571
virtual Double_t GetSumOfWeights() const
Return the sum of weights across all bins excluding under/overflows.
Definition TH1.h:559
virtual Int_t GetBin(Int_t binx, Int_t biny=0, Int_t binz=0) const
Return Global bin number corresponding to binx,y,z.
Definition TH1.cxx:5137
virtual Double_t GetMaximum(Double_t maxval=FLT_MAX) const
Return maximum value smaller than maxval of bins in the range, unless the value has been overridden b...
Definition TH1.cxx:8778
virtual Int_t GetNbinsX() const
Definition TH1.h:541
virtual void SetMaximum(Double_t maximum=-1111)
Definition TH1.h:652
TAxis * GetYaxis()
Definition TH1.h:572
virtual Double_t GetBinErrorLow(Int_t bin) const
Return lower error associated to bin number bin.
Definition TH1.cxx:9309
virtual void SetMinimum(Double_t minimum=-1111)
Definition TH1.h:653
virtual Double_t Integral(Option_t *option="") const
Return integral of bin contents.
Definition TH1.cxx:8170
virtual void SetBinContent(Int_t bin, Double_t content)
Set bin content see convention for numbering bins in TH1::GetBin In case the bin number is greater th...
Definition TH1.cxx:9452
virtual Double_t GetBinLowEdge(Int_t bin) const
Return bin lower edge for 1D histogram.
Definition TH1.cxx:9382
virtual Double_t GetEntries() const
Return the current number of entries.
Definition TH1.cxx:4574
TList * GetListOfFunctions() const
Definition TH1.h:488
virtual Double_t GetMeanError(Int_t axis=1) const
Return standard error of mean of this histogram along the X axis.
Definition TH1.cxx:7784
virtual Double_t GetMaximumStored() const
Definition TH1.h:533
virtual void GetMinimumAndMaximum(Double_t &min, Double_t &max) const
Retrieve the minimum and maximum values in the histogram.
Definition TH1.cxx:8964
virtual Int_t GetMaximumBin() const
Return location of bin with maximum value in the range.
Definition TH1.cxx:8810
@ kNormal
Errors with Normal (Wald) approximation: errorUp=errorLow= sqrt(N)
Definition TH1.h:115
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition TH1.cxx:5239
virtual Int_t GetContour(Double_t *levels=nullptr)
Return contour values into array levels if pointer levels is non zero.
Definition TH1.cxx:8640
const Double_t * GetBuffer() const
Definition TH1.h:483
virtual Bool_t IsHighlight() const
Definition TH1.h:585
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width for 1D histogram.
Definition TH1.cxx:9393
virtual void SetContour(Int_t nlevels, const Double_t *levels=nullptr)
Set the number and values of contour levels.
Definition TH1.cxx:8716
virtual Double_t GetBinErrorUp(Int_t bin) const
Return upper error associated to bin number bin.
Definition TH1.cxx:9340
virtual Int_t GetSumw2N() const
Definition TH1.h:562
virtual Double_t GetStdDevError(Int_t axis=1) const
Return error of standard deviation estimation for Normal distribution.
Definition TH1.cxx:7864
virtual Double_t GetMinimum(Double_t minval=-FLT_MAX) const
Return minimum value larger than minval of bins in the range, unless the value has been overridden by...
Definition TH1.cxx:8868
virtual void LabelsDeflate(Option_t *axis="X")
Reduce the number of bins for the axis passed in the option to the number of bins having a label.
Definition TH1.cxx:5423
virtual Int_t BufferEmpty(Int_t action=0)
Fill histogram with all entries in the buffer.
Definition TH1.cxx:1445
virtual Double_t GetKurtosis(Int_t axis=1) const
Definition TH1.cxx:7953
2-D histogram with a double per channel (see TH1 documentation)
Definition TH2.h:400
2-D histogram with a float per channel (see TH1 documentation)
Definition TH2.h:345
Helper class to represent a bin in the TH2Poly histogram.
Definition TH2Poly.h:25
2D Histogram with Polygonal Bins
Definition TH2Poly.h:66
static TClass * Class()
Service class for 2-D histogram classes.
Definition TH2.h:30
TH1D * ProjectionY(const char *name="_py", Int_t firstxbin=0, Int_t lastxbin=-1, Option_t *option="") const
Project a 2-D histogram into a 1-D histogram along Y (integration along X).
Definition TH2.cxx:2444
TH1D * ProjectionX(const char *name="_px", Int_t firstybin=0, Int_t lastybin=-1, Option_t *option="") const
Project a 2-D histogram into a 1-D histogram along X (integration along Y).
Definition TH2.cxx:2401
Double_t GetBinContent(Int_t binx, Int_t biny) const override
Definition TH2.h:97
static TClass * Class()
Double_t Integral(Option_t *option="") const override
Return integral of bin contents.
Definition TH2.cxx:1293
The 3-D histogram classes derived from the 1-D histogram classes.
Definition TH3.h:45
static TClass * Class()
The Histogram stack class.
Definition THStack.h:40
static TClass * Class()
The histogram painter class.
static Int_t ProjectSinusoidal2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function code for sinusoidal projection from Ernst-Jan Buis Source https://en....
void Paint(Option_t *option="") override
Control routine to paint any kind of histograms
TAxis * fYaxis
Pointer to Y axis.
std::unique_ptr< TPainter3dAlgorithms > fLego
Pointer to a TPainter3dAlgorithms object.
std::vector< Double_t > fXbuf
X buffer coordinates.
Int_t fXHighlightBin
X highlight bin.
TF3 * fCurrentF3
Current TF3 function.
virtual void PaintErrors(Option_t *option)
Draw 1D histograms error bars.
~THistPainter() override
destructor.
Int_t fShowProjection2
True if a second projection must be drawn (when calling SetShowProjectionXY on a TH2)
virtual void PaintTF3()
Control function to draw a 3D implicit functions.
virtual Int_t TableInit()
Initialize various options to draw 2D histograms.
virtual void PaintTH2PolyScatterPlot(Option_t *option)
Control function to draw a TH2Poly as a scatter plot.
static Int_t ProjectMollweide2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
static Int_t ProjectAitoff2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
virtual void PaintText(Option_t *option)
Control function to draw a 1D/2D histograms with the bin values.
Int_t DistancetoPrimitive(Int_t px, Int_t py) override
Compute the distance from the point px,py to a line.
virtual void PaintAxis(Bool_t drawGridOnly=kFALSE)
Draw axis (2D case) of an histogram.
virtual void PaintColorLevelsFast(Option_t *option)
[Rendering scheme for the COL2 and COLZ2 options] (HP14)
virtual Int_t PaintInit()
Compute histogram parameters used by the drawing routines.
virtual void Paint2DErrors(Option_t *option)
Draw 2D histograms errors.
Int_t fYHighlightBin
Y highlight bin.
virtual void PaintCandlePlot(Option_t *option)
Control function to draw a 2D histogram as a candle (box) plot or violin plot
virtual void PaintScatterPlot(Option_t *option)
Control function to draw a 2D histogram as a scatter plot.
void SetShowProjectionXY(const char *option, Int_t nbinsY, Int_t nbinsX) override
Set projection XY.
virtual void PaintLego(Option_t *option)
Control function to draw a 2D histogram as a lego plot.
virtual void PaintH3(Option_t *option="")
Control function to draw a 3D histograms.
Int_t fNcuts
Number of graphical cuts.
TString fShowOption
Option to draw the projection.
virtual void PaintHighlightBin(Option_t *option="")
Paint highlight bin as TBox object.
virtual void PaintTH2PolyBins(Option_t *option)
Control function to draw a TH2Poly bins' contours.
virtual Int_t PaintContourLine(Double_t elev1, Int_t icont1, Double_t x1, Double_t y1, Double_t elev2, Int_t icont2, Double_t x2, Double_t y2, Double_t *xarr, Double_t *yarr, Int_t *itarr, Double_t *levels)
Fill the matrix xarr and yarr for Contour Plot.
Int_t DetectProjectionKind(Option_t *option)
Return projection kind from option string.
Int_t fShowProjection
True if a projection must be drawn.
virtual void PaintLegoAxis(TGaxis *axis, Double_t ang)
Draw the axis for legos and surface plots.
virtual void PaintTriangles(Option_t *option)
Control function to draw a table using Delaunay triangles.
virtual void HighlightBin(Int_t px, Int_t py)
Check on highlight bin.
virtual void PaintH3Box(Int_t iopt)
Control function to draw a 3D histogram with boxes.
Int_t MakeCuts(char *cutsopt) override
Decode string choptin and fill Graphical cuts structure.
TList * fFunctions
Pointer to histogram list of functions.
void DrawPanel() override
Display a panel with all histogram drawing options.
std::unique_ptr< TPie > fPie
Pointer to a TPie in case of option PIE.
static void PaintSpecialObjects(const TObject *obj, Option_t *option)
Static function to paint special objects like vectors and matrices.
virtual void PaintTitle()
new TGaxis/////////////////// Draw the histogram title
virtual void PaintTH2PolyColorLevels(Option_t *option)
Control function to draw a TH2Poly as a color plot.
virtual std::vector< THistRenderingRegion > ComputeRenderingRegions(TAxis *pAxis, Int_t nPixels, bool isLog)
Returns the rendering regions for an axis to use in the COL2 option.
virtual void ShowProjectionX(Int_t px, Int_t py)
Show projection onto X.
virtual void PaintPalette()
Paint the color palette on the right side of the pad.
TAxis * fXaxis
Pointer to X axis.
virtual void PaintStat2(Int_t dostat, TF1 *fit)
Draw the statistics box for 2D histograms.
virtual void PaintArrows(Option_t *option)
Control function to draw a table as an arrow plot
virtual void RecalculateRange()
Recompute the histogram range following graphics operations.
void PaintStat(Int_t dostat, TF1 *fit) override
Draw the statistics box for 1D and profile histograms.
static Int_t ProjectParabolic2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function code for parabolic projection from Ernst-Jan Buis.
std::unique_ptr< TGraph2DPainter > fGraph2DPainter
Pointer to a TGraph2DPainter object.
virtual void PaintBarH(Option_t *option)
Draw a bar char in a rotated pad (X vertical, Y horizontal)
virtual void PaintStat3(Int_t dostat, TF1 *fit)
Draw the statistics box for 3D histograms.
virtual void PaintSurface(Option_t *option)
Control function to draw a 2D histogram as a surface plot.
TList * fStack
Pointer to stack of histograms (if any)
THistPainter()
Default constructor.
TH1 * fH
Pointer to histogram to paint.
virtual void PaintTH2PolyText(Option_t *option)
Control function to draw a TH2Poly as a text plot.
virtual void ShowProjection3(Int_t px, Int_t py)
Show projection (specified by fShowProjection) of a TH3.
TAxis * fZaxis
Pointer to Z axis.
void SetHistogram(TH1 *h) override
Set current histogram to h
virtual void PaintFunction(Option_t *option)
[Paint functions associated to an histogram.](HP28")
virtual void PaintBar(Option_t *option)
Draw a bar-chart in a normal pad.
static Int_t ProjectMercator2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
virtual void PaintBoxes(Option_t *option)
Control function to draw a 2D histogram as a box plot
virtual Int_t MakeChopt(Option_t *option)
Decode string choptin and fill Hoption structure.
char * GetObjectInfo(Int_t px, Int_t py) const override
Display the histogram info (bin number, contents, integral up to bin corresponding to cursor position...
TList * GetContourList(Double_t contour) const override
Get a contour (as a list of TGraphs) using the Delaunay triangulation.
void ProcessMessage(const char *mess, const TObject *obj) override
Process message mess.
void SetShowProjection(const char *option, Int_t nbins) override
Set projection.
virtual void ShowProjectionY(Int_t px, Int_t py)
Show projection onto Y.
static const char * GetBestFormat(Double_t v, Double_t e, const char *f)
This function returns the best format to print the error value (e) knowing the parameter value (v) an...
virtual void PaintContour(Option_t *option)
Control function to draw a 2D histogram as a contour plot.
TCutG * fCuts[kMaxCuts]
Pointers to graphical cuts.
virtual void PaintTable(Option_t *option)
Control function to draw 2D/3D histograms (tables).
void ExecuteEvent(Int_t event, Int_t px, Int_t py) override
Execute the actions corresponding to event.
virtual Int_t PaintInitH()
Compute histogram parameters used by the drawing routines for a rotated pad.
virtual void PaintFrame()
Calculate range and clear pad (canvas).
Int_t fCutsOpt[kMaxCuts]
Sign of each cut.
virtual void PaintH3Iso()
Control function to draw a 3D histogram with Iso Surfaces.
std::vector< Double_t > fYbuf
Y buffer coordinates.
virtual void PaintH3BoxRaster()
Control function to draw a 3D histogram with boxes.
virtual void PaintHist(Option_t *option)
Control routine to draw 1D histograms
void SetHighlight() override
Set highlight (enable/disable) mode for fH.
virtual void DefineColorLevels(Int_t ndivz)
Define the color levels used to paint legos, surfaces etc..
TString fObjectInfo
virtual void PaintColorLevels(Option_t *option)
Control function to draw a 2D histogram as a color plot.
Bool_t IsInside(Int_t x, Int_t y) override
Return kTRUE if the cell ix, iy is inside one of the graphical cuts.
A class to define a conversion from pixel values to pixel color.
Definition TAttImage.h:33
static TImagePalette * CreateCOLPalette(Int_t nContours)
Factory method to creates an image palette for histogram plotting.
An abstract interface to image processing library.
Definition TImage.h:29
static TImage * Create()
Create an image.
Definition TImage.cxx:34
void Reset()
To draw Mathematical Formula.
Definition TLatex.h:20
A doubly linked list.
Definition TList.h:38
TObject * FindObject(const char *name) const override
Find an object in this list using its name.
Definition TList.cxx:708
void Add(TObject *obj) override
Definition TList.h:81
TObject * Remove(TObject *obj) override
Remove object from the list.
Definition TList.cxx:952
TObject * First() const override
Return the first object in the list. Returns 0 when list is empty.
Definition TList.cxx:789
virtual TObjLink * FirstLink() const
Definition TList.h:107
TObject * At(Int_t idx) const override
Returns the object at position idx. Returns 0 if idx is out of range.
Definition TList.cxx:487
void AddFirst(TObject *obj) override
Add object at the beginning of the list.
Definition TList.cxx:97
TMatrixTBase.
static TClass * Class()
A TMultiGraph is a collection of TGraph (or derived) objects.
Definition TMultiGraph.h:34
TList * GetListOfGraphs() const
Definition TMultiGraph.h:70
static TClass * Class()
virtual Int_t IsInside(Double_t x, Double_t y) const
Return 1 if the point (x,y) is inside one of the graphs 0 otherwise.
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:50
An array of TObjects.
Definition TObjArray.h:31
Mother of all ROOT objects.
Definition TObject.h:42
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:461
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:204
virtual Option_t * GetDrawOption() const
Get option used by the graphics system to draw this object.
Definition TObject.cxx:444
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1082
virtual TObject * FindObject(const char *name) const
Must be redefined in derived classes.
Definition TObject.cxx:424
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:886
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:548
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1096
virtual const char * GetTitle() const
Returns title of object.
Definition TObject.cxx:506
void ResetBit(UInt_t f)
Definition TObject.h:203
@ kCannotPick
if object in a pad cannot be picked
Definition TObject.h:76
@ kCanDelete
if object in a list can be deleted
Definition TObject.h:71
@ kMustCleanup
if object destructor must call RecursiveRemove()
Definition TObject.h:73
void DrawFaceMove3(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 3rd variant for "MOVING SCREEN" algorithm (draw level lines only)
void DrawLevelLines(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw level lines without hidden line removal.
void SurfaceFunction(Int_t ia, Int_t ib, Double_t *f, Double_t *t)
Service function for Surfaces.
void DrawFaceMode1(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *t)
Draw face - 1st variant (2 colors: 1st for external surface, 2nd for internal)
void GouraudFunction(Int_t ia, Int_t ib, Double_t *f, Double_t *t)
Find part of surface with luminosity in the corners.
void DrawFaceMove1(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 1st variant for "MOVING SCREEN" algorithm (draw face with level lines)
void DrawFaceRaster2(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 2nd variant for "RASTER SCREEN" algorithm (draw face for stacked lego plot)
void LegoFunction(Int_t ia, Int_t ib, Int_t &nv, Double_t *ab, Double_t *vv, Double_t *t)
Service function for Legos.
void DrawFaceMove2(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 2nd variant for "MOVING SCREEN" algorithm (draw face for stacked lego plot)
void DrawFaceRaster1(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 1st variant for "RASTER SCREEN" algorithm (draw face with level lines)
void DrawFaceMode3(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *t)
Draw face - 3rd option (draw face for stacked lego plot)
void DrawFaceMode2(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *t)
Draw face - 2nd option (fill in correspondence with function levels)
The palette painting class.
The histogram statistics painter class.
Definition TPaveStats.h:18
Int_t GetOptStat() const
Return the stat option.
virtual void SetStatFormat(const char *format="6.4g")
Change (i.e. set) the format for printing statistics.
void SetOptStat(Int_t stat=1)
Set the stat option.
virtual const char * GetFitFormat() const
Definition TPaveStats.h:35
virtual void SetFitFormat(const char *format="5.4g")
Change (i.e. set) the format for printing fit parameters in statistics box.
Int_t GetOptFit() const
Return the fit option.
void SetParent(TObject *obj) override
Definition TPaveStats.h:53
void SetOptFit(Int_t fit=1)
Set the fit option.
virtual const char * GetStatFormat() const
Definition TPaveStats.h:36
void Paint(Option_t *option="") override
Paint the pave stat.
static TClass * Class()
A Pave (see TPave) with text, lines or/and boxes inside.
Definition TPaveText.h:21
virtual TText * AddText(Double_t x1, Double_t y1, const char *label)
Add a new Text line to this pavetext at given coordinates.
static TClass * Class()
void Clear(Option_t *option="") override
Clear all lines in this pavetext.
virtual TText * GetLine(Int_t number) const
Get Pointer to line number in this pavetext.
const char * GetName() const override
Returns name of object.
Definition TPave.h:58
virtual void SetName(const char *name="")
Definition TPave.h:81
virtual void SetBorderSize(Int_t bordersize=4)
Sets the border size of the TPave box and shadow.
Definition TPave.h:79
Option_t * GetOption() const override
Definition TPave.h:59
Double_t GetX1NDC() const
Definition TPave.h:61
virtual void SetX2NDC(Double_t x2)
Definition TPave.h:85
Profile2D histograms are used to display the mean value of Z and its error for each cell in X,...
Definition TProfile2D.h:27
static TClass * Class()
Profile Histogram.
Definition TProfile.h:32
static TClass * Class()
Random number generator class based on the maximally equidistributed combined Tausworthe generator by...
Definition TRandom2.h:27
Sequenceable collection abstract base class.
Basic string class.
Definition TString.h:137
void ToLower()
Change string to lower-case.
Definition TString.cxx:1190
const char * Data() const
Definition TString.h:385
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition TString.h:633
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2460
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2438
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:642
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:661
Int_t GetOptStat() const
Definition TStyle.h:247
Color_t GetStatTextColor() const
Definition TStyle.h:260
Float_t GetTitleX() const
Definition TStyle.h:282
Int_t GetOptTitle() const
Definition TStyle.h:248
Float_t GetStatFontSize() const
Definition TStyle.h:263
Float_t GetBarOffset() const
Definition TStyle.h:184
Float_t GetStatX() const
Definition TStyle.h:266
Float_t GetTitleSize(Option_t *axis="X") const
Return title size.
Definition TStyle.cxx:1241
Float_t GetTitleY() const
Definition TStyle.h:283
Style_t GetTitleFont(Option_t *axis="X") const
Return title font.
Definition TStyle.cxx:1217
Bool_t GetHistMinimumZero() const
Definition TStyle.h:239
Float_t GetStatY() const
Definition TStyle.h:267
Color_t GetTitleFillColor() const
Definition TStyle.h:273
Style_t GetTitleStyle() const
Definition TStyle.h:275
Color_t GetStatColor() const
Definition TStyle.h:259
Float_t GetBarWidth() const
Definition TStyle.h:185
void SetDrawBorder(Int_t drawborder=1)
Definition TStyle.h:346
Float_t GetStatH() const
Definition TStyle.h:269
Width_t GetTitleBorderSize() const
Definition TStyle.h:277
Int_t GetColorPalette(Int_t i) const
Return color number i in current palette.
Definition TStyle.cxx:1102
Float_t GetErrorX() const
Definition TStyle.h:188
Double_t GetHistTopMargin() const
Definition TStyle.h:240
void SetBarOffset(Float_t baroff=0.5)
Definition TStyle.h:339
Float_t GetEndErrorSize() const
Definition TStyle.h:187
Int_t GetDrawBorder() const
Definition TStyle.h:186
Width_t GetStatBorderSize() const
Definition TStyle.h:261
Color_t GetTitleTextColor() const
Definition TStyle.h:274
void SetBarWidth(Float_t barwidth=0.5)
Definition TStyle.h:340
Float_t GetTitleH() const
Definition TStyle.h:285
Style_t GetStatStyle() const
Definition TStyle.h:264
Float_t GetStatW() const
Definition TStyle.h:268
const char * GetFitFormat() const
Definition TStyle.h:201
const char * GetStatFormat() const
Definition TStyle.h:265
Int_t GetNumberOfColors() const
Return number of colors in the color palette.
Definition TStyle.cxx:1176
Int_t GetOptFit() const
Definition TStyle.h:246
Int_t GetNumberContours() const
Definition TStyle.h:243
const char * GetPaintTextFormat() const
Definition TStyle.h:252
Style_t GetStatFont() const
Definition TStyle.h:262
Float_t GetTitleFontSize() const
Definition TStyle.h:276
Int_t GetTitleAlign() const
Definition TStyle.h:272
Float_t GetTitleW() const
Definition TStyle.h:284
virtual int Load(const char *module, const char *entry="", Bool_t system=kFALSE)
Load a shared library.
Definition TSystem.cxx:1873
Base class for several text objects.
Definition TText.h:22
TVectorT.
Definition TVectorT.h:29
static TClass * Class()
See TView3D.
Definition TView.h:25
virtual Double_t GetPsi()=0
virtual Double_t * GetRmax()=0
virtual void SetAxisNDC(const Double_t *x1, const Double_t *x2, const Double_t *y1, const Double_t *y2, const Double_t *z1, const Double_t *z2)=0
virtual Double_t * GetRmin()=0
virtual void WCtoNDC(const Float_t *pw, Float_t *pn)=0
virtual void SetOutlineToCube()=0
virtual Int_t GetDistancetoAxis(Int_t axis, Int_t px, Int_t py, Double_t &ratio)=0
virtual Double_t * GetTnorm()=0
virtual void ExecuteRotateView(Int_t event, Int_t px, Int_t py)=0
virtual TSeqCollection * GetOutline()=0
virtual void PadRange(Int_t rback)=0
virtual void SetRange(const Double_t *min, const Double_t *max)=0
virtual void FindNormal(Double_t x, Double_t y, Double_t z, Double_t &zn)=0
virtual void AxisVertex(Double_t ang, Double_t *av, Int_t &ix1, Int_t &ix2, Int_t &iy1, Int_t &iy2, Int_t &iz1, Int_t &iz2)=0
virtual void SetView(Double_t longitude, Double_t latitude, Double_t psi, Int_t &irep)=0
Abstract base class used by ROOT graphics editor.
static TVirtualPadEditor * GetPadEditor(Bool_t load=kTRUE)
Returns the pad editor dialog. Static method.
small helper class to store/restore gPad context in TPad methods
Definition TVirtualPad.h:61
Helper class to store interactive parameters for individual objects Should be used via gPad->Interact...
Definition TVirtualPad.h:75
TVirtualPad is an abstract base class for the Pad and Canvas classes.
Definition TVirtualPad.h:51
virtual Double_t PadtoX(Double_t x) const =0
virtual void UpdateAsync()=0
virtual Double_t AbsPixeltoX(Double_t px)=0
virtual void PaintBox(Double_t x1, Double_t y1, Double_t x2, Double_t y2, Option_t *option="")=0
virtual Double_t PadtoY(Double_t y) const =0
virtual Double_t AbsPixeltoY(Double_t py)=0
virtual Bool_t OpaqueMoving() const =0
TZoomInteractive(TVirtualPad &parent, Int_t px, Int_t py)
void ChangeRange(TAxis *xaxis, TAxis *yaxis)
void MovePoint(TVirtualPad &parent, Int_t px, Int_t py)
TLine * line
void box(Int_t pat, Double_t x1, Double_t y1, Double_t x2, Double_t y2)
Definition fillpatterns.C:1
Double_t y[n]
Definition legend1.C:17
return c1
Definition legend1.C:41
Double_t x[n]
Definition legend1.C:17
Double_t ey[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
Double_t ex[n]
Definition legend1.C:17
TH1F * h1
Definition legend1.C:5
TF1 * f1
Definition legend1.C:11
return c2
Definition legend2.C:14
Int_t Nint(T x)
Round to nearest integer. Rounds half integers to the nearest even integer.
Definition TMath.h:706
Short_t Max(Short_t a, Short_t b)
Returns the largest of a and b.
Definition TMathBase.h:249
Double_t Prob(Double_t chi2, Int_t ndf)
Computation of the probability for a certain Chi-squared (chi2) and number of degrees of freedom (ndf...
Definition TMath.cxx:637
Double_t ATan(Double_t)
Returns the principal value of the arc tangent of x, expressed in radians.
Definition TMath.h:653
constexpr Double_t PiOver2()
Definition TMath.h:54
Double_t Log(Double_t x)
Returns the natural logarithm of x.
Definition TMath.h:769
constexpr Double_t DegToRad()
Conversion from degree to radian: .
Definition TMath.h:82
Double_t Sqrt(Double_t x)
Returns the square root of x.
Definition TMath.h:675
LongDouble_t Power(LongDouble_t x, LongDouble_t y)
Returns x raised to the power y.
Definition TMath.h:734
Short_t Min(Short_t a, Short_t b)
Returns the smallest of a and b.
Definition TMathBase.h:197
Double_t Cos(Double_t)
Returns the cosine of an angle of x radians.
Definition TMath.h:607
constexpr Double_t Pi()
Definition TMath.h:40
Bool_t AreEqualRel(Double_t af, Double_t bf, Double_t relPrec)
Comparing floating points.
Definition TMath.h:429
Double_t Sin(Double_t)
Returns the sine of an angle of x radians.
Definition TMath.h:601
Double_t Tan(Double_t)
Returns the tangent of an angle of x radians.
Definition TMath.h:613
Long64_t BinarySearch(Long64_t n, const T *array, T value)
Binary search in an array of n values to locate value.
Definition TMathBase.h:329
constexpr Double_t RadToDeg()
Conversion from radian to degree: .
Definition TMath.h:75
Double_t Log10(Double_t x)
Returns the common (base-10) logarithm of x.
Definition TMath.h:775
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:122
Histograms' drawing options structure.
Definition Hoption.h:27
int Curve
"C" A smooth Curve is drawn.
Definition Hoption.h:35
int Proj
"AITOFF", "MERCATOR", "SINUSOIDAL" and "PARABOLIC" projections for 2d plots.
Definition Hoption.h:63
int Axis
"A" Axis are not drawn around the graph.
Definition Hoption.h:33
int Box
"BOX" Draw 2D plot with proportional Boxes.
Definition Hoption.h:44
int Scat
"SCAT" Draw 2D plot a Scatter plot.
Definition Hoption.h:52
int Text
"TEXT" Draw 2D plot with the content of each cell.
Definition Hoption.h:54
int Color
"COL" Draw 2D plot with Colored boxes.
Definition Hoption.h:46
int AxisPos
"X+" and "Y+" Axis position
Definition Hoption.h:64
int List
"LIST" Generate the TObjArray "contours". To be used with option "CONT"
Definition Hoption.h:62
int Logx
log scale in X. Also set by histogram option
Definition Hoption.h:74
int Zscale
"Z" Display the color palette.
Definition Hoption.h:59
int MinimumZero
"MIN0" or gStyle->GetHistMinimumZero()
Definition Hoption.h:67
int Contour
"CONTn" Draw 2D plot as a Contour plot (0 <= n <= 5).
Definition Hoption.h:48
int Off
"][" The first and last vertical lines are not drawn.
Definition Hoption.h:38
int Func
"FUNC" Draw only the function (for example in case of fit).
Definition Hoption.h:49
long Candle
"CANDLE" and "VIOLIN" Draw a 2D histogram as candle/box plot or violin plot.
Definition Hoption.h:57
int Spec
"SPEC" TSpectrum graphics
Definition Hoption.h:65
int FrontBox
"FB" Suppress the front box for the 3D plots.
Definition Hoption.h:60
int Pie
"PIE" Draw 1D plot as a pie chart.
Definition Hoption.h:56
int Star
"*" With option "P", a * is plotted at each point.
Definition Hoption.h:42
int Zero
"0" if selected with any LEGO option the empty bins are not drawn.
Definition Hoption.h:66
int Logz
log scale in Z. Also set by histogram option
Definition Hoption.h:76
int Tri
"TRI" Draw TGraph2D with Delaunay triangles.
Definition Hoption.h:55
int BackBox
"BB" Suppress the back box for the 3D plots.
Definition Hoption.h:61
int Mark
"P" The current Marker is drawn at each point.
Definition Hoption.h:40
int Arrow
"ARR" Draw 2D plot with Arrows.
Definition Hoption.h:43
int Line
"L" A simple polyline through every point is drawn.
Definition Hoption.h:39
int Same
"SAME" Histogram is plotted in the current pad.
Definition Hoption.h:41
int Lego
"LEGO" and "LEGOn" Draw as a Lego plot(1 <= n <= 4).
Definition Hoption.h:51
int Bar
"B", "BAR" and "HBAR" A Bar chart is drawn at each point.
Definition Hoption.h:34
int Polar
"POL" Draw 2D plot with Polar coordinates.
Definition Hoption.h:47
int Fill
"F" A fill area is drawn ("CF" draw a smooth fill area).
Definition Hoption.h:37
int Hist
"HIST" Draw only the histogram.
Definition Hoption.h:50
int Surf
"SURF" and "SURFn" Draw as a Surface ((1 <= n <= 4).
Definition Hoption.h:53
int Logy
log scale in Y. Also set by histogram option
Definition Hoption.h:75
int System
"POL", "CYL", "SPH" and "PSR" Type of coordinate system for 3D plots.
Definition Hoption.h:58
int Error
"En" Draw Errors with current marker type and size (0 <= n <=6).
Definition Hoption.h:36
Histogram parameters structure.
Definition Hparam.h:31
Double_t baroffset
Offset of bin for bars or legos [0,1].
Definition Hparam.h:46
Double_t ylowedge
Low edge of axis.
Definition Hparam.h:37
Double_t xmin
Minimum value along X.
Definition Hparam.h:34
Int_t ylast
Last bin number along Y.
Definition Hparam.h:51
Int_t xfirst
First bin number along X.
Definition Hparam.h:48
Double_t zmin
Minimum value along Z.
Definition Hparam.h:42
Double_t xbinsize
Bin size in case of equidistant bins.
Definition Hparam.h:32
Double_t ymin
Minimum value along y.
Definition Hparam.h:38
Double_t allchan
Integrated sum of contents.
Definition Hparam.h:45
Double_t xlowedge
Low edge of axis.
Definition Hparam.h:33
Double_t ymax
Maximum value along y.
Definition Hparam.h:39
Double_t factor
Multiplication factor (normalization)
Definition Hparam.h:44
Int_t xlast
Last bin number along X.
Definition Hparam.h:49
Double_t ybinsize
Bin size in case of equidistant bins.
Definition Hparam.h:36
Double_t barwidth
Width of bin for bars and legos [0,1].
Definition Hparam.h:47
Double_t zmax
Maximum value along Z.
Definition Hparam.h:43
Double_t xmax
Maximum value along X.
Definition Hparam.h:35
Int_t yfirst
First bin number along Y.
Definition Hparam.h:50
auto * th2
Definition textalign.C:18
TMarker m
Definition textangle.C:8
TLine l
Definition textangle.C:4
auto * tt
Definition textangle.C:16