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#include "Hoption.h"
57#include "Hparam.h"
58#include "TPluginManager.h"
59#include "TPaletteAxis.h"
60#include "TCrown.h"
61#include "TArrow.h"
62#include "TVirtualPadPainter.h"
63#include "TVirtualPadEditor.h"
64#include "TEnv.h"
65#include "TPoint.h"
66#include "TImage.h"
67#include "TCandle.h"
68#include "strlcpy.h"
69
70/*! \class THistPainter
71 \ingroup Histpainter
72 \brief The histogram painter class. Implements all histograms' drawing's options.
73
74- [Introduction](\ref HP00)
75- [Histograms' plotting options](\ref HP01)
76 - [Options supported for 1D and 2D histograms](\ref HP01a)
77 - [Options supported for 1D histograms](\ref HP01b)
78 - [Options supported for 2D histograms](\ref HP01c)
79 - [Options supported for 3D histograms](\ref HP01d)
80 - [Options supported for histograms' stacks (THStack)](\ref HP01e)
81- [Setting the Style](\ref HP02)
82- [Setting line, fill, marker, and text attributes](\ref HP03)
83- [Setting Tick marks on the histogram axis](\ref HP04)
84- [Giving titles to the X, Y and Z axis](\ref HP05)
85- [The option SAME](\ref HP060)
86 - [Limitations](\ref HP060a)
87- [Colors automatically picked in palette](\ref HP061)
88- [Superimposing two histograms with different scales in the same pad](\ref HP06)
89- [Statistics Display](\ref HP07)
90- [Fit Statistics](\ref HP08)
91- [The error bars options](\ref HP09)
92- [The bar chart option](\ref HP100)
93- [The BAR and HBAR options](\ref HP10)
94- [The SCATter plot option (legacy draw option)](\ref HP11)
95- [The ARRow option](\ref HP12)
96- [The BOX option](\ref HP13)
97- [The COLor option (default for 2D and 3D histograms)](\ref HP14)
98- [The CANDLE and VIOLIN options](\ref HP140)
99 - [The CANDLE option](\ref HP140a)
100 - [The VIOLIN option](\ref HP140b)
101- [The TEXT and TEXTnn Option](\ref HP15)
102- [The CONTour options](\ref HP16)
103 - [The LIST option](\ref HP16a)
104 - [The AITOFF, MERCATOR, SINUSOIDAL and PARABOLIC options](\ref HP16b)
105- [The LEGO options](\ref HP17)
106- [The SURFace options](\ref HP18)
107- [Cylindrical, Polar, Spherical and PseudoRapidity/Phi options](\ref HP19)
108- [Base line for bar-charts and lego plots](\ref HP20)
109- [TH2Poly Drawing](\ref HP20a)
110- [The SPEC option](\ref HP21)
111- [Option Z : Adding the color palette on the right side of the pad](\ref HP22)
112- [Setting the color palette](\ref HP23)
113- [Drawing a sub-range of a 2-D histogram; the [cutg] option](\ref HP24)
114- [Drawing options for 3D histograms](\ref HP25)
115- [Drawing option for histograms' stacks](\ref HP26)
116- [Drawing of 3D implicit functions](\ref HP27)
117- [Associated functions drawing](\ref HP28)
118- [Drawing using OpenGL](\ref HP29)
119 - [General information: plot types and supported options](\ref HP29a)
120 - [TH3 as color boxes](\ref HP290)
121 - [TH3 as boxes (spheres)](\ref HP29b)
122 - [TH3 as iso-surface(s)](\ref HP29c)
123 - [TF3 (implicit function)](\ref HP29d)
124 - [Parametric surfaces](\ref HP29e)
125 - [Interaction with the plots](\ref HP29f)
126 - [Selectable parts](\ref HP29g)
127 - [Rotation and zooming](\ref HP29h)
128 - [Panning](\ref HP29i)
129 - [Box cut](\ref HP29j)
130 - [Plot specific interactions (dynamic slicing etc.)](\ref HP29k)
131 - [Surface with option GLSURF](\ref HP29l)
132 - [TF3](\ref HP29m)
133 - [Box](\ref HP29n)
134 - [Iso](\ref HP29o)
135 - [Parametric plot](\ref HP29p)
136- [Highlight mode for histogram](\ref HP30)
137 - [Highlight mode and user function](\ref HP30a)
138
139
140\anchor HP00
141## Introduction
142
143
144Histograms are drawn via the `THistPainter` class. Each histogram has a
145pointer to its own painter (to be usable in a multithreaded program). When the
146canvas has to be redrawn, the `Paint` function of each objects in the
147pad is called. In case of histograms, `TH1::Paint` invokes directly
148`THistPainter::Paint`.
149
150To draw a histogram `h` it is enough to do:
151
152 h->Draw();
153
154`h` can be of any kind: 1D, 2D or 3D. To choose how the histogram will
155be drawn, the `Draw()` method can be invoked with an option. For instance
156to draw a 2D histogram as a lego plot it is enough to do:
157
158 h->Draw("lego");
159
160`THistPainter` offers many options to paint 1D, 2D and 3D histograms.
161
162When the `Draw()` method of a histogram is called for the first time
163(`TH1::Draw`), it creates a `THistPainter` object and saves a
164pointer to this "painter" as a data member of the histogram. The
165`THistPainter` class specializes in the drawing of histograms. It is
166separated from the histogram so that one can have histograms without the
167graphics overhead, for example in a batch program. Each histogram having its own
168painter (rather than a central singleton painter painting all histograms), allows
169two histograms to be drawn in two threads without overwriting the painter's
170values.
171
172When a displayed histogram is filled again, there is no need to call the
173`Draw()` method again; the image will be refreshed the next time the
174pad will be updated.
175
176A pad is updated after one of these three actions:
177
1781. a carriage control on the ROOT command line,
1792. a click inside the pad,
1803. a call to `TPad::Update`.
181
182
183By default a call to `TH1::Draw()` clears the pad of all objects
184before drawing the new image of the histogram. One can use the `SAME`
185option to leave the previous display intact and superimpose the new histogram.
186The same histogram can be drawn with different graphics options in different
187pads.
188
189When a displayed histogram is deleted, its image is automatically removed
190from the pad.
191
192To create a copy of the histogram when drawing it, one can use
193`TH1::DrawClone()`. This will clone the histogram and allow to change
194and delete the original one without affecting the clone.
195
196
197\anchor HP01
198### Histograms' plotting options
199
200
201Most options can be concatenated with or without spaces or commas, for example:
202
203 h->Draw("E1 SAME");
204
205The options are not case sensitive:
206
207 h->Draw("e1 same");
208
209
210The default drawing option can be set with `TH1::SetOption` and retrieve
211using `TH1::GetOption`:
212
213 root [0] h->Draw(); // Draw "h" using the standard histogram representation.
214 root [1] h->Draw("E"); // Draw "h" using error bars
215 root [3] h->SetOption("E"); // Change the default drawing option for "h"
216 root [4] h->Draw(); // Draw "h" using error bars
217 root [5] h->GetOption(); // Retrieve the default drawing option for "h"
218 (const Option_t* 0xa3ff948)"E"
219
220
221\anchor HP01a
222#### Options supported for 1D and 2D histograms
223
224| Option | Description |
225|----------|-------------------------------------------------------------------|
226| "E" | Draw error bars. |
227| "AXIS" | Draw only axis. |
228| "AXIG" | Draw only grid (if the grid is requested). |
229| \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). |
230| "FUNC" | When an histogram has a fitted function, this option allows to draw the fit result only. |
231| "SAME" | Superimpose on previous picture in the same pad. |
232| "SAMES" | Same as "SAME" and draw the statistics box|
233| "PFC" | Palette Fill Color: histogram's fill color is taken in the current palette. |
234| "PLC" | Palette Line Color: histogram's line color is taken in the current palette. |
235| "PMC" | Palette Marker Color: histogram's marker color is taken in the current palette. |
236| "LEGO" | Draw a lego plot with hidden line removal. |
237| "LEGO1" | Draw a lego plot with hidden surface removal. |
238| "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.|
239| "LEGO3" | Draw a lego plot with hidden surface removal, like LEGO1 but the border lines of each lego-bar are not drawn.|
240| "LEGO4" | Draw a lego plot with hidden surface removal, like LEGO1 but without the shadow effect on each lego-bar.|
241| "TEXT" | Draw bin contents as text (format set via `gStyle->SetPaintTextFormat`).|
242| "TEXTnn" | Draw bin contents as text at angle nn (0 < nn <= 90). |
243| "X+" | The X-axis is drawn on the top side of the plot. |
244| "Y+" | The Y-axis is drawn on the right side of the plot. |
245| "MIN0" | Set minimum value for the Y axis to 0, equivalent to gStyle->SetHistMinimumZero(). |
246
247
248\anchor HP01b
249#### Options supported for 1D histograms
250
251| Option | Description |
252|----------|-------------------------------------------------------------------|
253| " " | Default. |
254| "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.|
255| "][" | When this option is selected the first and last vertical lines of the histogram are not drawn.|
256| "B" | Bar chart option.|
257| "BAR" | Like option "B", but bars can be drawn with a 3D effect.|
258| "HBAR" | Like option "BAR", but bars are drawn horizontally.|
259| "C" | Draw a smooth Curve through the histogram bins.|
260| "E0" | Draw error bars. Markers are drawn for bins with 0 contents. Combined with E1 or E2 it avoids error bars clipping|
261| "E1" | Draw error bars with perpendicular lines at the edges.|
262| "E2" | Draw error bars with rectangles.|
263| "E3" | Draw a fill area through the end points of the vertical error bars.|
264| "E4" | Draw a smoothed filled area through the end points of the error bars.|
265| "E5" | Like E3 but ignore the bins with 0 contents.|
266| "E6" | Like E4 but ignore the bins with 0 contents.|
267| "X0" | When used with one of the "E" option, it suppress the error bar along X as `gStyle->SetErrorX(0)` would do.|
268| "L" | Draw a line through the bin contents.|
269| "P" | Draw current marker at each bin except empty bins.|
270| "P*" | Draw a star marker at each bin except empty bins.|
271| "P0" | Draw current marker at each bin including empty bins.|
272| "PIE" | Draw histogram as a Pie Chart.|
273| "*H" | Draw histogram with a * at each bin.|
274| "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.|
275
276
277
278\anchor HP01c
279#### Options supported for 2D histograms
280
281| Option | Description |
282|--------------|------------------------------------------------------------------|
283| " " | Default (color plot).|
284| "ARR" | Arrow mode. Shows gradient between adjacent cells.|
285| "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. |
286| "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.|
287| "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).|
288| "COL1" | Same as "COL" but in case of histogram with negative content the empty bins are not drawn.
289| "COLZ" | Same as "COL". In addition the color palette is also drawn.|
290| "COL2" | Alternative rendering algorithm to "COL". Can significantly improve rendering performance for large, non-sparse 2-D histograms.|
291| "COLZ2" | Same as "COL2". In addition the color palette is also drawn.|
292| "Z CJUST" | In combination with colored options "COL","CONT0" etc: Justify labels in the color palette at color boundaries. For more details see `TPaletteAxis`|
293| "CANDLE" | Draw a candle plot along X axis.|
294| "CANDLEX" | Same as "CANDLE".|
295| "CANDLEY" | Draw a candle plot along Y axis.|
296| "CANDLEXn" | Draw a candle plot along X axis. Different candle-styles with n from 1 to 6.|
297| "CANDLEYn" | Draw a candle plot along Y axis. Different candle-styles with n from 1 to 6.|
298| "VIOLIN" | Draw a violin plot along X axis.|
299| "VIOLINX" | Same as "VIOLIN".|
300| "VIOLINY" | Draw a violin plot along Y axis.|
301| "VIOLINXn" | Draw a violin plot along X axis. Different violin-styles with n being 1 or 2.|
302| "VIOLINYn" | Draw a violin plot along Y axis. Different violin-styles with n being 1 or 2.|
303| "CONT" | Draw a contour plot (same as CONT0).|
304| "CONT0" | Draw a contour plot using surface colors to distinguish contours.|
305| "CONT1" | Draw a contour plot using line styles to distinguish contours.|
306| "CONT2" | Draw a contour plot using the same line style for all contours.|
307| "CONT3" | Draw a contour plot using fill area colors.|
308| "CONT4" | Draw a contour plot using surface colors (SURF option at theta = 0).|
309| "LIST" | Generate a list of TGraph objects for each contour.|
310| "SAME0" | Same as "SAME" but do not use the z-axis range of the first plot. |
311| "SAMES0" | Same as "SAMES" but do not use the z-axis range of the first plot. |
312| "CYL" | Use Cylindrical coordinates. The X coordinate is mapped on the angle and the Y coordinate on the cylinder length.|
313| "POL" | Use Polar coordinates. The visible X range mapped on the angle and the visible Y coordinate on the radius.|
314| "POLF" | Fixed Polar coordinates. The histogram X coordinate mapped on the angle and the Y coordinate on the radius.|
315| "POLN" | Natural Polar coordinates. The X coordinate directly represent angle in radian and the Y coordinate is the radius.|
316| "SPH" | Use Spherical coordinates. The X coordinate is mapped on the latitude and the Y coordinate on the longitude.|
317| "PSR" | Use PseudoRapidity/Phi coordinates. The X coordinate is mapped on Phi.|
318| "SURF" | Draw a surface plot with hidden line removal.|
319| "SURF1" | Draw a surface plot with hidden surface removal.|
320| "SURF2" | Draw a surface plot using colors to show the cell contents.|
321| "SURF3" | Same as SURF with in addition a contour view drawn on the top.|
322| "SURF4" | Draw a surface using Gouraud shading.|
323| "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.|
324| "AITOFF" | Draw a contour via an AITOFF projection.|
325| "MERCATOR" | Draw a contour via an Mercator projection.|
326| "SINUSOIDAL" | Draw a contour via an Sinusoidal projection.|
327| "PARABOLIC" | Draw a contour via an Parabolic projection.|
328| "MOLLWEIDE" | Draw a contour via an Mollweide projection.|
329| "LEGO9" | Draw the 3D axis only. Mainly needed for internal use |
330| "FB" | With LEGO or SURFACE, suppress the Front-Box.|
331| "BB" | With LEGO or SURFACE, suppress the Back-Box.|
332| "A" | With LEGO or SURFACE, suppress the axis.|
333| "SCAT" | Draw a scatter-plot (legacy draw option).|
334| "[cutg]" | Draw only the sub-range selected by the TCutG named "cutg".|
335
336
337
338\anchor HP01d
339#### Options supported for 3D histograms
340
341| Option | Description |
342|----------|-------------------------------------------------------------------|
343| " " | Default (color plot).|
344| "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)`.|
345| "BOX" | Draw a for each cell with volume proportional to the content's absolute value. An hidden line removal algorithm is used|
346| "BOX1" | Same as BOX but an hidden surface removal algorithm is used|
347| "BOX2" | The boxes' colors are picked in the current palette according to the bins' contents|
348| "BOX2Z" | Same as "BOX2". In addition the color palette is also drawn.|
349| "BOX3" | Same as BOX1, but the border lines of each lego-bar are not drawn.|
350| "LEGO" | Same as `BOX`.|
351
352\anchor HP01e
353#### Options supported for histograms' stacks (`THStack`)
354
355| Option | Description |
356|------------|-----------------------------------------------------------------|
357| " " | Default, the histograms are drawn on top of each other (as lego plots for 2D histograms).|
358| "NOSTACK" | Histograms in the stack are all paint in the same pad as if the option `SAME` had been specified.|
359| "NOSTACKB" | Histograms are drawn next to each other as bar charts.|
360| "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.|
361| "PADSn" | Like PADS but the current pad/canvas is subdivided into a `n` columns, automatically calculating the number of rows.|
362| "PFC" | Palette Fill Color: stack's fill color is taken in the current palette. |
363| "PLC" | Palette Line Color: stack's line color is taken in the current palette. |
364| "PMC" | Palette Marker Color: stack's marker color is taken in the current palette. |
365
366
367
368\anchor HP02
369### Setting the Style
370
371
372Histograms use the current style (`gStyle`). When one changes the current
373style and would like to propagate the changes to the histogram,
374`TH1::UseCurrentStyle` should be called. Call `UseCurrentStyle` on
375each histogram is needed.
376
377To force all the histogram to use the current style use:
378
379 gROOT->ForceStyle();
380
381All the histograms read after this call will use the current style.
382
383
384\anchor HP03
385### Setting line, fill, marker, and text attributes
386
387
388The histogram classes inherit from the attribute classes:
389`TAttLine`, `TAttFill` and `TAttMarker`.
390See the description of these classes for the list of options.
391
392
393\anchor HP04
394### Setting Tick marks on the histogram axis
395
396
397The `TPad::SetTicks` method specifies the type of tick marks on the axis.
398If ` tx = gPad->GetTickx()` and `ty = gPad->GetTicky()` then:
399
400 tx = 1; tick marks on top side are drawn (inside)
401 tx = 2; tick marks and labels on top side are drawn
402 ty = 1; tick marks on right side are drawn (inside)
403 ty = 2; tick marks and labels on right side are drawn
404
405By default only the left Y axis and X bottom axis are drawn
406(`tx = ty = 0`)
407
408`TPad::SetTicks(tx,ty)` allows to set these options.
409See also The `TAxis` functions to set specific axis attributes.
410
411In case multiple color filled histograms are drawn on the same pad, the fill
412area may hide the axis tick marks. One can force a redraw of the axis over all
413the histograms by calling:
414
415 gPad->RedrawAxis();
416
417
418\anchor HP05
419### Giving titles to the X, Y and Z axis
420
421
422 h->GetXaxis()->SetTitle("X axis title");
423 h->GetYaxis()->SetTitle("Y axis title");
424
425The histogram title and the axis titles can be any `TLatex` string.
426The titles are part of the persistent histogram.
427
428
429\anchor HP060
430### The option "SAME"
431
432
433By default, when an histogram is drawn, the current pad is cleared before
434drawing. In order to keep the previous drawing and draw on top of it the
435option `SAME` should be use. The histogram drawn with the option
436`SAME` uses the coordinates system available in the current pad.
437
438This option can be used alone or combined with any valid drawing option but
439some combinations must be use with care.
440
441\anchor HP060a
442#### Limitations
443
444- It does not work when combined with the `LEGO` and `SURF` options unless the
445 histogram plotted with the option `SAME` has exactly the same
446 ranges on the X, Y and Z axis as the currently drawn histogram. To superimpose
447 lego plots [histograms' stacks](\ref HP26) should be used.
448
449
450\anchor HP061
451### Colors automatically picked in palette
452
453\since **ROOT version 6.09/01**
454
455When several histograms are painted in the same canvas thanks to the option "SAME"
456or via a `THStack` it might be useful to have an easy and automatic way to choose
457their color. The simplest way is to pick colors in the current active color
458palette. Palette coloring for histogram is activated thanks to the options `PFC`
459(Palette Fill Color), `PLC` (Palette Line Color) and `PMC` (Palette Marker Color).
460When one of these options is given to `TH1::Draw` the histogram get its color
461from the current color palette defined by `gStyle->SetPalette(...)`. The color
462is determined according to the number of objects having palette coloring in
463the current pad.
464
465Begin_Macro(source)
466../../../tutorials/hist/hist005_TH1_palettecolor.C
467End_Macro
468
469Begin_Macro(source)
470../../../tutorials/hist/hist027_THStack_palette_color.C
471End_Macro
472
473Begin_Macro(source)
474../../../tutorials/hist/hist025_THStack_2d_palette_color.C
475End_Macro
476
477\anchor HP06
478### Superimposing two histograms with different scales in the same pad
479
480
481The following example creates two histograms, the second histogram is the bins
482integral of the first one. It shows a procedure to draw the two histograms in
483the same pad and it draws the scale of the second histogram using a new vertical
484axis on the right side. See also the tutorial `transpad.C` for a variant
485of this example.
486
487Begin_Macro(source)
488{
489 auto c1 = new TCanvas("c1","c1",600,400);
490 // create/fill draw h1
491 gStyle->SetOptStat(kFALSE);
492 auto h1 = new TH1F("h1","Superimposing two histograms with different scales",100,-3,3);
493 Int_t i;
494 for (i=0;i<10000;i++) h1->Fill(gRandom->Gaus(0,1));
495 h1->Draw();
496 c1->Update();
497
498 // create hint1 filled with the bins integral of h1
499 auto hint1 = new TH1F("hint1","h1 bins integral",100,-3,3);
500 float sum = 0.f;
501 for (i=1;i<=100;i++) {
502 sum += h1->GetBinContent(i);
503 hint1->SetBinContent(i,sum);
504 }
505
506 // scale hint1 to the pad coordinates
507 float rightmax = 1.1*hint1->GetMaximum();
508 float scale = gPad->GetUymax()/rightmax;
509 hint1->SetLineColor(kRed);
510 hint1->Scale(scale);
511 hint1->Draw("same");
512
513 // draw an axis on the right side
514 auto axis = new TGaxis(gPad->GetUxmax(),gPad->GetUymin(),
515 gPad->GetUxmax(), gPad->GetUymax(),0,rightmax,510,"+L");
516 axis->SetLineColor(kRed);
517 axis->SetTextColor(kRed);
518 axis->Draw();
519}
520End_Macro
521
522
523\anchor HP07
524### Statistics Display
525
526
527The type of information shown in the histogram statistics box can be selected
528with:
529
530 gStyle->SetOptStat(mode);
531
532The `mode` has up to nine digits that can be set to on (1 or 2), off (0).
533
534 mode = ksiourmen (default = 000001111)
535 k = 1; kurtosis printed
536 k = 2; kurtosis and kurtosis error printed
537 s = 1; skewness printed
538 s = 2; skewness and skewness error printed
539 i = 1; integral of bins printed
540 i = 2; integral of bins with option "width" printed
541 o = 1; number of overflows printed
542 u = 1; number of underflows printed
543 r = 1; standard deviation printed
544 r = 2; standard deviation and standard deviation error printed
545 m = 1; mean value printed
546 m = 2; mean and mean error values printed
547 e = 1; number of entries printed
548 n = 1; name of histogram is printed
549
550For example:
551
552 gStyle->SetOptStat(11);
553
554displays only the name of histogram and the number of entries, whereas:
555
556 gStyle->SetOptStat(1101);
557
558displays the name of histogram, mean value and standard deviation.
559
560<b>WARNING 1:</b> never do:
561
562 gStyle->SetOptStat(0001111);
563
564but instead do:
565
566 gStyle->SetOptStat(1111);
567
568because `0001111` will be taken as an octal number!
569
570<b>WARNING 2:</b> for backward compatibility with older versions
571
572 gStyle->SetOptStat(1);
573
574is taken as:
575
576 gStyle->SetOptStat(1111)
577
578To print only the name of the histogram do:
579
580 gStyle->SetOptStat(1000000001);
581
582<b>NOTE</b> that in case of 2D histograms, when selecting only underflow
583(10000) or overflow (100000), the statistics box will show all combinations
584of underflow/overflows and not just one single number.
585
586The parameter mode can be any combination of the letters `kKsSiIourRmMen`
587
588 k : kurtosis printed
589 K : kurtosis and kurtosis error printed
590 s : skewness printed
591 S : skewness and skewness error printed
592 i : integral of bins printed
593 I : integral of bins with option "width" printed
594 o : number of overflows printed
595 u : number of underflows printed
596 r : standard deviation printed
597 R : standard deviation and standard deviation error printed
598 m : mean value printed
599 M : mean value mean error values printed
600 e : number of entries printed
601 n : name of histogram is printed
602
603For example, to print only name of histogram and number of entries do:
604
605 gStyle->SetOptStat("ne");
606
607To print only the name of the histogram do:
608
609 gStyle->SetOptStat("n");
610
611The default value is:
612
613 gStyle->SetOptStat("nemr");
614
615When a histogram is painted, a `TPaveStats` object is created and added
616to the list of functions of the histogram. If a `TPaveStats` object
617already exists in the histogram list of functions, the existing object is just
618updated with the current histogram parameters.
619
620Once a histogram is painted, the statistics box can be accessed using
621`h->FindObject("stats")`. In the command line it is enough to do:
622
623 Root > h->Draw()
624 Root > TPaveStats *st = (TPaveStats*)h->FindObject("stats")
625
626because after `h->Draw()` the histogram is automatically painted. But
627in a script file the painting should be forced using `gPad->Update()`
628in order to make sure the statistics box is created:
629
630 h->Draw();
631 gPad->Update();
632 TPaveStats *st = (TPaveStats*)h->FindObject("stats");
633
634Without `gPad->Update()` the line `h->FindObject("stats")` returns a null pointer.
635
636When a histogram is drawn with the option `SAME`, the statistics box
637is not drawn. To force the statistics box drawing with the option
638`SAME`, the option `SAMES` must be used.
639If the new statistics box hides the previous statistics box, one can change
640its position with these lines (`h` being the pointer to the histogram):
641
642 Root > TPaveStats *st = (TPaveStats*)h->FindObject("stats")
643 Root > st->SetX1NDC(newx1); //new x start position
644 Root > st->SetX2NDC(newx2); //new x end position
645
646To change the type of information for an histogram with an existing
647`TPaveStats` one should do:
648
649 st->SetOptStat(mode);
650
651Where `mode` has the same meaning than when calling `gStyle->SetOptStat(mode)`
652(see above).
653
654One can delete the statistics box for a histogram `TH1* h` with:
655
656 h->SetStats(0)
657
658and activate it again with:
659
660 h->SetStats(1).
661
662Labels used in the statistics box ("Mean", "Std Dev", ...) can be changed from
663`$ROOTSYS/etc/system.rootrc` or `.rootrc` (look for the string `Hist.Stats.`).
664
665
666\anchor HP08
667### Fit Statistics
668
669
670The type of information about fit parameters printed in the histogram statistics
671box can be selected via the parameter mode. The parameter mode can be
672`= pcev` (default `= 0111`)
673
674 p = 1; print Probability
675 c = 1; print Chisquare/Number of degrees of freedom
676 e = 1; print errors (if e=1, v must be 1)
677 v = 1; print name/values of parameters
678
679Example:
680
681 gStyle->SetOptFit(1011);
682
683print fit probability, parameter names/values and errors.
684
6851. When `v = 1` is specified, only the non-fixed parameters are shown.
6862. When `v = 2` all parameters are shown.
687
688Note: `gStyle->SetOptFit(1)` means "default value", so it is equivalent
689to `gStyle->SetOptFit(111)`
690
691
692\anchor HP09
693### The error bars options
694
695
696| Option | Description |
697|----------|-------------------------------------------------------------------|
698| "E" | Default. Shows only the error bars, not a marker.|
699| "E1" | Small lines are drawn at the end of the error bars.|
700| "E2" | Error rectangles are drawn.|
701| "E3" | A filled area is drawn through the end points of the vertical error bars.|
702| "E4" | A smoothed filled area is drawn through the end points of the vertical error bars.|
703| "E0" | Draw error bars. Markers are drawn for bins with 0 contents. Combined with E1 or E2 it avoids error bars clipping|
704| "E5" | Like E3 but ignore the bins with 0 contents.|
705| "E6" | Like E4 but ignore the bins with 0 contents.|
706| "X0" | When used with one of the "E" option, it suppress the error bar along X as `gStyle->SetErrorX(0)` would do.|
707
708Begin_Macro(source)
709{
710 auto c1 = new TCanvas("c1","c1",600,400);
711 auto he = new TH1F("he","Distribution drawn with error bars (option E1) ",100,-3,3);
712 for (int i=0; i<10000; i++) he->Fill(gRandom->Gaus(0,1));
713 gStyle->SetEndErrorSize(3);
714 gStyle->SetErrorX(1.);
715 he->SetMarkerStyle(20);
716 he->Draw("E1");
717}
718End_Macro
719
720The options "E3" and "E4" draw an error band through the end points of the
721vertical error bars. With "E4" the error band is smoothed. Because of the
722smoothing algorithm used some artefacts may appear at the end of the band
723like in the following example. In such cases "E3" should be used instead
724of "E4".
725
726Begin_Macro(source)
727{
728 auto ce4 = new TCanvas("ce4","ce4",600,400);
729 ce4->Divide(2,1);
730 auto he4 = new TH1F("he4","Distribution drawn with option E4",100,-3,3);
731 Int_t i;
732 for (i=0;i<10000;i++) he4->Fill(gRandom->Gaus(0,1));
733 he4->SetFillColor(kRed);
734 he4->GetXaxis()->SetRange(40,48);
735 ce4->cd(1);
736 he4->Draw("E4");
737 ce4->cd(2);
738 auto he3 = (TH1F*)he4->DrawClone("E3");
739 he3->SetTitle("Distribution drawn option E3");
740}
741End_Macro
742
7432D histograms can be drawn with error bars as shown is the following example:
744
745Begin_Macro(source)
746{
747 auto c2e = new TCanvas("c2e","c2e",600,400);
748 auto h2e = new TH2F("h2e","TH2 drawn with option E",40,-4,4,40,-20,20);
749 float px, py;
750 for (Int_t i = 0; i < 25000; i++) {
751 gRandom->Rannor(px,py);
752 h2e->Fill(px,5*py);
753 }
754 h2e->Draw("E");
755}
756End_Macro
757
758
759\anchor HP100
760### The bar chart option
761
762
763The option "B" allows to draw simple vertical bar charts.
764The bar width is controlled with `TH1::SetBarWidth()`,
765and the bar offset within the bin, with `TH1::SetBarOffset()`.
766These two settings are useful to draw several histograms on the
767same plot as shown in the following example:
768
769Begin_Macro(source)
770{
771 int i;
772 const Int_t nx = 8;
773 string os_X[nx] = {"8","32","128","512","2048","8192","32768","131072"};
774 float d_35_0[nx] = {0.75, -3.30, -0.92, 0.10, 0.08, -1.69, -1.29, -2.37};
775 float d_35_1[nx] = {1.01, -3.02, -0.65, 0.37, 0.34, -1.42, -1.02, -2.10};
776
777 auto cb = new TCanvas("cb","cb",600,400);
778 cb->SetGrid();
779
780 gStyle->SetHistMinimumZero();
781
782 auto h1b = new TH1F("h1b","Option B example",nx,0,nx);
783 h1b->SetFillColor(4);
784 h1b->SetBarWidth(0.4);
785 h1b->SetBarOffset(0.1);
786 h1b->SetStats(0);
787 h1b->SetMinimum(-5);
788 h1b->SetMaximum(5);
789
790 for (i=1; i<=nx; i++) {
791 h1b->SetBinContent(i, d_35_0[i-1]);
792 h1b->GetXaxis()->SetBinLabel(i,os_X[i-1].c_str());
793 }
794
795 h1b->Draw("b");
796
797 auto h2b = new TH1F("h2b","h2b",nx,0,nx);
798 h2b->SetFillColor(38);
799 h2b->SetBarWidth(0.4);
800 h2b->SetBarOffset(0.5);
801 h2b->SetStats(0);
802 for (i=1;i<=nx;i++) h2b->SetBinContent(i, d_35_1[i-1]);
803
804 h2b->Draw("b same");
805}
806End_Macro
807
808
809\anchor HP10
810### The "BAR" and "HBAR" options
811
812
813When the option `bar` or `hbar` is specified, a bar chart is drawn. A vertical
814bar-chart is drawn with the options `bar`, `bar0`, `bar1`, `bar2`, `bar3`, `bar4`.
815An horizontal bar-chart is drawn with the options `hbar`, `hbar0`, `hbar1`,
816`hbar2`, `hbar3`, `hbar4` (hist006_TH1_bar_charts.C).
817
818- The bar is filled with the histogram fill color.
819- The left side of the bar is drawn with a light fill color.
820- The right side of the bar is drawn with a dark fill color.
821- The percentage of the bar drawn with either the light or dark color is:
822 - 0% for option "(h)bar" or "(h)bar0"
823 - 10% for option "(h)bar1"
824 - 20% for option "(h)bar2"
825 - 30% for option "(h)bar3"
826 - 40% for option "(h)bar4"
827
828When an histogram has errors the option ["HIST"](\ref OPTHIST) together with the `(h)bar` option.
829
830Begin_Macro(source)
831../../../tutorials/hist/hist006_TH1_bar_charts.C
832End_Macro
833
834To control the bar width (default is the bin width) `TH1::SetBarWidth()`
835should be used.
836
837To control the bar offset (default is 0) `TH1::SetBarOffset()` should
838be used.
839
840These two parameters are useful when several histograms are plotted using
841the option `SAME`. They allow to plot the histograms next to each other.
842
843
844\anchor HP11
845### The SCATter plot option (legacy draw option)
846
847\attention
848Use of option `SCAT` has been deprecated. It was the default drawing option for 2D and
8493D histograms. The new default option is `COL` (heat-map).
850
851
852For each cell (i,j) a number of points proportional to the cell content is
853drawn. A maximum of `kNMAX` points per cell is drawn. If the maximum is above
854`kNMAX` contents are normalized to `kNMAX` (`kNMAX=2000`).
855If option is of the form `scat=ff`, (eg `scat=1.8`,
856`scat=1e-3`), then `ff` is used as a scale factor to compute the
857number of dots. `scat=1` is the default.
858
859By default the scatter plot is painted with a "dot marker" which not scalable
860(see the `TAttMarker` documentation). To change the marker size, a scalable marker
861type should be used. For instance a circle (marker style 20).
862
863Begin_Macro(source)
864{
865 auto c1 = new TCanvas("c1","c1",600,400);
866 auto hscat = new TH2F("hscat","Option SCATter example (default for 2D histograms) ",40,-4,4,40,-20,20);
867 float px, py;
868 for (Int_t i = 0; i < 25000; i++) {
869 gRandom->Rannor(px,py);
870 hscat->Fill(px,5*py);
871 hscat->Fill(3+0.5*px,2*py-10.);
872 }
873 hscat->Draw("scat=0.5"); // This a legacy draw option. Please consider using TScatter
874}
875End_Macro
876
877
878\anchor HP12
879### The ARRow option
880
881
882Shows gradient between adjacent cells. For each cell (i,j) an arrow is drawn
883The orientation of the arrow follows the cell gradient.
884
885Begin_Macro(source)
886{
887 auto c1 = new TCanvas("c1","c1",600,400);
888 auto harr = new TH2F("harr","Option ARRow example",20,-4,4,20,-20,20);
889 harr->SetLineColor(kRed);
890 float px, py;
891 for (Int_t i = 0; i < 25000; i++) {
892 gRandom->Rannor(px,py);
893 harr->Fill(px,5*py);
894 harr->Fill(3+0.5*px,2*py-10.,0.1);
895 }
896 harr->Draw("ARR");
897}
898End_Macro
899
900\since **ROOT version 6.17/01**
901
902The option `ARR` can be combined with the option `COL` or `COLZ`.
903
904Begin_Macro(source)
905{
906 auto c1 = new TCanvas("c1","c1",600,400);
907 auto harr = new TH2F("harr","Option ARR + COLZ example",20,-4,4,20,-20,20);
908 harr->SetStats(0);
909 float px, py;
910 for (Int_t i = 0; i < 25000; i++) {
911 gRandom->Rannor(px,py);
912 harr->Fill(px,5*py);
913 harr->Fill(3+0.5*px,2*py-10.,0.1);
914 }
915 harr->Draw("ARR COLZ");
916}
917End_Macro
918
919
920\anchor HP13
921### The BOX option
922
923
924For each cell (i,j) a box is drawn. The size (surface) of the box is
925proportional to the absolute value of the cell content.
926The cells with a negative content are drawn with a `X` on top of the box.
927
928Begin_Macro(source)
929{
930 auto c1 = new TCanvas("c1","c1",600,400);
931 auto hbox = new TH2F("hbox","Option BOX example",3,0,3,3,0,3);
932 hbox->SetFillColor(42);
933 hbox->Fill(0.5, 0.5, 1.);
934 hbox->Fill(0.5, 1.5, 4.);
935 hbox->Fill(0.5, 2.5, 3.);
936 hbox->Fill(1.5, 0.5, 2.);
937 hbox->Fill(1.5, 1.5, 12.);
938 hbox->Fill(1.5, 2.5, -6.);
939 hbox->Fill(2.5, 0.5, -4.);
940 hbox->Fill(2.5, 1.5, 6.);
941 hbox->Fill(2.5, 2.5, 0.5);
942 hbox->Draw("BOX");
943}
944End_Macro
945
946With option `BOX1` a button is drawn for each cell with surface
947proportional to content's absolute value. A sunken button is drawn for
948negative values a raised one for positive.
949
950Begin_Macro(source)
951{
952 auto c1 = new TCanvas("c1","c1",600,400);
953 auto hbox1 = new TH2F("hbox1","Option BOX1 example",3,0,3,3,0,3);
954 hbox1->SetFillColor(42);
955 hbox1->Fill(0.5, 0.5, 1.);
956 hbox1->Fill(0.5, 1.5, 4.);
957 hbox1->Fill(0.5, 2.5, 3.);
958 hbox1->Fill(1.5, 0.5, 2.);
959 hbox1->Fill(1.5, 1.5, 12.);
960 hbox1->Fill(1.5, 2.5, -6.);
961 hbox1->Fill(2.5, 0.5, -4.);
962 hbox1->Fill(2.5, 1.5, 6.);
963 hbox1->Fill(2.5, 2.5, 0.5);
964 hbox1->Draw("BOX1");
965}
966End_Macro
967
968When the option `SAME` (or "SAMES") is used with the option `BOX`,
969the boxes' sizes are computed taking the previous plots into account. The range
970along the Z axis is imposed by the first plot (the one without option
971`SAME`); therefore the order in which the plots are done is relevant.
972
973Begin_Macro(source)
974{
975 auto c1 = new TCanvas("c1","c1",600,400);
976 auto hb1 = new TH2F("hb1","Example of BOX plots with option SAME ",40,-3,3,40,-3,3);
977 auto hb2 = new TH2F("hb2","hb2",40,-3,3,40,-3,3);
978 auto hb3 = new TH2F("hb3","hb3",40,-3,3,40,-3,3);
979 auto hb4 = new TH2F("hb4","hb4",40,-3,3,40,-3,3);
980 for (Int_t i=0;i<1000;i++) {
981 double x,y;
982 gRandom->Rannor(x,y);
983 if (x>0 && y>0) hb1->Fill(x,y,4);
984 if (x<0 && y<0) hb2->Fill(x,y,3);
985 if (x>0 && y<0) hb3->Fill(x,y,2);
986 if (x<0 && y>0) hb4->Fill(x,y,1);
987 }
988 hb1->SetFillColor(1);
989 hb2->SetFillColor(2);
990 hb3->SetFillColor(3);
991 hb4->SetFillColor(4);
992 hb1->Draw("box");
993 hb2->Draw("box same");
994 hb3->Draw("box same");
995 hb4->Draw("box same");
996}
997End_Macro
998
999\since **ROOT version 6.17/01:**
1000
1001Sometimes the change of the range of the Z axis is unwanted, in which case, one
1002can use `SAME0` (or `SAMES0`) option to opt out of this change.
1003
1004Begin_Macro(source)
1005{
1006 auto h2 = new TH2F("h2"," ",10,0,10,10,20,30);
1007 auto hf = (TH2F*)h2->Clone("hf");
1008 h2->SetBit(TH1::kNoStats);
1009 hf->SetBit(TH1::kNoStats);
1010 h2->Fill(5,22);
1011 h2->Fill(5,23);
1012 h2->Fill(6,22);
1013 h2->Fill(6,23);
1014 hf->Fill(6,23);
1015 hf->Fill(6,23);
1016 hf->Fill(6,23);
1017 hf->Fill(6,23);
1018 hf->Fill(5,23);
1019
1020 auto hf_copy1 = hf->Clone("hf_copy1");
1021 TLatex lt;
1022
1023 auto cx = new TCanvas(); cx->Divide(2,1);
1024
1025 cx->cd(1);
1026 h2->Draw("box");
1027 hf->Draw("text colz same");
1028 lt.DrawLatexNDC(0.3,0.5,"SAME");
1029
1030 cx->cd(2);
1031 h2->Draw("box");
1032 hf_copy1->Draw("text colz same0");
1033 lt.DrawLatexNDC(0.3,0.5,"SAME0");
1034}
1035End_Macro
1036
1037
1038\anchor HP14
1039### The COLor option (default for 2D histograms)
1040
1041The magnitude of individual cell (i,j) is represented as a color picked in the current color palette.
1042This data visualization technique is often called a heat map (or heat-map).
1043
1044The color table used is defined in the current style.
1045
1046If the histogram's minimum and maximum are the same (flat histogram), the
1047mapping on colors is not possible, therefore nothing is painted. To paint a
1048flat histogram it is enough to set the histogram minimum
1049(`TH1::SetMinimum()`) different from the bins' content.
1050
1051The default number of color levels used to paint the cells is 20.
1052It can be changed with `TH1::SetContour()` or
1053`TStyle::SetNumberContours()`. The higher this number is, the smoother
1054is the color change between cells.
1055
1056The color palette in TStyle can be modified via `gStyle->SetPalette()`.
1057
1058All the non-empty bins are painted. Empty bins (bins with content and error equal to 0) are
1059not painted unless some bins have a negative content because in that case the null bins
1060might be not empty.
1061
1062`TProfile2D` histograms are handled differently because, for this type of 2D
1063histograms, it is possible to know if an empty bin has been filled or not. So even
1064if all the bins' contents are positive some empty bins might be painted. And vice versa,
1065if some bins have a negative content some empty bins might be not painted.
1066
1067Combined with the option `COL`, the option `Z` allows to
1068display the color palette defined by `gStyle->SetPalette()`.
1069
1070In the following example, the histogram has only positive bins; the empty
1071bins (containing 0) are not drawn.
1072
1073Begin_Macro(source)
1074{
1075 auto c1 = new TCanvas("c1","c1",600,400);
1076 auto hcol1 = new TH2F("hcol1","Option COLor example ",40,-4,4,40,-20,20);
1077 float px, py;
1078 for (Int_t i = 0; i < 25000; i++) {
1079 gRandom->Rannor(px,py);
1080 hcol1->Fill(px,5*py);
1081 }
1082 hcol1->Draw("COLZ");
1083}
1084End_Macro
1085
1086In the first plot of following example, the histogram has some negative bins;
1087the empty bins (containing 0) are drawn. In some cases one wants to not draw
1088empty bins (containing 0) of histograms having a negative minimum. The option
1089`1`, used to produce the second plot in the following picture, allows to do that.
1090
1091Begin_Macro(source)
1092{
1093 auto c1 = new TCanvas("c1","c1",600,600);
1094 c1->Divide(1,2);
1095 auto hcol23 = new TH2F("hcol23","Option COLZ example ",40,-4,4,40,-20,20);
1096 auto hcol24 = new TH2F("hcol24","Option COLZ1 example ",40,-4,4,40,-20,20);
1097 float px, py;
1098 for (Int_t i = 0; i < 25000; i++) {
1099 gRandom->Rannor(px,py);
1100 hcol23->Fill(px,5*py);
1101 hcol24->Fill(px,5*py);
1102 }
1103 hcol23->Fill(0.,0.,-200.);
1104 hcol24->Fill(0.,0.,-200.);
1105 c1->cd(1); hcol23->Draw("COLZ");
1106 c1->cd(2); hcol24->Draw("COLZ1");
1107}
1108End_Macro
1109
1110When the maximum of the histogram is set to a smaller value than the real maximum,
1111 the bins having a content between the new maximum and the real maximum are
1112painted with the color corresponding to the new maximum.
1113
1114When the minimum of the histogram is set to a greater value than the real minimum,
1115 the bins having a value between the real minimum and the new minimum are not drawn
1116 unless the option `0` is set.
1117In other words, option `COLZ0` forces the painting of bins with content < set minimum with
1118 a color corresponding to the set minimum. In contrast, option `COLZ` would not draw values
1119 smaller than the specified minimum. Note that both `COLZ` and `COLZ0` still do not draw
1120 empty bins, ie bins with `content == error == 0`, if the set min is not negative.
1121(Note that option `COLZ0` for TH2Poly has a different behavior than for TH2.)
1122
1123The following example illustrates the option `0` combined with the option `COL`.
1124
1125Begin_Macro(source)
1126{
1127 auto c1 = new TCanvas("c1","c1",600,600);
1128 c1->Divide(1,2);
1129 auto hcol21 = new TH2F("hcol21","Option COLZ",40,-4,4,40,-20,20);
1130 auto hcol22 = new TH2F("hcol22","Option COLZ0",40,-4,4,40,-20,20);
1131 float px, py;
1132 for (Int_t i = 0; i < 25000; i++) {
1133 gRandom->Rannor(px,py);
1134 hcol21->Fill(px,5*py);
1135 hcol22->Fill(px,5*py);
1136 }
1137 hcol21->SetBit(TH1::kNoStats);
1138 hcol22->SetBit(TH1::kNoStats);
1139 c1->cd(1); hcol21->Draw("COLZ");
1140 c1->cd(2); hcol22->Draw("COLZ0");
1141 hcol21->SetMaximum(100);
1142 hcol21->SetMinimum(40);
1143 hcol22->SetMaximum(100);
1144 hcol22->SetMinimum(40);
1145}
1146End_Macro
1147
1148Note that the behavior of `COLZ` is not symmetric: it does not draw values below the specified minimum,
1149but does draw values above the specified maximum by clipping them to the maximum color. In contrast, `COLZ0`
1150clips color on both lower and upper sides. Both `COLZ0` and `COLZ` exclude drawing empty bins (`content == error == 0`),
1151if the set minimum is not negative.
1152
1153\since **ROOT version 6.09/01:**
1154
1155When the option SAME (or "SAMES") is used with the option COL, the boxes' color
1156are computed taking the previous plots into account. The range along the Z axis
1157is imposed by the first plot (the one without option SAME); therefore the order
1158in which the plots are done is relevant. Same as [in the `BOX` option](\ref HP13), one can use
1159`SAME0` (or `SAMES0`) to opt out of this imposition.
1160
1161Begin_Macro(source)
1162{
1163 auto c = new TCanvas("c","Example of col plots with option SAME",200,10,700,500);
1164 auto h1 = new TH2F("h1","h1",40,-3,3,40,-3,3);
1165 auto h2 = new TH2F("h2","h2",40,-3,3,40,-3,3);
1166 auto h3 = new TH2F("h3","h3",40,-3,3,40,-3,3);
1167 auto h4 = new TH2F("h4","h4",40,-3,3,40,-3,3);
1168 h1->SetBit(TH1::kNoStats);
1169 for (Int_t i=0;i<5000;i++) {
1170 double x,y;
1171 gRandom->Rannor(x,y);
1172 if(x>0 && y>0) h1->Fill(x,y,4);
1173 if(x<0 && y<0) h2->Fill(x,y,3);
1174 if(x>0 && y<0) h3->Fill(x,y,2);
1175 if(x<0 && y>0) h4->Fill(x,y,1);
1176 }
1177 h1->Draw("colz");
1178 h2->Draw("col same");
1179 h3->Draw("col same");
1180 h4->Draw("col same");
1181}
1182End_Macro
1183
1184The option `COL` can be combined with the option `POL`:
1185
1186Begin_Macro(source)
1187{
1188 auto c1 = new TCanvas("c1","c1",600,400);
1189 auto hcol1 = new TH2F("hcol1","Option COLor combined with POL",40,-4,4,40,-4,4);
1190 float px, py;
1191 for (Int_t i = 0; i < 25000; i++) {
1192 gRandom->Rannor(px,py);
1193 hcol1->Fill(px,py);
1194 }
1195 hcol1->Draw("COLZPOL");
1196}
1197End_Macro
1198
1199\since **ROOT version 6.07/03:**
1200
1201A second rendering technique is also available with the COL2 and COLZ2 options.
1202
1203These options provide potential performance improvements compared to the standard
1204COL option. The performance comparison of the COL2 to the COL option depends on
1205the histogram and the size of the rendering region in the current pad. In general,
1206a small (approx. less than 100 bins per axis), sparsely populated TH2 will render
1207faster with the COL option.
1208
1209However, for larger histograms (approx. more than 100 bins per axis)
1210that are not sparse, the COL2 option will provide up to 20 times performance improvements.
1211For example, a 1000x1000 bin TH2 that is not sparse will render an order of magnitude
1212faster with the COL2 option.
1213
1214The COL2 option will also scale its performance based on the size of the
1215pixmap the histogram image is being rendered into. It also is much better optimized for
1216sessions where the user is forwarding X11 windows through an `ssh` connection.
1217
1218For the most part, the COL2 and COLZ2 options are a drop in replacement to the COL
1219and COLZ options. There is one major difference and that concerns the treatment of
1220bins with zero content. The COL2 and COLZ2 options color these bins the color of zero.
1221
1222COL2 option renders the histogram as a bitmap. Therefore it cannot be saved in vector
1223graphics file format like PostScript or PDF (an empty image will be generated). It can
1224be saved only in bitmap files like PNG format for instance.
1225
1226
1227\anchor HP140
1228### The CANDLE and VIOLIN options
1229
1230The mechanism behind Candle plots and Violin plots is very similar. Because of this they are
1231implemented in the same class TCandle. The keywords CANDLE or VIOLIN will initiate the drawing of
1232the corresponding plots. Followed by the keyword the user can select a plot direction (X or V for
1233vertical projections, or Y or H for horizontal projections) and/or predefined definitions
1234(1-6 for candles, 1-2 for violins). The order doesn't matter. Default is X and 1.
1235
1236Instead of using the predefined representations, the candle and violin parameters can be
1237changed individually. In that case the option have the following form:
1238
1239 CANDLEX(<option-string>)
1240 CANDLEY(<option-string>)
1241 VIOLINX(<option-string>)
1242 VIOLINY(<option-string>).
1243
1244All zeros at the beginning of `option-string` can be omitted.
1245
1246`option-string` consists eight values, defined as follow:
1247
1248 "CANDLEX(zhpawMmb)"
1249
1250Where:
1251
1252 - `b = 0`; no box drawn
1253 - `b = 1`; the box is drawn. As the candle-plot is also called a box-plot it
1254 makes sense in the very most cases to always draw the box
1255 - `b = 2`; draw a filled box with border
1256
1257 - `m = 0`; no median drawn
1258 - `m = 1`; median is drawn as a line
1259 - `m = 2`; median is drawn with errors (notches)
1260 - `m = 3`; median is drawn as a circle
1261
1262 - `M = 0`; no mean drawn
1263 - `M = 1`; mean is drawn as a dashed line
1264 - `M = 3`; mean is drawn as a circle
1265
1266 - `w = 0`; no whisker drawn
1267 - `w = 1`; whisker is drawn to end of distribution.
1268 - `w = 2`; whisker is drawn to max 1.5*iqr
1269
1270 - `a = 0`; no anchor drawn
1271 - `a = 1`; the anchors are drawn
1272
1273 - `p = 0`; no points drawn
1274 - `p = 1`; only outliers are drawn
1275 - `p = 2`; all datapoints are drawn
1276 - `p = 3`: all datapoints are drawn scattered
1277
1278 - `h = 0`; no histogram is drawn
1279 - `h = 1`; histogram at the left or bottom side is drawn
1280 - `h = 2`; histogram at the right or top side is drawn
1281 - `h = 3`; histogram at left and right or top and bottom (violin-style) is drawn
1282
1283 - `z = 0`; no zero indicator line is drawn
1284 - `z = 1`; zero indicator line is drawn.
1285
1286As one can see all individual options for both candle and violin plots can be accessed by this
1287mechanism. In deed the keywords CANDLE(<option-string>) and VIOLIN(<option-string>) have the same
1288meaning. So you can parametrise an option-string for a candle plot and use the keywords VIOLIN and
1289vice versa, if you wish.
1290
1291Using a logarithmic x- or y-axis is possible for candle and violin charts.
1292
1293\since **ROOT version 6.11/01**
1294
1295a logarithmic z-axis is possible, too but will only affect violin charts of course.
1296
1297\anchor HP140a
1298#### The CANDLE option
1299
1300<a href="http://en.wikipedia.org/wiki/Box_plot">A Candle plot</a> (also known as
1301a "box plot" or "whisker plot") was invented in 1977 by John Tukey. It is a convenient
1302way to describe graphically a data distribution (D) with only five numbers:
1303
1304 1. The minimum value of the distribution D (bottom or left whisker).
1305 2. The lower quartile (Q1): 25% of the data points in D are less than Q1 (bottom of the box).
1306 3. The median (M): 50% of the data points in D are less than M.
1307 4. The upper quartile (Q3): 75% of the data points in D are less than Q3 (top of the box).
1308 5. The maximum value of the distribution D (top or right whisker).
1309
1310In this implementation a TH2 is considered as a collection of TH1 along
1311X (option `CANDLE` or `CANDLEX`) or Y (option `CANDLEY`).
1312Each TH1 is represented as one candle.
1313
1314Begin_Macro(source)
1315../../../tutorials/hist/hist052_Graphics_candle_plot_whiskers.C
1316End_Macro
1317
1318The candle reduces the information coming from a whole distribution into few values.
1319Independently from the number of entries or the significance of the underlying distribution
1320a candle will always look like a candle. So candle plots should be used carefully in
1321particular with unknown distributions. The definition of a candle is based on
1322__unbinned data__. Here, candles are created from binned data. Because of this, the
1323deviation is connected to the bin width used. The calculation of the quantiles
1324normally done on unbinned data also. Because data are binned, this will
1325only work the best possible way within the resolution of one bin
1326
1327Because of all these facts one should take care that:
1328
1329 - there are enough points per candle
1330 - the bin width is small enough (more bins will increase the maximum
1331 available resolution of the quantiles although there will be some
1332 bins with no entries)
1333 - never make a candle-plot if the underlying distribution is double-distributed
1334 - only create candles of distributions that are more-or-less gaussian (the
1335 MPV should be not too far away from the mean).
1336
1337#### What a candle is made of
1338
1339\since **ROOT version 6.07/05**
1340
1341##### The box
1342The box displays the position of the inter-quantile-range of the underlying
1343distribution. The box contains 25% of the distribution below the median
1344and 25% of the distribution above the median. If the underlying distribution is large
1345enough and gaussian shaped the end-points of the box represent \f$ 0.6745\times\sigma \f$
1346(Where \f$ \sigma \f$ is the standard deviation of the gaussian). The width and
1347the position of the box can be modified by SetBarWidth() and SetBarOffset().
1348The +-25% quantiles are calculated by the GetQuantiles() methods.
1349
1350\since **ROOT version 6.11/01**
1351
1352Using the static function TCandle::SetBoxRange(double) the box definition will be
1353overwritten. E.g. using a box range of 0.68 will redefine the area of the lower box edge
1354to the upper box edge in order to cover 68% of the distribution illustrated by that candle.
1355The static function will affect all candle-charts in the running program.
1356Default is 0.5.
1357
1358Using the static function TCandle::SetScaledCandle(bool) the width of the box (and the
1359whole candle) can be influenced. Deactivated, the width is constant (to be set by
1360SetBarWidth() ). Activated, the width of the boxes will be scaled to each other based on the
1361amount of data in the corresponding candle, the maximum width can be influenced by
1362SetBarWidth(). The static function will affect all candle-charts in the running program.
1363Default is false. Scaling between multiple candle-charts (using "same" or THStack) is not
1364supported, yet
1365
1366##### The Median
1367For a sorted list of numbers, the median is the value in the middle of the list.
1368E.g. if a sorted list is made of five numbers "1,2,3,6,7" 3 will be the median
1369because it is in the middle of the list. If the number of entries is even the
1370average of the two values in the middle will be used. As histograms are binned
1371data, the situation is a bit more complex. The following example shows this:
1372
1373~~~ {.cpp}
1374void quantiles() {
1375 auto h = new TH1I("h","h",10,0,10);
1376 //h->Fill(3);
1377 //h->Fill(3);
1378 h->Fill(4);
1379 h->Draw();
1380 double p = 0.;
1381 double q = 0.;
1382 h->GetQuantiles(1,&q,&p);
1383
1384 cout << "Median is: " << q << std::endl;
1385}
1386~~~
1387
1388Here the bin-width is 1.0. If the two Fill(3) are commented out, as there are currently,
1389the example will return a calculated median of 4.5, because that's the bin center
1390of the bin in which the value 4.0 has been dropped. If the two Fill(3) are not
1391commented out, it will return 3.75, because the algorithm tries to evenly distribute
1392the individual values of a bin with bin content > 0. It means the sorted list
1393would be "3.25, 3.75, 4.5".
1394
1395The consequence is a median of 3.75. This shows how important it is to use a
1396small enough bin-width when using candle-plots on binned data.
1397If the distribution is large enough and gaussian shaped the median will be exactly
1398equal to the mean.
1399The median can be shown as a line or as a circle or not shown at all.
1400
1401In order to show the significance of the median notched candle plots apply a "notch" or
1402narrowing of the box around the median. The significance is defined by
1403\f$ 1.57\times\frac{iqr}{N} \f$ and will be represented as the size of the notch
1404(where iqr is the size of the box and N is the number of entries of the whole
1405distribution). Candle plots like these are usually called "notched candle plots".
1406
1407In case the significance of the median is greater that the size of the box, the
1408box will have an unnatural shape. Usually it means the chart has not enough data,
1409or that representing this uncertainty is not useful
1410
1411##### The Mean
1412The mean can be drawn as a dashed line or as a circle or not drawn at all.
1413The mean is the arithmetic average of the values in the distribution.
1414It is calculated using GetMean(). Because histograms are
1415binned data, the mean value can differ from a calculation on the raw-data.
1416If the distribution is large enough and gaussian shaped the mean will be
1417exactly the median.
1418
1419##### The Whiskers
1420The whiskers represent the part of the distribution not covered by the box.
1421The upper 25% and the lower 25% of the distribution are located within the whiskers.
1422Two representations are available.
1423
1424 - A simple one (using w=1) defining the lower whisker from the lowest data value
1425 to the bottom of the box, and the upper whisker from the top of the box to the
1426 highest data value. In this representation the whisker-lines are dashed.
1427 - A more complex one having a further restriction. The whiskers are still connected
1428 to the box but their length cannot exceed \f$ 1.5\times iqr \f$. So it might
1429 be that the outermost part of the underlying distribution will not be covered
1430 by the whiskers. Usually these missing parts will be represented by the outliers
1431 (see points). Of course the upper and the lower whisker may differ in length.
1432 In this representation the whiskers are drawn as solid lines.
1433
1434\since **ROOT version 6.11/01**
1435
1436Using the static function TCandle::SetWhiskerRange(double) the whisker definition w=1
1437will be overwritten. E.g. using a whisker-range of 0.95 and w=1 will redefine the area of
1438the lower whisker to the upper whisker in order to cover 95% of the distribution inside
1439that candle. The static function will affect all candle-charts in the running program.
1440Default is 1.
1441
1442If the distribution is large enough and gaussian shaped, the maximum length of
1443the whisker will be located at \f$ \pm 2.698 \sigma \f$ (when using the
14441.5*iqr-definition (w=2), where \f$ \sigma \f$ is the standard deviation
1445(see picture above). In that case 99.3% of the total distribution will be covered
1446by the box and the whiskers, whereas 0.7% are represented by the outliers.
1447
1448##### The Anchors
1449The anchors have no special meaning in terms of statistical calculation. They mark
1450the end of the whiskers and they have the width of the box. Both representation
1451with and without anchors are common.
1452
1453##### The Points
1454Depending on the configuration the points can have different meanings:
1455 - If p=1 the points represent the outliers. If they are shown, it means
1456 some parts of the underlying distribution are not covered by the whiskers.
1457 This can only occur when the whiskers are set to option w=2. Here the whiskers
1458 can have a maximum length of \f$ 1.5 \times iqr \f$. So any points outside the
1459 whiskers will be drawn as outliers. The outliers will be represented by crosses.
1460 - If p=2 all points in the distribution will be painted as crosses. This is
1461 useful for small datasets only (up to 10 or 20 points per candle).
1462 The outliers are shown along the candle. Because the underlying distribution
1463 is binned, is frequently occurs that a bin contains more than one value.
1464 Because of this the points will be randomly scattered within their bin along
1465 the candle axis. If the bin content for a bin is exactly 1 (usually
1466 this happens for the outliers) if will be drawn in the middle of the bin along
1467 the candle axis. As the maximum number of points per candle is limited by kNMax/2
1468 on very large datasets scaling will be performed automatically. In that case one
1469 would loose all outliers because they have usually a bin content of 1 (and a
1470 bin content between 0 and 1 after the scaling). Because of this all bin contents
1471 between 0 and 1 - after the scaling - will be forced to be 1.
1472 - As the drawing of all values on large datasets can lead to big amounts of crosses,
1473 one can show all values as a scatter plot instead by choosing p=3. The points will be
1474 drawn as dots and will be scattered within the width of the candle. The color
1475 of the points will be the color of the candle-chart.
1476
1477##### Other Options
1478Is is possible to combine all options of candle and violin plots with each other. E.g. a box-plot
1479with a histogram.
1480
1481#### How to use the candle-plots drawing option
1482
1483There are six predefined candle-plot representations:
1484
1485 - "CANDLEX1": Standard candle (whiskers cover the whole distribution)
1486 - "CANDLEX2": Standard candle with better whisker definition + outliers.
1487 It is a good compromise
1488 - "CANDLEX3": Like candle2 but with a mean as a circle.
1489 It is easier to distinguish mean and median
1490 - "CANDLEX4": Like candle3 but showing the uncertainty of the median as well
1491 (notched candle plots).
1492 For bigger datasets per candle
1493 - "CANDLEX5": Like candle2 but showing all data points.
1494 For very small datasets
1495 - "CANDLEX6": Like candle2 but showing all datapoints scattered.
1496 For huge datasets
1497
1498
1499The following picture shows how the six predefined representations look.
1500
1501Begin_Macro
1502{
1503 auto c1 = new TCanvas("c1","c1",700,800);
1504 c1->Divide(2,3);
1505 gStyle->SetOptStat(kFALSE);
1506
1507 auto hcandle = new TH2F("hcandle"," ",10,-4,4,40,-20,20);
1508 float px, py;
1509 for (Int_t i = 0; i < 15000; i++) {
1510 gRandom->Rannor(px,py);
1511 hcandle->Fill(px,5*py);
1512 }
1513 hcandle->SetMarkerSize(0.5);
1514
1515 TH2F *h2;
1516 for (Int_t i=1; i<7; i++) {
1517 c1->cd(i);
1518 h2 = (TH2F*)hcandle->DrawClone(Form("CANDLE%d",i));
1519 h2->SetTitle(Form("CANDLE%d",i));
1520 }
1521}
1522End_Macro
1523
1524
1525#### Example 1
1526Box and improved whisker, no mean, no median, no anchor no outliers
1527
1528 h1->Draw("CANDLEX(2001)");
1529
1530#### Example 2
1531A Candle-definition like "CANDLEX2" (New standard candle with better whisker definition + outliers)
1532
1533 h1->Draw("CANDLEX(112111)");
1534
1535#### Example 3
1536The following example shows how several candle plots can be super-imposed using
1537the option SAME. Note that the bar-width and bar-offset are active on candle plots.
1538Also the color, the line width, the size of the points and so on can be changed by the
1539standard attribute setting methods such as SetLineColor() SetLineWidth().
1540
1541Begin_Macro(source)
1542../../../tutorials/hist/hist049_Graphics_candle_plot.C
1543End_Macro
1544
1545\anchor HP140b
1546#### The VIOLIN option
1547
1548<a href="http://en.wikipedia.org/wiki/Violin_plot">A violin plot</a> is a candle plot
1549that also encodes the pdf information at each point.
1550
1551
1552Quartiles and mean are also represented at each point, with a marker
1553and two lines.
1554
1555In this implementation a TH2 is considered as a collection of TH1 along
1556X (option `VIOLIN` or `VIOLINX`) or Y (option `VIOLINY`).
1557
1558#### What a violin is made of
1559
1560\since **ROOT version 6.09/02**
1561
1562##### The histogram
1563The histogram is typically drawn to both directions with respect to the middle-line of the
1564corresponding bin. This can be achieved by using h=3. It is possible to draw a histogram only to
1565one side (h=1, or h=2).
1566The maximum number of bins in the histogram is limited to 500, if the number of bins in the used
1567histogram is higher it will be rebinned automatically. The maximum height of the histogram can
1568be modified by using SetBarWidth() and the position can be changed with SetBarOffset().
1569A solid fill style is recommended.
1570
1571\since **ROOT version 6.11/01**
1572
1573Using the static function TCandle::SetScaledViolin(bool) the height of the histogram or the
1574violin can be influenced. Activated, the height of the bins of the individual violins will be
1575scaled with respect to each other, the maximum height can be influenced by SetBarWidth().
1576Deactivated, the height of the bin with the maximum content of each individual violin is
1577set to a constant value using SetBarWidth(). The static function will affect all violin-charts
1578in the running program. Default is true. Scaling between multiple violin-charts
1579(using "same" or THStack) is not supported, yet.
1580
1581##### The zero indicator line
1582Typical for violin charts is a line in the background over the whole histogram indicating
1583the bins with zero entries. The zero indicator line can be activated with z=1. The line color
1584will always be the same as the fill-color of the histogram.
1585
1586##### The Mean
1587The Mean is illustrated with the same mechanism as used for candle plots. Usually a circle is used.
1588
1589##### Whiskers
1590The whiskers are illustrated by the same mechanism as used for candle plots. There is only one
1591difference. When using the simple whisker definition (w=1) and the zero indicator line (z=1), then
1592the whiskers will be forced to be solid (usually hashed)
1593
1594##### Points
1595The points are illustrated by the same mechanism as used for candle plots. E.g. VIOLIN2 uses
1596better whisker definition (w=2) and outliers (p=1).
1597
1598##### Other options
1599It is possible to combine all options of candle or violin plots with each other. E.g. a violin plot
1600including a box-plot.
1601
1602#### How to use the violin-plots drawing option
1603
1604There are two predefined violin-plot representations:
1605 - "VIOLINX1": Standard violin (histogram, mean, whisker over full distribution,
1606 zero indicator line)
1607 - "VIOLINX2": Line VIOLINX1 both with better whisker definition + outliers.
1608
1609A solid fill style is recommended for this plot (as opposed to a hollow or
1610hashed style).
1611
1612Begin_Macro(source)
1613{
1614 auto c1 = new TCanvas("c1","c1",600,400);
1615 Int_t nx(6), ny(40);
1616 double xmin(0.0), xmax(+6.0), ymin(0.0), ymax(+4.0);
1617 auto hviolin = new TH2F("hviolin", "Option VIOLIN example", nx, xmin, xmax, ny, ymin, ymax);
1618 TF1 f1("f1", "gaus", +0,0 +4.0);
1619 double x,y;
1620 for (Int_t iBin=1; iBin<hviolin->GetNbinsX(); ++iBin) {
1621 double xc = hviolin->GetXaxis()->GetBinCenter(iBin);
1622 f1.SetParameters(1, 2.0+TMath::Sin(1.0+xc), 0.2+0.1*(xc-xmin)/xmax);
1623 for(Int_t i=0; i<10000; ++i){
1624 x = xc;
1625 y = f1.GetRandom();
1626 hviolin->Fill(x, y);
1627 }
1628 }
1629 hviolin->SetFillColor(kGray);
1630 hviolin->SetMarkerStyle(20);
1631 hviolin->SetMarkerSize(0.5);
1632 hviolin->Draw("VIOLIN");
1633 c1->Update();
1634}
1635End_Macro
1636
1637The next example illustrates a time development of a certain value:
1638
1639Begin_Macro(source)
1640../../../tutorials/hist/hist047_Graphics_candle_decay.C
1641End_Macro
1642
1643
1644\anchor HP15
1645### The TEXT and TEXTnn Option
1646
1647
1648For each bin the content is printed. The text attributes are:
1649
1650- text font = current TStyle font (`gStyle->SetTextFont()`).
1651- text size = 0.02*padheight*markersize (if `h` is the histogram drawn
1652 with the option `TEXT` the marker size can be changed with
1653 `h->SetMarkerSize(markersize)`).
1654- text color = marker color.
1655
1656By default the format `g` is used. This format can be redefined
1657by calling `gStyle->SetPaintTextFormat()`.
1658
1659It is also possible to use `TEXTnn` in order to draw the text with
1660the angle `nn` (`0 < nn <= 90`).
1661
1662For 2D histograms the text is plotted in the center of each non empty cells.
1663It is possible to plot empty cells by calling `gStyle->SetHistMinimumZero()`
1664or providing MIN0 draw option. For 1D histogram the text is plotted at a y
1665position equal to the bin content.
1666
1667For 2D histograms when the option "E" (errors) is combined with the option
1668text ("TEXTE"), the error for each bin is also printed.
1669
1670Begin_Macro(source)
1671{
1672 auto c01 = new TCanvas("c01","c01",700,400);
1673 c01->Divide(2,1);
1674 auto htext1 = new TH1F("htext1","Option TEXT on 1D histograms ",10,-4,4);
1675 auto htext2 = new TH2F("htext2","Option TEXT on 2D histograms ",10,-4,4,10,-20,20);
1676 float px, py;
1677 for (Int_t i = 0; i < 25000; i++) {
1678 gRandom->Rannor(px,py);
1679 htext1->Fill(px,0.1);
1680 htext2->Fill(px,5*py,0.1);
1681 }
1682 gStyle->SetPaintTextFormat("4.1f m");
1683 htext2->SetMarkerSize(1.8);
1684 c01->cd(1);
1685 htext2->Draw("TEXT45");
1686 c01->cd(2);
1687 htext1->Draw();
1688 htext1->Draw("HIST TEXT0 SAME");
1689}
1690End_Macro
1691
1692\since **ROOT version 6.07/07:**
1693
1694In case several histograms are drawn on top ot each other (using option `SAME`),
1695the text can be shifted using `SetBarOffset()`. It specifies an offset for the
1696text position in each cell, in percentage of the bin width.
1697
1698Begin_Macro(source)
1699{
1700 auto c03 = new TCanvas("c03","c03",700,400);
1701 gStyle->SetOptStat(0);
1702 auto htext3 = new TH2F("htext3","Several 2D histograms drawn with option TEXT",10,-4,4,10,-20,20);
1703 auto htext4 = new TH2F("htext4","htext4",10,-4,4,10,-20,20);
1704 auto htext5 = new TH2F("htext5","htext5",10,-4,4,10,-20,20);
1705 float px, py;
1706 for (Int_t i = 0; i < 25000; i++) {
1707 gRandom->Rannor(px,py);
1708 htext3->Fill(4*px,20*py,0.1);
1709 htext4->Fill(4*px,20*py,0.5);
1710 htext5->Fill(4*px,20*py,1.0);
1711 }
1712 htext4->SetMarkerSize(1.8);
1713 htext5->SetMarkerSize(1.8);
1714 htext5->SetMarkerColor(kRed);
1715 htext4->SetBarOffset(0.2);
1716 htext5->SetBarOffset(-0.2);
1717 htext3->Draw("COL");
1718 htext4->Draw("TEXT SAME");
1719 htext5->Draw("TEXT SAME");
1720}
1721End_Macro
1722
1723In the case of profile histograms it is possible to print the number
1724of entries instead of the bin content. It is enough to combine the
1725option "E" (for entries) with the option "TEXT".
1726
1727Begin_Macro(source)
1728{
1729 auto c02 = new TCanvas("c02","c02",700,400);
1730 c02->Divide(2,1);
1731 gStyle->SetPaintTextFormat("g");
1732
1733 auto profile = new TProfile("profile","profile",10,0,10);
1734 profile->SetMarkerSize(2.2);
1735 profile->Fill(0.5,1);
1736 profile->Fill(1.5,2);
1737 profile->Fill(2.5,3);
1738 profile->Fill(3.5,4);
1739 profile->Fill(4.5,5);
1740 profile->Fill(5.5,5);
1741 profile->Fill(6.5,4);
1742 profile->Fill(7.5,3);
1743 profile->Fill(8.5,2);
1744 profile->Fill(9.5,1);
1745 c02->cd(1); profile->Draw("HIST TEXT0");
1746 c02->cd(2); profile->Draw("HIST TEXT0E");
1747}
1748End_Macro
1749
1750\anchor HP16
1751### The CONTour options
1752
1753
1754The following contour options are supported:
1755
1756| Option | Description |
1757|----------|-----------------------------------------------------------------------------|
1758| "CONT" | Draw a contour plot (same as CONT0). |
1759| "CONT0" | Draw a contour plot using surface colors to distinguish contours. |
1760| "CONT1" | Draw a contour plot using the line colors to distinguish contours. |
1761| "CONT2" | Draw a contour plot using the line styles (1 to 5) to distinguish contours. |
1762| "CONT3" | Draw a contour plot using the same line style for all contours. |
1763| "CONT4" | Draw a contour plot using surface colors (`SURF` option at theta = 0). |
1764
1765
1766The following example shows a 2D histogram plotted with the option
1767`CONTZ`. The option `CONT` draws a contour plot using surface
1768colors to distinguish contours. Combined with the option `CONT` (or
1769`CONT0`), the option `Z` allows to display the color palette
1770defined by `gStyle->SetPalette()`.
1771
1772Begin_Macro(source)
1773{
1774 auto c1 = new TCanvas("c1","c1",600,400);
1775 auto hcontz = new TH2F("hcontz","Option CONTZ example ",40,-4,4,40,-20,20);
1776 float px, py;
1777 for (Int_t i = 0; i < 25000; i++) {
1778 gRandom->Rannor(px,py);
1779 hcontz->Fill(px-1,5*py);
1780 hcontz->Fill(2+0.5*px,2*py-10.,0.1);
1781 }
1782 hcontz->Draw("CONTZ");
1783}
1784End_Macro
1785
1786The following example shows a 2D histogram plotted with the option
1787`CONT1Z`. The option `CONT1` draws a contour plot using the
1788line colors to distinguish contours. Combined with the option `CONT1`,
1789the option `Z` allows to display the color palette defined by
1790`gStyle->SetPalette()`.
1791
1792Begin_Macro(source)
1793{
1794 auto c1 = new TCanvas("c1","c1",600,400);
1795 auto hcont1 = new TH2F("hcont1","Option CONT1Z example ",40,-4,4,40,-20,20);
1796 float px, py;
1797 for (Int_t i = 0; i < 25000; i++) {
1798 gRandom->Rannor(px,py);
1799 hcont1->Fill(px-1,5*py);
1800 hcont1->Fill(2+0.5*px,2*py-10.,0.1);
1801 }
1802 hcont1->Draw("CONT1Z");
1803}
1804End_Macro
1805
1806The following example shows a 2D histogram plotted with the option
1807`CONT2`. The option `CONT2` draws a contour plot using the
1808line styles (1 to 5) to distinguish contours.
1809
1810Begin_Macro(source)
1811{
1812 auto c1 = new TCanvas("c1","c1",600,400);
1813 auto hcont2 = new TH2F("hcont2","Option CONT2 example ",40,-4,4,40,-20,20);
1814 float px, py;
1815 for (Int_t i = 0; i < 25000; i++) {
1816 gRandom->Rannor(px,py);
1817 hcont2->Fill(px-1,5*py);
1818 hcont2->Fill(2+0.5*px,2*py-10.,0.1);
1819 }
1820 hcont2->Draw("CONT2");
1821}
1822End_Macro
1823
1824The following example shows a 2D histogram plotted with the option
1825`CONT3`. The option `CONT3` draws contour plot using the same line style for
1826all contours.
1827
1828Begin_Macro(source)
1829{
1830 auto c1 = new TCanvas("c1","c1",600,400);
1831 auto hcont3 = new TH2F("hcont3","Option CONT3 example ",40,-4,4,40,-20,20);
1832 float px, py;
1833 for (Int_t i = 0; i < 25000; i++) {
1834 gRandom->Rannor(px,py);
1835 hcont3->Fill(px-1,5*py);
1836 hcont3->Fill(2+0.5*px,2*py-10.,0.1);
1837 }
1838 hcont3->SetLineStyle(kDotted);
1839 hcont3->Draw("CONT3");
1840}
1841End_Macro
1842
1843The following example shows a 2D histogram plotted with the option
1844`CONT4`. The option `CONT4` draws a contour plot using surface
1845colors to distinguish contours (`SURF` option at theta = 0). Combined
1846with the option `CONT` (or `CONT0`), the option `Z`
1847allows to display the color palette defined by `gStyle->SetPalette()`.
1848
1849Begin_Macro(source)
1850{
1851 auto c1 = new TCanvas("c1","c1",600,400);
1852 auto hcont4 = new TH2F("hcont4","Option CONT4Z example ",40,-4,4,40,-20,20);
1853 float px, py;
1854 for (Int_t i = 0; i < 25000; i++) {
1855 gRandom->Rannor(px,py);
1856 hcont4->Fill(px-1,5*py);
1857 hcont4->Fill(2+0.5*px,2*py-10.,0.1);
1858 }
1859 hcont4->Draw("CONT4Z");
1860}
1861End_Macro
1862
1863The default number of contour levels is 20 equidistant levels and can be changed
1864with `TH1::SetContour()` or `TStyle::SetNumberContours()`.
1865
1866\anchor HP16a
1867#### The LIST option
1868
1869When option `LIST` is specified together with option
1870`CONT`, the points used to draw the contours are saved in
1871`TGraph` objects:
1872
1873 h->Draw("CONT LIST");
1874 gPad->Update();
1875
1876The contour are saved in `TGraph` objects once the pad is painted.
1877Therefore to use this functionality in a macro, `gPad->Update()`
1878should be performed after the histogram drawing. Once the list is
1879built, the contours are accessible in the following way:
1880
1881 TObjArray *contours = (TObjArray*)gROOT->GetListOfSpecials()->FindObject("contours");
1882 Int_t ncontours = contours->GetSize();
1883 TList *list = (TList*)contours->At(i);
1884
1885Where `i` is a contour number, and list contains a list of
1886`TGraph` objects.
1887For one given contour, more than one disjoint polyline may be generated.
1888The number of TGraphs per contour is given by:
1889
1890 list->GetSize();
1891
1892To access the first graph in the list one should do:
1893
1894 TGraph *gr1 = (TGraph*)list->First();
1895
1896
1897The following example (hist102_TH2_contour_list.C) shows how to use this functionality.
1898
1899Begin_Macro(source)
1900../../../tutorials/hist/hist102_TH2_contour_list.C
1901End_Macro
1902
1903\anchor HP16b
1904#### The AITOFF, MERCATOR, SINUSOIDAL and PARABOLIC options
1905
1906The following options select the `CONT4` option and are useful for
1907sky maps or exposure maps (earth.C).
1908
1909| Option | Description |
1910|--------------|---------------------------------------------------------------|
1911| "AITOFF" | Draw a contour via an AITOFF projection.|
1912| "MERCATOR" | Draw a contour via an Mercator projection.|
1913| "SINUSOIDAL" | Draw a contour via an Sinusoidal projection.|
1914| "PARABOLIC" | Draw a contour via an Parabolic projection.|
1915
1916Begin_Macro(source)
1917../../../tutorials/visualisation/graphics/earth.C
1918End_Macro
1919
1920
1921\anchor HP17
1922### The LEGO options
1923
1924
1925In a lego plot the cell contents are drawn as 3-d boxes. The height of each box
1926is proportional to the cell content. The lego aspect is control with the
1927following options:
1928
1929| Option | Description |
1930|----------|-------------------------------------------------------------------|
1931| "LEGO" | Draw a lego plot using the hidden lines removal technique.|
1932| "LEGO1" | Draw a lego plot using the hidden surface removal technique.|
1933| "LEGO2" | Draw a lego plot using colors to show the cell contents.|
1934| "LEGO3" | Draw a lego plot with hidden surface removal, like LEGO1 but the border lines of each lego-bar are not drawn.|
1935| "LEGO4" | Draw a lego plot with hidden surface removal, like LEGO1 but without the shadow effect on each lego-bar.|
1936| "0" | When used with any LEGO option, the empty bins are not drawn.|
1937
1938
1939See the limitations with [the option "SAME"](\ref HP060a).
1940
1941Line attributes can be used in lego plots to change the edges' style.
1942
1943The following example shows a 2D histogram plotted with the option
1944`LEGO`. The option `LEGO` draws a lego plot using the hidden
1945lines removal technique.
1946
1947Begin_Macro(source)
1948{
1949 auto c2 = new TCanvas("c2","c2",600,400);
1950 auto hlego = new TH2F("hlego","Option LEGO example ",40,-4,4,40,-20,20);
1951 float px, py;
1952 for (Int_t i = 0; i < 25000; i++) {
1953 gRandom->Rannor(px,py);
1954 hlego->Fill(px-1,5*py);
1955 hlego->Fill(2+0.5*px,2*py-10.,0.1);
1956 }
1957 hlego->Draw("LEGO");
1958}
1959End_Macro
1960
1961The following example shows a 2D histogram plotted with the option
1962`LEGO1`. The option `LEGO1` draws a lego plot using the
1963hidden surface removal technique. Combined with any `LEGOn` option, the
1964option `0` allows to not drawn the empty bins.
1965
1966Begin_Macro(source)
1967{
1968 auto c2 = new TCanvas("c2","c2",600,400);
1969 auto hlego1 = new TH2F("hlego1","Option LEGO1 example (with option 0) ",40,-4,4,40,-20,20);
1970 float px, py;
1971 for (Int_t i = 0; i < 25000; i++) {
1972 gRandom->Rannor(px,py);
1973 hlego1->Fill(px-1,5*py);
1974 hlego1->Fill(2+0.5*px,2*py-10.,0.1);
1975 }
1976 hlego1->SetFillColor(kYellow);
1977 hlego1->Draw("LEGO1 0");
1978}
1979End_Macro
1980
1981The following example shows a 2D histogram plotted with the option
1982`LEGO3`. Like the option `LEGO1`, the option `LEGO3`
1983draws a lego plot using the hidden surface removal technique but doesn't draw
1984the border lines of each individual lego-bar. This is very useful for histograms
1985having many bins. With such histograms the option `LEGO1` gives a black
1986image because of the border lines. This option also works with stacked legos.
1987
1988Begin_Macro(source)
1989{
1990 auto c2 = new TCanvas("c2","c2",600,400);
1991 auto hlego3 = new TH2F("hlego3","Option LEGO3 example",40,-4,4,40,-20,20);
1992 float px, py;
1993 for (Int_t i = 0; i < 25000; i++) {
1994 gRandom->Rannor(px,py);
1995 hlego3->Fill(px-1,5*py);
1996 hlego3->Fill(2+0.5*px,2*py-10.,0.1);
1997 }
1998 hlego3->SetFillColor(kRed);
1999 hlego3->Draw("LEGO3");
2000}
2001End_Macro
2002
2003The following example shows a 2D histogram plotted with the option
2004`LEGO2`. The option `LEGO2` draws a lego plot using colors to
2005show the cell contents. Combined with the option `LEGO2`, the option
2006`Z` allows to display the color palette defined by
2007`gStyle->SetPalette()`.
2008
2009Begin_Macro(source)
2010{
2011 auto c2 = new TCanvas("c2","c2",600,400);
2012 auto hlego2 = new TH2F("hlego2","Option LEGO2Z example ",40,-4,4,40,-20,20);
2013 float px, py;
2014 for (Int_t i = 0; i < 25000; i++) {
2015 gRandom->Rannor(px,py);
2016 hlego2->Fill(px-1,5*py);
2017 hlego2->Fill(2+0.5*px,2*py-10.,0.1);
2018 }
2019 hlego2->Draw("LEGO2Z");
2020}
2021End_Macro
2022
2023
2024
2025\anchor HP18
2026### The "SURFace" options
2027
2028
2029In a surface plot, cell contents are represented as a mesh.
2030The height of the mesh is proportional to the cell content.
2031
2032| Option | Description |
2033|----------|-------------------------------------------------------------------|
2034| "SURF" | Draw a surface plot using the hidden line removal technique.|
2035| "SURF1" | Draw a surface plot using the hidden surface removal technique.|
2036| "SURF2" | Draw a surface plot using colors to show the cell contents.|
2037| "SURF3" | Same as `SURF` with an additional filled contour plot on top.|
2038| "SURF4" | Draw a surface using the Gouraud shading technique.|
2039| "SURF5" | Used with one of the options CYL, PSR and CYL this option allows to draw a filled contour plot.|
2040| "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.|
2041| "SURF7" | Same as `SURF2` with an additional line contour plot on top.|
2042
2043
2044
2045See the limitations with [the option "SAME"](\ref HP060a).
2046
2047The following example shows a 2D histogram plotted with the option
2048`SURF`. The option `SURF` draws a lego plot using the hidden
2049lines removal technique.
2050
2051Begin_Macro(source)
2052{
2053 auto c2 = new TCanvas("c2","c2",600,400);
2054 auto hsurf = new TH2F("hsurf","Option SURF example ",30,-4,4,30,-20,20);
2055 float px, py;
2056 for (Int_t i = 0; i < 25000; i++) {
2057 gRandom->Rannor(px,py);
2058 hsurf->Fill(px-1,5*py);
2059 hsurf->Fill(2+0.5*px,2*py-10.,0.1);
2060 }
2061 hsurf->Draw("SURF");
2062}
2063End_Macro
2064
2065The following example shows a 2D histogram plotted with the option
2066`SURF1`. The option `SURF1` draws a surface plot using the
2067hidden surface removal technique. Combined with the option `SURF1`,
2068the option `Z` allows to display the color palette defined by
2069`gStyle->SetPalette()`.
2070
2071Begin_Macro(source)
2072{
2073 auto c2 = new TCanvas("c2","c2",600,400);
2074 auto hsurf1 = new TH2F("hsurf1","Option SURF1 example ",30,-4,4,30,-20,20);
2075 float px, py;
2076 for (Int_t i = 0; i < 25000; i++) {
2077 gRandom->Rannor(px,py);
2078 hsurf1->Fill(px-1,5*py);
2079 hsurf1->Fill(2+0.5*px,2*py-10.,0.1);
2080 }
2081 hsurf1->Draw("SURF1");
2082}
2083End_Macro
2084
2085The following example shows a 2D histogram plotted with the option
2086`SURF2`. The option `SURF2` draws a surface plot using colors
2087to show the cell contents. Combined with the option `SURF2`, the option
2088`Z` allows to display the color palette defined by
2089`gStyle->SetPalette()`.
2090
2091Begin_Macro(source)
2092{
2093 auto c2 = new TCanvas("c2","c2",600,400);
2094 auto hsurf2 = new TH2F("hsurf2","Option SURF2 example ",30,-4,4,30,-20,20);
2095 float px, py;
2096 for (Int_t i = 0; i < 25000; i++) {
2097 gRandom->Rannor(px,py);
2098 hsurf2->Fill(px-1,5*py);
2099 hsurf2->Fill(2+0.5*px,2*py-10.,0.1);
2100 }
2101 hsurf2->Draw("SURF2");
2102}
2103End_Macro
2104
2105The following example shows a 2D histogram plotted with the option
2106`SURF3`. The option `SURF3` draws a surface plot using the
2107hidden line removal technique with, in addition, a filled contour view drawn on the
2108top. Combined with the option `SURF3`, the option `Z` allows
2109to display the color palette defined by `gStyle->SetPalette()`.
2110
2111Begin_Macro(source)
2112{
2113 auto c2 = new TCanvas("c2","c2",600,400);
2114 auto hsurf3 = new TH2F("hsurf3","Option SURF3 example ",30,-4,4,30,-20,20);
2115 float px, py;
2116 for (Int_t i = 0; i < 25000; i++) {
2117 gRandom->Rannor(px,py);
2118 hsurf3->Fill(px-1,5*py);
2119 hsurf3->Fill(2+0.5*px,2*py-10.,0.1);
2120 }
2121 hsurf3->Draw("SURF3");
2122}
2123End_Macro
2124
2125The following example shows a 2D histogram plotted with the option
2126`SURF4`. The option `SURF4` draws a surface using the Gouraud
2127shading technique.
2128
2129Begin_Macro(source)
2130{
2131 auto c2 = new TCanvas("c2","c2",600,400);
2132 auto hsurf4 = new TH2F("hsurf4","Option SURF4 example ",30,-4,4,30,-20,20);
2133 float px, py;
2134 for (Int_t i = 0; i < 25000; i++) {
2135 gRandom->Rannor(px,py);
2136 hsurf4->Fill(px-1,5*py);
2137 hsurf4->Fill(2+0.5*px,2*py-10.,0.1);
2138 }
2139 hsurf4->SetFillColor(kOrange);
2140 hsurf4->Draw("SURF4");
2141}
2142End_Macro
2143
2144The following example shows a 2D histogram plotted with the option
2145`SURF5 CYL`. Combined with the option `SURF5`, the option
2146`Z` allows to display the color palette defined by `gStyle->SetPalette()`.
2147
2148Begin_Macro(source)
2149{
2150 auto c2 = new TCanvas("c2","c2",600,400);
2151 auto hsurf5 = new TH2F("hsurf4","Option SURF5 example ",30,-4,4,30,-20,20);
2152 float px, py;
2153 for (Int_t i = 0; i < 25000; i++) {
2154 gRandom->Rannor(px,py);
2155 hsurf5->Fill(px-1,5*py);
2156 hsurf5->Fill(2+0.5*px,2*py-10.,0.1);
2157 }
2158 hsurf5->Draw("SURF5 CYL");
2159}
2160End_Macro
2161
2162The following example shows a 2D histogram plotted with the option
2163`SURF7`. The option `SURF7` draws a surface plot using the
2164hidden surfaces removal technique with, in addition, a line contour view drawn on the
2165top. Combined with the option `SURF7`, the option `Z` allows
2166to display the color palette defined by `gStyle->SetPalette()`.
2167
2168Begin_Macro(source)
2169{
2170 auto c2 = new TCanvas("c2","c2",600,400);
2171 auto hsurf7 = new TH2F("hsurf3","Option SURF7 example ",30,-4,4,30,-20,20);
2172 float px, py;
2173 for (Int_t i = 0; i < 25000; i++) {
2174 gRandom->Rannor(px,py);
2175 hsurf7->Fill(px-1,5*py);
2176 hsurf7->Fill(2+0.5*px,2*py-10.,0.1);
2177 }
2178 hsurf7->Draw("SURF7");
2179}
2180End_Macro
2181
2182As shown in the following example, when a contour plot is painted on top of a
2183surface plot using the option `SAME`, the contours appear in 3D on the
2184surface.
2185
2186Begin_Macro(source)
2187{
2188 auto c20=new TCanvas("c20","c20",600,400);
2189 int NBins = 50;
2190 double d = 2;
2191 auto hsc = new TH2F("hsc", "Surface and contour with option SAME ", NBins, -d, d, NBins, -d, d);
2192 for (int bx = 1; bx <= NBins; ++bx) {
2193 for (int by = 1; by <= NBins; ++by) {
2194 double x = hsc->GetXaxis()->GetBinCenter(bx);
2195 double y = hsc->GetYaxis()->GetBinCenter(by);
2196 hsc->SetBinContent(bx, by, exp(-x*x)*exp(-y*y));
2197 }
2198 }
2199 hsc->Draw("surf2");
2200 hsc->Draw("CONT1 SAME");
2201}
2202End_Macro
2203
2204
2205\anchor HP19
2206### Cylindrical, Polar, Spherical and PseudoRapidity/Phi options
2207
2208
2209Legos and surfaces plots are represented by default in Cartesian coordinates.
2210Combined with any `LEGOn` or `SURFn` options the following
2211options allow to draw a lego or a surface in other coordinates systems.
2212
2213| Option | Description |
2214|----------|-------------------------------------------------------------------|
2215| "CYL" | Use Cylindrical coordinates. The X coordinate is mapped on the angle and the Y coordinate on the cylinder length.|
2216| "POL" | Use Polar coordinates. The X coordinate is mapped on the angle and the Y coordinate on the radius.|
2217| "SPH" | Use Spherical coordinates. The X coordinate is mapped on the latitude and the Y coordinate on the longitude.|
2218| "PSR" | Use PseudoRapidity/Phi coordinates. The X coordinate is mapped on Phi.|
2219
2220
2221
2222<b>WARNING:</b> Axis are not drawn with these options.
2223
2224The following example shows the same histogram as a lego plot is the four
2225different coordinates systems.
2226
2227Begin_Macro(source)
2228{
2229 auto c3 = new TCanvas("c3","c3",600,400);
2230 c3->Divide(2,2);
2231 auto hlcc = new TH2F("hlcc","Cylindrical coordinates",20,-4,4,20,-20,20);
2232 float px, py;
2233 for (Int_t i = 0; i < 25000; i++) {
2234 gRandom->Rannor(px,py);
2235 hlcc->Fill(px-1,5*py);
2236 hlcc->Fill(2+0.5*px,2*py-10.,0.1);
2237 }
2238 hlcc->SetFillColor(kYellow);
2239 c3->cd(1); hlcc->Draw("LEGO1 CYL");
2240 c3->cd(2); auto hlpc = (TH2F*) hlcc->DrawClone("LEGO1 POL");
2241 hlpc->SetTitle("Polar coordinates");
2242 c3->cd(3); auto hlsc = (TH2F*) hlcc->DrawClone("LEGO1 SPH");
2243 hlsc->SetTitle("Spherical coordinates");
2244 c3->cd(4); auto hlprpc = (TH2F*) hlcc->DrawClone("LEGO1 PSR");
2245 hlprpc->SetTitle("PseudoRapidity/Phi coordinates");
2246}
2247End_Macro
2248
2249The following example shows the same histogram as a surface plot is the four different coordinates systems.
2250
2251Begin_Macro(source)
2252{
2253 auto c4 = new TCanvas("c4","c4",600,400);
2254 c4->Divide(2,2);
2255 auto hscc = new TH2F("hscc","Cylindrical coordinates",20,-4,4,20,-20,20);
2256 float px, py;
2257 for (Int_t i = 0; i < 25000; i++) {
2258 gRandom->Rannor(px,py);
2259 hscc->Fill(px-1,5*py);
2260 hscc->Fill(2+0.5*px,2*py-10.,0.1);
2261 }
2262 c4->cd(1); hscc->Draw("SURF1 CYL");
2263 c4->cd(2); auto hspc = (TH2F*) hscc->DrawClone("SURF1 POL");
2264 hspc->SetTitle("Polar coordinates");
2265 c4->cd(3); auto hssc = (TH2F*) hscc->DrawClone("SURF1 SPH");
2266 hssc->SetTitle("Spherical coordinates");
2267 c4->cd(4); auto hsprpc = (TH2F*) hscc->DrawClone("SURF1 PSR");
2268 hsprpc->SetTitle("PseudoRapidity/Phi coordinates");
2269}
2270End_Macro
2271
2272
2273\anchor HP20
2274### Base line for bar-charts and lego plots
2275
2276
2277By default the base line used to draw the boxes for bar-charts and lego plots is
2278the histogram minimum. It is possible to force this base line to be 0, using MIN0 draw
2279option or with the command:
2280
2281 gStyle->SetHistMinimumZero();
2282
2283Begin_Macro(source)
2284{
2285 auto c5 = new TCanvas("c5","c5",700,400);
2286 c5->Divide(2,1);
2287 auto hz1 = new TH1F("hz1","Bar-chart drawn from 0",20,-3,3);
2288 auto hz2 = new TH2F("hz2","Lego plot drawn from 0",20,-3,3,20,-3,3);
2289 Int_t i;
2290 double x,y;
2291 hz1->SetFillColor(kBlue);
2292 hz2->SetFillColor(kBlue);
2293 for (i=0;i<10000;i++) {
2294 x = gRandom->Gaus(0,1);
2295 y = gRandom->Gaus(0,1);
2296 if (x>0) {
2297 hz1->Fill(x,1);
2298 hz2->Fill(x,y,1);
2299 } else {
2300 hz1->Fill(x,-1);
2301 hz2->Fill(x,y,-2);
2302 }
2303 }
2304 c5->cd(1); hz1->Draw("bar2 min0");
2305 c5->cd(2); hz2->Draw("lego1 min0");
2306}
2307End_Macro
2308
2309This option also works for horizontal plots. The example given in the section
2310["The bar chart option"](\ref HP100) appears as follow:
2311
2312Begin_Macro(source)
2313{
2314 int i;
2315 const Int_t nx = 8;
2316 string os_X[nx] = {"8","32","128","512","2048","8192","32768","131072"};
2317 float d_35_0[nx] = {0.75, -3.30, -0.92, 0.10, 0.08, -1.69, -1.29, -2.37};
2318 float d_35_1[nx] = {1.01, -3.02, -0.65, 0.37, 0.34, -1.42, -1.02, -2.10};
2319
2320 auto cbh = new TCanvas("cbh","cbh",400,600);
2321 cbh->SetGrid();
2322
2323 auto h1bh = new TH1F("h1bh","Option HBAR centered on 0",nx,0,nx);
2324 h1bh->SetFillColor(4);
2325 h1bh->SetBarWidth(0.4);
2326 h1bh->SetBarOffset(0.1);
2327 h1bh->SetStats(0);
2328 h1bh->SetMinimum(-5);
2329 h1bh->SetMaximum(5);
2330
2331 for (i=1; i<=nx; i++) {
2332 h1bh->Fill(os_X[i-1].c_str(), d_35_0[i-1]);
2333 h1bh->GetXaxis()->SetBinLabel(i,os_X[i-1].c_str());
2334 }
2335
2336 h1bh->Draw("hbar min0");
2337
2338 auto h2bh = new TH1F("h2bh","h2bh",nx,0,nx);
2339 h2bh->SetFillColor(38);
2340 h2bh->SetBarWidth(0.4);
2341 h2bh->SetBarOffset(0.5);
2342 h2bh->SetStats(0);
2343 for (i=1;i<=nx;i++) h2bh->Fill(os_X[i-1].c_str(), d_35_1[i-1]);
2344
2345 h2bh->Draw("hbar min0 same");
2346}
2347End_Macro
2348
2349
2350\anchor HP20a
2351### TH2Poly Drawing
2352
2353
2354The following options are supported:
2355
2356| Option | Description |
2357|----------|-------------------------------------------------------------------|
2358| "SCAT" | Draw a scatter plot (legacy draw option).|
2359| "COL" | Draw a color plot. All the bins are painted even the empty bins (default).|
2360| "COLZ" | Same as "COL". In addition the color palette is also drawn.|
2361| "0" | When used with any COL options, the empty bins are not drawn.|
2362| "TEXT" | Draw bin contents as text (format set via `gStyle->SetPaintTextFormat`).|
2363| "TEXTN" | Draw bin names as text.|
2364| "TEXTnn" | Draw bin contents as text at angle nn (0 < nn <= 90).|
2365| "L" | Draw the bins boundaries as lines. The lines attributes are the TGraphs ones.|
2366| "P" | Draw the bins boundaries as markers. The markers attributes are the TGraphs ones.|
2367| "F" | Draw the bins boundaries as filled polygons. The filled polygons attributes are the TGraphs ones.|
2368
2369
2370
2371`TH2Poly` can be drawn as a color plot (option COL). `TH2Poly` bins can have any
2372shapes. The bins are defined as graphs. The following macro is a very simple
2373example showing how to book a TH2Poly and draw it.
2374
2375Begin_Macro(source)
2376{
2377 auto ch2p1 = new TCanvas("ch2p1","ch2p1",600,400);
2378 auto h2p = new TH2Poly();
2379 h2p->SetName("h2poly_name");
2380 h2p->SetTitle("h2poly_title");
2381 double px1[] = {0, 5, 6};
2382 double py1[] = {0, 0, 5};
2383 double px2[] = {0, -1, -1, 0};
2384 double py2[] = {0, 0, -1, 3};
2385 double px3[] = {4, 3, 0, 1, 2.4};
2386 double py3[] = {4, 3.7, 1, 3.7, 2.5};
2387 h2p->AddBin(3, px1, py1);
2388 h2p->AddBin(4, px2, py2);
2389 h2p->AddBin(5, px3, py3);
2390 h2p->Fill(0.1, 0.01, 3);
2391 h2p->Fill(-0.5, -0.5, 7);
2392 h2p->Fill(-0.7, -0.5, 1);
2393 h2p->Fill(1, 3, 1.5);
2394 double fx[] = {0.1, -0.5, -0.7, 1};
2395 double fy[] = {0.01, -0.5, -0.5, 3};
2396 double fw[] = {3, 1, 1, 1.5};
2397 h2p->FillN(4, fx, fy, fw);
2398 h2p->Draw("col");
2399}
2400End_Macro
2401
2402Rectangular bins are a frequent case. The special version of
2403the `AddBin` method allows to define them more easily like
2404shown in the following example (hist037_TH2Poly_boxes.C).
2405
2406Begin_Macro(source)
2407../../../tutorials/hist/hist037_TH2Poly_boxes.C
2408End_Macro
2409
2410One `TH2Poly` bin can be a list of polygons. Such bins are defined
2411by calling `AddBin` with a `TMultiGraph`. The following example
2412shows a such case:
2413
2414Begin_Macro(source)
2415{
2416 auto ch2p2 = new TCanvas("ch2p2","ch2p2",600,400);
2417
2418 Int_t i, bin;
2419 const Int_t nx = 48;
2420 const char *states [nx] = {
2421 "alabama", "arizona", "arkansas", "california",
2422 "colorado", "connecticut", "delaware", "florida",
2423 "georgia", "idaho", "illinois", "indiana",
2424 "iowa", "kansas", "kentucky", "louisiana",
2425 "maine", "maryland", "massachusetts", "michigan",
2426 "minnesota", "mississippi", "missouri", "montana",
2427 "nebraska", "nevada", "new_hampshire", "new_jersey",
2428 "new_mexico", "new_york", "north_carolina", "north_dakota",
2429 "ohio", "oklahoma", "oregon", "pennsylvania",
2430 "rhode_island", "south_carolina", "south_dakota", "tennessee",
2431 "texas", "utah", "vermont", "virginia",
2432 "washington", "west_virginia", "wisconsin", "wyoming"
2433 };
2434 Double_t pop[nx] = {
2435 4708708, 6595778, 2889450, 36961664, 5024748, 3518288, 885122, 18537969,
2436 9829211, 1545801, 12910409, 6423113, 3007856, 2818747, 4314113, 4492076,
2437 1318301, 5699478, 6593587, 9969727, 5266214, 2951996, 5987580, 974989,
2438 1796619, 2643085, 1324575, 8707739, 2009671, 19541453, 9380884, 646844,
2439 11542645, 3687050, 3825657, 12604767, 1053209, 4561242, 812383, 6296254,
2440 24782302, 2784572, 621760, 7882590, 6664195, 1819777, 5654774, 544270
2441 };
2442
2443 Double_t lon1 = -130;
2444 Double_t lon2 = -65;
2445 Double_t lat1 = 24;
2446 Double_t lat2 = 50;
2447 auto p = new TH2Poly("USA","USA Population",lon1,lon2,lat1,lat2);
2448
2449 TFile::SetCacheFileDir(".");
2450 auto f = TFile::Open("http://root.cern/files/usa.root", "CACHEREAD");
2451
2452 TMultiGraph *mg;
2453 TKey *key;
2454 TIter nextkey(gDirectory->GetListOfKeys());
2455 while ((key = (TKey*)nextkey())) {
2456 TObject *obj = key->ReadObj();
2457 if (obj->InheritsFrom("TMultiGraph")) {
2458 mg = (TMultiGraph*)obj;
2459 bin = p->AddBin(mg);
2460 }
2461 }
2462
2463 for (i=0; i<nx; i++) p->Fill(states[i], pop[i]);
2464
2465 gStyle->SetOptStat(11);
2466 p->Draw("COLZ L");
2467}
2468End_Macro
2469
2470`TH2Poly` histograms can also be plotted using the GL interface using
2471the option "GLLEGO".
2472
2473\since **ROOT version 6.09/01**
2474
2475In some cases it can be useful to not draw the empty bins. the option "0"
2476combined with the option "COL" and "COLZ" allows to do that.
2477
2478Begin_Macro(source)
2479{
2480 auto chc = new TCanvas("chc","chc",600,400);
2481
2482 auto hc = new TH2Poly();
2483 hc->Honeycomb(0,0,.1,25,25);
2484 hc->SetName("hc");
2485 hc->SetTitle("Option COLZ 0");
2486 TRandom ran;
2487 for (int i = 0; i<300; i++) hc->Fill(ran.Gaus(2.,1), ran.Gaus(2.,1));
2488 hc->Draw("colz 0");
2489}
2490End_Macro
2491
2492\anchor HP21
2493### The SPEC option
2494
2495
2496This option allows to use the `TSpectrum2Painter` tools. See the full
2497documentation in `TSpectrum2Painter::PaintSpectrum`.
2498
2499
2500\anchor HP22
2501### Option "Z" : Adding the color palette on the right side of the pad
2502
2503
2504When this option is specified, a color palette with an axis indicating the value
2505of the corresponding color is drawn on the right side of the picture. In case,
2506not enough space is left, one can increase the size of the right margin by
2507calling `TPad::SetRightMargin()`. The attributes used to display the
2508palette axis values are taken from the Z axis of the object. For example, to
2509set the labels size on the palette axis do:
2510
2511 hist->GetZaxis()->SetLabelSize().
2512
2513<b>WARNING:</b> The palette axis is always drawn vertically.
2514
2515
2516\anchor HP23
2517### Setting the color palette
2518
2519
2520To change the color palette `TStyle::SetPalette` should be used, eg:
2521
2522 gStyle->SetPalette(ncolors,colors);
2523
2524For example the option `COL` draws a 2D histogram with cells
2525represented by a box filled with a color index which is a function
2526of the cell content.
2527If the cell content is N, the color index used will be the color number
2528in `colors[N]`, etc. If the maximum cell content is greater than
2529`ncolors`, all cell contents are scaled to `ncolors`.
2530
2531If ` ncolors <= 0`, a default palette (see below) of 50 colors is
2532defined. This palette is recommended for pads, labels ...
2533
2534`if ncolors == 1 && colors == 0`, then a Pretty Palette with a
2535Spectrum Violet->Red is created with 50 colors. That's the default rain bow
2536palette.
2537
2538Other pre-defined palettes with 255 colors are available when `colors == 0`.
2539The following value of `ncolors` give access to:
2540
2541
2542 if ncolors = 51 and colors=0, a Deep Sea palette is used.
2543 if ncolors = 52 and colors=0, a Grey Scale palette is used.
2544 if ncolors = 53 and colors=0, a Dark Body Radiator palette is used.
2545 if ncolors = 54 and colors=0, a two-color hue palette palette is used.(dark blue through neutral gray to bright
2546yellow) if ncolors = 55 and colors=0, a Rain Bow palette is used. if ncolors = 56 and colors=0, an inverted Dark Body
2547Radiator palette is used.
2548
2549
2550If `ncolors > 0 && colors == 0`, the default palette is used with a maximum of ncolors.
2551
2552The default palette defines:
2553
2554- index 0 to 9 : shades of grey
2555- index 10 to 19 : shades of brown
2556- index 20 to 29 : shades of blue
2557- index 30 to 39 : shades of red
2558- index 40 to 49 : basic colors
2559
2560The color numbers specified in the palette can be viewed by selecting
2561the item `colors` in the `VIEW` menu of the canvas tool bar.
2562The red, green, and blue components of a color can be changed thanks to
2563`TColor::SetRGB()`.
2564
2565\since **ROOT version 6.19/01**
2566
2567As default labels and ticks are drawn by `TGAxis` at equidistant (lin or log)
2568points as controlled by SetNdivisions.
2569If option "CJUST" is given labels and ticks are justified at the
2570color boundaries defined by the contour levels.
2571For more details see `TPaletteAxis`
2572
2573\anchor HP24
2574### Drawing a sub-range of a 2D histogram; the [cutg] option
2575
2576
2577Using a `TCutG` object, it is possible to draw a sub-range of a 2D
2578histogram. One must create a graphical cut (mouse or C++) and specify the name
2579of the cut between `[]` in the `Draw()` option.
2580For example (fit2a.C), with a `TCutG` named `cutg`, one can call:
2581
2582 myhist->Draw("surf1 [cutg]");
2583
2584To invert the cut, it is enough to put a `-` in front of its name:
2585
2586 myhist->Draw("surf1 [-cutg]");
2587
2588It is possible to apply several cuts (`,` means logical AND):
2589
2590 myhist->Draw("surf1 [cutg1,cutg2]");
2591
2592Begin_Macro(source)
2593../../../tutorials/fit/fit2a.C
2594End_Macro
2595
2596\anchor HP25
2597### Drawing options for 3D histograms
2598
2599
2600| Option | Description |
2601|----------|-------------------------------------------------------------------|
2602| "SCAT" | Draw a scatter plot (legacy draw option).|
2603| "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)`|
2604| "BOX" | Draw a for each cell with volume proportional to the content's absolute value. An hidden line removal algorithm is used|
2605| "BOX1" | Same as BOX but an hidden surface removal algorithm is used|
2606| "BOX2" | Same as "COL". The boxes' colors are picked in the current palette according to the bins' contents (default)|
2607| "BOX2Z" | Same as "BOX2". In addition the color palette is also drawn.|
2608| "BOX3" | Same as BOX1, but the border lines of each lego-bar are not drawn.|
2609
2610Note that instead of `BOX` one can also use `LEGO`.
2611
2612By default, 3D histograms are drawn as a colored box plots.
2613
2614The following example shows a 3D histogram plotted as a scatter plot.
2615
2616Begin_Macro(source)
2617{
2618 auto c06 = new TCanvas("c06","c06",600,400);
2619 gStyle->SetOptStat(kFALSE);
2620 auto h3scat = new TH3F("h3scat","Option SCAT",15,-2,2,15,-2,2,15,0,4);
2621 double x, y, z;
2622 for (Int_t i=0;i<10000;i++) {
2623 gRandom->Rannor(x, y);
2624 z = x*x + y*y;
2625 h3scat->Fill(x,y,z);
2626 }
2627 h3scat->Draw("SCAT"); // This a legacy draw option
2628}
2629End_Macro
2630
2631The following example shows a 3D histogram plotted with the option `BOX`.
2632
2633Begin_Macro(source)
2634{
2635 auto c16 = new TCanvas("c16","c16",600,400);
2636 gStyle->SetOptStat(kFALSE);
2637 auto h3box = new TH3F("h3box","Option BOX",15,-2,2,15,-2,2,15,0,4);
2638 double x, y, z;
2639 for (Int_t i=0;i<10000;i++) {
2640 gRandom->Rannor(x, y);
2641 z = x*x + y*y;
2642 h3box->Fill(x,y,z);
2643 }
2644 h3box->Draw("BOX");
2645}
2646End_Macro
2647
2648The following example shows a 3D histogram plotted with the option `BOX1`.
2649
2650Begin_Macro(source)
2651{
2652 auto c36 = new TCanvas("c36","c36",600,400);
2653 gStyle->SetOptStat(kFALSE);
2654 auto h3box = new TH3F("h3box","Option BOX1",10,-2.,2.,10,-2.,2.,10,-0.5,2.);
2655 double x, y, z;
2656 for (Int_t i=0;i<10000;i++) {
2657 gRandom->Rannor(x, y);
2658 z = abs(sin(x)/x + cos(y)*y);
2659 h3box->Fill(x,y,z);
2660 }
2661 h3box->SetFillColor(9);
2662 h3box->Draw("BOX1");
2663}
2664End_Macro
2665
2666The following example shows a 3D histogram plotted with the option `BOX2`.
2667
2668Begin_Macro(source)
2669{
2670 auto c56 = new TCanvas("c56","c56",600,400);
2671 gStyle->SetOptStat(kFALSE);
2672 auto h3box = new TH3F("h3box","Option BOX2 (default)",10,-2.,2.,10,-2.,2.,10,-0.5,2.);
2673 double x, y, z;
2674 for (Int_t i=0;i<10000;i++) {
2675 gRandom->Rannor(x, y);
2676 z = abs(sin(x)/x + cos(y)*y);
2677 h3box->Fill(x,y,z);
2678 }
2679 h3box->Draw("BOX2 Z");
2680}
2681End_Macro
2682
2683The following example shows a 3D histogram plotted with the option `BOX3`.
2684
2685Begin_Macro(source)
2686{
2687 auto c46 = new TCanvas("c46","c46",600,400);
2688 c46->SetFillColor(38);
2689 gStyle->SetOptStat(kFALSE);
2690 auto h3box = new TH3F("h3box","Option BOX3",15,-2,2,15,-2,2,15,0,4);
2691 double x, y, z;
2692 for (Int_t i=0;i<10000;i++) {
2693 gRandom->Rannor(x, y);
2694 z = x*x + y*y;
2695 h3box->Fill(x,y,z);
2696 }
2697 h3box->Draw("BOX3");
2698}
2699End_Macro
2700
2701For all the `BOX` options each bin is drawn as a 3D box with a volume proportional
2702to the absolute value of the bin content. The bins with a negative content are
2703drawn with a X on each face of the box as shown in the following example:
2704
2705Begin_Macro(source)
2706{
2707 auto c = new TCanvas("c","c",600,400);
2708 gStyle->SetOptStat(kFALSE);
2709 auto h3box = new TH3F("h3box","Option BOX1 with negative bins",3, 0., 4., 3, 0.,4., 3, 0., 4.);
2710 h3box->Fill(0., 2., 2., 10.);
2711 h3box->Fill(2., 2., 2., 5.);
2712 h3box->Fill(2., 2., .5, 2.);
2713 h3box->Fill(2., 2., 3., -1.);
2714 h3box->Fill(3., 2., 2., -10.);
2715 h3box->SetFillColor(8);
2716 h3box->Draw("box1");
2717}
2718End_Macro
2719
2720The following example shows a 3D histogram plotted with the option `ISO`.
2721
2722Begin_Macro(source)
2723{
2724 auto c26 = new TCanvas("c26","c26",600,400);
2725 gStyle->SetOptStat(kFALSE);
2726 auto h3iso = new TH3F("h3iso","Option ISO",15,-2,2,15,-2,2,15,0,4);
2727 double x, y, z;
2728 for (Int_t i=0;i<10000;i++) {
2729 gRandom->Rannor(x, y);
2730 z = x*x + y*y;
2731 h3iso->Fill(x,y,z);
2732 }
2733 h3iso->SetFillColor(kCyan);
2734 h3iso->Draw("ISO");
2735}
2736End_Macro
2737
2738
2739\anchor HP26
2740### Drawing option for histograms' stacks
2741
2742
2743Stacks of histograms are managed with the `THStack`. A `THStack`
2744is a collection of `TH1` (or derived) objects. For painting only the
2745`THStack` containing `TH1` only or
2746`THStack` containing `TH2` only will be considered.
2747
2748By default, histograms are shown stacked:
2749
27501. The first histogram is paint.
27512. The sum of the first and second, etc...
2752
2753If the option `NOSTACK` is specified, the histograms are all paint in
2754the same pad as if the option `SAME` had been specified. This allows to
2755compute X and Y scales common to all the histograms, like
2756`TMultiGraph` does for graphs.
2757
2758If the option `PADS` is specified, the current pad/canvas is subdivided into
2759a number of pads equal to the number of histograms and each histogram is paint
2760into a separate pad. With `PADSn`, the current pad/canvas is subdivided into
2761`n` columns, automatically calculating the number of rows.
2762
2763The following example shows various types of stacks (hist023_THStack_simple.C).
2764
2765Begin_Macro(source)
2766../../../tutorials/hist/hist023_THStack_simple.C
2767End_Macro
2768
2769The option `nostackb` allows to draw the histograms next to each
2770other as bar charts:
2771
2772Begin_Macro(source)
2773{
2774 auto cst0 = new TCanvas("cst0","cst0",600,400);
2775 auto hs = new THStack("hs","Stacked 1D histograms: option #font[82]{\"nostackb\"}");
2776
2777 auto h1 = new TH1F("h1","h1",10,-4,4);
2778 h1->FillRandom("gaus",20000);
2779 h1->SetFillColor(kRed);
2780 hs->Add(h1);
2781
2782 auto h2 = new TH1F("h2","h2",10,-4,4);
2783 h2->FillRandom("gaus",15000);
2784 h2->SetFillColor(kBlue);
2785 hs->Add(h2);
2786
2787 auto h3 = new TH1F("h3","h3",10,-4,4);
2788 h3->FillRandom("gaus",10000);
2789 h3->SetFillColor(kGreen);
2790 hs->Add(h3);
2791
2792 hs->Draw("nostackb");
2793 hs->GetXaxis()->SetNdivisions(-10);
2794 cst0->SetGridx();
2795}
2796End_Macro
2797
2798If at least one of the histograms in the stack has errors, the whole stack is
2799visualized by default with error bars. To visualize it without errors the
2800option `HIST` should be used.
2801
2802Begin_Macro(source)
2803{
2804 auto cst1 = new TCanvas("cst1","cst1",700,400);
2805 cst1->Divide(2,1);
2806
2807 auto hst11 = new TH1F("hst11", "", 20, -10, 10);
2808 hst11->Sumw2();
2809 hst11->FillRandom("gaus", 1000);
2810 hst11->SetFillColor(kViolet);
2811 hst11->SetLineColor(kViolet);
2812
2813 auto hst12 = new TH1F("hst12", "", 20, -10, 10);
2814 hst12->FillRandom("gaus", 500);
2815 hst12->SetFillColor(kBlue);
2816 hst12->SetLineColor(kBlue);
2817
2818 THStack st1("st1", "st1");
2819 st1.Add(hst11);
2820 st1.Add(hst12);
2821
2822 cst1->cd(1); st1.Draw();
2823 cst1->cd(2); st1.Draw("hist");
2824}
2825End_Macro
2826
2827\anchor HP27
2828### Drawing of 3D implicit functions
2829
2830
28313D implicit functions (`TF3`) can be drawn as iso-surfaces.
2832The implicit function f(x,y,z) = 0 is drawn in cartesian coordinates.
2833In the following example the options "FB" and "BB" suppress the
2834"Front Box" and "Back Box" around the plot.
2835
2836Begin_Macro(source)
2837{
2838 auto c2 = new TCanvas("c2","c2",600,400);
2839 auto f3 = new TF3("f3","sin(x*x+y*y+z*z-36)",-2,2,-2,2,-2,2);
2840 f3->SetClippingBoxOn(0,0,0);
2841 f3->SetFillColor(30);
2842 f3->SetLineColor(15);
2843 f3->Draw("FBBB");
2844}
2845End_Macro
2846
2847
2848\anchor HP28
2849### Associated functions drawing
2850
2851
2852An associated function is created by `TH1::Fit`. More than on fitted
2853function can be associated with one histogram (see `TH1::Fit`).
2854
2855A `TF1` object `f1` can be added to the list of associated
2856functions of an histogram `h` without calling `TH1::Fit`
2857simply doing:
2858
2859 h->GetListOfFunctions()->Add(f1);
2860
2861or
2862
2863 h->GetListOfFunctions()->Add(f1,someoption);
2864
2865To retrieve a function by name from this list, do:
2866
2867 TF1 *f1 = (TF1*)h->GetListOfFunctions()->FindObject(name);
2868
2869or
2870
2871 TF1 *f1 = h->GetFunction(name);
2872
2873Associated functions are automatically painted when an histogram is drawn.
2874To avoid the painting of the associated functions the option `HIST`
2875should be added to the list of the options used to paint the histogram.
2876
2877
2878\anchor HP29
2879### Drawing using OpenGL
2880
2881
2882The class `TGLHistPainter` allows to paint data set using the OpenGL 3D
2883graphics library. The plotting options start with `GL` keyword.
2884In addition, in order to inform canvases that OpenGL should be used to render
28853D representations, the following option should be set:
2886
2887 gStyle->SetCanvasPreferGL(true);
2888
2889
2890\anchor HP29a
2891#### General information: plot types and supported options
2892
2893The following types of plots are provided:
2894
2895For lego plots the supported options are:
2896
2897| Option | Description |
2898|----------|-------------------------------------------------------------------|
2899| "GLLEGO" | Draw a lego plot. It works also for `TH2Poly`.|
2900| "GLLEGO2"| Bins with color levels.|
2901| "GLLEGO3"| Cylindrical bars.|
2902
2903
2904
2905Lego painter in cartesian supports logarithmic scales for X, Y, Z.
2906In polar only Z axis can be logarithmic, in cylindrical only Y.
2907
2908For surface plots (`TF2` and `TH2`) the supported options are:
2909
2910| Option | Description |
2911|-----------|------------------------------------------------------------------|
2912| "GLSURF" | Draw a surface.|
2913| "GLSURF1" | Surface with color levels|
2914| "GLSURF2" | The same as "GLSURF1" but without polygon outlines.|
2915| "GLSURF3" | Color level projection on top of plot (works only in cartesian coordinate system).|
2916| "GLSURF4" | Same as "GLSURF" but without polygon outlines.|
2917
2918
2919
2920The surface painting in cartesian coordinates supports logarithmic scales along
2921X, Y, Z axis. In polar coordinates only the Z axis can be logarithmic,
2922in cylindrical coordinates only the Y axis.
2923
2924Additional options to SURF and LEGO - Coordinate systems:
2925
2926| Option | Description |
2927|----------|-------------------------------------------------------------------|
2928| " " | Default, cartesian coordinates system.|
2929| "POL" | Polar coordinates system.|
2930| "CYL" | Cylindrical coordinates system.|
2931| "SPH" | Spherical coordinates system.|
2932
2933
2934
2935\anchor HP290
2936#### TH3 as color boxes
2937
2938The supported option is:
2939
2940| Option | Description |
2941|----------|-------------------------------------------------------------------|
2942| "GLCOL" | H3 is drawn using semi-transparent colored boxes. See glvox1.C .|
2943
2944
2945
2946\anchor HP29b
2947#### TH3 as boxes (spheres)
2948
2949The supported options are:
2950
2951| Option | Description |
2952|----------|-------------------------------------------------------------------|
2953| "GLBOX" | TH3 as a set of boxes, size of box is proportional to bin content.|
2954| "GLBOX1" | The same as "glbox", but spheres are drawn instead of boxes.|
2955
2956
2957
2958\anchor HP29c
2959#### TH3 as iso-surface(s)
2960
2961The supported option is:
2962
2963| Option | Description |
2964|----------|-------------------------------------------------------------------|
2965| "GLISO" | TH3 is drawn using iso-surfaces.|
2966
2967
2968
2969\anchor HP29d
2970#### TF3 (implicit function)
2971
2972The supported option is:
2973
2974| Option | Description |
2975|----------|-------------------------------------------------------------------|
2976| "GL" | Draw a TF3.|
2977
2978
2979
2980\anchor HP29e
2981#### Parametric surfaces
2982
2983glparametric.C shows how to create parametric equations and visualize the surface.
2984
2985\anchor HP29f
2986#### Interaction with the plots
2987
2988All the interactions are implemented via standard methods
2989`DistancetoPrimitive()` and `ExecuteEvent()`. That's why all the
2990interactions with the OpenGL plots are possible only when the mouse cursor is
2991in the plot's area (the plot's area is the part of a the pad occupied by
2992gl-produced picture). If the mouse cursor is not above gl-picture, the standard
2993pad interaction is performed.
2994
2995\anchor HP29g
2996#### Selectable parts
2997
2998Different parts of the plot can be selected:
2999
3000- xoz, yoz, xoy back planes: When such a plane selected, it's highlighted in green
3001 if the dynamic slicing by this plane is supported, and it's highlighted in red,
3002 if the dynamic slicing is not supported.
3003- The plot itself:
3004 On surfaces, the selected surface is outlined in red. (TF3 and
3005 ISO are not outlined). On lego plots, the selected bin is
3006 highlighted. The bin number and content are displayed in pad's
3007 status bar. In box plots, the box or sphere is highlighted and
3008 the bin info is displayed in pad's status bar.
3009
3010
3011\anchor HP29h
3012#### Rotation and zooming
3013
3014
3015- Rotation:
3016 When the plot is selected, it can be rotated by pressing and
3017 holding the left mouse button and move the cursor.
3018- Zoom/Unzoom:
3019 Mouse wheel or 'j', 'J', 'k', 'K' keys.
3020
3021
3022\anchor HP29i
3023#### Panning
3024
3025The selected plot can be moved in a pad's area by pressing and
3026holding the left mouse button and the shift key.
3027
3028\anchor HP29j
3029#### Box cut
3030
3031Surface, iso, box, TF3 and parametric painters support box cut by
3032pressing the 'c' or 'C' key when the mouse cursor is in a plot's
3033area. That will display a transparent box, cutting away part of the
3034surface (or boxes) in order to show internal part of plot. This box
3035can be moved inside the plot's area (the full size of the box is
3036equal to the plot's surrounding box) by selecting one of the box
3037cut axes and pressing the left mouse button to move it.
3038
3039\anchor HP29k
3040#### Plot specific interactions (dynamic slicing etc.)
3041
3042Currently, all gl-plots support some form of slicing. When back plane
3043is selected (and if it's highlighted in green) you can press and hold
3044left mouse button and shift key and move this back plane inside
3045plot's area, creating the slice. During this "slicing" plot becomes
3046semi-transparent. To remove all slices (and projected curves for
3047surfaces) double click with left mouse button in a plot's area.
3048
3049\anchor HP29l
3050#### Surface with option "GLSURF"
3051
3052The surface profile is displayed on the slicing plane.
3053The profile projection is drawn on the back plane
3054by pressing `'p'` or `'P'` key.
3055
3056\anchor HP29m
3057#### TF3
3058
3059The contour plot is drawn on the slicing plane. For TF3 the color
3060scheme can be changed by pressing 's' or 'S'.
3061
3062\anchor HP29n
3063#### Box
3064
3065The contour plot corresponding to slice plane position is drawn in real time.
3066
3067\anchor HP29o
3068#### Iso
3069
3070Slicing is similar to "GLBOX" option.
3071
3072\anchor HP29p
3073#### Parametric plot
3074
3075No slicing. Additional keys: 's' or 'S' to change color scheme -
3076about 20 color schemes supported ('s' for "scheme"); 'l' or 'L' to
3077increase number of polygons ('l' for "level" of details), 'w' or 'W'
3078to show outlines ('w' for "wireframe").
3079
3080\anchor HP30
3081#### Highlight mode for histogram
3082
3083\since **ROOT version 6.15/01**
3084
3085\image html hlHisto3_top.gif "Highlight mode"
3086
3087Highlight mode is implemented for `TH1` (and for `TGraph`) class. When
3088highlight mode is on, mouse movement over the bin will be represented
3089graphically. Bin will be highlighted as "bin box" (presented by box
3090object). Moreover, any highlight (change of bin) emits signal
3091`TCanvas::Highlighted()` which allows the user to react and call their own
3092function. For a better understanding see also the tutorial `hist043` to `hist046`
3093located in `$ROOTSYS/tutorials/hist/`.
3094
3095Highlight mode is switched on/off by `TH1::SetHighlight()` function
3096or interactively from `TH1` context menu. `TH1::IsHighlight()` to verify
3097whether the highlight mode enabled or disabled, default it is disabled.
3098
3099~~~ {.cpp}
3100 root [0] .x $ROOTSYS/tutorials/hsimple.C
3101 root [1] hpx->SetHighlight(kTRUE) // or interactively from TH1 context menu
3102 root [2] hpx->IsHighlight()
3103 (bool) true
3104~~~
3105
3106\image html hlsimple_nofun.gif "Highlight mode for histogram"
3107
3108\anchor HP30a
3109#### Highlight mode and user function
3110
3111The user can use (connect) `TCanvas::Highlighted()` signal, which is always
3112emitted if there is a highlight bin and call user function via signal
3113and slot communication mechanism. `TCanvas::Highlighted()` is similar
3114`TCanvas::Picked()`
3115
3116- when selected object (histogram as a whole) is different from previous
3117then emit `Picked()` signal
3118- when selected (highlighted) bin from histogram is different from previous
3119then emit `Highlighted()` signal
3120
3121Any user function (or functions) has to be defined
3122`UserFunction(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)`.
3123In example (see below) has name `PrintInfo()`. All parameters of user
3124function are taken from
3125
3126 void TCanvas::Highlighted(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)
3127
3128- `pad` is pointer to pad with highlighted histogram
3129- `obj` is pointer to highlighted histogram
3130- `x` is highlighted x bin for 1D histogram
3131- `y` is highlighted y bin for 2D histogram (for 1D histogram not in use)
3132
3133Example how to create a connection from any `TCanvas` object to a user
3134`UserFunction()` slot (see also `TQObject::Connect()` for additional info)
3135
3136 TQObject::Connect("TCanvas", "Highlighted(TVirtualPad*,TObject*,Int_t,Int_t)",
3137 0, 0, "UserFunction(TVirtualPad*,TObject*,Int_t,Int_t)");
3138
3139or use non-static "simplified" function
3140`TCanvas::HighlightConnect(const char *slot)`
3141
3142 c1->HighlightConnect("UserFunction(TVirtualPad*,TObject*,Int_t,Int_t)");
3143
3144NOTE the signal and slot string must have a form
3145"(TVirtualPad*,TObject*,Int_t,Int_t)"
3146
3147 root [0] .x $ROOTSYS/tutorials/hsimple.C
3148 root [1] hpx->SetHighlight(kTRUE)
3149 root [2] .x hlprint.C
3150
3151file `hlprint.C`
3152~~~ {.cpp}
3153void PrintInfo(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)
3154{
3155 auto h = (TH1F *)obj;
3156 if (!h->IsHighlight()) // after highlight disabled
3157 h->SetTitle("highlight disable");
3158 else
3159 h->SetTitle(TString::Format("bin[%03d] (%5.2f) content %g", x,
3160 h->GetBinCenter(x), h->GetBinContent(x)));
3161 pad->Update();
3162}
3163
3164void hlprint()
3165{
3166 if (!gPad) return;
3167 gPad->GetCanvas()->HighlightConnect("PrintInfo(TVirtualPad*,TObject*,Int_t,Int_t)");
3168}
3169~~~
3170
3171\image html hlsimple.gif "Highlight mode and simple user function"
3172
3173For more complex demo please see for example tree200_temperature.C file.
3174
3175*/
3176
3178
3181
3182const Int_t kNMAX = 2000;
3183
3184const Int_t kMAXCONTOUR = 104;
3186
3187static std::unique_ptr<TBox> gXHighlightBox, gYHighlightBox; // highlight X and Y box
3188
3210
3211
3212////////////////////////////////////////////////////////////////////////////////
3213/// Default constructor.
3214
3216{
3217 fH = nullptr;
3218 fXaxis = nullptr;
3219 fYaxis = nullptr;
3220 fZaxis = nullptr;
3221 fFunctions = nullptr;
3222 fNcuts = 0;
3223 fStack = nullptr;
3224 fShowProjection = 0;
3225 fShowProjection2 = 0;
3226 fShowOption = "";
3227 for (int i=0; i<kMaxCuts; i++) {
3228 fCuts[i] = nullptr;
3229 fCutsOpt[i] = 0;
3230 }
3231 fXHighlightBin = -1;
3232 fYHighlightBin = -1;
3233 fCurrentF3 = nullptr;
3234
3235 gStringEntries = gEnv->GetValue("Hist.Stats.Entries", "Entries");
3236 gStringMean = gEnv->GetValue("Hist.Stats.Mean", "Mean");
3237 gStringMeanX = gEnv->GetValue("Hist.Stats.MeanX", "Mean x");
3238 gStringMeanY = gEnv->GetValue("Hist.Stats.MeanY", "Mean y");
3239 gStringMeanZ = gEnv->GetValue("Hist.Stats.MeanZ", "Mean z");
3240 gStringStdDev = gEnv->GetValue("Hist.Stats.StdDev", "Std Dev");
3241 gStringStdDevX = gEnv->GetValue("Hist.Stats.StdDevX", "Std Dev x");
3242 gStringStdDevY = gEnv->GetValue("Hist.Stats.StdDevY", "Std Dev y");
3243 gStringStdDevZ = gEnv->GetValue("Hist.Stats.StdDevZ", "Std Dev z");
3244 gStringUnderflow = gEnv->GetValue("Hist.Stats.Underflow", "Underflow");
3245 gStringOverflow = gEnv->GetValue("Hist.Stats.Overflow", "Overflow");
3246 gStringIntegral = gEnv->GetValue("Hist.Stats.Integral", "Integral");
3247 gStringIntegralBinWidth = gEnv->GetValue("Hist.Stats.IntegralBinWidth", "Integral(w)");
3248 gStringSkewness = gEnv->GetValue("Hist.Stats.Skewness", "Skewness");
3249 gStringSkewnessX = gEnv->GetValue("Hist.Stats.SkewnessX", "Skewness x");
3250 gStringSkewnessY = gEnv->GetValue("Hist.Stats.SkewnessY", "Skewness y");
3251 gStringSkewnessZ = gEnv->GetValue("Hist.Stats.SkewnessZ", "Skewness z");
3252 gStringKurtosis = gEnv->GetValue("Hist.Stats.Kurtosis", "Kurtosis");
3253 gStringKurtosisX = gEnv->GetValue("Hist.Stats.KurtosisX", "Kurtosis x");
3254 gStringKurtosisY = gEnv->GetValue("Hist.Stats.KurtosisY", "Kurtosis y");
3255 gStringKurtosisZ = gEnv->GetValue("Hist.Stats.KurtosisZ", "Kurtosis z");
3256}
3257
3258////////////////////////////////////////////////////////////////////////////////
3259/// destructor.
3260
3264
3265////////////////////////////////////////////////////////////////////////////////
3266/// Compute the distance from the point px,py to a line.
3267///
3268/// Compute the closest distance of approach from point px,py to elements of
3269/// an histogram. The distance is computed in pixels units.
3270///
3271/// Algorithm: Currently, this simple model computes the distance from the mouse
3272/// to the histogram contour only.
3273
3275{
3276
3277 Double_t defaultLabelSize = 0.04; // See TAttAxis.h for source of this value
3278
3279 const Int_t big = 9999;
3280 const Int_t kMaxDiff = 7;
3281
3282 if (fPie)
3283 return fPie->DistancetoPrimitive(px, py);
3284
3285 Double_t x = gPad->AbsPixeltoX(px);
3286 Double_t x1 = gPad->AbsPixeltoX(px+1);
3287
3288 Int_t puxmin = gPad->XtoAbsPixel(gPad->GetUxmin());
3289 Int_t puymin = gPad->YtoAbsPixel(gPad->GetUymin());
3290 Int_t puxmax = gPad->XtoAbsPixel(gPad->GetUxmax());
3291 Int_t puymax = gPad->YtoAbsPixel(gPad->GetUymax());
3292 Int_t curdist = big;
3293 Int_t yxaxis, dyaxis,xyaxis, dxaxis;
3294 Bool_t dsame;
3295 TObject *PadPointer = gPad->GetPadPointer();
3296 if (!PadPointer) return 0;
3297 TString doption = PadPointer->GetDrawOption();
3298 Double_t factor = 1;
3299 if (fH->GetNormFactor() != 0) {
3300 factor = fH->GetNormFactor()/fH->GetSumOfWeights();
3301 }
3302 // return if point is not in the histogram area
3303
3304 // If a 3D view exists, check distance to axis
3305 TView *view = gPad->GetView();
3306 Int_t d1,d2,d3;
3307 if (view && Hoption.Contour != 14) {
3308 Double_t ratio;
3309 d3 = view->GetDistancetoAxis(3, px, py, ratio);
3310 if (d3 <= kMaxDiff) {gPad->SetSelected(fZaxis); return 0;}
3311 d1 = view->GetDistancetoAxis(1, px, py, ratio);
3312 if (d1 <= kMaxDiff) {gPad->SetSelected(fXaxis); return 0;}
3313 d2 = view->GetDistancetoAxis(2, px, py, ratio);
3314 if (d2 <= kMaxDiff) {gPad->SetSelected(fYaxis); return 0;}
3315 if ( px > puxmin && px < puxmax && py > puymax && py < puymin) curdist = 1;
3316 goto FUNCTIONS;
3317 }
3318 // check if point is close to an axis
3319 doption.ToLower();
3320 dsame = kFALSE;
3321 if (doption.Contains("same")) dsame = kTRUE;
3322
3323 dyaxis = Int_t(2*(puymin-puymax)*TMath::Max(Double_t(fYaxis->GetLabelSize()), defaultLabelSize));
3324 if (doption.Contains("y+")) {
3325 xyaxis = puxmax + Int_t((puxmax-puxmin)*fYaxis->GetLabelOffset());
3326 if (px <= xyaxis+dyaxis && px >= xyaxis && py >puymax && py < puymin) {
3327 if (!dsame) {
3328 if (gPad->IsVertical()) gPad->SetSelected(fYaxis);
3329 else gPad->SetSelected(fXaxis);
3330 return 0;
3331 }
3332 }
3333 } else {
3334 xyaxis = puxmin - Int_t((puxmax-puxmin)*fYaxis->GetLabelOffset());
3335 if (px >= xyaxis-dyaxis && px <= xyaxis && py >puymax && py < puymin) {
3336 if (!dsame) {
3337 if (gPad->IsVertical()) gPad->SetSelected(fYaxis);
3338 else gPad->SetSelected(fXaxis);
3339 return 0;
3340 }
3341 }
3342 }
3343
3344 dxaxis = Int_t((puymin-puymax)*TMath::Max(Double_t(fXaxis->GetLabelSize()), defaultLabelSize));
3345 if (doption.Contains("x+")) {
3346 yxaxis = puymax - Int_t((puymin-puymax)*fXaxis->GetLabelOffset());
3347 if (py >= yxaxis-dxaxis && py <= yxaxis && px <puxmax && px > puxmin) {
3348 if (!dsame) {
3349 if (gPad->IsVertical()) gPad->SetSelected(fXaxis);
3350 else gPad->SetSelected(fYaxis);
3351 return 0;
3352 }
3353 }
3354 } else {
3355 yxaxis = puymin + Int_t((puymin-puymax)*fXaxis->GetLabelOffset());
3356 if (yxaxis < puymin) yxaxis = puymin;
3357 if (py <= yxaxis+dxaxis && py >= yxaxis && px <puxmax && px > puxmin) {
3358 if (!dsame) {
3359 if (gPad->IsVertical()) gPad->SetSelected(fXaxis);
3360 else gPad->SetSelected(fYaxis);
3361 return 0;
3362 }
3363 }
3364 }
3365
3366 if (fH->IsHighlight()) { // only if highlight is enable
3367 if ((px > puxmin) && (py < puymin) && (px < puxmax) && (py > puymax))
3368 HighlightBin(px, py);
3369 }
3370
3371 // if object is 2D or 3D return this object
3372 if (fH->GetDimension() == 2) {
3373 if (fH->InheritsFrom(TH2Poly::Class())) {
3374 TH2Poly *th2 = (TH2Poly*)fH;
3376 gPad->GetRangeAxis(xmin, ymin, xmax, ymax);
3377 Double_t pxu = gPad->AbsPixeltoX(px);
3378 Double_t pyu = gPad->AbsPixeltoY(py);
3379 if ((pxu>xmax) || (pxu < xmin) || (pyu>ymax) || (pyu < ymin)) {
3380 curdist = big;
3381 goto FUNCTIONS;
3382 } else {
3383 Int_t bin = th2->FindBin(pxu, pyu);
3384 if (bin>0) curdist = 1;
3385 else curdist = big;
3386 goto FUNCTIONS;
3387 }
3388 }
3389 Int_t delta2 = 5; //Give a margin of delta2 pixels to be in the 2-d area
3390 if ( px > puxmin + delta2
3391 && px < puxmax - delta2
3392 && py > puymax + delta2
3393 && py < puymin - delta2) {curdist =1; goto FUNCTIONS;}
3394 }
3395
3396 // point is inside histogram area. Find channel number
3397 if (gPad->IsVertical()) {
3398 Int_t bin = fXaxis->FindFixBin(gPad->PadtoX(x));
3399 Int_t binsup = fXaxis->FindFixBin(gPad->PadtoX(x1));
3400 Double_t binval = factor*fH->GetBinContent(bin);
3401 Int_t pybin = gPad->YtoAbsPixel(gPad->YtoPad(binval));
3402 if (binval == 0 && pybin < puymin) pybin = 10000;
3403 // special case if more than one bin for the pixel
3404 if (binsup-bin>1) {
3405 Double_t binvalmin, binvalmax;
3406 binvalmin=binval;
3407 binvalmax=binval;
3408 for (Int_t ibin=bin+1; ibin<binsup; ibin++) {
3409 Double_t binvaltmp = factor*fH->GetBinContent(ibin);
3410 if (binvalmin>binvaltmp) binvalmin=binvaltmp;
3411 if (binvalmax<binvaltmp) binvalmax=binvaltmp;
3412 }
3413 Int_t pybinmin = gPad->YtoAbsPixel(gPad->YtoPad(binvalmax));
3414 Int_t pybinmax = gPad->YtoAbsPixel(gPad->YtoPad(binvalmin));
3415 if (py<pybinmax+kMaxDiff/2 && py>pybinmin-kMaxDiff/2) pybin = py;
3416 }
3417 if (bin != binsup) { // Mouse on bin border
3418 Double_t binsupval = factor*fH->GetBinContent(binsup);
3419 Int_t pybinsub = gPad->YtoAbsPixel(gPad->YtoPad(binsupval));
3420 if (py <= TMath::Max(pybinsub,pybin) && py >= TMath::Min(pybinsub,pybin) && pybin != 10000) return 0;
3421 }
3422 if (TMath::Abs(py - pybin) <= kMaxDiff) return TMath::Abs(py - pybin);
3423 } else {
3424 Double_t y = gPad->AbsPixeltoY(py);
3425 Double_t y1 = gPad->AbsPixeltoY(py+1);
3426 Int_t bin = fXaxis->FindFixBin(gPad->PadtoY(y));
3427 Int_t binsup = fXaxis->FindFixBin(gPad->PadtoY(y1));
3428 Double_t binval = factor*fH->GetBinContent(bin);
3429 Int_t pxbin = gPad->XtoAbsPixel(gPad->XtoPad(binval));
3430 if (binval == 0 && pxbin > puxmin) pxbin = 10000;
3431 // special case if more than one bin for the pixel
3432 if (binsup-bin>1) {
3433 Double_t binvalmin, binvalmax;
3434 binvalmin=binval;
3435 binvalmax=binval;
3436 for (Int_t ibin=bin+1; ibin<binsup; ibin++) {
3437 Double_t binvaltmp = factor*fH->GetBinContent(ibin);
3438 if (binvalmin>binvaltmp) binvalmin=binvaltmp;
3439 if (binvalmax<binvaltmp) binvalmax=binvaltmp;
3440 }
3441 Int_t pxbinmin = gPad->XtoAbsPixel(gPad->XtoPad(binvalmax));
3442 Int_t pxbinmax = gPad->XtoAbsPixel(gPad->XtoPad(binvalmin));
3443 if (px<pxbinmax+kMaxDiff/2 && px>pxbinmin-kMaxDiff/2) pxbin = px;
3444 }
3445 if (TMath::Abs(px - pxbin) <= kMaxDiff) return TMath::Abs(px - pxbin);
3446 }
3447 // Loop on the list of associated functions and user objects
3448FUNCTIONS:
3449 TObject *f;
3450 TIter next(fFunctions);
3451 while ((f = (TObject*) next())) {
3452 Int_t dist;
3453 if (f->InheritsFrom(TF1::Class())) dist = f->DistancetoPrimitive(-px,py);
3454 else dist = f->DistancetoPrimitive(px,py);
3455 if (dist < kMaxDiff) {gPad->SetSelected(f); return dist;}
3456 }
3457 return curdist;
3458}
3459
3460////////////////////////////////////////////////////////////////////////////////
3461/// Display a panel with all histogram drawing options.
3462
3464{
3465
3466 gCurrentHist = fH;
3467 if (!gPad) {
3468 Error("DrawPanel", "need to draw histogram first");
3469 return;
3470 }
3472 editor->Show();
3473 gROOT->ProcessLine(TString::Format("((TCanvas*)0x%zx)->Selected((TVirtualPad*)0x%zx,(TObject*)0x%zx,1)",
3474 (size_t)gPad->GetCanvas(), (size_t)gPad, (size_t)fH).Data());
3475}
3476
3478protected:
3479 Int_t px1 = 0, py1 = 0;
3480 Double_t fX1 = 0, fY1 = 0, fX2 = 0, fY2 = 0;
3481
3482public:
3484 {
3485 px1 = px;
3486 py1 = py;
3487 fX1 = fX2 = parent.PadtoX(parent.AbsPixeltoX(px));
3488 fY1 = fY2 = parent.PadtoY(parent.AbsPixeltoY(py));
3489 }
3490
3491 void MovePoint(TVirtualPad &parent, Int_t px, Int_t py)
3492 {
3493 if (TMath::Abs(px1 - px) > 5 && TMath::Abs(py1 - py) > 5) {
3494 fX2 = parent.PadtoX(parent.AbsPixeltoX(px));
3495 fY2 = parent.PadtoY(parent.AbsPixeltoY(py));
3496 const char *opt = parent.OpaqueMoving() ? "izoombox" : "ilzoombox";
3497 parent.PaintBox(fX1, fY1, fX2, fY2, opt);
3498 parent.UpdateAsync();
3499 }
3500 }
3501
3502 void ChangeRange(TAxis *xaxis, TAxis *yaxis)
3503 {
3508 if (x1 < x2 && y1 < y2) {
3509 xaxis->SetRangeUser(x1, x2);
3510 yaxis->SetRangeUser(y1, y2);
3511 }
3512 }
3513
3514};
3515
3517public:
3519 Double_t xlow = 0, xup = 1, y0 = 0, factor = 1.;
3520};
3521
3522////////////////////////////////////////////////////////////////////////////////
3523/// Execute the actions corresponding to `event`.
3524///
3525/// This function is called when a histogram is clicked with the locator at
3526/// the pixel position px,py.
3527
3529{
3530 if (!gPad || !gPad->IsEditable())
3531 return;
3532
3533 if (fPie) {
3534 fPie->ExecuteEvent(event, px, py);
3535 return;
3536 }
3537
3538 auto &parent = *gPad;
3539
3540 // come here if we have a lego/surface in the pad
3541 TView *view = parent.GetView();
3542
3543 if (!fShowProjection && view && !view->TestBit(kCannotRotate)) {
3544 view->ExecuteRotateView(event, px, py);
3545 return;
3546 }
3547 Bool_t opaque = parent.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 hopt = fH->GetDrawOption();
3555 hopt.ToLower();
3556 if (hopt.Index("same") >= 0) {
3557 TIter next(parent.GetListOfPrimitives());
3558 while (auto obj = next()) {
3559 if (auto h1 = dynamic_cast<TH1 *>(obj)) {
3560 xaxis = h1->GetXaxis();
3561 yaxis = h1->GetYaxis();
3562 break;
3563 }
3564 }
3565 }
3566
3567 auto zoombox = parent.GetInteractive<TZoomInteractive>(this);
3568 auto h1edit = parent.GetInteractive<TEditInteractive>(this);
3569
3570 switch (event) {
3571
3572 case kButton1Down:
3573 if (dimension == 2)
3574 zoombox = parent.MakeInteractive<TZoomInteractive>(this, parent, px, py);
3575 // No break !!!
3576
3577 case kMouseMotion:
3578
3579 if (fShowProjection) {
3580 ShowProjection3(px,py);
3581 break;
3582 }
3583
3584 parent.SetCursor(kPointer);
3585 if ((dimension == 1) && gROOT->GetEditHistograms()) {
3586 h1edit = parent.MakeInteractive<TEditInteractive>(this);
3587
3588 Double_t baroffset = Hoption.Bar ? fH->GetBarOffset() : 0;
3589 Double_t barwidth = Hoption.Bar ? fH->GetBarWidth() : 1;
3590 h1edit->bin = fXaxis->FindFixBin(parent.PadtoX(parent.AbsPixeltoX(px)));
3591 Double_t binwidth = fXaxis->GetBinWidth(h1edit->bin);
3592 h1edit->xlow = fXaxis->GetBinLowEdge(h1edit->bin) + baroffset*binwidth;
3593 h1edit->xup = h1edit->xlow + barwidth*binwidth;
3594 h1edit->y0 = fH->GetBinContent(h1edit->bin);
3595 h1edit->factor = fH->GetNormFactor() / fH->GetSumOfWeights();
3596 if (!h1edit->factor)
3597 h1edit->factor = 1.;
3598
3599 parent.SetCursor(kArrowVer);
3600 }
3601
3602 break;
3603
3604 case kButton1Motion:
3605
3606 if ((dimension == 1) && h1edit) {
3607 Double_t yup = parent.PadtoY(parent.AbsPixeltoY(py)) / h1edit->factor;
3608 fH->SetBinContent(h1edit->bin, yup);
3609
3610 if (!opaque) {
3611 parent.PaintBox(parent.XtoPad(h1edit->xlow), parent.YtoPad(h1edit->y0), parent.XtoPad(h1edit->xup), parent.YtoPad(yup), "ilh1edit"); // Draw the new box
3612 parent.UpdateAsync();
3613 } else
3614 parent.Modified();
3615 }
3616
3617 if (zoombox && dimension == 2)
3618 zoombox->MovePoint(*gPad, px, py);
3619
3620 break;
3621
3622 case kWheelUp:
3623
3624 if (dimension == 2) {
3625 Int_t bin1 = TMath::Max(xaxis->GetFirst() + 1, 1);
3626 Int_t bin2 = TMath::Min(xaxis->GetLast() - 1, xaxis->GetNbins());
3627 if (bin2 > bin1)
3628 xaxis->SetRange(bin1, bin2);
3629 bin1 = TMath::Max(yaxis->GetFirst() + 1, 1);
3630 bin2 = TMath::Min(yaxis->GetLast() - 1, yaxis->GetNbins());
3631 if (bin2 > bin1)
3632 yaxis->SetRange(bin1,bin2);
3633 }
3634 parent.Modified();
3635 parent.Update();
3636
3637 break;
3638
3639 case kWheelDown:
3640
3641 if (dimension == 2) {
3642 Int_t bin1 = TMath::Max(xaxis->GetFirst() - 1, 1);
3643 Int_t bin2 = TMath::Min(xaxis->GetLast() + 1, xaxis->GetNbins());
3644 const bool resetXaxisRange = bin1 == 1 && xaxis->GetFirst() == 1 && bin2 == xaxis->GetNbins() && xaxis->GetLast() == xaxis->GetNbins();
3645 if (bin2 > bin1)
3646 xaxis->SetRange(bin1, bin2);
3647 if (resetXaxisRange)
3649 bin1 = TMath::Max(yaxis->GetFirst() - 1, 1);
3650 bin2 = TMath::Min(yaxis->GetLast() + 1, yaxis->GetNbins());
3651 const bool resetYaxisRange = bin1 == 1 && yaxis->GetFirst() == 1 && bin2 == yaxis->GetNbins() && yaxis->GetLast() == yaxis->GetNbins();
3652 if (bin2 > bin1)
3653 yaxis->SetRange(bin1, bin2);
3654 if (resetYaxisRange)
3656 }
3657 parent.Modified();
3658 parent.Update();
3659
3660 break;
3661
3662 case kButton1Up:
3663 if ((dimension == 1) && h1edit) {
3664 PaintInit(); // recalculate Hparam structure and recalculate range
3665 // might resize pad pixmap so should be called before any paint routine
3667 }
3668 if ((dimension == 2) && zoombox)
3669 zoombox->ChangeRange(xaxis, yaxis);
3670 parent.FreeInteractive(this); // remove interactive object
3671 parent.Modified();
3672
3673 break;
3674
3675 case kButton1Locate:
3676
3677 ExecuteEvent(kButton1Down, px, py);
3678
3679 while (true) {
3680 px = py = 0;
3681 event = parent.GetCanvasImp()->RequestLocator(px, py);
3682
3684
3685 if (event != -1) { // button is released
3686 ExecuteEvent(kButton1Up, px, py);
3687 return;
3688 }
3689 }
3690 }
3691}
3692
3693////////////////////////////////////////////////////////////////////////////////
3694/// Get a contour (as a list of TGraphs) using the Delaunay triangulation.
3695
3697{
3698 // Check if fH contains a TGraphDelaunay2D
3699 TList *hl = fH->GetListOfFunctions();
3700 TGraphDelaunay2D *dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
3701 // try with the old painter
3702 TGraphDelaunay *dtOld = nullptr;
3703 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
3704
3705 if (!dt && !dtOld) return nullptr;
3706
3707 gCurrentHist = fH;
3708
3709 if (!fGraph2DPainter)
3710 ((THistPainter*)this)->fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
3711
3712 return fGraph2DPainter->GetContourList(contour);
3713}
3714
3715////////////////////////////////////////////////////////////////////////////////
3716/// Display the histogram info (bin number, contents, integral up to bin
3717/// corresponding to cursor position px,py.
3718
3720{
3721
3722 if (!gPad) return (char*)"";
3723
3724 Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
3725 Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
3726 Double_t x1 = gPad->PadtoX(gPad->AbsPixeltoX(px+1));
3727 TString drawOption = fH->GetDrawOption();
3728 drawOption.ToLower();
3729 Double_t xmin, xmax, uxmin,uxmax;
3730 Double_t ymin, ymax, uymin,uymax;
3731 if (fH->GetDimension() == 2) {
3732 if (gPad->GetView() || drawOption.Index("cont") >= 0) {
3733 uxmin=gPad->GetUxmin();
3734 uxmax=gPad->GetUxmax();
3737 x = xmin +(xmax-xmin)*(x-uxmin)/(uxmax-uxmin);
3738 uymin=gPad->GetUymin();
3739 uymax=gPad->GetUymax();
3742 y = ymin +(ymax-ymin)*(y-uymin)/(uymax-uymin);
3743 }
3744 }
3745 Int_t binx,biny,binmin=0,binx1;
3746 if (gPad->IsVertical()) {
3747 binx = fXaxis->FindFixBin(x);
3748 if (drawOption.Index("same") >= 0) {
3749 TH1 *h1;
3750 TIter next(gPad->GetListOfPrimitives());
3751 while ((h1 = (TH1 *)next())) {
3752 if (!h1->InheritsFrom(TH1::Class())) continue;
3753 binmin = h1->GetXaxis()->GetFirst();
3754 break;
3755 }
3756 } else {
3757 binmin = fXaxis->GetFirst();
3758 }
3759 binx1 = fXaxis->FindFixBin(x1);
3760 // special case if more than 1 bin in x per pixel
3761 if (binx1-binx>1 && fH->GetDimension() == 1) {
3762 Double_t binval=fH->GetBinContent(binx);
3763 Int_t binnear=binx;
3764 for (Int_t ibin=binx+1; ibin<binx1; ibin++) {
3765 Double_t binvaltmp = fH->GetBinContent(ibin);
3766 if (TMath::Abs(y-binvaltmp) < TMath::Abs(y-binval)) {
3767 binval=binvaltmp;
3768 binnear=ibin;
3769 }
3770 }
3771 binx = binnear;
3772 }
3773 } else {
3774 x1 = gPad->PadtoY(gPad->AbsPixeltoY(py+1));
3775 binx = fXaxis->FindFixBin(y);
3776 if (drawOption.Index("same") >= 0) {
3777 TH1 *h1;
3778 TIter next(gPad->GetListOfPrimitives());
3779 while ((h1 = (TH1 *)next())) {
3780 if (!h1->InheritsFrom(TH1::Class())) continue;
3781 binmin = h1->GetXaxis()->GetFirst();
3782 break;
3783 }
3784 } else {
3785 binmin = fXaxis->GetFirst();
3786 }
3787 binx1 = fXaxis->FindFixBin(x1);
3788 // special case if more than 1 bin in x per pixel
3789 if (binx1-binx>1 && fH->GetDimension() == 1) {
3790 Double_t binval=fH->GetBinContent(binx);
3791 Int_t binnear=binx;
3792 for (Int_t ibin=binx+1; ibin<binx1; ibin++) {
3793 Double_t binvaltmp = fH->GetBinContent(ibin);
3794 if (TMath::Abs(x-binvaltmp) < TMath::Abs(x-binval)) {
3795 binval=binvaltmp;
3796 binnear=ibin;
3797 }
3798 }
3799 binx = binnear;
3800 }
3801 }
3802 if (fH->GetDimension() == 1) {
3804 TProfile *tp = (TProfile*)fH;
3805 fObjectInfo.Form("(x=%g, y=%g, binx=%d, binc=%g, bine=%g, binn=%d)",
3806 x, y, binx, fH->GetBinContent(binx), fH->GetBinError(binx),
3807 (Int_t) tp->GetBinEntries(binx));
3808 }
3809 else {
3810 Double_t integ = 0;
3811 for (Int_t bin=binmin;bin<=binx;bin++) {integ += fH->GetBinContent(bin);}
3812 fObjectInfo.Form("(x=%g, y=%g, binx=%d, binc=%g, Sum=%g)",
3813 x,y,binx,fH->GetBinContent(binx),integ);
3814 }
3815 } else if (fH->GetDimension() == 2) {
3816 if (fH->InheritsFrom(TH2Poly::Class())) {
3817 TH2Poly *th2 = (TH2Poly*)fH;
3818 biny = th2->FindBin(x,y);
3819 fObjectInfo.Form("%s (x=%g, y=%g, bin=%d, binc=%g)",
3820 th2->GetBinTitle(biny),x,y,biny,th2->GetBinContent(biny));
3821 }
3822 else if (fH->InheritsFrom(TProfile2D::Class())) {
3823 TProfile2D *tp = (TProfile2D*)fH;
3824 biny = fYaxis->FindFixBin(y);
3825 Int_t bin = fH->GetBin(binx,biny);
3826 fObjectInfo.Form("(x=%g, y=%g, binx=%d, biny=%d, binc=%g, bine=%g, binn=%d)",
3827 x, y, binx, biny, fH->GetBinContent(bin),
3828 fH->GetBinError(bin), (Int_t) tp->GetBinEntries(bin));
3829 } else {
3830 biny = fYaxis->FindFixBin(y);
3831 fObjectInfo.Form("(x=%g, y=%g, binx=%d, biny=%d, binc=%g bine=%g)",
3832 x,y,binx,biny,fH->GetBinContent(binx,biny),
3833 fH->GetBinError(binx,biny));
3834 }
3835 } else {
3836 // 3d case: retrieving the x,y,z bin is not yet implemented
3837 // print just the x,y info
3838 fObjectInfo.Form("(x=%g, y=%g)",x,y);
3839 }
3840
3841 return (char *)fObjectInfo.Data();
3842}
3843
3844////////////////////////////////////////////////////////////////////////////////
3845/// Set highlight (enable/disable) mode for fH
3846
3848{
3849 if (fH->IsHighlight()) return;
3850
3851 fXHighlightBin = -1;
3852 fYHighlightBin = -1;
3853 // delete previous highlight box
3854 if (gXHighlightBox) gXHighlightBox.reset();
3855 if (gYHighlightBox) gYHighlightBox.reset();
3856 // emit Highlighted() signal (user can check on disabled)
3857 if (gPad->GetCanvas()) gPad->GetCanvas()->Highlighted(gPad, fH, fXHighlightBin, fYHighlightBin);
3858}
3859
3860////////////////////////////////////////////////////////////////////////////////
3861/// Check on highlight bin
3862
3864{
3865 // call from DistancetoPrimitive (only if highlight is enable)
3866
3867 Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
3868 Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
3869 Int_t binx = fXaxis->FindFixBin(x);
3870 Int_t biny = fYaxis->FindFixBin(y);
3871 if (!gPad->IsVertical()) binx = fXaxis->FindFixBin(y);
3872
3873 Bool_t changedBin = kFALSE;
3874 if (binx != fXHighlightBin) {
3875 fXHighlightBin = binx;
3876 changedBin = kTRUE;
3877 } else if (fH->GetDimension() == 1) return;
3878 if (biny != fYHighlightBin) {
3879 fYHighlightBin = biny;
3880 changedBin = kTRUE;
3881 }
3882 if (!changedBin) return;
3883
3884 // Info("HighlightBin", "histo: %p '%s'\txbin: %d, ybin: %d",
3885 // (void *)fH, fH->GetName(), fXHighlightBin, fYHighlightBin);
3886
3887 // paint highlight bin as box (recursive calls PaintHighlightBin)
3888 gPad->Modified(kTRUE);
3889 gPad->Update();
3890
3891 // emit Highlighted() signal
3892 if (gPad->GetCanvas()) gPad->GetCanvas()->Highlighted(gPad, fH, fXHighlightBin, fYHighlightBin);
3893}
3894
3895////////////////////////////////////////////////////////////////////////////////
3896/// Paint highlight bin as TBox object
3897
3899{
3900 // call from PaintTitle
3901
3902 if (!fH->IsHighlight()) return;
3903
3904 Double_t uxmin = gPad->GetUxmin();
3905 Double_t uxmax = gPad->GetUxmax();
3906 Double_t uymin = gPad->GetUymin();
3907 Double_t uymax = gPad->GetUymax();
3908 if (gPad->GetLogx()) {
3909 uxmin = TMath::Power(10.0, uxmin);
3910 uxmax = TMath::Power(10.0, uxmax);
3911 }
3912 if (gPad->GetLogy()) {
3913 uymin = TMath::Power(10.0, uymin);
3914 uymax = TMath::Power(10.0, uymax);
3915 }
3916
3917 // testing specific possibility (after zoom, draw with "same", log, etc.)
3918 Double_t hcenter;
3919 if (gPad->IsVertical()) {
3921 if ((hcenter < uxmin) || (hcenter > uxmax)) return;
3922 } else {
3924 if ((hcenter < uymin) || (hcenter > uymax)) return;
3925 }
3926 if (fH->GetDimension() == 2) {
3928 if ((hcenter < uymin) || (hcenter > uymax)) return;
3929 }
3930
3931 // paint X highlight bin (for 1D or 2D)
3932 Double_t hbx1, hbx2, hby1, hby2;
3933 if (gPad->IsVertical()) {
3936 hby1 = uymin;
3937 hby2 = uymax;
3938 } else {
3939 hbx1 = uxmin;
3940 hbx2 = uxmax;
3943 }
3944
3945 if (!gXHighlightBox) {
3946 gXHighlightBox = std::make_unique<TBox>(hbx1, hby1, hbx2, hby2);
3947 gXHighlightBox->SetBit(kCannotPick);
3948 gXHighlightBox->SetFillColor(TColor::GetColor("#9797ff"));
3949 if (!TCanvas::SupportAlpha()) gXHighlightBox->SetFillStyle(3001);
3950 else gROOT->GetColor(gXHighlightBox->GetFillColor())->SetAlpha(0.5);
3951 }
3952 gXHighlightBox->SetX1(hbx1);
3953 gXHighlightBox->SetX2(hbx2);
3954 gXHighlightBox->SetY1(hby1);
3955 gXHighlightBox->SetY2(hby2);
3956 gXHighlightBox->Paint();
3957
3958 // Info("PaintHighlightBin", "histo: %p '%s'\txbin: %d, ybin: %d",
3959 // (void *)fH, fH->GetName(), fXHighlightBin, fYHighlightBin);
3960
3961 // paint Y highlight bin (only for 2D)
3962 if (fH->GetDimension() != 2) return;
3963 hbx1 = uxmin;
3964 hbx2 = uxmax;
3967
3968 if (!gYHighlightBox) {
3969 gYHighlightBox = std::make_unique<TBox>(hbx1, hby1, hbx2, hby2);
3970 gYHighlightBox->SetBit(kCannotPick);
3971 gYHighlightBox->SetFillColor(gXHighlightBox->GetFillColor());
3972 gYHighlightBox->SetFillStyle(gXHighlightBox->GetFillStyle());
3973 }
3974 gYHighlightBox->SetX1(hbx1);
3975 gYHighlightBox->SetX2(hbx2);
3976 gYHighlightBox->SetY1(hby1);
3977 gYHighlightBox->SetY2(hby2);
3978 gYHighlightBox->Paint();
3979}
3980
3981////////////////////////////////////////////////////////////////////////////////
3982/// Return `kTRUE` if the cell `ix`, `iy` is inside one of the graphical cuts.
3983
3985{
3986
3987 for (Int_t i=0;i<fNcuts;i++) {
3990 if (fCutsOpt[i] > 0) {
3991 if (!fCuts[i]->IsInside(x,y)) return kFALSE;
3992 } else {
3993 if (fCuts[i]->IsInside(x,y)) return kFALSE;
3994 }
3995 }
3996 return kTRUE;
3997}
3998
3999////////////////////////////////////////////////////////////////////////////////
4000/// Return `kTRUE` if the point `x`, `y` is inside one of the graphical cuts.
4001
4003{
4004
4005 for (Int_t i=0;i<fNcuts;i++) {
4006 if (fCutsOpt[i] > 0) {
4007 if (!fCuts[i]->IsInside(x,y)) return kFALSE;
4008 } else {
4009 if (fCuts[i]->IsInside(x,y)) return kFALSE;
4010 }
4011 }
4012 return kTRUE;
4013}
4014
4015////////////////////////////////////////////////////////////////////////////////
4016/// Decode string `choptin` and fill Hoption structure.
4017
4019{
4020
4021 char *l;
4022 char chopt[128];
4023 Int_t nch = strlen(choptin);
4024 strlcpy(chopt,choptin,128);
4025 Int_t hdim = fH->GetDimension();
4026 Bool_t explicitColor = kFALSE;
4027
4035 Hoption.Candle = 0;
4036 Hoption.Polar = 0;
4037
4038 // special 2D options
4039 Hoption.List = 0;
4040 Hoption.Zscale = 0;
4041 Hoption.FrontBox = 1;
4042 Hoption.BackBox = 1;
4044
4045 Hoption.Zero = 0;
4046
4048
4049 //check for graphical cuts
4050 MakeCuts(chopt);
4051
4052 for (Int_t i=0;i<nch;i++) chopt[i] = toupper(chopt[i]);
4053 if (hdim > 1) Hoption.Color = 1; // Default drawing option for 2D and 3D histograms
4054 if (!nch) Hoption.Hist = 1;
4055 if (fFunctions->First()) Hoption.Func = 1;
4056 if (fH->GetSumw2N() && hdim == 1) Hoption.Error = 2;
4057
4058 char *l1 = strstr(chopt,"PFC"); // Automatic Fill Color
4059 char *l2 = strstr(chopt,"PLC"); // Automatic Line Color
4060 char *l3 = strstr(chopt,"PMC"); // Automatic Marker Color
4061 if (l1 || l2 || l3) {
4062 Int_t i = gPad->NextPaletteColor();
4063 if (l1) {memcpy(l1," ",3); fH->SetFillColor(i);}
4064 if (l2) {memcpy(l2," ",3); fH->SetLineColor(i);}
4065 if (l3) {memcpy(l3," ",3); fH->SetMarkerColor(i);}
4066 Hoption.Hist = 1; // Make sure something is drawn in case there is no drawing option specified.
4067 }
4068
4069 l = strstr(chopt,"MIN0");
4070 if (l) {
4071 Hoption.MinimumZero = 1;
4072 memcpy(l," ",4);
4073 }
4074
4075 l = strstr(chopt,"SPEC");
4076 if (l) {
4077 Hoption.Color = 0;
4078 memcpy(l," ",4);
4079 Int_t bs=0;
4080 l = strstr(chopt,"BF(");
4081 if (l) {
4082 if (sscanf(&l[3],"%d",&bs) > 0) {
4083 Int_t i=0;
4084 while (l[i]!=')') {
4085 l[i] = ' ';
4086 i++;
4087 }
4088 l[i] = ' ';
4089 }
4090 }
4091 Hoption.Spec = TMath::Max(1600,bs);
4092 return 1;
4093 }
4094
4095 l = strstr(chopt,"GL");
4096 if (l) {
4097 memcpy(l," ",2);
4098 }
4099 l = strstr(chopt,"X+");
4100 if (l) {
4101 Hoption.AxisPos = 10;
4102 memcpy(l," ",2);
4103 }
4104 l = strstr(chopt,"Y+");
4105 if (l) {
4106 Hoption.AxisPos += 1;
4107 memcpy(l," ",2);
4108 }
4109 if ((Hoption.AxisPos == 10 || Hoption.AxisPos == 1) && (nch == 2)) Hoption.Hist = 1;
4110 if (Hoption.AxisPos == 11 && nch == 4) Hoption.Hist = 1;
4111
4112 l = strstr(chopt,"SAMES");
4113 if (l) {
4114 if (nch == 5) Hoption.Hist = 1;
4115 Hoption.Same = 2;
4116 memcpy(l," ",5);
4117 if (l[5] == '0') { Hoption.Same += 10; l[5] = ' '; }
4118 }
4119 l = strstr(chopt,"SAME");
4120 if (l) {
4121 if (nch == 4) Hoption.Hist = 1;
4122 Hoption.Same = 1;
4123 memcpy(l," ",4);
4124 if (l[4] == '0') { Hoption.Same += 10; l[4] = ' '; }
4125 }
4126
4127 l = strstr(chopt,"SCAT");
4128 if (l) {
4129 Warning("MakeChopt","option SCAT is deprecated.");
4130 Hoption.Scat = 1;
4131 memcpy(l," ",4);
4132 Hoption.Color = 0;
4133 }
4134
4135 l = strstr(chopt,"PIE");
4136 if (l) {
4137 Hoption.Pie = 1;
4138 memcpy(l," ",3);
4139 }
4140
4141
4142 l = strstr(chopt,"CANDLE");
4143 if (l) {
4144 TCandle candle;
4145 Hoption.Candle = candle.ParseOption(l);
4146 Hoption.Color = 0;
4147 }
4148
4149 l = strstr(chopt,"VIOLIN");
4150 if (l) {
4151 TCandle candle;
4152 Hoption.Candle = candle.ParseOption(l);
4153 Hoption.Color = 0;
4154 }
4155
4156 l = strstr(chopt,"LEGO");
4157 if (l) {
4158 Hoption.Color = 0;
4159 Hoption.Lego = 1; memcpy(l," ",4);
4160 if (l[4] == '1') { Hoption.Lego = 11; l[4] = ' '; }
4161 if (l[4] == '2') { Hoption.Lego = 12; l[4] = ' '; }
4162 if (l[4] == '3') { Hoption.Lego = 13; l[4] = ' '; }
4163 if (l[4] == '4') { Hoption.Lego = 14; l[4] = ' '; }
4164 if (l[4] == '9') { Hoption.Lego = 19; l[4] = ' '; }
4165 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4166 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4167 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4168 }
4169
4170 l = strstr(chopt,"SURF");
4171 if (l) {
4172 Hoption.Color = 0;
4173 Hoption.Surf = 1; memcpy(l," ",4);
4174 if (l[4] == '1') { Hoption.Surf = 11; l[4] = ' '; }
4175 if (l[4] == '2') { Hoption.Surf = 12; l[4] = ' '; }
4176 if (l[4] == '3') { Hoption.Surf = 13; l[4] = ' '; }
4177 if (l[4] == '4') { Hoption.Surf = 14; l[4] = ' '; }
4178 if (l[4] == '5') { Hoption.Surf = 15; l[4] = ' '; }
4179 if (l[4] == '6') { Hoption.Surf = 16; l[4] = ' '; }
4180 if (l[4] == '7') { Hoption.Surf = 17; l[4] = ' '; }
4181 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4182 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4183 }
4184
4185 l = strstr(chopt,"TF3");
4186 if (l) {
4187 memcpy(l," ",3);
4188 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4189 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4190 }
4191
4192 l = strstr(chopt,"ISO");
4193 if (l) {
4194 memcpy(l," ",3);
4195 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4196 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4197 Hoption.Color = 0;
4198 }
4199
4200 l = strstr(chopt,"LIST"); if (l) { Hoption.List = 1; memcpy(l," ",4);}
4201
4202 l = strstr(chopt,"CONT");
4203 if (l) {
4204 memcpy(l," ",4);
4205 if (hdim>1) {
4206 Hoption.Color = 0;
4207 Hoption.Contour = 1;
4208 if (l[4] == '1') { Hoption.Contour = 11; l[4] = ' '; }
4209 if (l[4] == '2') { Hoption.Contour = 12; l[4] = ' '; }
4210 if (l[4] == '3') { Hoption.Contour = 13; l[4] = ' '; }
4211 if (l[4] == '4') { Hoption.Contour = 14; l[4] = ' '; }
4212 if (l[4] == '5') { Hoption.Contour = 15; l[4] = ' '; }
4213 } else {
4214 Hoption.Hist = 1;
4215 }
4216 }
4217 l = strstr(chopt,"HBAR");
4218 if (l) {
4219 Hoption.Hist = 0;
4220 Hoption.Bar = 20; memcpy(l," ",4);
4221 if (l[4] == '1') { Hoption.Bar = 21; l[4] = ' '; }
4222 if (l[4] == '2') { Hoption.Bar = 22; l[4] = ' '; }
4223 if (l[4] == '3') { Hoption.Bar = 23; l[4] = ' '; }
4224 if (l[4] == '4') { Hoption.Bar = 24; l[4] = ' '; }
4225 }
4226 l = strstr(chopt,"BAR");
4227 if (l) {
4228 Hoption.Hist = 0;
4229 Hoption.Bar = 10; memcpy(l," ",3);
4230 if (l[3] == '1') { Hoption.Bar = 11; l[3] = ' '; }
4231 if (l[3] == '2') { Hoption.Bar = 12; l[3] = ' '; }
4232 if (l[3] == '3') { Hoption.Bar = 13; l[3] = ' '; }
4233 if (l[3] == '4') { Hoption.Bar = 14; l[3] = ' '; }
4234 }
4235
4236 l = strstr(chopt,"ARR" );
4237 if (l) {
4238 memcpy(l," ", 3);
4239 if (hdim>1) {
4240 Hoption.Arrow = 1;
4241 Hoption.Color = 0;
4242 l = strstr(chopt,"COL"); if (l) { Hoption.Arrow = 2; memcpy(l," ",3); }
4243 l = strstr(chopt,"Z"); if (l) { Hoption.Zscale = 1; memcpy(l," ",1); }
4244 } else {
4245 Hoption.Hist = 1;
4246 }
4247 }
4248 l = strstr(chopt,"BOX" );
4249 if (l) {
4250 memcpy(l," ", 3);
4251 if (hdim>1) {
4252 Hoption.Color = 0;
4253 Hoption.Box = 1;
4254 if (l[3] == '1') { Hoption.Box = 11; l[3] = ' '; }
4255 if (l[3] == '2') { Hoption.Box = 12; l[3] = ' '; }
4256 if (l[3] == '3') { Hoption.Box = 13; l[3] = ' '; }
4257 } else {
4258 Hoption.Hist = 1;
4259 }
4260 }
4261 l = strstr(chopt,"TEXT");
4262 if (l) {
4263 Int_t angle;
4264 if (sscanf(&l[4],"%d",&angle) > 0) {
4265 if (angle < 0) angle=0;
4266 if (angle > 90) angle=90;
4267 Hoption.Text = 1000+angle;
4268 } else {
4269 Hoption.Text = 1;
4270 }
4271 memcpy(l," ", 4);
4272 l = strstr(chopt,"N");
4273 if (l && fH->InheritsFrom(TH2Poly::Class())) Hoption.Text = 3000 + (Hoption.Text != 1 ? Hoption.Text : 0);
4274 Hoption.Color = 0;
4275 }
4276 l = strstr(chopt,"COLZ");
4277 if (l) {
4278 memcpy(l," ",4);
4279 if (hdim > 1) {
4280 explicitColor = kTRUE;
4281 Hoption.Color = 1;
4282 Hoption.Zscale = 1;
4283 if (l[4] == '2') { Hoption.Color = 3; l[4] = ' '; }
4284 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4285 l = strstr(chopt,"1"); if (l) { Hoption.Color = 2; memcpy(l," ",1); }
4286 } else {
4287 Hoption.Hist = 1;
4288 }
4289 }
4290 l = strstr(chopt,"COL" );
4291 if (l) {
4292 memcpy(l," ", 3);
4293 if (hdim > 1) {
4294 explicitColor = kTRUE;
4295 Hoption.Color = 1;
4296 if (l[3] == '2') { Hoption.Color = 3; l[3] = ' '; }
4297 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4298 l = strstr(chopt,"1"); if (l) { Hoption.Color = 2; memcpy(l," ",1); }
4299 } else {
4300 Hoption.Hist = 1;
4301 }
4302 }
4303 l = strstr(chopt,"FUNC"); if (l) { Hoption.Func = 2; memcpy(l," ",4); Hoption.Hist = 0; }
4304 l = strstr(chopt,"HIST"); if (l) { Hoption.Hist = 2; memcpy(l," ",4); Hoption.Func = 0; Hoption.Error = 0;}
4305 l = strstr(chopt,"AXIS"); if (l) { Hoption.Axis = 1; memcpy(l," ",4); }
4306 l = strstr(chopt,"AXIG"); if (l) { Hoption.Axis = 2; memcpy(l," ",4); }
4307 l = strstr(chopt,"SCAT"); if (l) { Hoption.Scat = 1; memcpy(l," ",4); }
4308 l = strstr(chopt,"POLN"); if (l) { Hoption.System = kPOLAR; Hoption.Polar = 3; memcpy(l," ",4); }
4309 l = strstr(chopt,"POLF"); if (l) { Hoption.System = kPOLAR; Hoption.Polar = 2; memcpy(l," ",4); }
4310 l = strstr(chopt,"POL"); if (l) { Hoption.System = kPOLAR; Hoption.Polar = 1; memcpy(l," ",3); }
4311 l = strstr(chopt,"CYL"); if (l) { Hoption.System = kCYLINDRICAL; memcpy(l," ",3); }
4312 l = strstr(chopt,"SPH"); if (l) { Hoption.System = kSPHERICAL; memcpy(l," ",3); }
4313 l = strstr(chopt,"PSR"); if (l) { Hoption.System = kRAPIDITY; memcpy(l," ",3); }
4314
4315 l = strstr(chopt,"TRI");
4316 if (l) {
4317 if (!explicitColor) Hoption.Color = 0;
4318 Hoption.Tri = 1; memcpy(l," ",3);
4319 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4320 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4321 l = strstr(chopt,"ERR"); if (l) memcpy(l," ",3);
4322 }
4323
4324 l = strstr(chopt,"AITOFF");
4325 if (l) {
4326 Hoption.Proj = 1; memcpy(l," ",6); //Aitoff projection
4327 }
4328 l = strstr(chopt,"MERCATOR");
4329 if (l) {
4330 Hoption.Proj = 2; memcpy(l," ",8); //Mercator projection
4331 }
4332 l = strstr(chopt,"SINUSOIDAL");
4333 if (l) {
4334 Hoption.Proj = 3; memcpy(l," ",10); //Sinusoidal projection
4335 }
4336 l = strstr(chopt,"PARABOLIC");
4337 if (l) {
4338 Hoption.Proj = 4; memcpy(l," ",9); //Parabolic projection
4339 }
4340 l = strstr(chopt,"MOLLWEIDE");
4341 if (l) {
4342 Hoption.Proj = 5; memcpy(l," ",9); //Mollweide projection
4343 }
4344 if (Hoption.Proj > 0) {
4345 if (!explicitColor) Hoption.Color = 0;
4346 Hoption.Contour = 14;
4347 }
4348
4349 if (strstr(chopt,"A")) Hoption.Axis = -1;
4350 if (strstr(chopt,"B")) Hoption.Bar = 1;
4351 if (strstr(chopt,"C") && !strstr(chopt,"CJUST")) { Hoption.Curve =1; Hoption.Hist = -1;}
4352 if (strstr(chopt,"F")) Hoption.Fill =1;
4353 if (strstr(chopt,"][")) {Hoption.Off =1; Hoption.Hist =1;}
4354 if (strstr(chopt,"F2")) Hoption.Fill =2;
4355 if (strstr(chopt,"L")) { Hoption.Line =1; Hoption.Hist = -1;}
4356 if (strstr(chopt,"P")) { Hoption.Mark =1; Hoption.Hist = -1;}
4357 if (strstr(chopt,"Z")) Hoption.Zscale =1;
4358 if (strstr(chopt,"*")) Hoption.Star =1;
4359 if (strstr(chopt,"H")) Hoption.Hist =2;
4360 if (strstr(chopt,"P0")) Hoption.Mark =10;
4361
4362 if (fH->InheritsFrom(TH2Poly::Class())) {
4363 if ((Hoption.Fill+Hoption.Line+Hoption.Mark != 0) && !explicitColor) Hoption.Color = 0;
4364 }
4365
4366 if (strstr(chopt,"E")) {
4367 if (hdim == 1) {
4368 Hoption.Error = 1;
4369 if (strstr(chopt,"E1")) Hoption.Error = 11;
4370 if (strstr(chopt,"E2")) Hoption.Error = 12;
4371 if (strstr(chopt,"E3")) Hoption.Error = 13;
4372 if (strstr(chopt,"E4")) Hoption.Error = 14;
4373 if (strstr(chopt,"E5")) Hoption.Error = 15;
4374 if (strstr(chopt,"E6")) Hoption.Error = 16;
4375 if (strstr(chopt,"E0")) Hoption.Error += 40;
4376 if (strstr(chopt,"X0")) {
4377 if (Hoption.Error == 1) Hoption.Error += 20;
4378 Hoption.Error += 10;
4379 }
4381 Hoption.Text += 2000;
4382 Hoption.Error = 0;
4383 }
4384 } else {
4385 if (Hoption.Error == 0) {
4386 Hoption.Error = 100;
4387 if (!explicitColor) Hoption.Color = 0;
4388 }
4389 if (Hoption.Text) {
4390 Hoption.Text += 2000;
4391 Hoption.Error = 0;
4392 }
4393 }
4394 }
4395
4396 if (Hoption.Surf == 15) {
4398 Hoption.Surf = 13;
4399 Warning("MakeChopt","option SURF5 is not supported in Cartesian and Polar modes");
4400 }
4401 }
4402
4403 // Copy options from current style
4404 Hoption.Logx = gPad->GetLogx();
4405 Hoption.Logy = gPad->GetLogy();
4406 Hoption.Logz = gPad->GetLogz();
4407
4408 // Check options incompatibilities
4409 if (Hoption.Bar == 1) Hoption.Hist = -1;
4410 return 1;
4411}
4412
4413////////////////////////////////////////////////////////////////////////////////
4414/// Decode string `choptin` and fill Graphical cuts structure.
4415
4417{
4418
4419 fNcuts = 0;
4420 char *left = (char*)strchr(choptin,'[');
4421 if (!left) return 0;
4422 char *right = (char*)strchr(choptin,']');
4423 if (!right) return 0;
4424 Int_t nch = right-left;
4425 if (nch < 2) return 0;
4426 char *cuts = left+1;
4427 *right = 0;
4428 char *comma, *minus;
4429 Int_t i;
4430 while (true) {
4431 comma = strchr(cuts,',');
4432 if (comma) *comma = 0;
4433 minus = strchr(cuts,'-');
4434 if (minus) cuts = minus+1;
4435 while (*cuts == ' ') cuts++;
4436 Int_t nc = strlen(cuts);
4437 while (cuts[nc-1] == ' ') {cuts[nc-1] = 0; nc--;}
4438 TIter next(gROOT->GetListOfSpecials());
4439 TCutG *cut=nullptr;
4440 TObject *obj;
4441 while ((obj = next())) {
4442 if (!obj->InheritsFrom(TCutG::Class())) continue;
4443 if (strcmp(obj->GetName(),cuts)) continue;
4444 cut = (TCutG*)obj;
4445 break;
4446 }
4447 if (cut) {
4448 fCuts[fNcuts] = cut;
4449 fCutsOpt[fNcuts] = 1;
4450 if (minus) fCutsOpt[fNcuts] = -1;
4451 fNcuts++;
4452 }
4453 if (!comma) break;
4454 cuts = comma+1;
4455 }
4456 for (i=0;i<=nch;i++) left[i] = ' ';
4457 return fNcuts;
4458}
4459
4460////////////////////////////////////////////////////////////////////////////////
4461/// [Control routine to paint any kind of histograms](\ref HP00)
4462
4464{
4465
4466 if (fH->GetBuffer()) fH->BufferEmpty(-1);
4467
4468 //For iOS: put the histogram on the top of stack of pickable objects.
4469 const TPickerStackGuard topPush(fH);
4470
4471 gPad->SetVertical(kTRUE);
4472
4473 TH1 *oldhist = gCurrentHist;
4474 gCurrentHist = fH;
4475 TH1 *hsave = fH;
4476 Double_t minsav = fH->GetMinimumStored();
4477
4478 if (!MakeChopt(option)) return; //check options and fill Hoption structure
4479
4480 // Paint using TSpectrum2Painter
4481 if (Hoption.Spec) {
4482 if (!TableInit()) return;
4483 if (!TClass::GetClass("TSpectrum2Painter")) gSystem->Load("libSpectrumPainter");
4484 gROOT->ProcessLineFast(TString::Format("TSpectrum2Painter::PaintSpectrum((TH2F*)0x%zx,\"%s\",%d)",
4485 (size_t)fH, option, Hoption.Spec).Data());
4486 return;
4487 }
4488
4489 // Deflate the labels in case of alphanumeric labels
4493
4494 if (Hoption.Pie) {
4495 if (fH->GetDimension() == 1) {
4496 if (!fPie)
4497 fPie = std::make_unique<TPie>(fH);
4498 fPie->Paint(option);
4499 } else {
4500 Error("Paint", "Option PIE is for 1D histograms only");
4501 }
4502 return;
4503 } else {
4504 fPie.reset();
4505 }
4506
4507 fXbuf.resize(kNMAX);
4508 fYbuf.resize(kNMAX);
4509 if (fH->GetDimension() > 2) {
4510 PaintH3(option);
4511 fH->SetMinimum(minsav);
4512 if (Hoption.Func) {
4513 Hoption_t hoptsave = Hoption;
4514 Hparam_t hparsave = Hparam;
4516 SetHistogram(hsave);
4517 Hoption = hoptsave;
4518 Hparam = hparsave;
4519 }
4520 gCurrentHist = oldhist;
4521 fXbuf.clear();
4522 fYbuf.clear();
4523 return;
4524 }
4525 TView *view = gPad->GetView();
4526 if (view) {
4527 if (!Hoption.Lego && !Hoption.Surf && !Hoption.Tri) {
4528 delete view;
4529 gPad->SetView(nullptr);
4530 }
4531 }
4532 if (fH->GetDimension() > 1 || Hoption.Lego || Hoption.Surf) {
4533 // In case of 1D histogram, Z axis becomes Y axis.
4534 Int_t logysav=0, logzsav=0;
4535 if (fH->GetDimension() == 1) {
4536 logysav = Hoption.Logy;
4537 logzsav = Hoption.Logz;
4538 Hoption.Logz = 0;
4539 if (Hoption.Logy) {
4540 Hoption.Logz = 1;
4541 Hoption.Logy = 0;
4542 }
4543 }
4545 if (Hoption.Func) {
4546 Hoption_t hoptsave = Hoption;
4547 Hparam_t hparsave = Hparam;
4549 SetHistogram(hsave);
4550 Hoption = hoptsave;
4551 Hparam = hparsave;
4552 }
4553 fH->SetMinimum(minsav);
4554 gCurrentHist = oldhist;
4555 fXbuf.clear();
4556 fYbuf.clear();
4557 if (fH->GetDimension() == 1) {
4558 Hoption.Logy = logysav;
4559 Hoption.Logz = logzsav;
4560 }
4561 return;
4562 }
4563
4564 if (Hoption.Bar >= 20) {
4566 fXbuf.clear();
4567 fYbuf.clear();
4568 return;
4569 }
4570
4571 gPad->RangeAxisChanged(); //emit RangeAxisChanged() signal to sync axes
4572 // fill Hparam structure with histo parameters
4573 if (!PaintInit()) {
4574 fXbuf.clear();
4575 fYbuf.clear();
4576 return;
4577 }
4578
4579 // Picture surround (if new page) and page number (if requested).
4580 // Histogram surround (if not option "Same").
4581 PaintFrame();
4582
4583 // Paint histogram axis only
4584 Bool_t gridx = gPad->GetGridx();
4585 Bool_t gridy = gPad->GetGridy();
4586 if (Hoption.Axis > 0) {
4587 if (Hoption.Axis > 1) PaintAxis(kTRUE); //axis with grid
4588 else {
4589 if (gridx) gPad->SetGridx(0);
4590 if (gridy) gPad->SetGridy(0);
4592 if (gridx) gPad->SetGridx(1);
4593 if (gridy) gPad->SetGridy(1);
4594 }
4595 if ((Hoption.Same%10) ==1) Hoption.Same += 1;
4596 goto paintstat;
4597 }
4598 if (gridx || gridy) PaintAxis(kTRUE); // Draw the grid only
4599
4600 // test for options BAR or HBAR
4601 if (Hoption.Bar >= 10) {
4603 }
4604
4605 // do not draw histogram if error bars required
4606 if (!Hoption.Error) {
4607 if (Hoption.Hist && Hoption.Bar<10) PaintHist(option);
4608 }
4609
4610 // test for error bars or option E
4611 if (Hoption.Error) {
4613 if (Hoption.Hist == 2) PaintHist(option);
4614 }
4615
4617
4618 // test for associated function
4619 if (Hoption.Func) {
4620 Hoption_t hoptsave = Hoption;
4621 Hparam_t hparsave = Hparam;
4623 SetHistogram(hsave);
4624 Hoption = hoptsave;
4625 Hparam = hparsave;
4626 }
4627
4628 if (gridx) gPad->SetGridx(0);
4629 if (gridy) gPad->SetGridy(0);
4631 if (gridx) gPad->SetGridx(1);
4632 if (gridy) gPad->SetGridy(1);
4633
4634 PaintTitle(); // Draw histogram title
4635
4636 // Draw box with histogram statistics and/or fit parameters
4637paintstat:
4638 if ((Hoption.Same%10) != 1 && !fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
4639 TIter next(fFunctions);
4640 TObject *obj = nullptr;
4641 while ((obj = next())) {
4642 if (obj->InheritsFrom(TF1::Class())) break;
4643 obj = nullptr;
4644 }
4645
4646 //Stat is painted twice (first, it will be in canvas' list of primitives),
4647 //second, it will be here, this is not required on iOS.
4648 //Condition is ALWAYS true on a platform different from iOS.
4649 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode())
4650 PaintStat(gStyle->GetOptStat(),(TF1*)obj);
4651 }
4652 fH->SetMinimum(minsav);
4653 gCurrentHist = oldhist;
4654 fXbuf.clear();
4655 fYbuf.clear();
4656}
4657
4658////////////////////////////////////////////////////////////////////////////////
4659/// [Control function to draw a table as an arrow plot](\ref HP12)
4660
4662{
4663 Double_t xk, xstep, yk, ystep;
4664 Double_t dx, dy, x1, x2, y1, y2, xc, yc, dxn, dyn;
4667 Double_t xrg = gPad->GetUxmin();
4668 Double_t yrg = gPad->GetUymin();
4669 Double_t xln = gPad->GetUxmax() - xrg;
4670 Double_t yln = gPad->GetUymax() - yrg;
4671 Double_t cx = (xln/Double_t(ncx))/2.;
4672 Double_t cy = (yln/Double_t(ncy))/2.;
4673 Double_t dn = 1.E-30;
4674
4675 auto arrow = new TArrow();
4676 arrow->SetAngle(30);
4677 arrow->SetFillStyle(1001);
4678 arrow->SetFillColor(fH->GetLineColor());
4679 arrow->SetLineColor(fH->GetLineColor());
4680 arrow->SetLineWidth(fH->GetLineWidth());
4681
4682 // Initialize the levels on the Z axis
4683 Int_t ncolors=0, ndivz=0;
4684 Double_t scale=0.;
4685 if (Hoption.Arrow>1) {
4686 ncolors = gStyle->GetNumberOfColors();
4687 Int_t ndiv = fH->GetContour();
4688 if (ndiv == 0 ) {
4689 ndiv = gStyle->GetNumberContours();
4690 fH->SetContour(ndiv);
4691 }
4692 ndivz = TMath::Abs(ndiv);
4693 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
4694 scale = ndivz/(fH->GetMaximum()-fH->GetMinimum());
4695 }
4696
4697 for (Int_t id=1;id<=2;id++) {
4698 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
4699 yk = fYaxis->GetBinLowEdge(j);
4700 ystep = fYaxis->GetBinWidth(j);
4701 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
4702 xk = fXaxis->GetBinLowEdge(i);
4703 xstep = fXaxis->GetBinWidth(i);
4704 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
4705 if (i == Hparam.xfirst) {
4706 dx = fH->GetBinContent(i+1, j) - fH->GetBinContent(i, j);
4707 } else if (i == Hparam.xlast) {
4708 dx = fH->GetBinContent(i, j) - fH->GetBinContent(i-1, j);
4709 } else {
4710 dx = 0.5*(fH->GetBinContent(i+1, j) - fH->GetBinContent(i-1, j));
4711 }
4712 if (j == Hparam.yfirst) {
4713 dy = fH->GetBinContent(i, j+1) - fH->GetBinContent(i, j);
4714 } else if (j == Hparam.ylast) {
4715 dy = fH->GetBinContent(i, j) - fH->GetBinContent(i, j-1);
4716 } else {
4717 dy = 0.5*(fH->GetBinContent(i, j+1) - fH->GetBinContent(i, j-1));
4718 }
4719 if (id == 1) {
4720 dn = TMath::Max(dn, TMath::Abs(dx));
4721 dn = TMath::Max(dn, TMath::Abs(dy));
4722 } else if (id == 2) {
4723 xc = xrg + xln*(Double_t(i - Hparam.xfirst+1)-0.5)/Double_t(ncx);
4724 dxn = cx*dx/dn;
4725 x1 = xc - dxn;
4726 x2 = xc + dxn;
4727 yc = yrg + yln*(Double_t(j - Hparam.yfirst+1)-0.5)/Double_t(ncy);
4728 dyn = cy*dy/dn;
4729 y1 = yc - dyn;
4730 y2 = yc + dyn;
4731 if (Hoption.Arrow>1) {
4732 int color = Int_t(0.01+(fH->GetBinContent(i, j)-fH->GetMinimum())*scale);
4733 Int_t theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
4734 if (theColor > ncolors-1) theColor = ncolors-1;
4735 arrow->SetFillColor(gStyle->GetColorPalette(theColor));
4736 arrow->SetLineColor(gStyle->GetColorPalette(theColor));
4737 }
4738 if (TMath::Abs(x2-x1) > 0. || TMath::Abs(y2-y1) > 0.) {
4739 arrow->PaintArrow(x1, y1, x2, y2, 0.015, "|>");
4740 } else {
4741 arrow->PaintArrow(x1, y1, x2, y2, 0.005, "|>");
4742 }
4743 }
4744 }
4745 }
4746 }
4747
4749}
4750
4751////////////////////////////////////////////////////////////////////////////////
4752/// Draw axis (2D case) of an histogram.
4753///
4754/// If `drawGridOnly` is `TRUE`, only the grid is painted (if needed). This allows
4755/// to draw the grid and the axis separately. In `THistPainter::Paint` this
4756/// feature is used to make sure that the grid is drawn in the background and
4757/// the axis tick marks in the foreground of the pad.
4758
4760{
4761
4762 //On iOS, grid should not be pickable and can not be highlighted.
4763 //Condition is never true on a platform different from iOS.
4764 if (drawGridOnly && (gPad->PadInHighlightMode() || gPad->PadInSelectionMode()))
4765 return;
4766
4767 if (Hoption.Axis == -1) return;
4768 if (Hoption.Same && Hoption.Axis <= 0) return;
4769
4770 // Repainting alphanumeric labels axis on a plot done with
4771 // the option HBAR (horizontal) needs some adjustments.
4772 TAxis *xaxis = nullptr;
4773 TAxis *yaxis = nullptr;
4774 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4775 if (fXaxis->GetLabels() || fYaxis->GetLabels()) { // One axis has alphanumeric labels
4776 TIter next(gPad->GetListOfPrimitives());
4777 TObject *obj;
4778 // Check if the first TH1 of THStack in the pad is drawn with the option HBAR
4779 while ((obj = next())) {
4780 if (!obj->InheritsFrom(TH1::Class()) &&
4781 !obj->InheritsFrom(THStack::Class())) continue;
4782 TString opt = obj->GetDrawOption();
4783 opt.ToLower();
4784 // if drawn with HBAR, the axis should be inverted and the pad set to horizontal
4785 if (strstr(opt,"hbar")) {
4786 gPad->SetVertical(kFALSE);
4787 xaxis = fXaxis;
4788 yaxis = fYaxis;
4789 if (!strcmp(xaxis->GetName(),"xaxis")) {
4790 fXaxis = yaxis;
4791 fYaxis = xaxis;
4792 }
4793 }
4794 break;
4795 }
4796 }
4797 }
4798
4799 static char chopt[10] = "";
4800 Double_t gridl = 0;
4801 Int_t ndiv, ndivx, ndivy, nx1, nx2, ndivsave;
4802 Int_t useHparam = 0;
4803 Double_t umin, umax, uminsave, umaxsave;
4804 Short_t xAxisPos = Hoption.AxisPos/10;
4805 Short_t yAxisPos = Hoption.AxisPos - 10*xAxisPos;
4806
4807 Double_t axmin = gPad->GetUxmin();
4808 Double_t axmax = gPad->GetUxmax();
4809 Double_t aymin = gPad->GetUymin();
4810 Double_t aymax = gPad->GetUymax();
4811 char *cw = nullptr;
4812 TGaxis axis;
4813
4814 // In case of option 'cont4' or in case of option 'same' over a 'cont4 plot'
4815 // Hparam must be use for the axis limits.
4816 if (Hoption.Contour == 14) useHparam = 1;
4817 if (Hoption.Same) {
4818 TObject *obj;
4819 TIter next(gPad->GetListOfPrimitives());
4820 while ((obj=next())) {
4821 if (strstr(obj->GetDrawOption(),"cont4")) {
4822 useHparam = 1;
4823 break;
4824 }
4825 }
4826 }
4827
4828 // Paint X axis
4829
4830 //To make X-axis selectable on iOS device.
4831 if (gPad->PadInSelectionMode())
4832 gPad->PushSelectableObject(fXaxis);
4833
4834 //This condition is ALWAYS true, unless it works on iOS (can be false on iOS).
4835 if (gPad->PadInSelectionMode() || !gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && gPad->GetSelected() == fXaxis)) {
4836 ndivx = fXaxis->GetNdivisions();
4837 if (ndivx > 1000) {
4838 nx2 = ndivx/100;
4839 nx1 = TMath::Max(1, ndivx%100);
4840 ndivx = 100*nx2 + Int_t(Float_t(nx1)*gPad->GetAbsWNDC());
4841 }
4842 axis.SetTextAngle(0);
4844
4845 chopt[0] = 0;
4846 strlcat(chopt, "SDH",10);
4847 if (ndivx < 0) strlcat(chopt, "N",10);
4848 if (gPad->GetGridx()) {
4849 gridl = (aymax-aymin)/(gPad->GetY2() - gPad->GetY1());
4850 strlcat(chopt, "W",10);
4851 }
4852
4853 // Define X-Axis limits
4854 if (Hoption.Logx) {
4855 strlcat(chopt, "G",10);
4856 ndiv = TMath::Abs(ndivx);
4857 if (useHparam) {
4858 umin = TMath::Power(10,Hparam.xmin);
4859 umax = TMath::Power(10,Hparam.xmax);
4860 } else {
4861 umin = TMath::Power(10,axmin);
4862 umax = TMath::Power(10,axmax);
4863 }
4864 } else {
4865 ndiv = TMath::Abs(ndivx);
4866 if (useHparam) {
4867 umin = Hparam.xmin;
4868 umax = Hparam.xmax;
4869 } else {
4870 umin = axmin;
4871 umax = axmax;
4872 }
4873 }
4874
4875 // Display axis as time
4876 if (fXaxis->GetTimeDisplay()) {
4877 strlcat(chopt,"t",10);
4878 if (strlen(fXaxis->GetTimeFormatOnly()) == 0) {
4880 }
4881 }
4882
4883 // The main X axis can be on the bottom or on the top of the pad
4884 Double_t xAxisYPos1, xAxisYPos2;
4885 if (xAxisPos == 1) {
4886 // Main X axis top
4887 xAxisYPos1 = aymax;
4888 xAxisYPos2 = aymin;
4889 } else {
4890 // Main X axis bottom
4891 xAxisYPos1 = aymin;
4892 xAxisYPos2 = aymax;
4893 }
4894
4895 // Paint the main X axis (always)
4896 uminsave = umin;
4897 umaxsave = umax;
4898 ndivsave = ndiv;
4899 axis.SetOption(chopt);
4900 if (xAxisPos) {
4901 strlcat(chopt, "-",10);
4902 gridl = -gridl;
4903 }
4904 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4905 axis.SetLabelSize(0.);
4906 axis.SetTitle("");
4907 }
4908 axis.PaintAxis(axmin, xAxisYPos1,
4909 axmax, xAxisYPos1,
4910 umin, umax, ndiv, chopt, gridl, drawGridOnly);
4911
4912 // Paint additional X axis (if needed)
4913 // On iOS, this additional X axis is neither pickable, nor highlighted.
4914 // Additional checks PadInSelectionMode etc. does not effect non-iOS platform.
4915 if (gPad->GetTickx() && !gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
4916 if (xAxisPos) {
4917 cw=strstr(chopt,"-");
4918 *cw='z';
4919 } else {
4920 strlcat(chopt, "-",10);
4921 }
4922 if (gPad->GetTickx() < 2) strlcat(chopt, "U",10);
4923 if ((cw=strstr(chopt,"W"))) *cw='z';
4924 axis.SetTitle("");
4925 axis.PaintAxis(axmin, xAxisYPos2,
4926 axmax, xAxisYPos2,
4927 uminsave, umaxsave, ndivsave, chopt, gridl, drawGridOnly);
4928 }
4929 }//End of "if pad in selection mode etc".
4930
4931 // Paint Y axis
4932 //On iOS, Y axis must pushed into the stack of selectable objects.
4933 if (gPad->PadInSelectionMode())
4934 gPad->PushSelectableObject(fYaxis);
4935
4936 //This conditions is ALWAYS true on a platform, different from iOS (on iOS can be true, can be false).
4937 if (gPad->PadInSelectionMode() || !gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && gPad->GetSelected() == fYaxis)) {
4938 ndivy = fYaxis->GetNdivisions();
4940
4941 chopt[0] = 0;
4942 strlcat(chopt, "SDH",10);
4943 if (ndivy < 0) strlcat(chopt, "N",10);
4944 if (gPad->GetGridy()) {
4945 gridl = (axmax-axmin)/(gPad->GetX2() - gPad->GetX1());
4946 strlcat(chopt, "W",10);
4947 }
4948
4949 // Define Y-Axis limits
4950 if (Hoption.Logy) {
4951 strlcat(chopt, "G",10);
4952 ndiv = TMath::Abs(ndivy);
4953 if (useHparam) {
4954 umin = TMath::Power(10,Hparam.ymin);
4955 umax = TMath::Power(10,Hparam.ymax);
4956 } else {
4957 umin = TMath::Power(10,aymin);
4958 umax = TMath::Power(10,aymax);
4959 }
4960 } else {
4961 ndiv = TMath::Abs(ndivy);
4962 if (useHparam) {
4963 umin = Hparam.ymin;
4964 umax = Hparam.ymax;
4965 } else {
4966 umin = aymin;
4967 umax = aymax;
4968 }
4969 }
4970
4971 // Display axis as time
4972 if (fYaxis->GetTimeDisplay()) {
4973 strlcat(chopt,"t",10);
4974 if (strlen(fYaxis->GetTimeFormatOnly()) == 0) {
4976 }
4977 }
4978
4979 // The main Y axis can be on the left or on the right of the pad
4980 Double_t yAxisXPos1, yAxisXPos2;
4981 if (yAxisPos == 1) {
4982 // Main Y axis left
4983 yAxisXPos1 = axmax;
4984 yAxisXPos2 = axmin;
4985 } else {
4986 // Main Y axis right
4987 yAxisXPos1 = axmin;
4988 yAxisXPos2 = axmax;
4989 }
4990
4991 // Paint the main Y axis (always)
4992 uminsave = umin;
4993 umaxsave = umax;
4994 ndivsave = ndiv;
4995 axis.SetOption(chopt);
4996 if (yAxisPos) {
4997 strlcat(chopt, "+L",10);
4998 gridl = -gridl;
4999 }
5000 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
5001 axis.SetLabelSize(0.);
5002 axis.SetTitle("");
5003 }
5004 axis.PaintAxis(yAxisXPos1, aymin,
5005 yAxisXPos1, aymax,
5006 umin, umax, ndiv, chopt, gridl, drawGridOnly);
5007
5008 // Paint the additional Y axis (if needed)
5009 // Additional checks for pad mode are required on iOS: this "second" axis is
5010 // neither pickable, nor highlighted. Additional checks have no effect on non-iOS platform.
5011 if (gPad->GetTicky() && !gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
5012 if (gPad->GetTicky() < 2) {
5013 strlcat(chopt, "U",10);
5015 } else {
5016 strlcat(chopt, "+L",10);
5017 }
5018 if ((cw=strstr(chopt,"W"))) *cw='z';
5019 axis.SetTitle("");
5020 axis.PaintAxis(yAxisXPos2, aymin,
5021 yAxisXPos2, aymax,
5022 uminsave, umaxsave, ndivsave, chopt, gridl, drawGridOnly);
5023 }
5024 }//End of "if pad is in selection mode etc."
5025
5026 // Reset the axis if they have been inverted in case of option HBAR
5027 if (xaxis) {
5028 fXaxis = xaxis;
5029 fYaxis = yaxis;
5030 }
5031}
5032
5033////////////////////////////////////////////////////////////////////////////////
5034/// [Draw a bar-chart in a normal pad.](\ref HP10)
5035
5037{
5038
5039 Int_t bar = Hoption.Bar - 10;
5040 Double_t xmin,xmax,ymin,ymax,umin,umax,w,y;
5043 TBox box;
5044 Int_t hcolor = fH->GetFillColor();
5045 if (hcolor == gPad->GetFrameFillColor()) ++hcolor;
5046 Int_t hstyle = fH->GetFillStyle();
5047 box.SetFillColor(hcolor);
5048 box.SetFillStyle(hstyle);
5049 box.SetLineStyle(fH->GetLineStyle());
5050 box.SetLineColor(fH->GetLineColor());
5051 box.SetLineWidth(fH->GetLineWidth());
5052 for (Int_t bin=fXaxis->GetFirst();bin<=fXaxis->GetLast();bin++) {
5053 y = fH->GetBinContent(bin);
5054 xmin = gPad->XtoPad(fXaxis->GetBinLowEdge(bin));
5055 xmax = gPad->XtoPad(fXaxis->GetBinUpEdge(bin));
5056 ymin = gPad->GetUymin();
5057 ymax = gPad->YtoPad(y);
5058 if (ymax < gPad->GetUymin()) continue;
5059 if (ymax > gPad->GetUymax()) ymax = gPad->GetUymax();
5060 if (ymin < gPad->GetUymin()) ymin = gPad->GetUymin();
5061 if (Hoption.MinimumZero && ymin < 0)
5062 ymin=TMath::Min(0.,gPad->GetUymax());
5063 w = (xmax-xmin)*width;
5064 xmin += offset*(xmax-xmin);
5065 xmax = xmin + w;
5066 if (bar < 1) {
5067 box.PaintBox(xmin,ymin,xmax,ymax);
5068 } else {
5069 umin = xmin + bar*(xmax-xmin)/10.;
5070 umax = xmax - bar*(xmax-xmin)/10.;
5071 box.SetFillColor(TColor::GetColorBright(hcolor)); //bright
5072 box.PaintBox(xmin,ymin,umin,ymax);
5073 box.SetFillColor(hcolor);
5074 box.PaintBox(umin,ymin,umax,ymax);
5075 box.SetFillColor(TColor::GetColorDark(hcolor)); //dark
5076 box.PaintBox(umax,ymin,xmax,ymax);
5077 }
5078 }
5079}
5080
5081////////////////////////////////////////////////////////////////////////////////
5082/// [Draw a bar char in a rotated pad (X vertical, Y horizontal)](\ref HP10)
5083
5085{
5086
5087 gPad->SetVertical(kFALSE);
5088
5089 PaintInitH();
5090
5091 TAxis *xaxis = fXaxis;
5092 TAxis *yaxis = fYaxis;
5093 if (!strcmp(xaxis->GetName(),"xaxis")) {
5094 fXaxis = yaxis;
5095 fYaxis = xaxis;
5096 }
5097
5098 PaintFrame();
5100
5101 Int_t bar = Hoption.Bar - 20;
5102 Double_t xmin,xmax,ymin,ymax,umin,umax,w;
5105 TBox box;
5106 Int_t hcolor = fH->GetFillColor();
5107 if (hcolor == gPad->GetFrameFillColor()) ++hcolor;
5108 Int_t hstyle = fH->GetFillStyle();
5109 box.SetFillColor(hcolor);
5110 box.SetFillStyle(hstyle);
5111 box.SetLineStyle(fH->GetLineStyle());
5112 box.SetLineColor(fH->GetLineColor());
5113 box.SetLineWidth(fH->GetLineWidth());
5114 for (Int_t bin=fYaxis->GetFirst();bin<=fYaxis->GetLast();bin++) {
5115 ymin = gPad->YtoPad(fYaxis->GetBinLowEdge(bin));
5116 ymax = gPad->YtoPad(fYaxis->GetBinUpEdge(bin));
5117 xmin = gPad->GetUxmin();
5118 xmax = gPad->XtoPad(fH->GetBinContent(bin));
5119 if (xmax < gPad->GetUxmin()) continue;
5120 if (xmax > gPad->GetUxmax()) xmax = gPad->GetUxmax();
5121 if (xmin < gPad->GetUxmin()) xmin = gPad->GetUxmin();
5122 if (Hoption.MinimumZero && xmin < 0)
5123 xmin=TMath::Min(0.,gPad->GetUxmax());
5124 w = (ymax-ymin)*width;
5125 ymin += offset*(ymax-ymin);
5126 ymax = ymin + w;
5127 if (bar < 1) {
5128 box.PaintBox(xmin,ymin,xmax,ymax);
5129 } else {
5130 umin = ymin + bar*(ymax-ymin)/10.;
5131 umax = ymax - bar*(ymax-ymin)/10.;
5132 box.SetFillColor(TColor::GetColorDark(hcolor)); //dark
5133 box.PaintBox(xmin,ymin,xmax,umin);
5134 box.SetFillColor(hcolor);
5135 box.PaintBox(xmin,umin,xmax,umax);
5136 box.SetFillColor(TColor::GetColorBright(hcolor)); //bright
5137 box.PaintBox(xmin,umax,xmax,ymax);
5138 }
5139 }
5140
5141 PaintTitle();
5142
5143 // Draw box with histogram statistics and/or fit parameters
5144 if ((Hoption.Same%10) != 1 && !fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
5145 TIter next(fFunctions);
5146 TObject *obj = nullptr;
5147 while ((obj = next())) {
5148 if (obj->InheritsFrom(TF1::Class())) break;
5149 obj = nullptr;
5150 }
5151 PaintStat(gStyle->GetOptStat(),(TF1*)obj);
5152 }
5153
5154 fXaxis = xaxis;
5155 fYaxis = yaxis;
5156}
5157
5158////////////////////////////////////////////////////////////////////////////////
5159/// [Control function to draw a 2D histogram as a box plot](\ref HP13)
5160
5162{
5163
5164 Style_t fillsav = fH->GetFillStyle();
5165 Style_t colsav = fH->GetFillColor();
5166 if (fH->GetFillColor() == 0) fH->SetFillStyle(0);
5167 if (Hoption.Box == 11) fH->SetFillStyle(1001);
5168 fH->TAttLine::Modify();
5169 fH->TAttFill::Modify();
5170
5171 Double_t z, xk,xstep, yk, ystep, xcent, ycent, xlow, xup, ylow, yup;
5172 Double_t ux1 = gPad->PixeltoX(1);
5173 Double_t ux0 = gPad->PixeltoX(0);
5174 Double_t uy1 = gPad->PixeltoY(1);
5175 Double_t uy0 = gPad->PixeltoY(0);
5176 Double_t dxmin = 0.51*(gPad->PadtoX(ux1)-gPad->PadtoX(ux0));
5177 Double_t dymin = 0.51*(gPad->PadtoY(uy0)-gPad->PadtoY(uy1));
5178
5179 Double_t zmin = TMath::Max(fH->GetMinimum(),0.);
5182 Double_t zminlin = zmin, zmaxlin = zmax;
5183
5184 // In case of option SAME, zmin and zmax values are taken from the
5185 // first plotted 2D histogram.
5186 if (Hoption.Same > 0 && Hoption.Same < 10) {
5187 TH2 *h2;
5188 TIter next(gPad->GetListOfPrimitives());
5189 while ((h2 = (TH2 *)next())) {
5190 if (!h2->InheritsFrom(TH2::Class())) continue;
5191 zmin = TMath::Max(h2->GetMinimum(), 0.);
5192 zmax = TMath::Max(TMath::Abs(h2->GetMaximum()),
5193 TMath::Abs(h2->GetMinimum()));
5194 zminlin = zmin;
5195 zmaxlin = zmax;
5196 if (Hoption.Logz) {
5197 if (zmin <= 0) {
5198 zmin = TMath::Log10(zmax*0.001);
5199 } else {
5200 zmin = TMath::Log10(zmin);
5201 }
5202 zmax = TMath::Log10(zmax);
5203 }
5204 break;
5205 }
5206 } else {
5207 if (Hoption.Logz) {
5208 if (zmin > 0) {
5209 zmin = TMath::Log10(zmin);
5210 zmax = TMath::Log10(zmax);
5211 } else {
5212 return;
5213 }
5214 }
5215 }
5216
5217 Double_t zratio, dz = zmax - zmin;
5218 Bool_t kZminNeg = kFALSE;
5219 if (fH->GetMinimum()<0) kZminNeg = kTRUE;
5220 Bool_t kZNeg = kFALSE;
5221
5222 // Define the dark and light colors the "button style" boxes.
5223 Color_t color = fH->GetFillColor();
5224 Color_t light=0, dark=0;
5225 if (Hoption.Box == 11) {
5226 light = TColor::GetColorBright(color);
5227 dark = TColor::GetColorDark(color);
5228 }
5229
5230 // Loop over all the bins and draw the boxes
5231 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
5232 yk = fYaxis->GetBinLowEdge(j);
5233 ystep = fYaxis->GetBinWidth(j);
5234 ycent = 0.5*ystep;
5235 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
5236 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
5237 xk = fXaxis->GetBinLowEdge(i);
5238 xstep = fXaxis->GetBinWidth(i);
5239 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
5240 xcent = 0.5*xstep;
5241 z = Hparam.factor*fH->GetBinContent(bin);
5242 kZNeg = kFALSE;
5243
5244 if (TMath::Abs(z) < zminlin) continue; // Can be the case with ...
5245 if (TMath::Abs(z) > zmaxlin) z = zmaxlin; // ... option Same
5246 if (kZminNeg && z==0) continue; // Do not draw empty bins if case of histo with negative bins.
5247
5248 if (z < 0) {
5249 if (Hoption.Logz) continue;
5250 z = -z;
5251 kZNeg = kTRUE;
5252 }
5253 if (Hoption.Logz) {
5254 if (z != 0) z = TMath::Log10(z);
5255 else z = zmin;
5256 }
5257
5258 if (dz == 0) continue;
5259 zratio = TMath::Sqrt((z-zmin)/dz);
5260 if (zratio == 0) continue;
5261
5262 xup = xcent*zratio + xk + xcent;
5263 xlow = 2*(xk + xcent) - xup;
5264 if (xup-xlow < dxmin) xup = xlow+dxmin;
5265 if (Hoption.Logx) {
5266 if (xup > 0) xup = TMath::Log10(xup);
5267 else continue;
5268 if (xlow > 0) xlow = TMath::Log10(xlow);
5269 else continue;
5270 }
5271
5272 yup = ycent*zratio + yk + ycent;
5273 ylow = 2*(yk + ycent) - yup;
5274 if (yup-ylow < dymin) yup = ylow+dymin;
5275 if (Hoption.Logy) {
5276 if (yup > 0) yup = TMath::Log10(yup);
5277 else continue;
5278 if (ylow > 0) ylow = TMath::Log10(ylow);
5279 else continue;
5280 }
5281
5282 xlow = TMath::Max(xlow, gPad->GetUxmin());
5283 ylow = TMath::Max(ylow, gPad->GetUymin());
5284 xup = TMath::Min(xup , gPad->GetUxmax());
5285 yup = TMath::Min(yup , gPad->GetUymax());
5286
5287 if (xlow >= xup) continue;
5288 if (ylow >= yup) continue;
5289
5290 if (Hoption.Box == 1) {
5291 fH->SetFillColor(color);
5292 fH->TAttFill::Modify();
5293 gPad->PaintBox(xlow, ylow, xup, yup);
5294 if (kZNeg) {
5295 gPad->PaintLine(xlow, ylow, xup, yup);
5296 gPad->PaintLine(xlow, yup, xup, ylow);
5297 }
5298 } else if (Hoption.Box == 11) {
5299 // Draw the center of the box
5300 fH->SetFillColor(color);
5301 fH->TAttFill::Modify();
5302 gPad->PaintBox(xlow, ylow, xup, yup);
5303
5304 // Draw top&left part of the box
5305 Double_t x[7], y[7];
5306 Double_t bwidth = 0.1;
5307 x[0] = xlow; y[0] = ylow;
5308 x[1] = xlow + bwidth*(xup-xlow); y[1] = ylow + bwidth*(yup-ylow);
5309 x[2] = x[1]; y[2] = yup - bwidth*(yup-ylow);
5310 x[3] = xup - bwidth*(xup-xlow); y[3] = y[2];
5311 x[4] = xup; y[4] = yup;
5312 x[5] = xlow; y[5] = yup;
5313 x[6] = xlow; y[6] = ylow;
5314 if (kZNeg) fH->SetFillColor(dark);
5315 else fH->SetFillColor(light);
5316 fH->TAttFill::Modify();
5317 gPad->PaintFillArea(7, x, y);
5318
5319 // Draw bottom&right part of the box
5320 x[0] = xlow; y[0] = ylow;
5321 x[1] = xlow + bwidth*(xup-xlow); y[1] = ylow + bwidth*(yup-ylow);
5322 x[2] = xup - bwidth*(xup-xlow); y[2] = y[1];
5323 x[3] = x[2]; y[3] = yup - bwidth*(yup-ylow);
5324 x[4] = xup; y[4] = yup;
5325 x[5] = xup; y[5] = ylow;
5326 x[6] = xlow; y[6] = ylow;
5327 if (kZNeg) fH->SetFillColor(light);
5328 else fH->SetFillColor(dark);
5329 fH->TAttFill::Modify();
5330 gPad->PaintFillArea(7, x, y);
5331 }
5332 }
5333 }
5334
5336 fH->SetFillStyle(fillsav);
5337 fH->SetFillColor(colsav);
5338 fH->TAttFill::Modify();
5339}
5340
5341
5342
5343////////////////////////////////////////////////////////////////////////////////
5344/// [Control function to draw a 2D histogram as a candle (box) plot or violin plot](\ref HP14)
5345
5347{
5348 TH1D *hproj = nullptr;
5349 TH2D *h2 = (TH2D*)fH;
5350
5351 TCandle myCandle;
5353 myCandle.SetMarkerColor(fH->GetLineColor());
5354 myCandle.SetLineColor(fH->GetLineColor());
5355 myCandle.SetLineWidth(fH->GetLineWidth());
5356 myCandle.SetFillColor(fH->GetFillColor());
5357 myCandle.SetFillStyle(fH->GetFillStyle());
5358 myCandle.SetMarkerSize(fH->GetMarkerSize());
5359 myCandle.SetMarkerStyle(fH->GetMarkerStyle());
5361
5362 Bool_t swapXY = myCandle.IsHorizontal();
5363 const Double_t standardCandleWidth = 0.66;
5364 const Double_t standardHistoWidth = 0.8;
5365
5366 double allMaxContent = 0, allMaxIntegral = 0;
5367 if (myCandle.IsViolinScaled())
5368 allMaxContent = h2->GetBinContent(h2->GetMaximumBin());
5369
5370 if (!swapXY) { // Vertical candle
5371 //Determining the slice with the maximum integral - if necessary
5372 if (myCandle.IsCandleScaled())
5373 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast; i++) {
5374 hproj = h2->ProjectionY("_px", i, i);
5375 if (hproj->Integral() > allMaxIntegral) allMaxIntegral = hproj->Integral();
5376 }
5377 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast; i++) {
5378 Double_t binPosX = fXaxis->GetBinLowEdge(i);
5379 Double_t binWidth = fXaxis->GetBinWidth(i);
5380 hproj = h2->ProjectionY("_px", i, i);
5381 if (hproj->GetEntries() != 0) {
5382 Double_t candleWidth = fH->GetBarWidth();
5383 Double_t offset = fH->GetBarOffset()*binWidth;
5384 double myMaxContent = hproj->GetBinContent(hproj->GetMaximumBin());
5385 double myIntegral = hproj->Integral();
5386 Double_t histoWidth = candleWidth;
5387 if (candleWidth > 0.999 && candleWidth < 1.001) {
5388 candleWidth = standardCandleWidth;
5389 histoWidth = standardHistoWidth;
5390 }
5391 if (Hoption.Logz && myMaxContent > 0) {
5392 histoWidth *= myMaxContent/TMath::Log10(myMaxContent);
5393 if (myCandle.IsViolinScaled() && myMaxContent > 0 && allMaxContent > 0)
5394 histoWidth *= TMath::Log10(myMaxContent)/TMath::Log10(allMaxContent);
5395 } else if (myCandle.IsViolinScaled() && (allMaxContent > 0))
5396 histoWidth *= myMaxContent/allMaxContent;
5397 if (myCandle.IsCandleScaled() && (allMaxIntegral > 0))
5398 candleWidth *= myIntegral/allMaxIntegral;
5399
5400 myCandle.SetAxisPosition(binPosX+binWidth/2. + offset);
5401 myCandle.SetCandleWidth(candleWidth*binWidth);
5402 myCandle.SetHistoWidth(histoWidth*binWidth);
5403 myCandle.SetHistogram(hproj);
5404 myCandle.Paint();
5405 }
5406 }
5407 } else { // Horizontal candle
5408 //Determining the slice with the maximum integral - if necessary
5409 if (myCandle.IsCandleScaled())
5410 for (Int_t i=Hparam.yfirst; i<=Hparam.ylast; i++) {
5411 hproj = h2->ProjectionX("_py", i, i);
5412 if (hproj->Integral() > allMaxIntegral) allMaxIntegral = hproj->Integral();
5413 }
5414 for (Int_t i=Hparam.yfirst; i<=Hparam.ylast; i++) {
5415 Double_t binPosY = fYaxis->GetBinLowEdge(i);
5416 Double_t binWidth = fYaxis->GetBinWidth(i);
5417 hproj = h2->ProjectionX("_py", i, i);
5418 if (hproj->GetEntries() != 0) {
5419 Double_t candleWidth = fH->GetBarWidth();
5420 Double_t offset = fH->GetBarOffset()*binWidth;
5421 double myMaxContent = hproj->GetBinContent(hproj->GetMaximumBin());
5422 double myIntegral = hproj->Integral();
5423 Double_t histoWidth = candleWidth;
5424 if (candleWidth > 0.999 && candleWidth < 1.001) {
5425 candleWidth = standardCandleWidth;
5426 histoWidth = standardHistoWidth;
5427 }
5428 if (Hoption.Logz && myMaxContent > 0) {
5429 histoWidth *= myMaxContent/TMath::Log10(myMaxContent);
5430 if (myCandle.IsViolinScaled() && myMaxContent > 0 && allMaxContent > 0)
5431 histoWidth *= TMath::Log10(myMaxContent)/TMath::Log10(allMaxContent);
5432 } else if (myCandle.IsViolinScaled() && (allMaxContent > 0))
5433 histoWidth *= myMaxContent/allMaxContent;
5434 if (myCandle.IsCandleScaled() && (allMaxIntegral > 0))
5435 candleWidth *= myIntegral/allMaxIntegral;
5436
5437 myCandle.SetAxisPosition(binPosY+binWidth/2. + offset);
5438 myCandle.SetCandleWidth(candleWidth*binWidth);
5439 myCandle.SetHistoWidth(histoWidth*binWidth);
5440 myCandle.SetHistogram(hproj);
5441 myCandle.Paint();
5442 }
5443 }
5444 }
5445 delete hproj;
5446}
5447
5448
5449
5450////////////////////////////////////////////////////////////////////////////////
5451/// Returns the rendering regions for an axis to use in the COL2 option
5452///
5453/// The algorithm analyses the size of the axis compared to the size of
5454/// the rendering region. It figures out the boundaries to use for each color
5455/// of the rendering region. Only one axis is computed here.
5456///
5457/// This allows for a single computation of the boundaries before iterating
5458/// through all of the bins.
5459///
5460/// \param pAxis the axis to consider
5461/// \param nPixels the number of pixels to render axis into
5462/// \param isLog whether the axis is log scale
5463
5464std::vector<THistRenderingRegion>
5466{
5467 std::vector<THistRenderingRegion> regions;
5468
5469 enum STRATEGY { Bins, Pixels } strategy;
5470
5471 Int_t nBins = (pAxis->GetLast() - pAxis->GetFirst() + 1);
5472
5473 if (nBins >= nPixels) {
5474 // more bins than pixels... we should loop over pixels and sample
5475 strategy = Pixels;
5476 } else {
5477 // fewer bins than pixels... we should loop over bins
5478 strategy = Bins;
5479 }
5480
5481 if (isLog) {
5482
5483 Double_t xMin = pAxis->GetBinLowEdge(pAxis->GetFirst());
5484 Int_t binOffset=0;
5485 while (xMin <= 0 && ((pAxis->GetFirst()+binOffset) != pAxis->GetLast()) ) {
5486 binOffset++;
5487 xMin = pAxis->GetBinLowEdge(pAxis->GetFirst()+binOffset);
5488 }
5489 if (xMin <= 0) {
5490 // this should cause an error if we have
5491 return regions;
5492 }
5493 Double_t xMax = pAxis->GetBinUpEdge(pAxis->GetLast());
5494
5495 if (strategy == Bins) {
5496 // logarithmic plot. we find the pixel for the bin
5497 // pixel = eta * log10(V) - alpha
5498 // where eta = nPixels/(log10(Vmax)-log10(Vmin))
5499 // and alpha = nPixels*log10(Vmin)/(log10(Vmax)-log10(Vmin))
5500 // and V is axis value
5501 Double_t eta = (nPixels-1.0)/(TMath::Log10(xMax) - TMath::Log10(xMin));
5502 Double_t offset = -1.0 * eta * TMath::Log10(xMin);
5503
5504 for (Int_t bin=pAxis->GetFirst()+binOffset; bin<=pAxis->GetLast(); bin++) {
5505
5506 // linear plot. we simply need to find the appropriate bin
5507 // for the
5508 Double_t xLowValue = pAxis->GetBinLowEdge(bin);
5509 Double_t xUpValue = pAxis->GetBinUpEdge(bin);
5510 Int_t xPx0 = eta*TMath::Log10(xLowValue)+ offset;
5511 Int_t xPx1 = eta*TMath::Log10(xUpValue) + offset;
5512 THistRenderingRegion region = {std::make_pair(xPx0, xPx1),
5513 std::make_pair(bin, bin+1)};
5514 regions.push_back(region);
5515 }
5516
5517 } else {
5518
5519 // loop over pixels
5520
5521 Double_t beta = (TMath::Log10(xMax) - TMath::Log10(xMin))/(nPixels-1.0);
5522
5523 for (Int_t pixelIndex=0; pixelIndex<(nPixels-1); pixelIndex++) {
5524 // linear plot
5525 Int_t binLow = pAxis->FindBin(xMin*TMath::Power(10.0, beta*pixelIndex));
5526 Int_t binHigh = pAxis->FindBin(xMin*TMath::Power(10.0, beta*(pixelIndex+1)));
5527 THistRenderingRegion region = { std::make_pair(pixelIndex, pixelIndex+1),
5528 std::make_pair(binLow, binHigh)};
5529 regions.push_back(region);
5530 }
5531 }
5532 } else {
5533 // standard linear plot
5534
5535 if (strategy == Bins) {
5536 // loop over bins
5537 for (Int_t bin=pAxis->GetFirst(); bin<=pAxis->GetLast(); bin++) {
5538
5539 // linear plot. we simply need to find the appropriate bin
5540 // for the
5541 Int_t xPx0 = ((bin - pAxis->GetFirst()) * nPixels)/nBins;
5542 Int_t xPx1 = xPx0 + nPixels/nBins;
5543
5544 // make sure we don't compute beyond our bounds
5545 if (xPx1>= nPixels) xPx1 = nPixels-1;
5546
5547 THistRenderingRegion region = {std::make_pair(xPx0, xPx1),
5548 std::make_pair(bin, bin+1)};
5549 regions.push_back(region);
5550 }
5551 } else {
5552 // loop over pixels
5553 for (Int_t pixelIndex=0; pixelIndex<nPixels-1; pixelIndex++) {
5554 // linear plot
5555 Int_t binLow = (nBins*pixelIndex)/nPixels + pAxis->GetFirst();
5556 Int_t binHigh = binLow + nBins/nPixels;
5557 THistRenderingRegion region = { std::make_pair(pixelIndex, pixelIndex+1),
5558 std::make_pair(binLow, binHigh)};
5559 regions.push_back(region);
5560 }
5561 }
5562 }
5563
5564 return regions;
5565}
5566
5567////////////////////////////////////////////////////////////////////////////////
5568/// [Rendering scheme for the COL2 and COLZ2 options] (\ref HP14)
5569
5571{
5572
5573 if (Hoption.System != kCARTESIAN) {
5574 Error("THistPainter::PaintColorLevelsFast(Option_t*)",
5575 "Only cartesian coordinates supported by 'COL2' option. Using 'COL' option instead.");
5576 PaintColorLevels(nullptr);
5577 return;
5578 }
5579
5580 Double_t z;
5581
5582 // Use existing max or min values. If either is already set
5583 // the appropriate value to use.
5584 Double_t zmin = fH->GetMinimumStored();
5585 Double_t zmax = fH->GetMaximumStored();
5586 Double_t originalZMin = zmin;
5587 Double_t originalZMax = zmax;
5588 if ((zmin == -1111) && (zmax == -1111)) {
5589 fH->GetMinimumAndMaximum(zmin, zmax);
5590 fH->SetMinimum(zmin);
5591 fH->SetMaximum(zmax);
5592 } else if (zmin == -1111) {
5593 zmin = fH->GetMinimum();
5594 fH->SetMinimum(zmin);
5595 } else if (zmax == -1111) {
5596 zmax = fH->GetMaximum();
5597 fH->SetMaximum(zmax);
5598 }
5599
5600 Double_t dz = zmax - zmin;
5601 if (dz <= 0) { // Histogram filled with a constant value
5602 zmax += 0.1*TMath::Abs(zmax);
5603 zmin -= 0.1*TMath::Abs(zmin);
5604 dz = zmax - zmin;
5605 }
5606
5607 if (Hoption.Logz) {
5608 if (zmin > 0) {
5609 zmin = TMath::Log10(zmin);
5610 zmax = TMath::Log10(zmax);
5611 dz = zmax - zmin;
5612 } else {
5613 Error("THistPainter::PaintColorLevelsFast(Option_t*)",
5614 "Cannot plot logz because bin content is less than 0.");
5615 return;
5616 }
5617 }
5618
5619 // Initialize the levels on the Z axis
5620 Int_t ndiv = fH->GetContour();
5621 if (ndiv == 0 ) {
5622 ndiv = gStyle->GetNumberContours();
5623 fH->SetContour(ndiv);
5624 }
5625 std::vector<Double_t> colorBounds(ndiv);
5626 std::vector<Double_t> contours(ndiv, 0);
5627 if (!fH->TestBit(TH1::kUserContour)) {
5628 fH->SetContour(ndiv);
5629 } else {
5630 fH->GetContour(contours.data());
5631 }
5632
5633 Double_t step = 1.0/ndiv;
5634 for (Int_t i=0; i<ndiv; ++i) {
5635 colorBounds[i] = step*i;
5636 }
5637
5638 auto pFrame = gPad->GetFrame();
5639 Int_t px0 = gPad->XtoPixel(pFrame->GetX1());
5640 Int_t px1 = gPad->XtoPixel(pFrame->GetX2());
5641 Int_t py0 = gPad->YtoPixel(pFrame->GetY1());
5642 Int_t py1 = gPad->YtoPixel(pFrame->GetY2());
5643 Int_t nXPixels = px1-px0;
5644 Int_t nYPixels = py0-py1; // y=0 is at the top of the screen
5645
5646 std::vector<Double_t> buffer(nXPixels*nYPixels, 0);
5647
5648 auto xRegions = ComputeRenderingRegions(fXaxis, nXPixels, Hoption.Logx);
5649 auto yRegions = ComputeRenderingRegions(fYaxis, nYPixels, Hoption.Logy);
5650 if (xRegions.empty() || yRegions.empty()) {
5651 Error("THistPainter::PaintColorLevelFast(Option_t*)",
5652 "Encountered error while computing rendering regions.");
5653 return;
5654 }
5655
5656 Bool_t minExists = kFALSE;
5657 Bool_t maxExists = kFALSE;
5658 Double_t minValue = 1.;
5659 Double_t maxValue = 0.;
5660 for (auto& yRegion : yRegions) {
5661 for (auto& xRegion : xRegions ) {
5662
5663 const auto& xBinRange = xRegion.fBinRange;
5664 const auto& yBinRange = yRegion.fBinRange;
5665
5666 // sample the range
5667 z = fH->GetBinContent(xBinRange.second-1, yBinRange.second-1);
5668
5669 if (Hoption.Logz) {
5670 if (z > 0) z = TMath::Log10(z);
5671 else z = zmin;
5672 }
5673
5674 // obey the user's max and min values if they were set
5675 if (z > zmax) z = zmax;
5676 if (z < zmin) z = zmin;
5677
5679 // contours are absolute values
5680 auto index = TMath::BinarySearch(contours.size(), contours.data(), z);
5681 z = colorBounds[index];
5682 } else {
5683 Int_t index = 0;
5684 if (dz != 0) {
5685 index = 0.001 + ((z - zmin)/dz)*ndiv;
5686 }
5687
5688 if (index == static_cast<Int_t>(colorBounds.size())) {
5689 index--;
5690 }
5691
5692 // Do a little bookkeeping to use later for getting libAfterImage to produce
5693 // the correct colors
5694 if (index == 0) {
5695 minExists = kTRUE;
5696 } else if (index == static_cast<Int_t>(colorBounds.size()-1)) {
5697 maxExists = kTRUE;
5698 }
5699
5700 z = colorBounds[index];
5701
5702 if (z < minValue) {
5703 minValue = z;
5704 }
5705 if (z > maxValue) {
5706 maxValue = z;
5707 }
5708 }
5709
5710 // fill in the actual pixels
5711 const auto& xPixelRange = xRegion.fPixelRange;
5712 const auto& yPixelRange = yRegion.fPixelRange;
5713 for (Int_t xPx = xPixelRange.first; xPx <= xPixelRange.second; ++xPx) {
5714 for (Int_t yPx = yPixelRange.first; yPx <= yPixelRange.second; ++yPx) {
5715 Int_t pixel = yPx*nXPixels + xPx;
5716 buffer[pixel] = z;
5717 }
5718 }
5719 } // end px loop
5720 } // end py loop
5721
5722 // This is a bit of a hack to ensure that we span the entire color range and
5723 // don't screw up the colors for a sparse histogram. No one will notice that I set a
5724 // single pixel on the edge of the image to a different color. This is even more
5725 // true because the chosen pixels will be covered by the axis.
5726 if (minValue != maxValue) {
5727 if ( !minExists) {
5728 buffer.front() = 0;
5729 }
5730
5731 if ( !maxExists) {
5732 buffer[buffer.size()-nXPixels] = 0.95;
5733 }
5734 }
5735
5736 // Generate the TImage
5738 TImage* pImage = TImage::Create();
5740 pImage->SetImage(buffer.data(), nXPixels, nYPixels, pPalette);
5741 delete pPalette;
5742
5743 auto pp = gPad->GetPainter();
5744 if (pp)
5745 pp->DrawImage(pImage, px0, py1);
5746
5747 delete pImage;
5748
5749 if (Hoption.Zscale)
5750 PaintPalette();
5751
5752 // Reset the maximum and minimum values to their original values
5753 // when this function was called. If we don't do this, an initial
5754 // value of -1111 will be replaced with the true max or min values.
5755 fH->SetMinimum(originalZMin);
5756 fH->SetMaximum(originalZMax);
5757}
5758
5759////////////////////////////////////////////////////////////////////////////////
5760/// [Control function to draw a 2D histogram as a color plot.](\ref HP14)
5761
5763{
5764 Double_t z, e, zc, xk, xstep, yk, ystep, xlow, xup, ylow, yup;
5765
5766 Double_t zmin = fH->GetMinimum();
5767 Double_t zmax = fH->GetMaximum();
5768
5769 Double_t dz = zmax - zmin;
5770 if (dz <= 0) { // Histogram filled with a constant value
5771 zmax += 0.1*TMath::Abs(zmax);
5772 zmin -= 0.1*TMath::Abs(zmin);
5773 dz = zmax - zmin;
5774 }
5775
5776 // In case of option SAME, zmin and zmax values are taken from the
5777 // first plotted 2D histogram.
5778 if (Hoption.Same > 0 && Hoption.Same < 10) {
5779 TH2 *h2;
5780 TIter next(gPad->GetListOfPrimitives());
5781 while ((h2 = (TH2 *)next())) {
5782 if (!h2->InheritsFrom(TH2::Class())) continue;
5783 zmin = h2->GetMinimum();
5784 zmax = h2->GetMaximum();
5785 fH->SetMinimum(zmin);
5786 fH->SetMaximum(zmax);
5787 if (Hoption.Logz) {
5788 if (zmin <= 0) {
5789 zmin = TMath::Log10(zmax*0.001);
5790 } else {
5791 zmin = TMath::Log10(zmin);
5792 }
5793 zmax = TMath::Log10(zmax);
5794 }
5795 dz = zmax - zmin;
5796 break;
5797 }
5798 } else {
5799 if (Hoption.Logz) {
5800 if (zmin > 0) {
5801 zmin = TMath::Log10(zmin);
5802 zmax = TMath::Log10(zmax);
5803 dz = zmax - zmin;
5804 } else {
5805 return;
5806 }
5807 }
5808 }
5809
5810 Style_t fillsav = fH->GetFillStyle();
5811 Style_t colsav = fH->GetFillColor();
5812 fH->SetFillStyle(1001);
5813 fH->TAttFill::Modify();
5814
5815 // Initialize the levels on the Z axis
5816 Int_t ncolors = gStyle->GetNumberOfColors();
5817 Int_t ndiv = fH->GetContour();
5818 if (ndiv == 0) {
5819 ndiv = gStyle->GetNumberContours();
5820 fH->SetContour(ndiv);
5821 }
5822 Int_t ndivz = TMath::Abs(ndiv);
5823 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
5824 Double_t scale = (dz ? ndivz / dz : 1.0);
5825
5826 Double_t xmin = gPad->GetUxmin();
5827 Double_t xmax = gPad->GetUxmax();
5828 Double_t ymin = gPad->GetUymin();
5829 Double_t ymax = gPad->GetUymax();
5830
5831 // range used for polar coordinates
5832 Double_t pxmin = xmin, pxmax = xmax, pymin = ymin, pymax = ymax, pkr = 0.5;
5833 if ((Hoption.System == kPOLAR) && (Hoption.Polar == 2)) {
5834 pxmin = fXaxis->GetXmin();
5835 pxmax = fXaxis->GetXmax();
5836 if (Hoption.Logx) {
5837 if (pxmax <= 0)
5838 return;
5839 pxmax = TMath::Log10(pxmax);
5840 if (pxmin <= 0)
5841 pxmin = pxmax - 5;
5842 else
5843 pxmin = TMath::Log10(pxmin);
5844 }
5845 pkr = 0.45; // makes fixed range more pretty
5846 pymin = fYaxis->GetXmin();
5847 pymax = fYaxis->GetXmax();
5848 if (Hoption.Logy) {
5849 if (pymax <= 0)
5850 return;
5851 pymax = TMath::Log10(pymax);
5852 if (pymin <= 0)
5853 pymin = pymax - 5;
5854 else
5855 pymin = TMath::Log10(pymin);
5856 } else if ((pymax > 0) && (pymin > 0)) {
5857 // force minimal radius to 0 to display natural polar graphics
5858 pymin = 0;
5859 }
5860 }
5861
5862 if ((Hoption.System == kPOLAR) && (Hoption.Polar == 3)) {
5863 // do not touch boundaries when draw without axis histogram
5864 if (!Hoption.Same)
5865 pkr = 0.45;
5866 // for natural coordinates force minimal radius to 0
5867 if (!Hoption.Logy && (pymax > 0))
5868 pymin = 0;
5869 }
5870
5871 Int_t color;
5872 TProfile2D* prof2d = dynamic_cast<TProfile2D*>(fH);
5873 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
5874 yk = fYaxis->GetBinLowEdge(j);
5875 ystep = fYaxis->GetBinWidth(j);
5876 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
5877 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
5878 xk = fXaxis->GetBinLowEdge(i);
5879 xstep = fXaxis->GetBinWidth(i);
5880 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
5881 z = fH->GetBinContent(bin);
5882 e = fH->GetBinError(bin);
5883 // if fH is a profile histogram do not draw empty bins
5884 if (prof2d) {
5885 const Double_t binEntries = prof2d->GetBinEntries(bin);
5886 if (binEntries == 0)
5887 continue;
5888 } else {
5889 // don't draw the empty bins for non-profile histograms
5890 // with positive content
5891 if (z == 0 && e == 0) {
5892 if (zmin >= 0 || Hoption.Logz) continue;
5893 if (Hoption.Color == 2) continue;
5894 }
5895 }
5896
5897 if (Hoption.Logz)
5898 z = z > 0 ? TMath::Log10(z) : zmin;
5899 if (z < zmin && !Hoption.Zero)
5900 continue;
5901 xup = xk + xstep;
5902 xlow = xk;
5903 if (Hoption.Logx) {
5904 if ((xup <= 0) || (xlow <= 0))
5905 continue;
5906 xup = TMath::Log10(xup);
5907 xlow = TMath::Log10(xlow);
5908 }
5909 yup = yk + ystep;
5910 ylow = yk;
5911 if (Hoption.Logy) {
5912 if ((yup <= 0) || (ylow <= 0))
5913 continue;
5914 yup = TMath::Log10(yup);
5915 ylow = TMath::Log10(ylow);
5916 }
5917 if ((xup < xmin) || (yup < ymin) || (xlow > xmax) || (ylow > ymax))
5918 continue;
5919 if (xlow < xmin)
5920 xlow = xmin;
5921 if (ylow < ymin)
5922 ylow = ymin;
5923 if (xup > xmax)
5924 xup = xmax;
5925 if (yup > ymax)
5926 yup = ymax;
5927
5929 zc = fH->GetContourLevelPad(0);
5930 if (z < zc) continue;
5931 color = -1;
5932 for (Int_t k=0; k<ndiv; k++) {
5933 zc = fH->GetContourLevelPad(k);
5934 if (z < zc) {
5935 continue;
5936 } else {
5937 color++;
5938 }
5939 }
5940 } else {
5941 color = Hoption.Zero ? Int_t(0.01+(std::max(z, zmin)-zmin)*scale) : Int_t(0.01+(z-zmin)*scale);
5942 }
5943
5944 Int_t theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
5945 if (theColor > ncolors-1)
5946 theColor = ncolors-1;
5947 auto fillColor = gStyle->GetColorPalette(theColor);
5948 if (Hoption.System != kPOLAR) {
5949 fH->SetFillColor(fillColor);
5950 fH->TAttFill::Modify();
5951 gPad->PaintBox(xlow, ylow, xup, yup);
5952 } else {
5953 Double_t midx = (xmin + xmax) / 2;
5954 Double_t midy = (ymin + ymax) / 2;
5955 Double_t rx = xmax - xmin;
5956 Double_t ry = ymax - ymin;
5957 Double_t a1, a2;
5958
5959 if (Hoption.Polar == 3) {
5960 a1 = xlow / TMath::Pi() * 180;
5961 a2 = xup / TMath::Pi() * 180;
5962 } else {
5963 a1 = ((xlow - pxmin) / (pxmax - pxmin) - 0.5) * 360;
5964 a2 = ((xup - pxmin) / (pxmax - pxmin) - 0.5) * 360;
5965 }
5966 Double_t r1 = (ylow - pymin) / (pymax - pymin) * rx * pkr;
5967 Double_t r2 = (yup - pymin) / (pymax - pymin) * rx * pkr;
5968
5969 TCrown crown(midx, midy, r1, r2, a1, a2);
5970 crown.SetYXRatio(rx > 0 ? ry / rx : 1);
5971 crown.SetFillColor(fillColor);
5972 crown.SetLineColor(fH->GetLineColor());
5973 crown.SetLineWidth(fH->GetLineWidth());
5974 crown.SetLineStyle(fH->GetLineStyle());
5975 crown.Paint();
5976 }
5977 }
5978 }
5979
5981
5982 fH->SetFillStyle(fillsav);
5983 fH->SetFillColor(colsav);
5984 fH->TAttFill::Modify();
5985
5986}
5987
5988////////////////////////////////////////////////////////////////////////////////
5989/// [Control function to draw a 2D histogram as a contour plot.](\ref HP16)
5990
5992{
5993
5994 Int_t i, j, count, ncontour, icol, n, lj, m, ix, jx, ljfill;
5995 Int_t itars, mode, ir[4];
5996 Double_t xsave, ysave, thesave,phisave,x[4], y[4], zc[4];
5997
5998 if (Hoption.Contour == 14) {
5999 Hoption.Surf = 12;
6000 Hoption.Axis = 1;
6001 thesave = gPad->GetTheta();
6002 phisave = gPad->GetPhi();
6003 gPad->SetPhi(0.);
6004 gPad->SetTheta(90.);
6006 gPad->SetPhi(phisave);
6007 gPad->SetTheta(thesave);
6008 TView *view = gPad->GetView();
6009 if (view) view->SetBit(kCannotRotate); //tested in ExecuteEvent
6010 PaintAxis();
6011 return;
6012 }
6013
6014 if (Hoption.Same) {
6015 // If the contour is painted on a 3d plot, the contour lines are
6016 // paint in 3d too.
6017 TObject *obj;
6018 TIter next(gPad->GetListOfPrimitives());
6019 while ((obj=next())) {
6020 if (strstr(obj->GetDrawOption(),"surf") ||
6021 strstr(obj->GetDrawOption(),"lego") ||
6022 strstr(obj->GetDrawOption(),"tri")) {
6023 Hoption.Surf = 16;
6025 return;
6026 }
6027 }
6028 }
6029
6030 if (Hoption.Contour == 15) {
6031 TGraphDelaunay2D *dt = nullptr;
6032 TGraphDelaunay *dtOld = nullptr;
6033 TList *hl = fH->GetListOfFunctions();
6034 dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
6035 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
6036 if (!dt && !dtOld) return;
6037 if (!fGraph2DPainter)
6038 fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
6039 fGraph2DPainter->Paint(option);
6040 return;
6041 }
6042
6043 gPad->SetBit(TGraph::kClipFrame);
6044
6045 std::vector<Double_t> levels(2*kMAXCONTOUR);
6046 std::vector<Double_t> xarr(2*kMAXCONTOUR);
6047 std::vector<Double_t> yarr(2*kMAXCONTOUR);
6048 std::vector<Int_t> itarr(2*kMAXCONTOUR);
6049
6050 Int_t npmax = 0;
6051 for (i=0;i<2*kMAXCONTOUR;i++) itarr[i] = 0;
6052
6053 ncontour = fH->GetContour();
6054 if (ncontour == 0) {
6055 ncontour = gStyle->GetNumberContours();
6056 fH->SetContour(ncontour);
6057 }
6058 if (ncontour > kMAXCONTOUR) {
6059 Warning("PaintContour", "maximum number of contours is %d, asked for %d",
6060 kMAXCONTOUR, ncontour);
6061 ncontour = kMAXCONTOUR-1;
6062 }
6063 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ncontour);
6064
6065 for (i=0;i<ncontour;i++) levels[i] = fH->GetContourLevelPad(i);
6066 Int_t linesav = fH->GetLineStyle();
6067 Int_t colorsav = fH->GetLineColor();
6068 Int_t fillsav = fH->GetFillColor();
6069 if (Hoption.Contour == 13) {
6070 fH->TAttLine::Modify();
6071 }
6072
6073 std::vector<std::unique_ptr<TPolyLine>> polys;
6074 TObjArray *contours = nullptr;
6075 TList *list = nullptr;
6076 TGraph *graph = nullptr;
6077 std::vector<Int_t> np;
6078 if (Hoption.Contour == 1 || (Hoption.List && (Hoption.Contour == 11 || Hoption.Contour == 12 || Hoption.Contour == 13))) {
6079 np.resize(ncontour);
6080 for (i=0;i<ncontour;i++)
6081 np[i] = 0;
6082 for (i=0;i<ncontour;i++)
6083 polys.emplace_back(std::make_unique<TPolyLine>(100));
6084 if (Hoption.List == 1) {
6085 contours = (TObjArray*)gROOT->GetListOfSpecials()->FindObject("contours");
6086 if (contours) {
6087 gROOT->GetListOfSpecials()->Remove(contours);
6088 count = contours->GetSize();
6089 for (i=0;i<count;i++) {
6090 list = (TList*)contours->At(i);
6091 if (list) list->Delete();
6092 }
6093 contours->Delete();
6094 delete contours;
6095 }
6096 contours = new TObjArray(ncontour);
6097 contours->SetName("contours");
6098 gROOT->GetListOfSpecials()->Add(contours);
6099 for (i=0;i<ncontour;i++) {
6100 list = new TList();
6101 contours->Add(list);
6102 }
6103 }
6104 }
6105 Int_t theColor;
6106 Int_t ncolors = gStyle->GetNumberOfColors();
6107 Int_t ndivz = TMath::Abs(ncontour);
6108
6109 Int_t k,ipoly;
6110 for (j=Hparam.yfirst; j<Hparam.ylast; j++) {
6111 y[0] = fYaxis->GetBinCenter(j);
6112 y[1] = y[0];
6113 y[2] = fYaxis->GetBinCenter(j+1);
6114 y[3] = y[2];
6115 for (i=Hparam.xfirst; i<Hparam.xlast; i++) {
6116 zc[0] = fH->GetBinContent(i, j);
6117 zc[1] = fH->GetBinContent(i+1, j);
6118 zc[2] = fH->GetBinContent(i+1, j+1);
6119 zc[3] = fH->GetBinContent(i, j+1);
6120 if (!IsInside(fXaxis->GetBinCenter(i),fYaxis->GetBinCenter(j))) continue;
6121 if (Hoption.Logz) {
6122 if (zc[0] > 0) zc[0] = TMath::Log10(zc[0]);
6123 else zc[0] = Hparam.zmin;
6124 if (zc[1] > 0) zc[1] = TMath::Log10(zc[1]);
6125 else zc[1] = Hparam.zmin;
6126 if (zc[2] > 0) zc[2] = TMath::Log10(zc[2]);
6127 else zc[2] = Hparam.zmin;
6128 if (zc[3] > 0) zc[3] = TMath::Log10(zc[3]);
6129 else zc[3] = Hparam.zmin;
6130 }
6131 for (k=0;k<4;k++) {
6132 ir[k] = TMath::BinarySearch(ncontour, levels.data(), zc[k]);
6133 }
6134 if (ir[0] != ir[1] || ir[1] != ir[2] || ir[2] != ir[3] || ir[3] != ir[0]) {
6135 x[0] = fXaxis->GetBinCenter(i);
6136 x[3] = x[0];
6137 x[1] = fXaxis->GetBinCenter(i+1);
6138 x[2] = x[1];
6139 if (zc[0] <= zc[1]) n = 0; else n = 1;
6140 if (zc[2] <= zc[3]) m = 2; else m = 3;
6141 if (zc[n] > zc[m]) n = m;
6142 n++;
6143 lj=1;
6144 for (ix=1;ix<=4;ix++) {
6145 m = n%4 + 1;
6146 ljfill = PaintContourLine(zc[n-1],ir[n-1],x[n-1],y[n-1],zc[m-1],
6147 ir[m-1],x[m-1],y[m-1], xarr.data()+lj-1,yarr.data()+lj-1,itarr.data()+lj-1, levels.data());
6148 lj += 2*ljfill;
6149 n = m;
6150 }
6151
6152 if (zc[0] <= zc[1]) n = 0; else n = 1;
6153 if (zc[2] <= zc[3]) m = 2; else m = 3;
6154 if (zc[n] > zc[m]) n = m;
6155 n++;
6156 lj=2;
6157 for (ix=1;ix<=4;ix++) {
6158 if (n == 1) m = 4;
6159 else m = n-1;
6160 ljfill = PaintContourLine(zc[n-1],ir[n-1],x[n-1],y[n-1],zc[m-1],
6161 ir[m-1],x[m-1],y[m-1],xarr.data()+lj-1,yarr.data()+lj-1,itarr.data()+lj-1, levels.data());
6162 lj += 2*ljfill;
6163 n = m;
6164 }
6165
6166 // Re-order endpoints
6167
6168 count = 0;
6169 for (ix=1; ix<=lj-5; ix +=2) {
6170 //count = 0;
6171 while (itarr[ix-1] != itarr[ix]) {
6172 xsave = xarr[ix];
6173 ysave = yarr[ix];
6174 itars = itarr[ix];
6175 for (jx=ix; jx<=lj-5; jx +=2) {
6176 xarr[jx] = xarr[jx+2];
6177 yarr[jx] = yarr[jx+2];
6178 itarr[jx] = itarr[jx+2];
6179 }
6180 xarr[lj-3] = xsave;
6181 yarr[lj-3] = ysave;
6182 itarr[lj-3] = itars;
6183 if (count > 100) break;
6184 count++;
6185 }
6186 }
6187
6188 if (count > 100) continue;
6189 for (ix=1; ix<=lj-2; ix +=2) {
6190 theColor = Int_t((itarr[ix-1]+0.99)*Float_t(ncolors)/Float_t(ndivz));
6191 icol = gStyle->GetColorPalette(theColor);
6192 if (Hoption.Contour == 11) {
6193 fH->SetLineColor(icol);
6194 }
6195 if (Hoption.Contour == 12) {
6196 mode = icol%5;
6197 if (mode == 0) mode = 5;
6199 }
6200 if (Hoption.Contour != 1) {
6201 fH->TAttLine::Modify();
6202 gPad->PaintPolyLine(2,xarr.data()+ix-1,yarr.data()+ix-1);
6203 if ((Hoption.Contour != 11 && Hoption.Contour != 12 && Hoption.Contour != 13) || !Hoption.List)
6204 continue;
6205 }
6206
6207 ipoly = itarr[ix-1];
6208 if (ipoly >=0 && ipoly <ncontour) {
6209 polys[ipoly]->SetPoint(np[ipoly] ,xarr[ix-1],yarr[ix-1]);
6210 polys[ipoly]->SetPoint(np[ipoly]+1,xarr[ix], yarr[ix]);
6211 np[ipoly] += 2;
6212 if (npmax < np[ipoly]) npmax = np[ipoly];
6213 }
6214 }
6215 } // end of if (ir[0]
6216 } //end of for (i
6217 } //end of for (j
6218
6220 std::vector<Double_t> xp, yp;
6221 Int_t nadd,iminus,iplus;
6222 Int_t istart;
6223 Int_t first = ncontour;
6224 std::vector<Int_t> polysort;
6225 Int_t contListNb;
6226 if (Hoption.Contour != 1) {
6227 if (!Hoption.List || (Hoption.Contour != 11 && Hoption.Contour != 12 && Hoption.Contour != 13))
6228 goto theEND;
6229 }
6230
6231 //The 2 points line generated above are now sorted/merged to generate
6232 //a list of consecutive points.
6233 // If the option "List" has been specified, the list of points is saved
6234 // in the form of TGraph objects in the ROOT list of special objects.
6235 xmin = gPad->GetUxmin();
6236 ymin = gPad->GetUymin();
6237 xp.resize(2*npmax);
6238 yp.resize(2*npmax);
6239 polysort.resize(ncontour);
6240 //find first positive contour
6241 for (ipoly=0;ipoly<ncontour;ipoly++) {
6242 if (levels[ipoly] >= 0) {first = ipoly; break;}
6243 }
6244 //store negative contours from 0 to minimum, then all positive contours
6245 k = 0;
6246 for (ipoly=first-1;ipoly>=0;ipoly--) {polysort[k] = ipoly; k++;}
6247 for (ipoly=first;ipoly<ncontour;ipoly++) {polysort[k] = ipoly; k++;}
6248 // if Contour==1 we can now draw sorted contours, otherwise (11,12,13) just store
6249 contListNb = 0;
6250 if (Hoption.Contour == 1) fH->SetFillStyle(1001);
6251 for (k=0;k<ncontour;k++) {
6252 ipoly = polysort[k];
6253 if (Hoption.List) list = (TList*)contours->At(contListNb);
6254 contListNb++;
6255 if (np[ipoly] == 0)
6256 continue;
6257 Double_t *xx = polys[ipoly]->GetX();
6258 Double_t *yy = polys[ipoly]->GetY();
6259 istart = 0;
6260 while (true) {
6261 iminus = npmax;
6262 iplus = iminus+1;
6263 xp[iminus]= xx[istart]; yp[iminus] = yy[istart];
6264 xp[iplus] = xx[istart+1]; yp[iplus] = yy[istart+1];
6265 xx[istart] = xmin; yy[istart] = ymin;
6266 xx[istart+1] = xmin; yy[istart+1] = ymin;
6267 while (true) {
6268 nadd = 0;
6269 for (i=2;i<np[ipoly];i+=2) {
6270 if ((iplus < 2*npmax-1) && (xx[i] == xp[iplus]) && (yy[i] == yp[iplus])) {
6271 iplus++;
6272 xp[iplus] = xx[i+1]; yp[iplus] = yy[i+1];
6273 xx[i] = xmin; yy[i] = ymin;
6274 xx[i+1] = xmin; yy[i+1] = ymin;
6275 nadd++;
6276 }
6277 if ((iminus > 0) && (xx[i+1] == xp[iminus]) && (yy[i+1] == yp[iminus])) {
6278 iminus--;
6279 xp[iminus] = xx[i]; yp[iminus] = yy[i];
6280 xx[i] = xmin; yy[i] = ymin;
6281 xx[i+1] = xmin; yy[i+1] = ymin;
6282 nadd++;
6283 }
6284 }
6285 if (nadd == 0) break;
6286 }
6287 theColor = Int_t((ipoly+0.99)*Float_t(ncolors)/Float_t(ndivz));
6288 icol = gStyle->GetColorPalette(theColor);
6289 if (Hoption.Contour == 1) {
6290 if (ndivz > 1) fH->SetFillColor(icol);
6291 fH->TAttFill::Modify();
6292 gPad->PaintFillArea(iplus-iminus+1,xp.data()+iminus,yp.data()+iminus);
6293 }
6294 if (Hoption.List) {
6295 graph = new TGraph(iplus-iminus+1,xp.data()+iminus,yp.data()+iminus);
6296 if (Hoption.Contour == 1)
6297 graph->SetFillColor(icol);
6298 else if (Hoption.Contour == 11)
6299 graph->SetLineColor(icol);
6300 else if (Hoption.Contour == 12) {
6301 mode = icol%5;
6302 if (mode == 0) mode = 5;
6303 graph->SetLineStyle(mode);
6304 }
6305 graph->SetLineWidth(fH->GetLineWidth());
6306 list->Add(graph);
6307 }
6308 //check if more points are left
6309 istart = 0;
6310 for (i=2;i<np[ipoly];i+=2) {
6311 if (xx[i] != xmin && yy[i] != ymin) {
6312 istart = i;
6313 break;
6314 }
6315 }
6316 if (istart == 0) break;
6317 }
6318 }
6319
6320theEND:
6321 gPad->ResetBit(TGraph::kClipFrame);
6323 fH->SetLineStyle(linesav);
6324 fH->SetLineColor(colorsav);
6325 fH->SetFillColor(fillsav);
6326}
6327
6328////////////////////////////////////////////////////////////////////////////////
6329/// Fill the matrix `xarr` and `yarr` for Contour Plot.
6330
6332 Double_t elev2, Int_t icont2, Double_t x2, Double_t y2,
6333 Double_t *xarr, Double_t *yarr, Int_t *itarr, Double_t *levels)
6334{
6335
6336 Bool_t vert;
6337 Double_t tlen, tdif, elev, diff, pdif, xlen;
6338 Int_t n, i, icount;
6339
6340 if (x1 == x2) {
6341 vert = kTRUE;
6342 tlen = y2 - y1;
6343 } else {
6344 vert = kFALSE;
6345 tlen = x2 - x1;
6346 }
6347
6348 n = icont1 +1;
6349 tdif = elev2 - elev1;
6350 i = 0;
6351 icount = 0;
6352 while (n <= icont2 && i <= kMAXCONTOUR/2 -3) {
6353 //elev = fH->GetContourLevel(n);
6354 elev = levels[n];
6355 diff = elev - elev1;
6356 pdif = diff/tdif;
6357 xlen = tlen*pdif;
6358 if (vert) {
6359 if (Hoption.Logx)
6360 xarr[i] = TMath::Log10(x1);
6361 else
6362 xarr[i] = x1;
6363 if (Hoption.Logy)
6364 yarr[i] = TMath::Log10(y1 + xlen);
6365 else
6366 yarr[i] = y1 + xlen;
6367 } else {
6368 if (Hoption.Logx)
6369 xarr[i] = TMath::Log10(x1 + xlen);
6370 else
6371 xarr[i] = x1 + xlen;
6372 if (Hoption.Logy)
6373 yarr[i] = TMath::Log10(y1);
6374 else
6375 yarr[i] = y1;
6376 }
6377 itarr[i] = n;
6378 icount++;
6379 i +=2;
6380 n++;
6381 }
6382 return icount;
6383}
6384
6385////////////////////////////////////////////////////////////////////////////////
6386/// [Draw 1D histograms error bars.](\ref HP09)
6387
6389{
6390
6391 // On iOS, we do not highlight histogram, if it's not picked at the moment
6392 // (but part of histogram (axis or pavestat) was picked, that's why this code
6393 // is called at all. This conditional statement never executes on non-iOS platform.
6394 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH) return;
6395
6396 const Int_t kBASEMARKER=8;
6397 Double_t xp, yp, ex1, ex2, ey1, ey2;
6398 Double_t delta;
6399 Double_t s2x, s2y, bxsize, bysize, symbolsize, xerror, sbasex, sbasey;
6400 Double_t xi1, xi2, xi3, xi4, yi1, yi2, yi3, yi4;
6402 Double_t logxmin = 0;
6403 Double_t logymin = 0;
6404 Double_t offset = 0.;
6405 Double_t width = 0.;
6406 Int_t i, k, npoints, first, last, fixbin;
6407 Int_t if1 = 0;
6408 Int_t if2 = 0;
6409 Bool_t drawmarker;
6410 Int_t errormarker;
6411 Int_t option0, option1, option2, option3, option4, optionE, optionEX0, optionI0;
6412 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};
6413 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};
6414
6415 std::vector<Double_t> xline, yline, xsegm, ysegm, xmarker, ymarker;
6416 option0 = option1 = option2 = option3 = option4 = optionE = optionEX0 = optionI0 = 0;
6417 if (Hoption.Error >= 40) {Hoption.Error -=40; option0 = 1;}
6418 if (Int_t(Hoption.Error/10) == 2) {optionEX0 = 1; Hoption.Error -= 10;}
6419 if (Hoption.Error == 31) {optionEX0 = 1; Hoption.Error = 1;}
6420 if (Hoption.Error == 11) option1 = 1;
6421 if (Hoption.Error == 12) option2 = 1;
6422 if (Hoption.Error == 13) option3 = 1;
6423 if (Hoption.Error == 14) {option4 = 1; option3 = 1;}
6424 if (Hoption.Error == 15) {optionI0 = 1; option3 = 1;}
6425 if (Hoption.Error == 16) {optionI0 = 1; option4 = 1; option3 = 1;}
6426 if (option2+option3 == 0) optionE = 1;
6427 if (Hoption.Error == 0) optionE = 0;
6428 if (fXaxis->GetXbins()->fN) fixbin = 0;
6429 else fixbin = 1;
6430
6431 offset = fH->GetBarOffset();
6432 width = fH->GetBarWidth();
6433
6435 if (optionEX0) {
6436 xerror = 0;
6437 } else {
6438 xerror = gStyle->GetErrorX();
6439 }
6440 symbolsize = fH->GetMarkerSize();
6441 if (errormarker == 1) symbolsize = 0.01;
6442 sbasex = sbasey = symbolsize*kBASEMARKER;
6443 if (errormarker >= 20 && errormarker <= 49) {
6444 sbasex *= cxx[errormarker-20];
6445 sbasey *= cyy[errormarker-20];
6446 }
6447 // set the graphics attributes
6448
6449 fH->TAttLine::Modify();
6450 fH->TAttFill::Modify();
6451 fH->TAttMarker::Modify();
6452
6453 // set the first and last bin
6454
6455 Double_t factor = Hparam.factor;
6456 first = Hparam.xfirst;
6457 last = Hparam.xlast;
6458 npoints = last - first +1;
6459 xmin = gPad->GetUxmin();
6460 xmax = gPad->GetUxmax();
6461 ymin = gPad->GetUymin();
6462 ymax = gPad->GetUymax();
6463
6464 xsegm.reserve(1024);
6465 ysegm.reserve(1024);
6466 if (!xsegm.capacity() || !ysegm.capacity()) {
6467 Error("PaintErrors", "out of memory for lines painting");
6468 return;
6469 }
6470
6471 auto flush_segmentes = [&]() {
6472 if (xsegm.size() > 0) {
6473 gPad->PaintSegments(xsegm.size()/2, xsegm.data(), ysegm.data());
6474 xsegm.clear();
6475 ysegm.clear();
6476 }
6477 };
6478
6479 auto add_segment = [&](Double_t x1, Double_t y1, Double_t x2, Double_t y2) {
6480 xsegm.emplace_back(x1);
6481 xsegm.emplace_back(x2);
6482 ysegm.emplace_back(y1);
6483 ysegm.emplace_back(y2);
6484 if (xsegm.size() == xsegm.capacity())
6485 flush_segmentes();
6486 };
6487
6488 auto flush_markers = [&]() {
6489 if (xmarker.size() > 0) {
6490 gPad->PaintPolyMarker(xmarker.size(), xmarker.data(), ymarker.data());
6491 xmarker.clear();
6492 ymarker.clear();
6493 }
6494 };
6495
6496 auto add_marker = [&](Double_t x, Double_t y) {
6497 if (xmarker.capacity() == 0) {
6498 xmarker.reserve(256);
6499 ymarker.reserve(256);
6500 }
6501
6502 xmarker.emplace_back(x);
6503 ymarker.emplace_back(y);
6504 if (xmarker.size() == xmarker.capacity()) {
6505 flush_segmentes();
6506 flush_markers();
6507 }
6508 };
6509
6510
6511 if (option3) {
6512 xline.resize(2*npoints);
6513 yline.resize(2*npoints);
6514 if ((npoints > 0) && (xline.empty() || yline.empty())) {
6515 Error("PaintErrors", "too many points, out of memory");
6516 return;
6517 }
6518 if1 = 1;
6519 if2 = 2*npoints;
6520 }
6521
6522 // compute the offset of the error bars due to the symbol size
6523 s2x = gPad->PixeltoX(Int_t(0.5*sbasex)) - gPad->PixeltoX(0);
6524 s2y =-gPad->PixeltoY(Int_t(0.5*sbasey)) + gPad->PixeltoY(0);
6525
6526 // compute size of the lines at the end of the error bars
6527 Int_t dxend = Int_t(gStyle->GetEndErrorSize());
6528 bxsize = gPad->PixeltoX(dxend) - gPad->PixeltoX(0);
6529 bysize =-gPad->PixeltoY(dxend) + gPad->PixeltoY(0);
6530
6531
6532 if (fixbin) {
6533 if (Hoption.Logx) xp = TMath::Power(10,Hparam.xmin) + 0.5*Hparam.xbinsize;
6534 else xp = Hparam.xmin + 0.5*Hparam.xbinsize;
6535 } else {
6536 delta = fH->GetBinWidth(first);
6537 xp = fH->GetBinLowEdge(first) + 0.5*delta;
6538 }
6539
6540 // if errormarker = 0 or symbolsize = 0. no symbol is drawn
6541 if (Hoption.Logx) logxmin = TMath::Power(10,Hparam.xmin);
6542 if (Hoption.Logy) logymin = TMath::Power(10,Hparam.ymin);
6543
6544 // ---------------------- Loop over the points---------------------
6545 for (k=first; k<=last; k++) {
6546
6547 // get the data
6548 // xp = X position of the current point
6549 // yp = Y position of the current point
6550 // ex1 = Low X error
6551 // ex2 = Up X error
6552 // ey1 = Low Y error
6553 // ey2 = Up Y error
6554 // (xi,yi) = Error bars coordinates
6555
6556 // apply offset on errors for bar histograms
6557 Double_t xminTmp = gPad->XtoPad(fXaxis->GetBinLowEdge(k));
6558 Double_t xmaxTmp = gPad->XtoPad(fXaxis->GetBinUpEdge(k));
6559 if (Hoption.Logx) {
6560 xminTmp = TMath::Power(10, xminTmp);
6561 xmaxTmp = TMath::Power(10, xmaxTmp);
6562 }
6563 Double_t w = (xmaxTmp-xminTmp)*width;
6564 xminTmp += offset*(xmaxTmp-xminTmp);
6565 xmaxTmp = xminTmp + w;
6566 xp = (xminTmp+xmaxTmp)/2.;
6567
6568 if (Hoption.Logx) {
6569 if (xp <= 0) goto L30;
6570 if (xp < logxmin) goto L30;
6571 if (xp > TMath::Power(10,xmax)) break;
6572 } else {
6573 if (xp < xmin) goto L30;
6574 if (xp > xmax) break;
6575 }
6576 yp = factor*fH->GetBinContent(k);
6577 if (optionI0 && yp==0) goto L30;
6578 if (fixbin) {
6579 ex1 = xerror*Hparam.xbinsize;
6580 } else {
6581 delta = fH->GetBinWidth(k);
6582 ex1 = xerror*delta;
6583 }
6584 if (fH->GetBinErrorOption() == TH1::kNormal) {
6585 ey1 = factor*fH->GetBinError(k);
6586 ey2 = ey1;
6587 } else {
6588 ey1 = factor*fH->GetBinErrorLow(k);
6589 ey2 = factor*fH->GetBinErrorUp(k);
6590 }
6591 ex2 = ex1;
6592
6593 xi4 = xp;
6594 xi3 = xp;
6595 xi2 = xp + ex2;
6596 xi1 = xp - ex1;
6597
6598 yi1 = yp;
6599 yi2 = yp;
6600 yi3 = yp - ey1;
6601 yi4 = yp + ey2;
6602
6603 // take the LOG if necessary
6604 if (Hoption.Logx) {
6605 xi1 = TMath::Log10(TMath::Max(xi1,logxmin));
6606 xi2 = TMath::Log10(TMath::Max(xi2,logxmin));
6607 xi3 = TMath::Log10(TMath::Max(xi3,logxmin));
6608 xi4 = TMath::Log10(TMath::Max(xi4,logxmin));
6609 }
6610 if (Hoption.Logy) {
6611 yi1 = TMath::Log10(TMath::Max(yi1,logymin));
6612 yi2 = TMath::Log10(TMath::Max(yi2,logymin));
6613 yi3 = TMath::Log10(TMath::Max(yi3,logymin));
6614 yi4 = TMath::Log10(TMath::Max(yi4,logymin));
6615 }
6616
6617 // test if error bars are not outside the limits
6618 // otherwise they are truncated
6619
6620 xi1 = TMath::Max(xi1,xmin);
6621 xi2 = TMath::Min(xi2,xmax);
6622 yi3 = TMath::Max(yi3,ymin);
6623 yi4 = TMath::Min(yi4,ymax);
6624
6625 // test if the marker is on the frame limits. If "Yes", the
6626 // marker will not be drawn and the error bars will be readjusted.
6627
6628 drawmarker = kTRUE;
6629 if (!option0 && !option3) {
6630 if (Hoption.Logy && yp < logymin) goto L30;
6631 if (yi1 < ymin || yi1 > ymax) goto L30;
6632 if (Hoption.Error != 0 && yp == 0 && ey1 <= 0) drawmarker = kFALSE;
6633 }
6634 if (!symbolsize || !errormarker) drawmarker = kFALSE;
6635
6636 // draw the error rectangles
6637 if (option2) {
6638 if ((yi3 >= ymax) || (yi4 <= ymin))
6639 goto L30;
6640 gPad->PaintBox(xi1,yi3,xi2,yi4);
6641 }
6642
6643 // keep points for fill area drawing
6644 if (option3) {
6645 xline[if1-1] = xi3;
6646 xline[if2-1] = xi3;
6647 yline[if1-1] = yi4;
6648 yline[if2-1] = yi3;
6649 if1++;
6650 if2--;
6651 }
6652
6653 // draw the error bars
6654 if (Hoption.Logy && yp < logymin)
6655 drawmarker = kFALSE;
6656 if (optionE && drawmarker) {
6657 if ((yi3 < yi1 - s2y) && (yi3 < ymax))
6658 add_segment(xi3,yi3,xi4,TMath::Min(yi1 - s2y,ymax));
6659 if ((yi1 + s2y < yi4) && (yi4 > ymin))
6660 add_segment(xi3,TMath::Max(yi1 + s2y, ymin),xi4,yi4);
6661 // don't duplicate the horizontal line
6662 if (Hoption.Hist != 2) {
6663 if (yi1<ymax && yi1>ymin) {
6664 if (xi1 < xi3 - s2x)
6665 add_segment(xi1,yi1,xi3 - s2x,yi2);
6666 if (xi3 + s2x < xi2)
6667 add_segment(xi3 + s2x,yi1,xi2,yi2);
6668 }
6669 }
6670 }
6671 if (optionE && !drawmarker && (ey1 != 0 || ey2 !=0)) {
6672 if ((yi3 < yi1) && (yi3 < ymax))
6673 add_segment(xi3,yi3,xi4,TMath::Min(yi1,ymax));
6674 if ((yi1 < yi4) && (yi4 > ymin))
6675 add_segment(xi3,TMath::Max(yi1,ymin),xi4,yi4);
6676 // don't duplicate the horizontal line
6677 if (Hoption.Hist != 2) {
6678 if (yi1<ymax && yi1>ymin) {
6679 if (xi1 < xi3)
6680 add_segment(xi1,yi1,xi3,yi2);
6681 if (xi3 < xi2)
6682 add_segment(xi3,yi1,xi2,yi2);
6683 }
6684 }
6685 }
6686
6687 // draw line at the end of the error bars
6688
6689 if (option1 && drawmarker) {
6690
6691 if (yi3 < yi1-s2y && yi3 < ymax && yi3 > ymin)
6692 add_segment(xi3 - bxsize, yi3, xi3 + bxsize, yi3);
6693 if (yi4 > yi1+s2y && yi4 < ymax && yi4 > ymin)
6694 add_segment(xi3 - bxsize, yi4, xi3 + bxsize, yi4);
6695 if (yi1 <= ymax && yi1 >= ymin) {
6696 if (xi1 < xi3-s2x)
6697 add_segment(xi1, yi1 - bysize, xi1, yi1 + bysize);
6698 if (xi2 > xi3+s2x)
6699 add_segment(xi2, yi1 - bysize, xi2, yi1 + bysize);
6700 }
6701 }
6702
6703 // draw the marker
6704
6705 if (drawmarker)
6706 add_marker(xi3, yi1);
6707
6708L30:
6709 if (fixbin) xp += Hparam.xbinsize;
6710 else {
6711 if (k < last) {
6712 delta = fH->GetBinWidth(k+1);
6713 xp = fH->GetBinLowEdge(k+1) + 0.5*delta;
6714 }
6715 }
6716 } //end of for loop
6717
6718 flush_segmentes();
6719
6720 flush_markers();
6721
6722
6723 // draw the filled area
6724
6725 if (option3) {
6726 TGraph graph;
6727 graph.SetLineStyle(fH->GetLineStyle());
6728 graph.SetLineColor(fH->GetLineColor());
6729 graph.SetLineWidth(fH->GetLineWidth());
6730 graph.SetFillStyle(fH->GetFillStyle());
6731 graph.SetFillColor(fH->GetFillColor());
6732 Int_t logx = gPad->GetLogx();
6733 Int_t logy = gPad->GetLogy();
6734 gPad->SetLogx(0);
6735 gPad->SetLogy(0);
6736
6737 // In some cases the number of points in the fill area is smaller than
6738 // 2*npoints. In such cases the array xline and yline must be arranged
6739 // before being plotted. The next loop does that.
6740 if (if2 > npoints) {
6741 for (i=1; i<if1; i++) {
6742 xline[if1-2+i] = xline[if2-1+i];
6743 yline[if1-2+i] = yline[if2-1+i];
6744 }
6745 npoints = if1-1;
6746 }
6747 if (option4) graph.PaintGraph(2*npoints,xline.data(),yline.data(),"FC");
6748 else graph.PaintGraph(2*npoints,xline.data(),yline.data(),"F");
6749 gPad->SetLogx(logx);
6750 gPad->SetLogy(logy);
6751 }
6752}
6753
6754////////////////////////////////////////////////////////////////////////////////
6755/// Draw 2D histograms errors.
6756
6758{
6759
6760 fH->TAttMarker::Modify();
6761 fH->TAttLine::Modify();
6762
6763 // Define the 3D view
6764 fXbuf[0] = Hparam.xmin;
6765 fYbuf[0] = Hparam.xmax;
6766 fXbuf[1] = Hparam.ymin;
6767 fYbuf[1] = Hparam.ymax;
6768 fXbuf[2] = Hparam.zmin;
6769 fYbuf[2] = Hparam.zmax*(1. + gStyle->GetHistTopMargin());
6770 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
6771 TView *view = gPad ? gPad->GetView() : nullptr;
6772 if (!view) {
6773 Error("Paint2DErrors", "no TView in current pad");
6774 return;
6775 }
6776 Double_t thedeg = 90 - gPad->GetTheta();
6777 Double_t phideg = -90 - gPad->GetPhi();
6778 Double_t psideg = view->GetPsi();
6779 Int_t irep;
6780 view->SetView(phideg, thedeg, psideg, irep);
6781
6782 // Set color/style for back box
6783 fLego->SetFillStyle(gPad->GetFrameFillStyle());
6784 fLego->SetFillColor(gPad->GetFrameFillColor());
6785 fLego->TAttFill::Modify();
6786 Int_t backcolor = gPad->GetFrameFillColor();
6787 if (Hoption.System != kCARTESIAN) backcolor = 0;
6788 view->PadRange(backcolor);
6789 fLego->SetFillStyle(fH->GetFillStyle());
6790 fLego->SetFillColor(fH->GetFillColor());
6791 fLego->TAttFill::Modify();
6792
6793 // Paint the Back Box if needed
6794 if (Hoption.BackBox && !Hoption.Same && !Hoption.Lego && !Hoption.Surf) {
6795 fLego->InitMoveScreen(-1.1,1.1);
6796 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
6798 fLego->BackBox(90);
6799 }
6800
6801 // Paint the Errors
6802 Double_t x, ex, x1, x2;
6803 Double_t y, ey, y1, y2;
6804 Double_t z, ez1, ez2, z1, z2;
6805 Double_t temp1[3],temp2[3];
6806 Double_t xyerror;
6807 if (Hoption.Error == 110) {
6808 xyerror = 0;
6809 } else {
6810 xyerror = gStyle->GetErrorX();
6811 }
6812
6813 Double_t xk, xstep, yk, ystep;
6814 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
6815 y = fYaxis->GetBinCenter(j);
6816 ey = fYaxis->GetBinWidth(j)*xyerror;
6817 y1 = y-ey;
6818 y2 = y+ey;
6819 if (Hoption.Logy) {
6820 if (y > 0) y = TMath::Log10(y);
6821 else continue;
6822 if (y1 > 0) y1 = TMath::Log10(y1);
6823 else y1 = Hparam.ymin;
6824 if (y2 > 0) y2 = TMath::Log10(y2);
6825 else y2 = Hparam.ymin;
6826 }
6827 yk = fYaxis->GetBinLowEdge(j);
6828 ystep = fYaxis->GetBinWidth(j);
6829 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
6830 xk = fXaxis->GetBinLowEdge(i);
6831 xstep = fXaxis->GetBinWidth(i);
6832 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
6833 Int_t bin = fH->GetBin(i,j);
6834 x = fXaxis->GetBinCenter(i);
6835 ex = fXaxis->GetBinWidth(i)*xyerror;
6836 x1 = x-ex;
6837 x2 = x+ex;
6838 if (Hoption.Logx) {
6839 if (x > 0) x = TMath::Log10(x);
6840 else continue;
6841 if (x1 > 0) x1 = TMath::Log10(x1);
6842 else x1 = Hparam.xmin;
6843 if (x2 > 0) x2 = TMath::Log10(x2);
6844 else x2 = Hparam.xmin;
6845 }
6846 z = fH->GetBinContent(bin);
6847 if (fH->GetBinErrorOption() == TH1::kNormal) {
6848 ez1 = fH->GetBinError(bin);
6849 ez2 = ez1;
6850 }
6851 else {
6852 ez1 = fH->GetBinErrorLow(bin);
6853 ez2 = fH->GetBinErrorUp(bin);
6854 }
6855 z1 = z - ez1;
6856 z2 = z + ez2;
6857 if (Hoption.Logz) {
6858 if (z > 0) z = TMath::Log10(z);
6859 else z = Hparam.zmin;
6860 if (z1 > 0) z1 = TMath::Log10(z1);
6861 else z1 = Hparam.zmin;
6862 if (z2 > 0) z2 = TMath::Log10(z2);
6863 else z2 = Hparam.zmin;
6864
6865 }
6866 if (z <= Hparam.zmin) continue;
6867 if (z > Hparam.zmax) z = Hparam.zmax;
6868
6869 temp1[0] = x1;
6870 temp1[1] = y;
6871 temp1[2] = z;
6872 temp2[0] = x2;
6873 temp2[1] = y;
6874 temp2[2] = z;
6875 gPad->PaintLine3D(temp1, temp2);
6876 temp1[0] = x;
6877 temp1[1] = y1;
6878 temp1[2] = z;
6879 temp2[0] = x;
6880 temp2[1] = y2;
6881 temp2[2] = z;
6882 gPad->PaintLine3D(temp1, temp2);
6883 temp1[0] = x;
6884 temp1[1] = y;
6885 temp1[2] = z1;
6886 temp2[0] = x;
6887 temp2[1] = y;
6888 temp2[2] = z2;
6889 gPad->PaintLine3D(temp1, temp2);
6890 temp1[0] = x;
6891 temp1[1] = y;
6892 temp1[2] = z;
6893 view->WCtoNDC(temp1, &temp2[0]);
6894 gPad->PaintPolyMarker(1, &temp2[0], &temp2[1]);
6895 }
6896 }
6897
6898 // Paint the Front Box if needed
6899 if (Hoption.FrontBox) {
6900 fLego->InitMoveScreen(-1.1,1.1);
6902 fLego->FrontBox(90);
6903 }
6904
6905 // Paint the Axis if needed
6906 if (!Hoption.Axis && !Hoption.Same && !Hoption.Lego && !Hoption.Surf) {
6907 TGaxis axis;
6908 PaintLegoAxis(&axis, 90);
6909 }
6910
6911 fLego.reset();
6912}
6913
6914////////////////////////////////////////////////////////////////////////////////
6915/// Calculate range and clear pad (canvas).
6916
6918{
6919
6920 if (Hoption.Same) return;
6921
6923
6924 if (Hoption.Lego || Hoption.Surf || Hoption.Tri ||
6925 Hoption.Contour == 14 || Hoption.Error >= 100) {
6926 TObject *frame = gPad->FindObject("TFrame");
6927 if (frame) gPad->Remove(frame);
6928 return;
6929 }
6930
6931 //The next statement is always executed on non-iOS platform,
6932 //on iOS depends on pad mode.
6933 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode())
6934 gPad->PaintPadFrame(Hparam.xmin,Hparam.ymin,Hparam.xmax,Hparam.ymax);
6935}
6936
6937////////////////////////////////////////////////////////////////////////////////
6938/// [Paint functions associated to an histogram.](\ref HP28")
6939
6941{
6942 auto lnk = fFunctions->FirstLink();
6943
6944 while (lnk) {
6945 auto obj = lnk->GetObject();
6946 TVirtualPad::TContext ctxt(true);
6947 if (obj->InheritsFrom(TF2::Class())) {
6948 if (!obj->TestBit(TF2::kNotDraw)) {
6949 if (Hoption.Lego || Hoption.Surf || Hoption.Error >= 100) {
6950 TF2 *f2 = (TF2*)obj;
6951 f2->SetMinimum(fH->GetMinimum());
6952 f2->SetMaximum(fH->GetMaximum());
6953 f2->SetRange(fH->GetXaxis()->GetXmin(), fH->GetYaxis()->GetXmin(), fH->GetXaxis()->GetXmax(), fH->GetYaxis()->GetXmax() );
6954 f2->Paint("surf same");
6955 } else {
6956 obj->Paint("cont3 same");
6957 }
6958 }
6959 } else if (obj->InheritsFrom(TF1::Class())) {
6960 if (!obj->TestBit(TF1::kNotDraw)) obj->Paint("lsame");
6961 } else {
6962 //Let's make this 'function' selectable on iOS device (for example, it can be TPaveStat).
6963 gPad->PushSelectableObject(obj);
6964
6965 //The next statement is ALWAYS executed on non-iOS platform, on iOS it depends on pad's mode
6966 //and picked object.
6967 if (!gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && obj == gPad->GetSelected()))
6968 obj->Paint(lnk->GetOption());
6969 }
6970 lnk = lnk->Next();
6971 }
6972}
6973
6974////////////////////////////////////////////////////////////////////////////////
6975/// [Control routine to draw 1D histograms](\ref HP01b)
6976
6978{
6979
6980 //On iOS: do not highlight hist, if part of it was selected.
6981 //Never executes on non-iOS platform.
6982 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
6983 return;
6984
6985 static char chopth[17];
6986
6987 Int_t htype, oldhtype;
6988 Int_t i, j, first, last, nbins, fixbin;
6989 Double_t c1, yb;
6990 yb = 0;
6991
6992 strlcpy(chopth, " ",17);
6993
6996 Double_t baroffset = fH->GetBarOffset();
6997 Double_t barwidth = fH->GetBarWidth();
6998 Double_t baroffsetsave = gStyle->GetBarOffset();
6999 Double_t barwidthsave = gStyle->GetBarWidth();
7000 gStyle->SetBarOffset(baroffset);
7001 gStyle->SetBarWidth(barwidth);
7002
7003 // Create "LIFE" structure to keep current histogram status
7004
7005 first = Hparam.xfirst;
7006 last = Hparam.xlast;
7007 nbins = last - first + 1;
7008
7009 std::vector<Double_t> keepx, keepy;
7010 if (fXaxis->GetXbins()->fN) fixbin = 0;
7011 else fixbin = 1;
7012 if (fixbin) keepx.resize(2);
7013 else keepx.resize(nbins+1);
7014 keepy.resize(nbins);
7015 Double_t logymin = 0;
7016 if (Hoption.Logy) logymin = TMath::Power(10,ymin);
7017
7018 // Loop on histogram bins
7019
7020 for (j=first; j<=last;j++) {
7022 if (TMath::Abs(ymax-ymin) > 0) {
7023 if (Hoption.Logy) yb = TMath::Log10(TMath::Max(c1,.1*logymin));
7024 else yb = c1;
7025 }
7026 if (!Hoption.Line) {
7027 yb = TMath::Max(yb, ymin);
7028 yb = TMath::Min(yb, ymax);
7029 }
7030 keepy[j-first] = yb;
7031 }
7032
7033 // Draw histogram according to value of FillStyle and FillColor
7034
7035 if (fixbin) { keepx[0] = Hparam.xmin; keepx[1] = Hparam.xmax; }
7036 else {
7037 for (i=0; i<nbins; i++) keepx[i] = fXaxis->GetBinLowEdge(i+first);
7038 keepx[nbins] = fXaxis->GetBinUpEdge(nbins-1+first);
7039 }
7040
7041 // Prepare Fill area (systematic with option "Bar").
7042
7043 oldhtype = fH->GetFillStyle();
7044 htype = oldhtype;
7045 if (Hoption.Bar) {
7046 if (htype == 0 || htype == 1000) htype = 1001;
7047 }
7048
7049 Width_t lw = (Width_t)fH->GetLineWidth();
7050
7051 // Code option for GrapHist
7052
7053 if (Hoption.Line) chopth[0] = 'L';
7054 if (Hoption.Star) chopth[1] = '*';
7055 if (Hoption.Mark) chopth[2] = 'P';
7056 if (Hoption.Mark == 10) chopth[3] = '0';
7058 if (Hoption.Curve) chopth[3] = 'C';
7059 if (Hoption.Hist > 0) chopth[4] = 'H';
7060 else if (Hoption.Bar) chopth[5] = 'B';
7061 if (Hoption.Logy) chopth[6] = '1';
7062 if (fH->GetFillColor() && htype) {
7063 if (Hoption.Hist > 0 || Hoption.Curve || Hoption.Line) {
7064 chopth[7] = 'F';
7065 }
7066 }
7067 }
7068 if (!fixbin && strlen(chopth)) {
7069 chopth[8] = 'N';
7070 }
7071
7072 if (Hoption.Fill == 2) chopth[13] = '2';
7073
7074 // Option LOGX
7075
7076 if (Hoption.Logx) {
7077 chopth[9] = 'G';
7078 chopth[10] = 'X';
7079 if (fixbin) {
7080 keepx[0] = TMath::Power(10,keepx[0]);
7081 keepx[1] = TMath::Power(10,keepx[1]);
7082 }
7083 }
7084
7085 if (Hoption.Off) {
7086 chopth[11] = ']';
7087 chopth[12] = '[';
7088 }
7089
7090 // Draw the histogram
7091
7092 TGraph graph;
7093 graph.SetLineWidth(lw);
7094 graph.SetLineStyle(fH->GetLineStyle());
7095 graph.SetLineColor(fH->GetLineColor());
7096 graph.SetFillStyle(htype);
7097 graph.SetFillColor(fH->GetFillColor());
7099 graph.SetMarkerSize(fH->GetMarkerSize());
7102
7103 graph.PaintGrapHist(nbins, keepx.data(), keepy.data() ,chopth);
7104
7105 gStyle->SetBarOffset(baroffsetsave);
7106 gStyle->SetBarWidth(barwidthsave);
7107
7108 htype=oldhtype;
7109}
7110
7111////////////////////////////////////////////////////////////////////////////////
7112/// [Control function to draw a 3D histograms.](\ref HP01d)
7113
7115{
7116
7117 TString cmd;
7118 TString opt = option;
7119 opt.ToLower();
7120 Int_t irep;
7121 Float_t NEntries = fH->GetEntries();
7122
7123 if (fCurrentF3 || strstr(opt,"tf3")) {
7124 PaintTF3();
7125 return;
7126 }
7127
7128 if (NEntries > 0) {
7129 if (Hoption.Box || Hoption.Lego || Hoption.Color) {
7130 if (Hoption.Box == 11 || Hoption.Lego == 11) {
7131 PaintH3Box(1);
7132 } else if (Hoption.Box == 12 || Hoption.Lego == 12 || Hoption.Color == 1) {
7133 PaintH3Box(2);
7134 } else if (Hoption.Box == 13 || Hoption.Lego == 13) {
7135 PaintH3Box(3);
7136 } else {
7138 }
7139 return;
7140 }
7141
7142 if (strstr(opt,"iso")) {
7143 PaintH3Iso();
7144 return;
7145 }
7146 }
7147
7148 TView *view = gPad ? gPad->GetView() : nullptr;
7149 if (!view) return;
7150
7151 if (strstr(opt,"fb")) Hoption.FrontBox = 0;
7152 if (strstr(opt,"bb")) Hoption.BackBox = 0;
7153
7154 Double_t thedeg = 90 - gPad->GetTheta();
7155 Double_t phideg = -90 - gPad->GetPhi();
7156 Double_t psideg = view->GetPsi();
7157 view->SetView(phideg, thedeg, psideg, irep);
7158
7159 if(NEntries > 0) { // Paint as 3D scatter plot
7160 cmd.Form("TPolyMarker3D::PaintH3((TH1 *)0x%zx,\"%s\");",(size_t)fH,option);
7161 gROOT->ProcessLine(cmd.Data());
7162 } else {
7163 TAxis* xAxis = fH->GetXaxis();
7164 TAxis* yAxis = fH->GetYaxis();
7165 TAxis* zAxis = fH->GetZaxis();
7166 Double_t xmin = xAxis->GetXmin();
7167 Double_t xmax = xAxis->GetXmax();
7168 Double_t ymin = yAxis->GetXmin();
7169 Double_t ymax = yAxis->GetXmax();
7170 Double_t zmin = zAxis->GetXmin();
7171 Double_t zmax = zAxis->GetXmax();
7172 view->SetRange(xmin, ymin, zmin, xmax, ymax, zmax); // Set the axis limits (Xmin, Ymin, Zmin, Xmax, Ymax, Zmax)
7173 }
7174
7175 if (Hoption.Same) return;
7176
7177 // Draw axis
7178 view->SetOutlineToCube();
7179 TSeqCollection *ol = view->GetOutline();
7180 if (ol && Hoption.BackBox && Hoption.FrontBox) ol->Paint(option);
7182
7183 if (!Hoption.Axis && !Hoption.Same) {
7184 TGaxis axis;
7185 PaintLegoAxis(&axis, 90);
7186 }
7187
7188 // Draw palette. In case of 4D plot with TTree::Draw() the palette should
7189 // be painted with the option colz.
7190 if (fH->GetDrawOption() && strstr(opt,"colz")) {
7191 Int_t ndiv = fH->GetContour();
7192 if (ndiv == 0 ) {
7193 ndiv = gStyle->GetNumberContours();
7194 fH->SetContour(ndiv);
7195 }
7196 PaintPalette();
7197 }
7198
7199 // Draw title
7200 PaintTitle();
7201
7202 //Draw stats and fit results
7203 TF1 *fit = nullptr;
7204 TIter next(fFunctions);
7205 while (auto obj = next()) {
7206 if (obj->InheritsFrom(TF1::Class())) {
7207 fit = (TF1*)obj;
7208 break;
7209 }
7210 }
7211 if ((Hoption.Same%10) != 1) {
7212 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7214 }
7215 }
7216
7217}
7218
7219////////////////////////////////////////////////////////////////////////////////
7220/// Compute histogram parameters used by the drawing routines.
7221
7223{
7224
7225 if (fH->GetDimension() > 1 || Hoption.Lego || Hoption.Surf) return 1;
7226
7227 Int_t i;
7228 static const char *where = "PaintInit";
7229 Double_t yMARGIN = gStyle->GetHistTopMargin();
7230 Int_t maximum = 0;
7231 Int_t minimum = 0;
7232 if (fH->GetMaximumStored() != -1111) maximum = 1;
7233 if (fH->GetMinimumStored() != -1111) minimum = 1;
7234
7235 // Compute X axis parameters
7236
7237 Int_t last = fXaxis->GetLast();
7238 Int_t first = fXaxis->GetFirst();
7241 Hparam.xlast = last;
7242 Hparam.xfirst = first;
7245
7246 // if log scale in X, replace xmin,max by the log
7247 if (Hoption.Logx) {
7248 if (Hparam.xmax<=0) {
7249 Error(where, "cannot set X axis to log scale");
7250 return 0;
7251 }
7252 if (Hparam.xlowedge <=0 ) {
7253 if (Hoption.Same) {
7254 TH1* h1 = nullptr;
7255 TObject *obj;
7256 TIter next(gPad->GetListOfPrimitives());
7257 while ((obj = (TObject *)next())) {
7258 if (obj->InheritsFrom(TH1::Class())) { h1 = (TH1*)(obj) ; break; }
7259 if (obj->InheritsFrom(THStack::Class())) { h1 = ((THStack*)(obj))->GetHistogram() ; break; }
7260 if (obj->InheritsFrom(TGraph::Class())) { h1 = ((TGraph*)(obj))->GetHistogram() ; break; }
7261 if (obj->InheritsFrom(TMultiGraph::Class())) { h1 = ((TMultiGraph*)(obj))->GetHistogram(); break; }
7262 if (obj->InheritsFrom(TGraph2D::Class())) { h1 = ((TGraph2D*)(obj))->GetHistogram(); break; }
7263 if (obj->InheritsFrom(TF1::Class())) { h1 = ((TF1*)(obj))->GetHistogram(); break; }
7264 }
7265 if (h1) {
7267 } else {
7268 Error(where, "undefined user's coordinates. Cannot use option SAME");
7269 return 0;
7270 }
7271 } else {
7272 for (i=first; i<=last; i++) {
7273 Double_t binLow = fXaxis->GetBinLowEdge(i);
7274 if (binLow>0) {
7275 Hparam.xlowedge = binLow;
7276 break;
7277 }
7278 if (binLow == 0 && fH->GetBinContent(i) !=0) {
7279 Hparam.xlowedge = fXaxis->GetBinUpEdge(i)*0.001;
7280 break;
7281 }
7282 }
7283 if (Hparam.xlowedge<=0) {
7284 Error(where, "cannot set X axis to log scale");
7285 return 0;
7286 }
7287 }
7289 }
7294 if (Hparam.xlast > last) Hparam.xlast = last;
7295 if (Hparam.xfirst < first) Hparam.xfirst = first;
7296 }
7297
7298 // Compute Y axis parameters
7299 Double_t bigp = TMath::Power(10,32);
7300 Double_t ymax = -bigp;
7301 Double_t ymin = bigp;
7302 Double_t c1, e1;
7303 Double_t xv[1];
7304 Double_t fval;
7305 TObject *f;
7306 TF1 *f1;
7307 Double_t allchan = 0;
7308 Int_t nonNullErrors = 0;
7309 TIter next(fFunctions);
7310 for (i=first; i<=last;i++) {
7311 c1 = fH->GetBinContent(i);
7312 if (std::isnan(c1) || std::isinf(c1))
7313 continue;
7315 if (Hoption.Logy) {
7316 if (c1 > 0) ymin = TMath::Min(ymin,c1);
7317 } else {
7319 }
7320 if (Hoption.Error) {
7322 e1 = fH->GetBinError(i);
7323 else
7324 e1 = fH->GetBinErrorUp(i);
7325 if (e1 > 0) nonNullErrors++;
7326 ymax = TMath::Max(ymax,c1+e1);
7328 e1 = fH->GetBinErrorLow(i);
7329
7330 if (Hoption.Logy) {
7331 if (c1-e1>0.01*TMath::Abs(c1)) ymin = TMath::Min(ymin,c1-e1);
7332 } else {
7333 ymin = TMath::Min(ymin,c1-e1);
7334 }
7335 }
7336 if (Hoption.Func) {
7337 xv[0] = fXaxis->GetBinCenter(i);
7338 while ((f = (TObject*) next())) {
7339 if (f->IsA() == TF1::Class()) {
7340 f1 = (TF1*)f;
7341 if (xv[0] < f1->GetXmin() || xv[0] > f1->GetXmax()) continue;
7342 fval = f1->Eval(xv[0],0,0);
7343 if (f1->GetMaximumStored() != -1111) fval = TMath::Min(f1->GetMaximumStored(), fval);
7344 ymax = TMath::Max(ymax,fval);
7345 if (Hoption.Logy) {
7346 if (c1 > 0 && fval > 0.3*c1) ymin = TMath::Min(ymin,fval);
7347 }
7348 }
7349 }
7350 next.Reset();
7351 }
7352 allchan += c1;
7353 }
7354 if (!nonNullErrors) {
7355 if (Hoption.Error) {
7356 if (!Hoption.Mark && !Hoption.Line && !Hoption.Star && !Hoption.Curve) Hoption.Hist = 2;
7357 Hoption.Error=0;
7358 }
7359 }
7360
7361
7362 // Take into account maximum , minimum
7363
7364 if (Hoption.Logy && ymin <= 0) {
7365 if (ymax >= 1) ymin = TMath::Max(.005,ymax*1e-10);
7366 else ymin = 0.001*ymax;
7367 }
7368
7369 Double_t xm = ymin;
7370 if (maximum) ymax = fH->GetMaximumStored();
7371 if (minimum) xm = fH->GetMinimumStored();
7372 if (Hoption.Logy && xm < 0) {
7373 Error(where, "log scale requested with a negative argument (%f)", xm);
7374 return 0;
7375 } else if (Hoption.Logy && xm>=0 && ymax==0) { // empty histogram in log scale
7376 ymin = 0.01;
7377 ymax = 10.;
7378 } else {
7379 ymin = xm;
7380 }
7381
7382 if (ymin >= ymax) {
7383 if (Hoption.Logy) {
7384 if (ymax > 0) ymin = 0.001*ymax;
7385 else {
7386 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", ymax);
7387 return 0;
7388 }
7389 }
7390 else {
7391 if (ymin > 0) {
7392 ymin = 0;
7393 ymax *= 2;
7394 } else if (ymin < 0) {
7395 ymax = 0;
7396 ymin *= 2;
7397 } else {
7398 ymin = 0;
7399 ymax = 1;
7400 }
7401 }
7402 }
7403
7404 // In some cases, mainly because of precision issues, ymin and ymax could almost equal.
7405 if (TMath::AreEqualRel(ymin,ymax,1E-15)) {
7406 ymin = ymin*(1-1E-14);
7407 ymax = ymax*(1+1E-14);
7408 }
7409
7410 // take into account normalization factor
7411 Hparam.allchan = allchan;
7412 Double_t factor = allchan;
7413 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
7414 if (allchan) factor /= allchan;
7415 if (factor == 0) factor = 1;
7416 Hparam.factor = factor;
7417 ymax = factor*ymax;
7418 ymin = factor*ymin;
7419 //just in case the norm factor is negative
7420 // this may happen with a positive norm factor and a negative integral !
7421 if (ymax < ymin) {
7422 Double_t temp = ymax;
7423 ymax = ymin;
7424 ymin = temp;
7425 }
7426
7427 // For log scales, histogram coordinates are LOG10(ymin) and
7428 // LOG10(ymax). Final adjustment (if not option "Same"
7429 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
7430 // Maximum and Minimum are not defined.
7431 if (Hoption.Logy) {
7432 if (ymin <=0 || ymax <=0) {
7433 Error(where, "Cannot set Y axis to log scale");
7434 return 0;
7435 }
7437 if (!minimum) ymin += TMath::Log10(0.5);
7439 if (!maximum) ymax += TMath::Log10(2*(0.9/0.95));
7440 if (!Hoption.Same) {
7441 Hparam.ymin = ymin;
7442 Hparam.ymax = ymax;
7443 }
7444 return 1;
7445 }
7446
7447 // final adjustment of ymin for linear scale.
7448 // if minimum is not set , then ymin is set to zero if >0
7449 // or to ymin - margin if <0.
7450 if (!minimum) {
7451 if (Hoption.MinimumZero) {
7452 if (ymin >= 0) ymin = 0;
7453 else ymin -= yMARGIN*(ymax-ymin);
7454 } else {
7455 Double_t dymin = yMARGIN*(ymax-ymin);
7456 if (ymin >= 0 && (ymin-dymin <= 0)) ymin = 0;
7457 else ymin -= dymin;
7458 }
7459 }
7460
7461 // final adjustment of YMAXI for linear scale (if not option "Same"):
7462 // decrease histogram height to MAX% of allowed height if HMAXIM
7463 // has not been called.
7464 if (!maximum) {
7465 ymax += yMARGIN*(ymax-ymin);
7466 }
7467
7468 Hparam.ymin = ymin;
7469 Hparam.ymax = ymax;
7470 return 1;
7471}
7472
7473////////////////////////////////////////////////////////////////////////////////
7474/// Compute histogram parameters used by the drawing routines for a rotated pad.
7475
7477{
7478
7479 static const char *where = "PaintInitH";
7480 Double_t yMARGIN = gStyle->GetHistTopMargin();
7481 Int_t maximum = 0;
7482 Int_t minimum = 0;
7483 if (fH->GetMaximumStored() != -1111) maximum = 1;
7484 if (fH->GetMinimumStored() != -1111) minimum = 1;
7485
7486 // Compute X axis parameters
7487
7488 Int_t last = fXaxis->GetLast();
7489 Int_t first = fXaxis->GetFirst();
7492 Hparam.xlast = last;
7493 Hparam.xfirst = first;
7496
7497 // if log scale in Y, replace ymin,max by the log
7498 if (Hoption.Logy) {
7499 if (Hparam.xlowedge <=0 ) {
7502 }
7503 if (Hparam.ymin <=0 || Hparam.ymax <=0) {
7504 Error(where, "cannot set Y axis to log scale");
7505 return 0;
7506 }
7511 if (Hparam.xlast > last) Hparam.xlast = last;
7512 }
7513
7514 // Compute Y axis parameters
7515 Double_t bigp = TMath::Power(10,32);
7516 Double_t xmax = -bigp;
7517 Double_t xmin = bigp;
7518 Double_t c1, e1;
7519 Double_t xv[1];
7520 Double_t fval;
7521 Int_t i;
7522 TObject *f;
7523 TF1 *f1;
7524 Double_t allchan = 0;
7525 TIter next(fFunctions);
7526 for (i=first; i<=last;i++) {
7527 c1 = fH->GetBinContent(i);
7530 if (Hoption.Error) {
7531 e1 = fH->GetBinError(i);
7532 xmax = TMath::Max(xmax,c1+e1);
7533 xmin = TMath::Min(xmin,c1-e1);
7534 }
7535 if (Hoption.Func) {
7536 xv[0] = fXaxis->GetBinCenter(i);
7537 while ((f = (TObject*) next())) {
7538 if (f->IsA() == TF1::Class()) {
7539 f1 = (TF1*)f;
7540 if (xv[0] < f1->GetXmin() || xv[0] > f1->GetXmax()) continue;
7541 fval = f1->Eval(xv[0],0,0);
7542 xmax = TMath::Max(xmax,fval);
7543 if (Hoption.Logy) {
7544 if (fval > 0.3*c1) xmin = TMath::Min(xmin,fval);
7545 }
7546 }
7547 }
7548 next.Reset();
7549 }
7550 allchan += c1;
7551 }
7552
7553 // Take into account maximum , minimum
7554
7555 if (Hoption.Logx && xmin <= 0) {
7556 if (xmax >= 1) xmin = TMath::Max(.5,xmax*1e-10);
7557 else xmin = 0.001*xmax;
7558 }
7559 Double_t xm = xmin;
7560 if (maximum) xmax = fH->GetMaximumStored();
7561 if (minimum) xm = fH->GetMinimumStored();
7562 if (Hoption.Logx && xm <= 0) {
7563 Error(where, "log scale requested with zero or negative argument (%f)", xm);
7564 return 0;
7565 }
7566 else xmin = xm;
7567 if (xmin >= xmax) {
7568 if (Hoption.Logx) {
7569 if (xmax > 0) xmin = 0.001*xmax;
7570 else {
7571 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", xmax);
7572 return 0;
7573 }
7574 }
7575 else {
7576 if (xmin > 0) {
7577 xmin = 0;
7578 xmax *= 2;
7579 } else if (xmin < 0) {
7580 xmax = 0;
7581 xmin *= 2;
7582 } else {
7583 xmin = 0;
7584 xmax = 1;
7585 }
7586 }
7587 }
7588
7589 // take into account normalization factor
7590 Hparam.allchan = allchan;
7591 Double_t factor = allchan;
7592 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
7593 if (allchan) factor /= allchan;
7594 if (factor == 0) factor = 1;
7595 Hparam.factor = factor;
7596 xmax = factor*xmax;
7597 xmin = factor*xmin;
7598
7599 // For log scales, histogram coordinates are LOG10(ymin) and
7600 // LOG10(ymax). Final adjustment (if not option "Same"
7601 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
7602 // Maximum and Minimum are not defined.
7603 if (Hoption.Logx) {
7604 if (xmin <=0 || xmax <=0) {
7605 Error(where, "Cannot set Y axis to log scale");
7606 return 0;
7607 }
7609 if (!minimum) xmin += TMath::Log10(0.5);
7611 if (!maximum) xmax += TMath::Log10(2*(0.9/0.95));
7612 if (!Hoption.Same) {
7613 Hparam.xmin = xmin;
7614 Hparam.xmax = xmax;
7615 }
7616 return 1;
7617 }
7618
7619 // final adjustment of ymin for linear scale.
7620 // if minimum is not set , then ymin is set to zero if >0
7621 // or to ymin - margin if <0.
7622 if (!minimum) {
7623 if (xmin >= 0) xmin = 0;
7624 else xmin -= yMARGIN*(xmax-xmin);
7625 }
7626
7627 // final adjustment of YMAXI for linear scale (if not option "Same"):
7628 // decrease histogram height to MAX% of allowed height if HMAXIM
7629 // has not been called.
7630 if (!maximum) {
7631 xmax += yMARGIN*(xmax-xmin);
7632 }
7633 Hparam.xmin = xmin;
7634 Hparam.xmax = xmax;
7635 return 1;
7636}
7637
7638////////////////////////////////////////////////////////////////////////////////
7639/// [Control function to draw a 3D histogram with boxes.](\ref HP25)
7640
7642{
7643 // Predefined box structure
7644 Double_t wxyz[8][3] = { {-1,-1,-1}, {1,-1,-1}, {1,1,-1}, {-1,1,-1},
7645 {-1,-1, 1}, {1,-1, 1}, {1,1, 1}, {-1,1, 1} };
7646 Int_t iface[6][4] = { {0,3,2,1}, {4,5,6,7},
7647 {0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7} };
7648
7649 // Define dimensions of world space
7650 TAxis *xaxis = fH->GetXaxis();
7651 TAxis *yaxis = fH->GetYaxis();
7652 TAxis *zaxis = fH->GetZaxis();
7653
7654 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7655 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7656 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7657 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7658 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7659 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7660
7661 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7662
7663 // Set view
7664 TView *view = gPad ? gPad->GetView() : nullptr;
7665 if (!view) {
7666 Error("PaintH3", "no TView in current pad");
7667 return;
7668 }
7669 Double_t thedeg = 90 - gPad->GetTheta();
7670 Double_t phideg = -90 - gPad->GetPhi();
7671 Double_t psideg = view->GetPsi();
7672 Int_t irep;
7673 view->SetView(phideg, thedeg, psideg, irep);
7674
7675 Int_t backcolor = gPad->GetFrameFillColor();
7676 view->PadRange(backcolor);
7677
7678 // Draw back surfaces of frame box
7679 fLego->InitMoveScreen(-1.1,1.1);
7680 if (Hoption.BackBox) {
7681 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
7683 fLego->BackBox(90);
7684 }
7685
7687
7688 // Define order of drawing
7689 Double_t *tnorm = view->GetTnorm();
7690 if (!tnorm) return;
7691 Int_t incrx = (tnorm[ 8] < 0.) ? -1 : +1;
7692 Int_t incry = (tnorm[ 9] < 0.) ? -1 : +1;
7693 Int_t incrz = (tnorm[10] < 0.) ? -1 : +1;
7694 Int_t ix1 = (incrx == +1) ? xaxis->GetFirst() : xaxis->GetLast();
7695 Int_t iy1 = (incry == +1) ? yaxis->GetFirst() : yaxis->GetLast();
7696 Int_t iz1 = (incrz == +1) ? zaxis->GetFirst() : zaxis->GetLast();
7697 Int_t ix2 = (incrx == +1) ? xaxis->GetLast() : xaxis->GetFirst();
7698 Int_t iy2 = (incry == +1) ? yaxis->GetLast() : yaxis->GetFirst();
7699 Int_t iz2 = (incrz == +1) ? zaxis->GetLast() : zaxis->GetFirst();
7700
7701 // Set graphic attributes (colour, style, etc.)
7702 Style_t fillsav = fH->GetFillStyle();
7703 Style_t colsav = fH->GetFillColor();
7704 Style_t coldark = TColor::GetColorDark(colsav);
7705 Style_t colbright = TColor::GetColorBright(colsav);
7706
7707 fH->SetFillStyle(1001);
7708 fH->TAttFill::Modify();
7709 fH->TAttLine::Modify();
7710 Int_t ncolors = gStyle->GetNumberOfColors();
7711 Int_t theColor;
7712
7713 // Create bin boxes and draw
7717
7718 Double_t pmin[3], pmax[3], sxyz[8][3];
7719 for (Int_t ix = ix1; ix !=ix2+incrx; ix += incrx) {
7720 pmin[0] = xaxis->GetBinLowEdge(ix);
7721 pmax[0] = xaxis->GetBinUpEdge(ix);
7722 for (Int_t iy = iy1; iy != iy2+incry; iy += incry) {
7723 pmin[1] = yaxis->GetBinLowEdge(iy);
7724 pmax[1] = yaxis->GetBinUpEdge(iy);
7725 for (Int_t iz = iz1; iz != iz2+incrz; iz += incrz) {
7726 pmin[2] = zaxis->GetBinLowEdge(iz);
7727 pmax[2] = zaxis->GetBinUpEdge(iz);
7728 Double_t w = fH->GetBinContent(fH->GetBin(ix,iy,iz));
7729 Bool_t neg = kFALSE;
7730 Int_t n = 5;
7731 if (w<0) {
7732 w = -w;
7733 neg = kTRUE;
7734 }
7735 if (w < wmin) continue;
7736 if (w > wmax) w = wmax;
7737 Double_t scale = (TMath::Power((w-wmin)/(wmax-wmin),1./3.))/2.;
7738 if (scale == 0) continue;
7739 for (Int_t i=0; i<3; ++i) {
7740 Double_t c = (pmax[i] + pmin[i])*0.5;
7741 Double_t d = (pmax[i] - pmin[i])*scale;
7742 for (Int_t k=0; k<8; ++k) { // set bin box vertices
7743 sxyz[k][i] = wxyz[k][i]*d + c;
7744 }
7745 }
7746 for (Int_t k=0; k<8; ++k) { // transform to normalized space
7747 view->WCtoNDC(&sxyz[k][0],&sxyz[k][0]);
7748 }
7749 Double_t x[8], y[8]; // draw bin box faces
7750 for (Int_t k=0; k<6; ++k) {
7751 for (Int_t i=0; i<4; ++i) {
7752 Int_t iv = iface[k][i];
7753 x[i] = sxyz[iv][0];
7754 y[i] = sxyz[iv][1];
7755 }
7756 x[4] = x[0] ; y[4] = y[0];
7757 if (neg) {
7758 x[5] = x[2] ; y[5] = y[2];
7759 x[6] = x[3] ; y[6] = y[3];
7760 x[7] = x[1] ; y[7] = y[1];
7761 n = 8;
7762 } else {
7763 n = 5;
7764 }
7765 Double_t z = (x[2]-x[0])*(y[3]-y[1]) - (y[2]-y[0])*(x[3]-x[1]);
7766 if (z <= 0.) continue;
7767 if (iopt == 2) {
7768 theColor = ncolors*((w-wmin)/(wmax-wmin)) -1;
7770 } else {
7771 if (k == 3 || k == 5) {
7772 fH->SetFillColor(coldark);
7773 } else if (k == 0 || k == 1) {
7774 fH->SetFillColor(colbright);
7775 } else {
7776 fH->SetFillColor(colsav);
7777 }
7778 }
7779 fH->TAttFill::Modify();
7780 gPad->PaintFillArea(4, x, y);
7781 if (iopt != 3)gPad->PaintPolyLine(n, x, y);
7782 }
7783 }
7784 }
7785 }
7786
7787 // Draw front surfaces of frame box
7788 if (Hoption.FrontBox) fLego->FrontBox(90);
7789
7790 // Draw axis and title
7791 if (!Hoption.Axis && !Hoption.Same) {
7792 TGaxis axis;
7793 PaintLegoAxis(&axis, 90);
7794 }
7795 PaintTitle();
7796
7797 // Draw palette. if needed.
7798 if (Hoption.Zscale) {
7799 Int_t ndiv = fH->GetContour();
7800 if (ndiv == 0 ) {
7801 ndiv = gStyle->GetNumberContours();
7802 fH->SetContour(ndiv);
7803 }
7804 PaintPalette();
7805 }
7806
7807 //Draw stats and fit results
7808 TF1 *fit = nullptr;
7809 TIter next(fFunctions);
7810 while (auto obj = next()) {
7811 if (obj->InheritsFrom(TF1::Class())) {
7812 fit = (TF1*)obj;
7813 break;
7814 }
7815 }
7816 if ((Hoption.Same%10) != 1) {
7817 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7819 }
7820 }
7821
7822 fLego.reset();
7823
7824 fH->SetFillStyle(fillsav);
7825 fH->SetFillColor(colsav);
7826 fH->TAttFill::Modify();
7827}
7828
7829////////////////////////////////////////////////////////////////////////////////
7830/// [Control function to draw a 3D histogram with boxes.](\ref HP25)
7831
7833{
7834 // Predefined box structure
7835 Double_t wxyz[8][3] = {
7836 {-1,-1,-1}, {1,-1,-1}, {1,1,-1}, {-1,1,-1}, // bottom vertices
7837 {-1,-1, 1}, {1,-1, 1}, {1,1, 1}, {-1,1, 1} // top vertices
7838 };
7839 Int_t iface[6][4] = {
7840 {0,3,2,1}, {4,5,6,7}, // bottom and top faces
7841 {0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7} // side faces
7842 };
7843 Double_t normal[6][3] = {
7844 {0,0,-1}, {0,0,1}, // Z-, Z+
7845 {0,-1,0}, {1,0,0}, {0,1,0}, {-1,0,0} // Y-, X+, Y+, X-
7846 };
7847
7848 // Define dimensions of world space
7849 TAxis *xaxis = fH->GetXaxis();
7850 TAxis *yaxis = fH->GetYaxis();
7851 TAxis *zaxis = fH->GetZaxis();
7852
7853 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7854 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7855 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7856 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7857 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7858 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7859
7860 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7861
7862 // Set view
7863 TView *view = gPad ? gPad->GetView() : nullptr;
7864 if (!view) {
7865 Error("PaintH3", "no TView in current pad");
7866 return;
7867 }
7868 Double_t thedeg = 90 - gPad->GetTheta();
7869 Double_t phideg = -90 - gPad->GetPhi();
7870 Double_t psideg = view->GetPsi();
7871 Int_t irep;
7872 view->SetView(phideg, thedeg, psideg, irep);
7873
7874 Int_t backcolor = gPad->GetFrameFillColor();
7875 view->PadRange(backcolor);
7876
7877 // Draw front surfaces of frame box
7878 if (Hoption.FrontBox) {
7879 fLego->InitMoveScreen(-1.1,1.1);
7881 }
7882
7883 // Initialize hidden line removal algorithm "raster screen"
7884 fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
7885
7886 // Define order of drawing
7887 Double_t *tnorm = view->GetTnorm();
7888 if (!tnorm) return;
7889 Int_t incrx = (tnorm[ 8] < 0.) ? +1 : -1;
7890 Int_t incry = (tnorm[ 9] < 0.) ? +1 : -1;
7891 Int_t incrz = (tnorm[10] < 0.) ? +1 : -1;
7892 Int_t ix1 = (incrx == +1) ? xaxis->GetFirst() : xaxis->GetLast();
7893 Int_t iy1 = (incry == +1) ? yaxis->GetFirst() : yaxis->GetLast();
7894 Int_t iz1 = (incrz == +1) ? zaxis->GetFirst() : zaxis->GetLast();
7895 Int_t ix2 = (incrx == +1) ? xaxis->GetLast() : xaxis->GetFirst();
7896 Int_t iy2 = (incry == +1) ? yaxis->GetLast() : yaxis->GetFirst();
7897 Int_t iz2 = (incrz == +1) ? zaxis->GetLast() : zaxis->GetFirst();
7898
7899 // Set line attributes (colour, style, etc.)
7900 fH->TAttLine::Modify();
7901
7902 // Create bin boxes and draw
7903 const Int_t NTMAX = 100;
7904 Double_t tt[NTMAX][2];
7908 Double_t pmin[3], pmax[3], sxyz[8][3], pp[4][2];
7909 for (Int_t ix = ix1; ix !=ix2+incrx; ix += incrx) {
7910 pmin[0] = xaxis->GetBinLowEdge(ix);
7911 pmax[0] = xaxis->GetBinUpEdge(ix);
7912 for (Int_t iy = iy1; iy != iy2+incry; iy += incry) {
7913 pmin[1] = yaxis->GetBinLowEdge(iy);
7914 pmax[1] = yaxis->GetBinUpEdge(iy);
7915 for (Int_t iz = iz1; iz != iz2+incrz; iz += incrz) {
7916 pmin[2] = zaxis->GetBinLowEdge(iz);
7917 pmax[2] = zaxis->GetBinUpEdge(iz);
7918 Double_t w = fH->GetBinContent(fH->GetBin(ix,iy,iz));
7919 Bool_t neg = kFALSE;
7920 if (w<0) {
7921 w = -w;
7922 neg = kTRUE;
7923 }
7924 if (w < wmin) continue;
7925 if (w > wmax) w = wmax;
7926 Double_t scale = (TMath::Power((w-wmin)/(wmax-wmin),1./3.))/2.;
7927 if (scale == 0) continue;
7928 for (Int_t i=0; i<3; ++i) {
7929 Double_t c = (pmax[i] + pmin[i])*0.5;
7930 Double_t d = (pmax[i] - pmin[i])*scale;
7931 for (Int_t k=0; k<8; ++k) { // set bin box vertices
7932 sxyz[k][i] = wxyz[k][i]*d + c;
7933 }
7934 }
7935 for (Int_t k=0; k<8; ++k) { // transform to normalized space
7936 view->WCtoNDC(&sxyz[k][0],&sxyz[k][0]);
7937 }
7938 for (Int_t k=0; k<6; ++k) { // draw box faces
7939 Double_t zn;
7940 view->FindNormal(normal[k][0], normal[k][1], normal[k][2], zn);
7941 if (zn <= 0) continue;
7942 for (Int_t i=0; i<4; ++i) {
7943 Int_t ip = iface[k][i];
7944 pp[i][0] = sxyz[ip][0];
7945 pp[i][1] = sxyz[ip][1];
7946 }
7947 for (Int_t i=0; i<4; ++i) {
7948 Int_t i1 = i;
7949 Int_t i2 = (i == 3) ? 0 : i + 1;
7950 Int_t nt;
7951 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7952 Double_t xdel = pp[i2][0] - pp[i1][0];
7953 Double_t ydel = pp[i2][1] - pp[i1][1];
7954 Double_t x[2], y[2];
7955 for (Int_t it = 0; it < nt; ++it) {
7956 x[0] = pp[i1][0] + xdel*tt[it][0];
7957 y[0] = pp[i1][1] + ydel*tt[it][0];
7958 x[1] = pp[i1][0] + xdel*tt[it][1];
7959 y[1] = pp[i1][1] + ydel*tt[it][1];
7960 gPad->PaintPolyLine(2, x, y);
7961 }
7962 }
7963 if (neg) {
7964 Int_t i1 = 0;
7965 Int_t i2 = 2;
7966 Int_t nt;
7967 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7968 Double_t xdel = pp[i2][0] - pp[i1][0];
7969 Double_t ydel = pp[i2][1] - pp[i1][1];
7970 Double_t x[2], y[2];
7971 for (Int_t it = 0; it < nt; ++it) {
7972 x[0] = pp[i1][0] + xdel*tt[it][0];
7973 y[0] = pp[i1][1] + ydel*tt[it][0];
7974 x[1] = pp[i1][0] + xdel*tt[it][1];
7975 y[1] = pp[i1][1] + ydel*tt[it][1];
7976 gPad->PaintPolyLine(2, x, y);
7977 }
7978 i1 = 1;
7979 i2 = 3;
7980 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7981 xdel = pp[i2][0] - pp[i1][0];
7982 ydel = pp[i2][1] - pp[i1][1];
7983 for (Int_t it = 0; it < nt; ++it) {
7984 x[0] = pp[i1][0] + xdel*tt[it][0];
7985 y[0] = pp[i1][1] + ydel*tt[it][0];
7986 x[1] = pp[i1][0] + xdel*tt[it][1];
7987 y[1] = pp[i1][1] + ydel*tt[it][1];
7988 gPad->PaintPolyLine(2, x, y);
7989 }
7990 }
7991 fLego->FillPolygonBorder(4, &pp[0][0]); // update raster screen
7992 }
7993 }
7994 }
7995 }
7996
7997 // Draw frame box
7998 if (Hoption.BackBox) {
7999 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
8001 fLego->BackBox(90);
8002 }
8003
8004 if (Hoption.FrontBox) fLego->FrontBox(90);
8005
8006 // Draw axis and title
8007 if (!Hoption.Axis && !Hoption.Same) {
8008 TGaxis axis;
8009 PaintLegoAxis(&axis, 90);
8010 }
8011 PaintTitle();
8012
8013 //Draw stats and fit results
8014 TF1 *fit = nullptr;
8015 TIter next(fFunctions);
8016 while (auto obj = next()) {
8017 if (obj->InheritsFrom(TF1::Class())) {
8018 fit = (TF1*)obj;
8019 break;
8020 }
8021 }
8022 if ((Hoption.Same%10) != 1) {
8023 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
8025 }
8026 }
8027
8028 fLego.reset();
8029}
8030
8031////////////////////////////////////////////////////////////////////////////////
8032/// [Control function to draw a 3D histogram with Iso Surfaces.](\ref HP25)
8033
8035{
8036
8037 const Double_t ydiff = 1;
8038 const Double_t yligh1 = 10;
8039 const Double_t qa = 0.15;
8040 const Double_t qd = 0.15;
8041 const Double_t qs = 0.8;
8042 Double_t fmin, fmax;
8043 Int_t i, irep;
8044 Int_t nbcol = 28;
8045 Int_t icol1 = 201;
8046 Int_t ic1 = icol1;
8047 Int_t ic2 = ic1+nbcol;
8048 Int_t ic3 = ic2+nbcol;
8049
8050 TAxis *xaxis = fH->GetXaxis();
8051 TAxis *yaxis = fH->GetYaxis();
8052 TAxis *zaxis = fH->GetZaxis();
8053
8054 Int_t nx = fH->GetNbinsX();
8055 Int_t ny = fH->GetNbinsY();
8056 Int_t nz = fH->GetNbinsZ();
8057
8058 std::vector<Double_t> x(nx);
8059 std::vector<Double_t> y(ny);
8060 std::vector<Double_t> z(nz);
8061
8062 for (i=0; i<nx; i++) x[i] = xaxis->GetBinCenter(i+1);
8063 for (i=0; i<ny; i++) y[i] = yaxis->GetBinCenter(i+1);
8064 for (i=0; i<nz; i++) z[i] = zaxis->GetBinCenter(i+1);
8065
8066 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
8067 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
8068 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
8069 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
8070 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
8071 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
8072
8073 Double_t s[3];
8074 s[0] = fH->GetSumOfWeights()/(fH->GetNbinsX()*fH->GetNbinsY()*fH->GetNbinsZ());
8075 s[1] = 0.5*s[0];
8076 s[2] = 1.5*s[0];
8077
8078 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
8079
8080 TView *view = gPad ? gPad->GetView() : nullptr;
8081 if (!view) {
8082 Error("PaintH3Iso", "no TView in current pad");
8083 return;
8084 }
8085 Double_t thedeg = 90 - gPad->GetTheta();
8086 Double_t phideg = -90 - gPad->GetPhi();
8087 Double_t psideg = view->GetPsi();
8088 view->SetView(phideg, thedeg, psideg, irep);
8089
8090 Int_t backcolor = gPad->GetFrameFillColor();
8091 if (Hoption.System != kCARTESIAN) backcolor = 0;
8092 view->PadRange(backcolor);
8093
8094 Double_t dcol = 0.5/Double_t(nbcol);
8095 TColor *colref = gROOT->GetColor(fH->GetFillColor());
8096 if (!colref) {
8097 return;
8098 }
8099 Float_t r, g, b, hue, light, satur;
8100 colref->GetRGB(r,g,b);
8101 TColor::RGBtoHLS(r,g,b,hue,light,satur);
8102 TColor *acol;
8103 for (Int_t col=0;col<nbcol;col++) {
8104 acol = gROOT->GetColor(col+icol1);
8105 TColor::HLStoRGB(hue, .4+col*dcol, satur, r, g, b);
8106 if (acol) acol->SetRGB(r, g, b);
8107 }
8108
8109 fLego->InitMoveScreen(-1.1,1.1);
8110
8111 if (Hoption.BackBox) {
8112 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
8114 fLego->BackBox(90);
8115 }
8116
8117 fLego->LightSource(0, ydiff, 0, 0, 0, irep);
8118 fLego->LightSource(1, yligh1, 1, 1, 1, irep);
8119 fLego->SurfaceProperty(qa, qd, qs, 1, irep);
8120 fmin = ydiff*qa;
8121 fmax = ydiff*qa + (yligh1+0.1)*(qd+qs);
8122 fLego->SetIsoSurfaceParameters(fmin, fmax, nbcol, ic1, ic2, ic3);
8123
8124 fLego->IsoSurface(1, s, nx, ny, nz, x.data(), y.data(), z.data(), "BF");
8125
8126 if (Hoption.FrontBox) {
8127 fLego->InitMoveScreen(-1.1,1.1);
8129 fLego->FrontBox(90);
8130 }
8131 if (!Hoption.Axis && !Hoption.Same) {
8132 TGaxis axis;
8133 PaintLegoAxis(&axis, 90);
8134 }
8135
8136 PaintTitle();
8137
8138 //Draw stats and fit results
8139 TF1 *fit = nullptr;
8140 TIter next(fFunctions);
8141 while (auto obj = next()) {
8142 if (obj->InheritsFrom(TF1::Class())) {
8143 fit = (TF1*)obj;
8144 break;
8145 }
8146 }
8147 if ((Hoption.Same%10) != 1) {
8148 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
8150 }
8151 }
8152
8153 fLego.reset();
8154}
8155
8156////////////////////////////////////////////////////////////////////////////////
8157/// [Control function to draw a 2D histogram as a lego plot.](\ref HP17)
8158
8160{
8161
8162 Int_t raster = 1;
8163 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
8164 Int_t nx = Hparam.xlast - Hparam.xfirst + 1;
8165 Int_t ny = Hparam.ylast - Hparam.yfirst + 1;
8166 Double_t zmin = Hparam.zmin;
8167 Double_t zmax = Hparam.zmax;
8168 Double_t xlab1 = Hparam.xmin;
8169 Double_t xlab2 = Hparam.xmax;
8170 Double_t ylab1 = Hparam.ymin;
8171 Double_t ylab2 = Hparam.ymax;
8172 Double_t dangle = 10*3.141592/180; //Delta angle for Rapidity option
8173 Double_t deltaz = TMath::Abs(zmin);
8174 if (deltaz == 0) deltaz = 1;
8175 if (zmin >= zmax) {
8176 zmin -= 0.5*deltaz;
8177 zmax += 0.5*deltaz;
8178 }
8179 Double_t z1c = zmin;
8180 Double_t z2c = zmin + (zmax-zmin)*(1+gStyle->GetHistTopMargin());
8181
8182 // Compute the lego limits and instantiate a lego object
8183 fXbuf[0] = -1;
8184 fYbuf[0] = 1;
8185 fXbuf[1] = -1;
8186 fYbuf[1] = 1;
8187 if (Hoption.System == kPOLAR) {
8188 fXbuf[2] = z1c;
8189 fYbuf[2] = z2c;
8190 } else if (Hoption.System == kCYLINDRICAL) {
8191 if (Hoption.Logy) {
8192 if (ylab1 > 0) fXbuf[2] = TMath::Log10(ylab1);
8193 else fXbuf[2] = 0;
8194 if (ylab2 > 0) fYbuf[2] = TMath::Log10(ylab2);
8195 else fYbuf[2] = 0;
8196 } else {
8197 fXbuf[2] = ylab1;
8198 fYbuf[2] = ylab2;
8199 }
8200 z1c = 0; z2c = 1;
8201 } else if (Hoption.System == kSPHERICAL) {
8202 fXbuf[2] = -1;
8203 fYbuf[2] = 1;
8204 z1c = 0; z2c = 1;
8205 } else if (Hoption.System == kRAPIDITY) {
8206 fXbuf[2] = -1/TMath::Tan(dangle);
8207 fYbuf[2] = 1/TMath::Tan(dangle);
8208 } else {
8209 fXbuf[0] = xlab1;
8210 fYbuf[0] = xlab2;
8211 fXbuf[1] = ylab1;
8212 fYbuf[1] = ylab2;
8213 fXbuf[2] = z1c;
8214 fYbuf[2] = z2c;
8215 raster = 0;
8216 }
8217
8218 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data(), Hoption.System);
8219
8220 Int_t nids = -1;
8221 TH1 * hid = nullptr;
8222 Color_t colormain = -1, colordark = -1;
8223 Bool_t drawShadowsInLego1 = kTRUE;
8224
8225 // LEGO3 is like LEGO1 except that the black lines around each lego are not drawn.
8226 if (Hoption.Lego == 13) {
8227 Hoption.Lego = 11;
8228 fLego->SetMesh(0);
8229 }
8230 // LEGO4 is like LEGO1 except no shadows are drawn.
8231 if (Hoption.Lego == 14) {
8232 Hoption.Lego = 11;
8233 drawShadowsInLego1 = kFALSE;
8234 }
8235
8236 // Initialize the levels on the Z axis
8237 Int_t ndiv = fH->GetContour();
8238 if (ndiv == 0 ) {
8239 ndiv = gStyle->GetNumberContours();
8240 fH->SetContour(ndiv);
8241 }
8242 Int_t ndivz = TMath::Abs(ndiv);
8243 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
8244
8245 // Initialize colors
8246 if (!fStack) {
8247 fLego->SetEdgeAtt(fH->GetLineColor(),fH->GetLineStyle(),fH->GetLineWidth(),0);
8248 } else {
8249 for (Int_t id=0;id<=fStack->GetSize();id++) {
8250 hid = (TH1*)fStack->At((id==0)?id:id-1);
8251 fLego->SetEdgeAtt(hid->GetLineColor(),hid->GetLineStyle(),hid->GetLineWidth(),id);
8252 }
8253 }
8254
8255 if (Hoption.Lego == 11) {
8256 nids = 1;
8257 if (fStack) nids = fStack->GetSize();
8258 hid = fH;
8259 for (Int_t id=0;id<=nids;id++) {
8260 if (id > 0 && fStack) hid = (TH1*)fStack->At(id-1);
8261 colormain = hid->GetFillColor();
8262 if (colormain == 1) colormain = 17; //avoid drawing with black
8263 if (drawShadowsInLego1) colordark = TColor::GetColorDark(colormain);
8264 else colordark = colormain;
8265 fLego->SetColorMain(colormain,id);
8266 fLego->SetColorDark(colordark,id);
8267 if (id <= 1) fLego->SetColorMain(colormain,-1); // Set Bottom color
8268 if (id == nids) fLego->SetColorMain(colormain,99); // Set Top color
8269 }
8270 }
8271
8272 // Now ready to draw the lego plot
8273 Int_t irep = 0;
8274
8275 TView *view = gPad ? gPad->GetView() : nullptr;
8276 if (!view) {
8277 Error("PaintLego", "no TView in current pad");
8278 return;
8279 }
8280
8281 Double_t thedeg = 90 - gPad->GetTheta();
8282 Double_t phideg = -90 - gPad->GetPhi();
8283 Double_t psideg = view->GetPsi();
8284 view->SetView(phideg, thedeg, psideg, irep);
8285
8286 fLego->SetLineColor(kBlack); // zgrid color for lego1 & lego2
8287 fLego->SetFillStyle(fH->GetFillStyle());
8288
8289 // Set color/style for back box
8290 fLego->SetFillStyle(gPad->GetFrameFillStyle());
8291 fLego->SetFillColor(gPad->GetFrameFillColor());
8292 fLego->TAttFill::Modify();
8293
8294 Int_t backcolor = gPad->GetFrameFillColor();
8295 if (Hoption.System != kCARTESIAN) backcolor = 0;
8296 view->PadRange(backcolor);
8297
8298 fLego->SetFillStyle(fH->GetFillStyle());
8299 fLego->SetFillColor(fH->GetFillColor());
8300 fLego->TAttFill::Modify();
8301
8302 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
8303
8304 if (raster) fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
8305 else fLego->InitMoveScreen(-1.1,1.1);
8306
8307 if (Hoption.Lego == 19) {
8309 if (Hoption.BackBox) fLego->BackBox(90);
8310 if (Hoption.FrontBox) fLego->FrontBox(90);
8311 if (!Hoption.Axis) { TGaxis axis; PaintLegoAxis(&axis, 90); }
8312 return;
8313 }
8314
8315 if (Hoption.Lego == 11 || Hoption.Lego == 12) {
8318 fLego->BackBox(90);
8319 }
8320 }
8321
8322 if (Hoption.Lego == 12) DefineColorLevels(ndivz);
8323
8324 fLego->SetLegoFunction(&TPainter3dAlgorithms::LegoFunction);
8326 if (Hoption.Lego == 11) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode3);
8327 if (Hoption.Lego == 12) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode2);
8328 if (Hoption.System == kPOLAR) {
8329 if (Hoption.Lego == 1) fLego->LegoPolar(1,nx,ny,"FB");
8330 if (Hoption.Lego == 11) fLego->LegoPolar(1,nx,ny,"BF");
8331 if (Hoption.Lego == 12) fLego->LegoPolar(1,nx,ny,"BF");
8332 } else if (Hoption.System == kCYLINDRICAL) {
8333 if (Hoption.Lego == 1) fLego->LegoCylindrical(1,nx,ny,"FB");
8334 if (Hoption.Lego == 11) fLego->LegoCylindrical(1,nx,ny,"BF");
8335 if (Hoption.Lego == 12) fLego->LegoCylindrical(1,nx,ny,"BF");
8336 } else if (Hoption.System == kSPHERICAL) {
8337 if (Hoption.Lego == 1) fLego->LegoSpherical(0,1,nx,ny,"FB");
8338 if (Hoption.Lego == 11) fLego->LegoSpherical(0,1,nx,ny,"BF");
8339 if (Hoption.Lego == 12) fLego->LegoSpherical(0,1,nx,ny,"BF");
8340 } else if (Hoption.System == kRAPIDITY) {
8341 if (Hoption.Lego == 1) fLego->LegoSpherical(1,1,nx,ny,"FB");
8342 if (Hoption.Lego == 11) fLego->LegoSpherical(1,1,nx,ny,"BF");
8343 if (Hoption.Lego == 12) fLego->LegoSpherical(1,1,nx,ny,"BF");
8344 } else {
8345 if (Hoption.Lego == 1) {
8347 fLego->LegoCartesian(90,nx,ny,"FB");}
8348 if (Hoption.Lego == 11) fLego->LegoCartesian(90,nx,ny,"BF");
8349 if (Hoption.Lego == 12) fLego->LegoCartesian(90,nx,ny,"BF");
8350 }
8351
8352 if (Hoption.Lego == 1 || Hoption.Lego == 11) {
8355 fLego->BackBox(90);
8356 }
8357 }
8358 if (Hoption.System == kCARTESIAN) {
8359 fLego->InitMoveScreen(-1.1,1.1);
8361 if (Hoption.FrontBox) fLego->FrontBox(90);
8362 }
8363 if (!Hoption.Axis && !Hoption.Same) {
8364 TGaxis axis;
8365 PaintLegoAxis(&axis, 90);
8366 }
8368 fLego.reset();
8369}
8370
8371////////////////////////////////////////////////////////////////////////////////
8372/// Draw the axis for legos and surface plots.
8373
8375{
8376
8377 static Double_t epsil = 0.001;
8378
8379 Double_t cosa, sina;
8380 Double_t bmin, bmax;
8381 Double_t r[24] /* was [3][8] */;
8382 Int_t ndivx, ndivy, ndivz, i;
8383 Double_t x1[3], x2[3], y1[3], y2[3], z1[3], z2[3], av[24] /* was [3][8] */;
8384 static char chopax[8], chopay[8], chopaz[8];
8385 Int_t ix1, ix2, iy1, iy2, iz1, iz2;
8386 Double_t rad;
8387
8388 TView *view = gPad ? gPad->GetView() : nullptr;
8389 if (!view) {
8390 Error("PaintLegoAxis", "no TView in current pad");
8391 return;
8392 }
8393
8394 // In polar coordinates, draw a short line going from the external circle
8395 // corresponding to r = 1 up to r = 1.1
8396 if (Hoption.System == kPOLAR) {
8397 r[0] = 1;
8398 r[1] = 0;
8399 r[2] = 0;
8400 view->WCtoNDC(r, x1);
8401 r[0] = 1.1;
8402 r[1] = 0;
8403 r[2] = 0;
8404 view->WCtoNDC(r, x2);
8405 gPad->PaintLine(x1[0],x1[1],x2[0],x2[1]);
8406 return;
8407 }
8408
8409 if (Hoption.System != kCARTESIAN) return;
8410
8411 rad = TMath::ATan(1.) * 4. /180.;
8412 cosa = TMath::Cos(ang*rad);
8413 sina = TMath::Sin(ang*rad);
8414
8415 view->AxisVertex(ang, av, ix1, ix2, iy1, iy2, iz1, iz2);
8416 for (i = 1; i <= 8; ++i) {
8417 r[i*3 - 3] = av[i*3 - 3] + av[i*3 - 2]*cosa;
8418 r[i*3 - 2] = av[i*3 - 2]*sina;
8419 r[i*3 - 1] = av[i*3 - 1];
8420 }
8421
8422 view->WCtoNDC(&r[ix1*3 - 3], x1);
8423 view->WCtoNDC(&r[ix2*3 - 3], x2);
8424 view->WCtoNDC(&r[iy1*3 - 3], y1);
8425 view->WCtoNDC(&r[iy2*3 - 3], y2);
8426 view->WCtoNDC(&r[iz1*3 - 3], z1);
8427 view->WCtoNDC(&r[iz2*3 - 3], z2);
8428
8429 view->SetAxisNDC(x1, x2, y1, y2, z1, z2);
8430
8431 Double_t *rmin = view->GetRmin();
8432 Double_t *rmax = view->GetRmax();
8433 if (!rmin || !rmax) return;
8434
8435 // Initialize the axis options
8436 if (x1[0] > x2[0]) strlcpy(chopax, "SDH=+",8);
8437 else strlcpy(chopax, "SDH=-",8);
8438 if (y1[0] > y2[0]) strlcpy(chopay, "SDH=+",8);
8439 else strlcpy(chopay, "SDH=-",8);
8440 if (z2[1] > z1[1]) strlcpy(chopaz, "SDH=+",8);
8441 else strlcpy(chopaz, "SDH=-",8);
8442
8443 // Option LOG is required ?
8444 if (Hoption.Logx) strlcat(chopax,"G",8);
8445 if (Hoption.Logy) strlcat(chopay,"G",8);
8446 if (Hoption.Logz) strlcat(chopaz,"G",8);
8447
8448 // Initialize the number of divisions. If the
8449 // number of divisions is negative, option 'N' is required.
8450 ndivx = fXaxis->GetNdivisions();
8451 ndivy = fYaxis->GetNdivisions();
8452 ndivz = fZaxis->GetNdivisions();
8453 if (ndivx < 0) {
8454 ndivx = TMath::Abs(ndivx);
8455 strlcat(chopax, "N",8);
8456 }
8457 if (ndivy < 0) {
8458 ndivy = TMath::Abs(ndivy);
8459 strlcat(chopay, "N",8);
8460 }
8461 if (ndivz < 0) {
8462 ndivz = TMath::Abs(ndivz);
8463 strlcat(chopaz, "N",8);
8464 }
8465
8466 // Set Axis attributes.
8467 // The variable SCALE rescales the VSIZ
8468 // in order to have the same label size for all angles.
8469
8470 axis->SetLineWidth(1);
8471
8472 // X axis drawing
8473 if (TMath::Abs(x1[0] - x2[0]) >= epsil || TMath::Abs(x1[1] - x2[1]) > epsil) {
8476 if (Hoption.Logx && !fH->InheritsFrom(TH3::Class())) {
8477 bmin = TMath::Power(10, rmin[0]);
8478 bmax = TMath::Power(10, rmax[0]);
8479 } else {
8480 bmin = rmin[0];
8481 bmax = rmax[0];
8482 }
8483 // Option time display is required ?
8484 if (fXaxis->GetTimeDisplay()) {
8485 strlcat(chopax,"t",8);
8486 if (strlen(fXaxis->GetTimeFormatOnly()) == 0) {
8487 axis->SetTimeFormat(fXaxis->ChooseTimeFormat(bmax-bmin));
8488 } else {
8490 }
8491 }
8492 axis->SetOption(chopax);
8493 axis->PaintAxis(x1[0], x1[1], x2[0], x2[1], bmin, bmax, ndivx, chopax);
8494 }
8495
8496 // Y axis drawing
8497 if (TMath::Abs(y1[0] - y2[0]) >= epsil || TMath::Abs(y1[1] - y2[1]) > epsil) {
8500 if (fYaxis->GetTitleOffset() == 0) axis->SetTitleOffset(1.5);
8501
8502 if (fH->GetDimension() < 2) {
8503 strlcpy(chopay, "V=+UN",8);
8504 ndivy = 0;
8505 }
8506 if (TMath::Abs(y1[0] - y2[0]) < epsil) {
8507 y2[0] = y1[0];
8508 }
8509 if (Hoption.Logy && !fH->InheritsFrom(TH3::Class())) {
8510 bmin = TMath::Power(10, rmin[1]);
8511 bmax = TMath::Power(10, rmax[1]);
8512 } else {
8513 bmin = rmin[1];
8514 bmax = rmax[1];
8515 }
8516 // Option time display is required ?
8517 if (fYaxis->GetTimeDisplay()) {
8518 strlcat(chopay,"t",8);
8519 if (strlen(fYaxis->GetTimeFormatOnly()) == 0) {
8520 axis->SetTimeFormat(fYaxis->ChooseTimeFormat(bmax-bmin));
8521 } else {
8523 }
8524 }
8525 axis->SetOption(chopay);
8526 axis->PaintAxis(y1[0], y1[1], y2[0], y2[1], bmin, bmax, ndivy, chopay);
8527 }
8528
8529 // Z axis drawing
8530 if (TMath::Abs(z1[0] - z2[0]) >= 100*epsil || TMath::Abs(z1[1] - z2[1]) > 100*epsil) {
8532 if (Hoption.Logz && !fH->InheritsFrom(TH3::Class())) {
8533 bmin = TMath::Power(10, rmin[2]);
8534 bmax = TMath::Power(10, rmax[2]);
8535 } else {
8536 bmin = rmin[2];
8537 bmax = rmax[2];
8538 }
8539 // Option time display is required ?
8540 if (fZaxis->GetTimeDisplay()) {
8541 strlcat(chopaz,"t",8);
8542 if (strlen(fZaxis->GetTimeFormatOnly()) == 0) {
8543 axis->SetTimeFormat(fZaxis->ChooseTimeFormat(bmax-bmin));
8544 } else {
8546 }
8547 }
8548 axis->SetOption(chopaz);
8549 TString ztit = fZaxis->GetTitle();
8550 if (ztit.Index(";")>0) {
8551 ztit.Remove(ztit.Index(";"),ztit.Length());
8552 axis->SetTitle(ztit.Data());
8553 }
8554 axis->PaintAxis(z1[0], z1[1], z2[0], z2[1], bmin, bmax, ndivz, chopaz);
8555 }
8556
8557 //fH->SetLineStyle(1); /// otherwise fEdgeStyle[i] gets overwritten!
8558}
8559
8560////////////////////////////////////////////////////////////////////////////////
8561/// [Paint the color palette on the right side of the pad.](\ref HP22)
8562
8564{
8565 TPaletteAxis *palette = (TPaletteAxis*)fFunctions->FindObject("palette");
8566 TView *view = gPad ? gPad->GetView() : nullptr;
8567 if (palette) {
8568 if (view) {
8569 if (!palette->TestBit(TPaletteAxis::kHasView)) {
8570 fFunctions->Remove(palette);
8571 delete palette; palette = nullptr;
8572 }
8573 } else {
8574 if (palette->TestBit(TPaletteAxis::kHasView)) {
8575 fFunctions->Remove(palette);
8576 delete palette; palette = nullptr;
8577 }
8578 }
8579 // make sure the histogram member of the palette is setup correctly. It may not be after a Clone()
8580 if (palette && !palette->GetHistogram()) palette->SetHistogram(fH);
8581 }
8582
8583 if (!palette) {
8584 Double_t xup = gPad->GetUxmax();
8585 Double_t x2 = gPad->PadtoX(gPad->GetX2());
8586 Double_t ymin = gPad->PadtoY(gPad->GetUymin());
8587 Double_t ymax = gPad->PadtoY(gPad->GetUymax());
8588 Double_t xr = 0.05*(gPad->GetX2() - gPad->GetX1());
8589 Double_t xmin = gPad->PadtoX(xup +0.1*xr);
8590 Double_t xmax = gPad->PadtoX(xup + xr);
8591 if (xmax > x2) xmax = gPad->PadtoX(gPad->GetX2()-0.01*xr);
8592 palette = new TPaletteAxis(xmin,ymin,xmax,ymax,fH);
8593 fFunctions->AddFirst(palette);
8594 palette->Paint();
8595 }
8596}
8597
8598////////////////////////////////////////////////////////////////////////////////
8599/// [Control function to draw a 2D histogram as a scatter plot.](\ref HP11)
8600
8602{
8603
8604 fH->TAttMarker::Modify();
8605
8606 Int_t k, marker;
8607 Double_t dz, z, xk,xstep, yk, ystep;
8608 Double_t scale = 1;
8609 Bool_t ltest = kFALSE;
8610 Double_t zmax = fH->GetMaximum();
8611 Double_t zmin = fH->GetMinimum();
8612 if (zmin == 0 && zmax == 0) return;
8613 if (zmin == zmax) {
8614 zmax += 0.1*TMath::Abs(zmax);
8615 zmin -= 0.1*TMath::Abs(zmin);
8616 }
8618 if (Hoption.Logz) {
8619 if (zmin > 0) zmin = TMath::Log10(zmin);
8620 else zmin = 0;
8621 if (zmax > 0) zmax = TMath::Log10(zmax);
8622 else zmax = 0;
8623 if (zmin == 0 && zmax == 0) return;
8624 dz = zmax - zmin;
8625 scale = 100/dz;
8626 if (ncells > 10000) scale /= 5;
8627 ltest = kTRUE;
8628 } else {
8629 dz = zmax - zmin;
8630 if (dz >= kNMAX || zmax < 1) {
8631 scale = (kNMAX-1)/dz;
8632 if (ncells > 10000) scale /= 5;
8633 ltest = kTRUE;
8634 }
8635 }
8636 if (fH->GetMinimumStored() == -1111) {
8637 Double_t yMARGIN = gStyle->GetHistTopMargin();
8638 if (Hoption.MinimumZero) {
8639 if (zmin >= 0) zmin = 0;
8640 else zmin -= yMARGIN*(zmax-zmin);
8641 } else {
8642 Double_t dzmin = yMARGIN*(zmax-zmin);
8643 if (zmin >= 0 && (zmin-dzmin <= 0)) zmin = 0;
8644 else zmin -= dzmin;
8645 }
8646 }
8647
8648 TString opt = option;
8649 opt.ToLower();
8650 if (opt.Contains("scat=")) {
8651 char optscat[100];
8652 strlcpy(optscat,opt.Data(),100);
8653 char *oscat = strstr(optscat,"scat=");
8654 char *blank = strstr(oscat," "); if (blank) *blank = 0;
8655 sscanf(oscat+5,"%lg",&scale);
8656 }
8657 // use an independent instance of a random generator
8658 // instead of gRandom to avoid conflicts and
8659 // to get same random numbers when drawing the same histogram
8660 TRandom2 random;
8661 marker=0;
8662 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
8663 yk = fYaxis->GetBinLowEdge(j);
8664 ystep = fYaxis->GetBinWidth(j);
8665 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
8666 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
8667 xk = fXaxis->GetBinLowEdge(i);
8668 xstep = fXaxis->GetBinWidth(i);
8669 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
8670 z = fH->GetBinContent(bin);
8671 if (z < zmin) z = zmin;
8672 if (z > zmax) z = zmax;
8673 if (Hoption.Logz) {
8674 if (z > 0) z = TMath::Log10(z) - zmin;
8675 } else {
8676 z -= zmin;
8677 }
8678 if (z <= 0) continue;
8679 k = Int_t(z*scale);
8680 if (ltest) k++;
8681 if (k > 0) {
8682 for (Int_t loop=0; loop<k; loop++) {
8683 if (k+marker >= kNMAX) {
8684 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
8685 marker=0;
8686 }
8687 fXbuf[marker] = (random.Rndm()*xstep) + xk;
8688 fYbuf[marker] = (random.Rndm()*ystep) + yk;
8689 if (Hoption.Logx) {
8690 if (fXbuf[marker] > 0) fXbuf[marker] = TMath::Log10(fXbuf[marker]);
8691 else break;
8692 }
8693 if (Hoption.Logy) {
8694 if (fYbuf[marker] > 0) fYbuf[marker] = TMath::Log10(fYbuf[marker]);
8695 else break;
8696 }
8697 if (fXbuf[marker] < gPad->GetUxmin()) break;
8698 if (fYbuf[marker] < gPad->GetUymin()) break;
8699 if (fXbuf[marker] > gPad->GetUxmax()) break;
8700 if (fYbuf[marker] > gPad->GetUymax()) break;
8701 marker++;
8702 }
8703 }
8704 }
8705 }
8706 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
8707
8709}
8710
8711////////////////////////////////////////////////////////////////////////////////
8712/// Static function to paint special objects like vectors and matrices.
8713/// This function is called via `gROOT->ProcessLine` to paint these objects
8714/// without having a direct dependency of the graphics or histogramming
8715/// system.
8716
8718{
8719
8720 if (!obj) return;
8721 TDirectory::TContext ctx{nullptr}; // No self-registration to directories
8722
8723 if (obj->InheritsFrom(TMatrixFBase::Class())) {
8724 // case TMatrixF
8725 TH2F *R__TMatrixFBase = new TH2F((TMatrixFBase &)*obj);
8726 R__TMatrixFBase->SetBit(kCanDelete);
8727 R__TMatrixFBase->Draw(option);
8728
8729 } else if (obj->InheritsFrom(TMatrixDBase::Class())) {
8730 // case TMatrixD
8731 TH2D *R__TMatrixDBase = new TH2D((TMatrixDBase &)*obj);
8732 R__TMatrixDBase->SetBit(kCanDelete);
8733 R__TMatrixDBase->Draw(option);
8734
8735 } else if (obj->InheritsFrom(TVectorF::Class())) {
8736 //case TVectorF
8737 TH1F *R__TVectorF = new TH1F((TVectorF &)*obj);
8738 R__TVectorF->SetBit(kCanDelete);
8739 R__TVectorF->Draw(option);
8740
8741 } else if (obj->InheritsFrom(TVectorD::Class())) {
8742 //case TVectorD
8743 TH1D *R__TVectorD = new TH1D((TVectorD &)*obj);
8744 R__TVectorD->SetBit(kCanDelete);
8745 R__TVectorD->Draw(option);
8746 }
8747}
8748
8749////////////////////////////////////////////////////////////////////////////////
8750/// [Draw the statistics box for 1D and profile histograms.](\ref HP07)
8751
8753{
8754 TString tt, tf;
8755 Int_t dofit;
8756 TPaveStats *stats = nullptr;
8757 TIter next(fFunctions);
8758 while (auto obj = next()) {
8759 if (obj->InheritsFrom(TPaveStats::Class())) {
8760 stats = (TPaveStats*)obj;
8761 break;
8762 }
8763 }
8764
8765 if (stats && dostat) {
8766 dofit = stats->GetOptFit();
8767 dostat = stats->GetOptStat();
8768 } else {
8769 dofit = gStyle->GetOptFit();
8770 }
8771 if (!dofit) fit = nullptr;
8772 if (dofit == 1) dofit = 111;
8773 if (dostat == 1) dostat = 1111;
8774 Int_t print_name = dostat%10;
8775 Int_t print_entries = (dostat/10)%10;
8776 Int_t print_mean = (dostat/100)%10;
8777 Int_t print_stddev = (dostat/1000)%10;
8778 Int_t print_under = (dostat/10000)%10;
8779 Int_t print_over = (dostat/100000)%10;
8780 Int_t print_integral= (dostat/1000000)%10;
8781 Int_t print_skew = (dostat/10000000)%10;
8782 Int_t print_kurt = (dostat/100000000)%10;
8783 Int_t nlines = print_name + print_entries + print_mean + print_stddev +
8784 print_under + print_over + print_integral +
8785 print_skew + print_kurt;
8786 Int_t print_fval = dofit%10;
8787 Int_t print_ferrors = (dofit/10)%10;
8788 Int_t print_fchi2 = (dofit/100)%10;
8789 Int_t print_fprob = (dofit/1000)%10;
8790 Int_t nlinesf = print_fval + print_fchi2 + print_fprob;
8791 if (fit) {
8792 if (print_fval < 2) nlinesf += fit->GetNumberFreeParameters();
8793 else nlinesf += fit->GetNpar();
8794 }
8795 if (fH->InheritsFrom(TProfile::Class())) nlinesf += print_mean + print_stddev;
8796
8797 // Pavetext with statistics
8798 Bool_t done = kFALSE;
8799 if (!dostat && !fit) {
8800 if (stats) { fFunctions->Remove(stats); delete stats;}
8801 return;
8802 }
8803 Double_t statw = gStyle->GetStatW();
8804 if (fit) statw = 1.8*gStyle->GetStatW();
8805 Double_t stath = (nlines+nlinesf)*gStyle->GetStatFontSize();
8806 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
8807 stath = 0.25*(nlines+nlinesf)*gStyle->GetStatH();
8808 }
8809 if (stats) {
8810 stats->Clear();
8811 done = kTRUE;
8812 } else {
8813 stats = new TPaveStats(
8814 gStyle->GetStatX()-statw,
8815 gStyle->GetStatY()-stath,
8816 gStyle->GetStatX(),
8817 gStyle->GetStatY(),"brNDC");
8818
8819 stats->SetParent(fH);
8820 stats->SetOptFit(dofit);
8821 stats->SetOptStat(dostat);
8822 stats->SetFillColor(gStyle->GetStatColor());
8823 stats->SetFillStyle(gStyle->GetStatStyle());
8825 stats->SetTextFont(gStyle->GetStatFont());
8826 if (gStyle->GetStatFont()%10 > 2)
8828 stats->SetFitFormat(gStyle->GetFitFormat());
8830 stats->SetName("stats");
8831
8833 stats->SetTextAlign(12);
8834 stats->SetBit(kCanDelete);
8835 stats->SetBit(kMustCleanup);
8836 }
8837 if (print_name) stats->AddText(fH->GetName());
8838 if (print_entries) {
8839 if (fH->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(fH->GetEntries()+0.5));
8840 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(fH->GetEntries()));
8841 stats->AddText(tt.Data());
8842 }
8843 if (print_mean) {
8844 if (print_mean == 1) {
8845 tf.Form("%s = %s%s",gStringMean.Data(),"%",stats->GetStatFormat());
8846 tt.Form(tf.Data(),fH->GetMean(1));
8847 } else {
8848 tf.Form("%s = %s%s #pm %s%s",gStringMean.Data(),"%",stats->GetStatFormat()
8849 ,"%",stats->GetStatFormat());
8850 tt.Form(tf.Data(),fH->GetMean(1),fH->GetMeanError(1));
8851 }
8852 stats->AddText(tt.Data());
8854 if (print_mean == 1) {
8855 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
8856 tt.Form(tf.Data(),fH->GetMean(2));
8857 } else {
8858 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
8859 ,"%",stats->GetStatFormat());
8860 tt.Form(tf.Data(),fH->GetMean(2),fH->GetMeanError(2));
8861 }
8862 stats->AddText(tt.Data());
8863 }
8864 }
8865 if (print_stddev) {
8866 if (print_stddev == 1) {
8867 tf.Form("%s = %s%s",gStringStdDev.Data(),"%",stats->GetStatFormat());
8868 tt.Form(tf.Data(),fH->GetStdDev(1));
8869 } else {
8870 tf.Form("%s = %s%s #pm %s%s",gStringStdDev.Data(),"%",stats->GetStatFormat()
8871 ,"%",stats->GetStatFormat());
8872 tt.Form(tf.Data(),fH->GetStdDev(1),fH->GetStdDevError(1));
8873 }
8874 stats->AddText(tt.Data());
8876 if (print_stddev == 1) {
8877 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
8878 tt.Form(tf.Data(),fH->GetStdDev(2));
8879 } else {
8880 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
8881 ,"%",stats->GetStatFormat());
8882 tt.Form(tf.Data(),fH->GetStdDev(2),fH->GetStdDevError(2));
8883 }
8884 stats->AddText(tt.Data());
8885 }
8886 }
8887 if (print_under) {
8888 tf.Form("%s = %s%s",gStringUnderflow.Data(),"%",stats->GetStatFormat());
8889 tt.Form(tf.Data(),fH->GetBinContent(0));
8890 stats->AddText(tt.Data());
8891 }
8892 if (print_over) {
8893 tf.Form("%s = %s%s",gStringOverflow.Data(),"%",stats->GetStatFormat());
8894 tt.Form(tf.Data(),fH->GetBinContent(fXaxis->GetNbins()+1));
8895 stats->AddText(tt.Data());
8896 }
8897 if (print_integral) {
8898 if (print_integral == 1) {
8899 tf.Form("%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
8900 tt.Form(tf.Data(),fH->Integral());
8901 } else {
8902 tf.Form("%s = %s%s",gStringIntegralBinWidth.Data(),"%",stats->GetStatFormat());
8903 tt.Form(tf.Data(),fH->Integral("width"));
8904 }
8905 stats->AddText(tt.Data());
8906 }
8907 if (print_skew) {
8908 if (print_skew == 1) {
8909 tf.Form("%s = %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat());
8910 tt.Form(tf.Data(),fH->GetSkewness(1));
8911 } else {
8912 tf.Form("%s = %s%s #pm %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat()
8913 ,"%",stats->GetStatFormat());
8914 tt.Form(tf.Data(),fH->GetSkewness(1),fH->GetSkewness(11));
8915 }
8916 stats->AddText(tt.Data());
8917 }
8918 if (print_kurt) {
8919 if (print_kurt == 1) {
8920 tf.Form("%s = %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat());
8921 tt.Form(tf.Data(),fH->GetKurtosis(1));
8922 } else {
8923 tf.Form("%s = %s%s #pm %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat()
8924 ,"%",stats->GetStatFormat());
8925 tt.Form(tf.Data(),fH->GetKurtosis(1),fH->GetKurtosis(11));
8926 }
8927 stats->AddText(tt.Data());
8928 }
8929
8930 // Draw Fit parameters
8931 if (fit) {
8932 Int_t ndf = fit->GetNDF();
8933 tf.Form("#chi^{2} / ndf = %s%s / %d","%",stats->GetFitFormat(),ndf);
8934 tt.Form(tf.Data(),fit->GetChisquare());
8935 if (print_fchi2) stats->AddText(tt.Data());
8936 if (print_fprob) {
8937 tf.Form("Prob = %s%s","%",stats->GetFitFormat());
8938 tt.Form(tf.Data(),TMath::Prob(fit->GetChisquare(),ndf));
8939 stats->AddText(tt.Data());
8940 }
8941 if (print_fval || print_ferrors) {
8942 Double_t parmin,parmax;
8943 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
8944 fit->GetParLimits(ipar,parmin,parmax);
8945 if (print_fval < 2 && parmin*parmax != 0 && parmin >= parmax) continue;
8946 if (print_ferrors) {
8947 tf.Form("%-8s = %s%s #pm %s ", fit->GetParName(ipar), "%",stats->GetFitFormat(),
8948 GetBestFormat(fit->GetParameter(ipar), fit->GetParError(ipar), stats->GetFitFormat()));
8949 tt.Form(tf.Data(),fit->GetParameter(ipar)
8950 ,fit->GetParError(ipar));
8951 } else {
8952 tf.Form("%-8s = %s%s ",fit->GetParName(ipar), "%",stats->GetFitFormat());
8953 tt.Form(tf.Data(),fit->GetParameter(ipar));
8954 }
8955 stats->AddText(tt.Data());
8956 }
8957 }
8958 }
8959
8960 if (!done) fFunctions->Add(stats);
8961 stats->Paint(stats->GetOption());
8962}
8963
8964////////////////////////////////////////////////////////////////////////////////
8965/// [Draw the statistics box for 2D histograms.](\ref HP07)
8966
8968{
8969
8970 if (fH->GetDimension() != 2) return;
8971 TH2 *h2 = (TH2*)fH;
8972
8973 TString tt, tf;
8974 Int_t dofit;
8975 TPaveStats *stats = nullptr;
8976 TIter next(fFunctions);
8977 while (auto obj = next()) {
8978 if (obj->InheritsFrom(TPaveStats::Class())) {
8979 stats = (TPaveStats*)obj;
8980 break;
8981 }
8982 }
8983 if (stats && dostat) {
8984 dofit = stats->GetOptFit();
8985 dostat = stats->GetOptStat();
8986 } else {
8987 dofit = gStyle->GetOptFit();
8988 }
8989 if (dostat == 1) dostat = 1111;
8990 Int_t print_name = dostat%10;
8991 Int_t print_entries = (dostat/10)%10;
8992 Int_t print_mean = (dostat/100)%10;
8993 Int_t print_stddev = (dostat/1000)%10;
8994 Int_t print_under = (dostat/10000)%10;
8995 Int_t print_over = (dostat/100000)%10;
8996 Int_t print_integral= (dostat/1000000)%10;
8997 Int_t print_skew = (dostat/10000000)%10;
8998 Int_t print_kurt = (dostat/100000000)%10;
8999 Int_t nlines = print_name + print_entries + 2*print_mean + 2*print_stddev + print_integral;
9000 if (print_under || print_over) nlines += 3;
9001
9002 // Pavetext with statistics
9003 if (!gStyle->GetOptFit()) fit = nullptr;
9004 Bool_t done = kFALSE;
9005 if (!dostat && !fit) {
9006 if (stats) { fFunctions->Remove(stats); delete stats;}
9007 return;
9008 }
9009 Double_t statw = gStyle->GetStatW();
9010 if (fit) statw = 1.8*gStyle->GetStatW();
9011 Double_t stath = nlines*gStyle->GetStatFontSize();
9012 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
9013 stath = 0.25*nlines*gStyle->GetStatH();
9014 }
9015 if (fit) stath += gStyle->GetStatH();
9016 if (stats) {
9017 stats->Clear();
9018 done = kTRUE;
9019 } else {
9020 stats = new TPaveStats(
9021 gStyle->GetStatX()-statw,
9022 gStyle->GetStatY()-stath,
9023 gStyle->GetStatX(),
9024 gStyle->GetStatY(),"brNDC");
9025
9026 stats->SetParent(fH);
9027 stats->SetOptFit(dofit);
9028 stats->SetOptStat(dostat);
9029 stats->SetFillColor(gStyle->GetStatColor());
9030 stats->SetFillStyle(gStyle->GetStatStyle());
9032 stats->SetName("stats");
9033
9035 stats->SetTextAlign(12);
9036 stats->SetTextFont(gStyle->GetStatFont());
9037 if (gStyle->GetStatFont()%10 > 2)
9039 stats->SetFitFormat(gStyle->GetFitFormat());
9041 stats->SetBit(kCanDelete);
9042 stats->SetBit(kMustCleanup);
9043 }
9044 if (print_name) stats->AddText(h2->GetName());
9045 if (print_entries) {
9046 if (h2->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(h2->GetEntries()+0.5));
9047 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(h2->GetEntries()));
9048 stats->AddText(tt.Data());
9049 }
9050 if (print_mean) {
9051 if (print_mean == 1) {
9052 tf.Form("%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
9053 tt.Form(tf.Data(),h2->GetMean(1));
9054 stats->AddText(tt.Data());
9055 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
9056 tt.Form(tf.Data(),h2->GetMean(2));
9057 stats->AddText(tt.Data());
9058 } else {
9059 tf.Form("%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
9060 ,"%",stats->GetStatFormat());
9061 tt.Form(tf.Data(),h2->GetMean(1),h2->GetMeanError(1));
9062 stats->AddText(tt.Data());
9063 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
9064 ,"%",stats->GetStatFormat());
9065 tt.Form(tf.Data(),h2->GetMean(2),h2->GetMeanError(2));
9066 stats->AddText(tt.Data());
9067 }
9068 }
9069 if (print_stddev) {
9070 if (print_stddev == 1) {
9071 tf.Form("%s = %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat());
9072 tt.Form(tf.Data(),h2->GetStdDev(1));
9073 stats->AddText(tt.Data());
9074 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
9075 tt.Form(tf.Data(),h2->GetStdDev(2));
9076 stats->AddText(tt.Data());
9077 } else {
9078 tf.Form("%s = %s%s #pm %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat()
9079 ,"%",stats->GetStatFormat());
9080 tt.Form(tf.Data(),h2->GetStdDev(1),h2->GetStdDevError(1));
9081 stats->AddText(tt.Data());
9082 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
9083 ,"%",stats->GetStatFormat());
9084 tt.Form(tf.Data(),h2->GetStdDev(2),h2->GetStdDevError(2));
9085 stats->AddText(tt.Data());
9086 }
9087 }
9088 if (print_integral) {
9089 tf.Form("%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
9090 tt.Form(tf.Data(),fH->Integral());
9091 stats->AddText(tt.Data());
9092 }
9093 if (print_skew) {
9094 if (print_skew == 1) {
9095 tf.Form("%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
9096 tt.Form(tf.Data(),h2->GetSkewness(1));
9097 stats->AddText(tt.Data());
9098 tf.Form("%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
9099 tt.Form(tf.Data(),h2->GetSkewness(2));
9100 stats->AddText(tt.Data());
9101 } else {
9102 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
9103 ,"%",stats->GetStatFormat());
9104 tt.Form(tf.Data(),h2->GetSkewness(1),h2->GetSkewness(11));
9105 stats->AddText(tt.Data());
9106 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
9107 ,"%",stats->GetStatFormat());
9108 tt.Form(tf.Data(),h2->GetSkewness(2),h2->GetSkewness(12));
9109 stats->AddText(tt.Data());
9110 }
9111 }
9112 if (print_kurt) {
9113 if (print_kurt == 1) {
9114 tf.Form("%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
9115 tt.Form(tf.Data(),h2->GetKurtosis(1));
9116 stats->AddText(tt.Data());
9117 tf.Form("%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
9118 tt.Form(tf.Data(),h2->GetKurtosis(2));
9119 stats->AddText(tt.Data());
9120 } else {
9121 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
9122 ,"%",stats->GetStatFormat());
9123 tt.Form(tf.Data(),h2->GetKurtosis(1),h2->GetKurtosis(11));
9124 stats->AddText(tt.Data());
9125 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
9126 ,"%",stats->GetStatFormat());
9127 tt.Form(tf.Data(),h2->GetKurtosis(2),h2->GetKurtosis(12));
9128 stats->AddText(tt.Data());
9129 }
9130 }
9131 if (print_under || print_over) {
9132 //get 3*3 under/overflows for 2d hist
9133 Double_t unov[9];
9134
9135 Int_t cellsX = h2->GetXaxis()->GetNbins() + 1;
9136 Int_t cellsY = h2->GetYaxis()->GetNbins() + 1;
9137 Int_t firstX = std::max(1, h2->GetXaxis()->GetFirst());
9138 Int_t firstY = std::max(1, h2->GetYaxis()->GetFirst());
9139 Int_t lastX = std::min(h2->GetXaxis()->GetLast(), h2->GetXaxis()->GetNbins());
9140 Int_t lastY = std::min(h2->GetYaxis()->GetLast(), h2->GetYaxis()->GetNbins());
9141
9142 unov[0] = h2->Integral( 0, firstX-1, lastY+1, cellsY );
9143 unov[1] = h2->Integral(firstX , lastX , lastY+1, cellsY );
9144 unov[2] = h2->Integral(lastX+1, cellsX , lastY+1, cellsY );
9145 unov[3] = h2->Integral( 0, firstX-1, firstY , lastY );
9146 unov[4] = h2->Integral(firstX , lastX , firstY , lastY );
9147 unov[5] = h2->Integral(lastX+1, cellsX , firstY , lastY );
9148 unov[6] = h2->Integral( 0, firstX-1, 0, firstY-1);
9149 unov[7] = h2->Integral(firstX, lastX, 0, firstY-1);
9150 unov[8] = h2->Integral(lastX+1, cellsX , 0, firstY-1);
9151
9152 tt.Form("%g|%g|%g\n", unov[0], unov[1], unov[2]);
9153 stats->AddText(tt.Data());
9154 tt.Form("%g|%g|%g\n", unov[3], unov[4], unov[5]);
9155 stats->AddText(tt.Data());
9156 tt.Form("%g|%g|%g\n", unov[6], unov[7], unov[8]);
9157 stats->AddText(tt.Data());
9158 }
9159
9160 // Draw Fit parameters
9161 if (fit) {
9162 Int_t ndf = fit->GetNDF();
9163 tt.Form("#chi^{2} / ndf = %6.4g / %d",fit->GetChisquare(),ndf);
9164 stats->AddText(tt.Data());
9165 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
9166 tt.Form("%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
9167 ,fit->GetParameter(ipar)
9168 ,fit->GetParError(ipar));
9169 stats->AddText(tt.Data());
9170 }
9171 }
9172
9173 if (!done) fFunctions->Add(stats);
9174 stats->Paint(stats->GetOption());
9175}
9176
9177////////////////////////////////////////////////////////////////////////////////
9178/// [Draw the statistics box for 3D histograms.](\ref HP07)
9179
9181{
9182
9183 if (fH->GetDimension() != 3) return;
9184 TH3 *h3 = (TH3*)fH;
9185
9186 TString tt, tf;
9187 Int_t dofit;
9188 TPaveStats *stats = nullptr;
9189 TIter next(fFunctions);
9190 while (auto obj = next()) {
9191 if (obj->InheritsFrom(TPaveStats::Class())) {
9192 stats = (TPaveStats*)obj;
9193 break;
9194 }
9195 }
9196 if (stats && dostat) {
9197 dofit = stats->GetOptFit();
9198 dostat = stats->GetOptStat();
9199 } else {
9200 dofit = gStyle->GetOptFit();
9201 }
9202 if (dostat == 1) dostat = 1111;
9203 Int_t print_name = dostat%10;
9204 Int_t print_entries = (dostat/10)%10;
9205 Int_t print_mean = (dostat/100)%10;
9206 Int_t print_stddev = (dostat/1000)%10;
9207 Int_t print_under = (dostat/10000)%10;
9208 Int_t print_over = (dostat/100000)%10;
9209 Int_t print_integral= (dostat/1000000)%10;
9210 Int_t print_skew = (dostat/10000000)%10;
9211 Int_t print_kurt = (dostat/100000000)%10;
9212 Int_t nlines = print_name + print_entries + 3*print_mean + 3*print_stddev + print_integral;
9213 if (print_under || print_over) nlines += 3;
9214
9215 // Pavetext with statistics
9216 if (!gStyle->GetOptFit()) fit = nullptr;
9217 Bool_t done = kFALSE;
9218 if (!dostat && !fit) {
9219 if (stats) { fFunctions->Remove(stats); delete stats;}
9220 return;
9221 }
9222 Double_t statw = gStyle->GetStatW();
9223 if (fit) statw = 1.8*gStyle->GetStatW();
9224 Double_t stath = nlines*gStyle->GetStatFontSize();
9225 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
9226 stath = 0.25*nlines*gStyle->GetStatH();
9227 }
9228 if (fit) stath += gStyle->GetStatH();
9229 if (stats) {
9230 stats->Clear();
9231 done = kTRUE;
9232 } else {
9233 stats = new TPaveStats(
9234 gStyle->GetStatX()-statw,
9235 gStyle->GetStatY()-stath,
9236 gStyle->GetStatX(),
9237 gStyle->GetStatY(),"brNDC");
9238
9239 stats->SetParent(fH);
9240 stats->SetOptFit(dofit);
9241 stats->SetOptStat(dostat);
9242 stats->SetFillColor(gStyle->GetStatColor());
9243 stats->SetFillStyle(gStyle->GetStatStyle());
9245 stats->SetName("stats");
9246
9248 stats->SetTextAlign(12);
9249 stats->SetTextFont(gStyle->GetStatFont());
9250 stats->SetFitFormat(gStyle->GetFitFormat());
9252 stats->SetBit(kCanDelete);
9253 stats->SetBit(kMustCleanup);
9254 }
9255 if (print_name) stats->AddText(h3->GetName());
9256 if (print_entries) {
9257 if (h3->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(h3->GetEntries()+0.5));
9258 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(h3->GetEntries()+0.5));
9259 stats->AddText(tt.Data());
9260 }
9261 if (print_mean) {
9262 if (print_mean == 1) {
9263 tf.Form("%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
9264 tt.Form(tf.Data(),h3->GetMean(1));
9265 stats->AddText(tt.Data());
9266 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
9267 tt.Form(tf.Data(),h3->GetMean(2));
9268 stats->AddText(tt.Data());
9269 tf.Form("%s = %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat());
9270 tt.Form(tf.Data(),h3->GetMean(3));
9271 stats->AddText(tt.Data());
9272 } else {
9273 tf.Form("%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
9274 ,"%",stats->GetStatFormat());
9275 tt.Form(tf.Data(),h3->GetMean(1),h3->GetMeanError(1));
9276 stats->AddText(tt.Data());
9277 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
9278 ,"%",stats->GetStatFormat());
9279 tt.Form(tf.Data(),h3->GetMean(2),h3->GetMeanError(2));
9280 stats->AddText(tt.Data());
9281 tf.Form("%s = %s%s #pm %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat()
9282 ,"%",stats->GetStatFormat());
9283 tt.Form(tf.Data(),h3->GetMean(3),h3->GetMeanError(3));
9284 stats->AddText(tt.Data());
9285 }
9286 }
9287 if (print_stddev) {
9288 if (print_stddev == 1) {
9289 tf.Form("%s = %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat());
9290 tt.Form(tf.Data(),h3->GetStdDev(1));
9291 stats->AddText(tt.Data());
9292 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
9293 tt.Form(tf.Data(),h3->GetStdDev(2));
9294 stats->AddText(tt.Data());
9295 tf.Form("%s = %s%s",gStringStdDevZ.Data(),"%",stats->GetStatFormat());
9296 tt.Form(tf.Data(),h3->GetStdDev(3));
9297 stats->AddText(tt.Data());
9298 } else {
9299 tf.Form("%s = %s%s #pm %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat()
9300 ,"%",stats->GetStatFormat());
9301 tt.Form(tf.Data(),h3->GetStdDev(1),h3->GetStdDevError(1));
9302 stats->AddText(tt.Data());
9303 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
9304 ,"%",stats->GetStatFormat());
9305 tt.Form(tf.Data(),h3->GetStdDev(2),h3->GetStdDevError(2));
9306 stats->AddText(tt.Data());
9307 tf.Form("%s = %s%s #pm %s%s",gStringStdDevZ.Data(),"%",stats->GetStatFormat()
9308 ,"%",stats->GetStatFormat());
9309 tt.Form(tf.Data(),h3->GetStdDev(3),h3->GetStdDevError(3));
9310 stats->AddText(tt.Data());
9311 }
9312 }
9313 if (print_integral) {
9314 tt.Form("%s = %6.4g",gStringIntegral.Data(),h3->Integral());
9315 stats->AddText(tt.Data());
9316 }
9317 if (print_skew) {
9318 if (print_skew == 1) {
9319 tf.Form("%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
9320 tt.Form(tf.Data(),h3->GetSkewness(1));
9321 stats->AddText(tt.Data());
9322 tf.Form("%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
9323 tt.Form(tf.Data(),h3->GetSkewness(2));
9324 stats->AddText(tt.Data());
9325 tf.Form("%s = %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat());
9326 tt.Form(tf.Data(),h3->GetSkewness(3));
9327 stats->AddText(tt.Data());
9328 } else {
9329 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
9330 ,"%",stats->GetStatFormat());
9331 tt.Form(tf.Data(),h3->GetSkewness(1),h3->GetSkewness(11));
9332 stats->AddText(tt.Data());
9333 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
9334 ,"%",stats->GetStatFormat());
9335 tt.Form(tf.Data(),h3->GetSkewness(2),h3->GetSkewness(12));
9336 stats->AddText(tt.Data());
9337 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat()
9338 ,"%",stats->GetStatFormat());
9339 tt.Form(tf.Data(),h3->GetSkewness(3),h3->GetSkewness(13));
9340 stats->AddText(tt.Data());
9341 }
9342 }
9343 if (print_kurt) {
9344 if (print_kurt == 1) {
9345 tf.Form("%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
9346 tt.Form(tf.Data(),h3->GetKurtosis(1));
9347 stats->AddText(tt.Data());
9348 tf.Form("%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
9349 tt.Form(tf.Data(),h3->GetKurtosis(2));
9350 stats->AddText(tt.Data());
9351 tf.Form("%s = %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat());
9352 tt.Form(tf.Data(),h3->GetKurtosis(3));
9353 stats->AddText(tt.Data());
9354 } else {
9355 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
9356 ,"%",stats->GetStatFormat());
9357 tt.Form(tf.Data(),h3->GetKurtosis(1),h3->GetKurtosis(11));
9358 stats->AddText(tt.Data());
9359 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
9360 ,"%",stats->GetStatFormat());
9361 tt.Form(tf.Data(),h3->GetKurtosis(2),h3->GetKurtosis(12));
9362 stats->AddText(tt.Data());
9363 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat()
9364 ,"%",stats->GetStatFormat());
9365 tt.Form(tf.Data(),h3->GetKurtosis(3),h3->GetKurtosis(13));
9366 stats->AddText(tt.Data());
9367 }
9368 }
9369 if (print_under || print_over) {
9370 // no underflow - overflow printing for a 3D histogram
9371 // one would need a 3D table
9372 }
9373
9374 // Draw Fit parameters
9375 if (fit) {
9376 Int_t ndf = fit->GetNDF();
9377 tt.Form("#chi^{2} / ndf = %6.4g / %d",fit->GetChisquare(),ndf);
9378 stats->AddText(tt.Data());
9379 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
9380 tt.Form("%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
9381 ,fit->GetParameter(ipar)
9382 ,fit->GetParError(ipar));
9383 stats->AddText(tt.Data());
9384 }
9385 }
9386
9387 if (!done) fFunctions->Add(stats);
9388 stats->Paint(stats->GetOption());
9389}
9390
9391////////////////////////////////////////////////////////////////////////////////
9392/// [Control function to draw a 2D histogram as a surface plot.](\ref HP18)
9393
9395{
9396
9397 const Double_t ydiff = 1;
9398 const Double_t yligh1 = 10;
9399 const Double_t qa = 0.15;
9400 const Double_t qd = 0.15;
9401 const Double_t qs = 0.8;
9402 Double_t fmin, fmax;
9403 Int_t raster = 0;
9404 Int_t irep = 0;
9405
9406 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
9409 Double_t zmin = Hparam.zmin;
9410 Double_t zmax = Hparam.zmax;
9411 Double_t xlab1 = Hparam.xmin;
9412 Double_t xlab2 = Hparam.xmax;
9413 Double_t ylab1 = Hparam.ymin;
9414 Double_t ylab2 = Hparam.ymax;
9415 Double_t dangle = 10*3.141592/180; //Delta angle for Rapidity option
9416 Double_t deltaz = TMath::Abs(zmin);
9417 if (deltaz == 0) deltaz = 1;
9418 if (zmin >= zmax) {
9419 zmin -= 0.5*deltaz;
9420 zmax += 0.5*deltaz;
9421 }
9422 Double_t z1c = zmin;
9423 Double_t z2c = zmin + (zmax-zmin)*(1+gStyle->GetHistTopMargin());
9424 // Compute the lego limits and instantiate a lego object
9425 fXbuf[0] = -1;
9426 fYbuf[0] = 1;
9427 fXbuf[1] = -1;
9428 fYbuf[1] = 1;
9429 if (Hoption.System >= kPOLAR && (Hoption.Surf == 1 || Hoption.Surf == 13)) raster = 1;
9430 if (Hoption.System == kPOLAR) {
9431 fXbuf[2] = z1c;
9432 fYbuf[2] = z2c;
9433 } else if (Hoption.System == kCYLINDRICAL) {
9434 if (Hoption.Logy) {
9435 if (ylab1 > 0) fXbuf[2] = TMath::Log10(ylab1);
9436 else fXbuf[2] = 0;
9437 if (ylab2 > 0) fYbuf[2] = TMath::Log10(ylab2);
9438 else fYbuf[2] = 0;
9439 } else {
9440 fXbuf[2] = ylab1;
9441 fYbuf[2] = ylab2;
9442 }
9443 z1c = 0; z2c = 1;
9444 } else if (Hoption.System == kSPHERICAL) {
9445 fXbuf[2] = -1;
9446 fYbuf[2] = 1;
9447 z1c = 0; z2c = 1;
9448 } else if (Hoption.System == kRAPIDITY) {
9449 fXbuf[2] = -1/TMath::Tan(dangle);
9450 fYbuf[2] = 1/TMath::Tan(dangle);
9451 } else {
9452 fXbuf[0] = xlab1;
9453 fYbuf[0] = xlab2;
9454 fXbuf[1] = ylab1;
9455 fYbuf[1] = ylab2;
9456 fXbuf[2] = z1c;
9457 fYbuf[2] = z2c;
9458 }
9459
9460 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data(), Hoption.System);
9461 fLego->SetEdgeAtt(fH->GetLineColor(),fH->GetLineStyle(),fH->GetLineWidth(),0);
9462 fLego->SetFillColor(fH->GetFillColor());
9463
9464 // Initialize the levels on the Z axis
9465 Int_t ndiv = fH->GetContour();
9466 if (ndiv == 0 ) {
9467 ndiv = gStyle->GetNumberContours();
9468 fH->SetContour(ndiv);
9469 }
9470 Int_t ndivz = TMath::Abs(ndiv);
9471 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
9472
9473 if (Hoption.Surf == 13 || Hoption.Surf == 15) fLego->SetMesh(3);
9474 if (Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) fLego->SetMesh(0);
9475
9476 // Close the surface in case of non cartesian coordinates.
9477
9478 if (Hoption.System != kCARTESIAN) {nx++; ny++;}
9479
9480 // Now ready to draw the surface plot
9481
9482 TView *view = gPad ? gPad->GetView() : nullptr;
9483 if (!view) {
9484 Error("PaintSurface", "no TView in current pad");
9485 return;
9486 }
9487
9488 Double_t thedeg = 90 - gPad->GetTheta();
9489 Double_t phideg = -90 - gPad->GetPhi();
9490 Double_t psideg = view->GetPsi();
9491 view->SetView(phideg, thedeg, psideg, irep);
9492
9493 // Set color/style for back box
9494 if (Hoption.Same) {
9495 fLego->SetFillStyle(0);
9496 fLego->SetFillColor(1);
9497 } else {
9498 fLego->SetFillStyle(gPad->GetFrameFillStyle());
9499 fLego->SetFillColor(gPad->GetFrameFillColor());
9500 }
9501 fLego->TAttFill::Modify();
9502
9503 Int_t backcolor = gPad->GetFrameFillColor();
9504 if (Hoption.System != kCARTESIAN) backcolor = 0;
9505 view->PadRange(backcolor);
9506
9507 fLego->SetFillStyle(fH->GetFillStyle());
9508 fLego->SetFillColor(fH->GetFillColor());
9509 fLego->TAttFill::Modify();
9510
9511 // Draw the filled contour on top
9512 Int_t icol1 = fH->GetFillColor();
9513
9514 Int_t hoption35 = Hoption.Surf;
9515 if (Hoption.Surf == 13 || Hoption.Surf == 15) {
9516 DefineColorLevels(ndivz);
9517 Hoption.Surf = 23;
9518 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9520 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"BF");
9521 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9522 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9523 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9524 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"BF");
9525 Hoption.Surf = hoption35;
9526 fLego->SetMesh(1);
9527 }
9528
9529 if (raster) fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
9530 else fLego->InitMoveScreen(-1.1,1.1);
9531
9532 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) {
9533 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9536 fLego->BackBox(90);
9537 }
9538 }
9539
9540 // Gouraud Shading surface
9541 if (Hoption.Surf == 14) {
9542 // Set light sources
9543 fLego->LightSource(0, ydiff, 0,0,0,irep);
9544 fLego->LightSource(1, yligh1 ,1,1,1,irep);
9545 fLego->SurfaceProperty(qa, qd, qs, 1, irep);
9546 fmin = ydiff*qa;
9547 fmax = fmin + (yligh1+0.1)*(qd+qs);
9548 Int_t nbcol = 28;
9549 icol1 = 201;
9550 Double_t dcol = 0.5/Double_t(nbcol);
9551 TColor *colref = gROOT->GetColor(fH->GetFillColor());
9552 if (!colref) return;
9553 Float_t r,g,b,hue,light,satur;
9554 colref->GetRGB(r,g,b);
9555 TColor::RGBtoHLS(r,g,b,hue,light,satur);
9556 TColor *acol;
9557 for (Int_t col=0;col<nbcol;col++) {
9558 acol = gROOT->GetColor(col+icol1);
9559 TColor::HLStoRGB(hue,.4+col*dcol,satur,r,g,b);
9560 if (acol) acol->SetRGB(r,g,b);
9561 }
9562 fLego->Spectrum(nbcol, fmin, fmax, icol1, 1, irep);
9563 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::GouraudFunction);
9565 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"BF");
9566 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9567 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9568 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9569 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"BF");
9570 } else if (Hoption.Surf == 15) {
9571 // The surface is not drawn in this case.
9572 } else {
9573 // Draw the surface
9574 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 16 || Hoption.Surf == 17) {
9575 DefineColorLevels(ndivz);
9576 } else {
9577 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9578 }
9579 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9580 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceRaster1);
9581 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode2);
9582 if (Hoption.System == kPOLAR) {
9583 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfacePolar(1,nx,ny,"FB");
9584 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfacePolar(1,nx,ny,"BF");
9585 } else if (Hoption.System == kCYLINDRICAL) {
9586 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceCylindrical(1,nx,ny,"FB");
9587 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9588 } else if (Hoption.System == kSPHERICAL) {
9589 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceSpherical(0,1,nx,ny,"FB");
9590 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9591 } else if (Hoption.System == kRAPIDITY) {
9592 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceSpherical(1,1,nx,ny,"FB");
9593 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9594 } else {
9595 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove1);
9596 if (Hoption.Surf == 16) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove3);
9597 if (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16) fLego->SurfaceCartesian(90,nx,ny,"FB");
9598 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCartesian(90,nx,ny,"BF");
9599 }
9600 }
9601
9602 // Paint the line contour on top for option SURF7
9603 if (Hoption.Surf == 17) {
9604 fLego->InitMoveScreen(-1.1,1.1);
9605 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9606 Hoption.Surf = 23;
9607 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9609 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"FB");
9610 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"FB");
9611 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"FB");
9612 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"FB");
9613 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"FB");
9614 }
9615
9616 if ((!Hoption.Same) &&
9617 (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16)) {
9620 fLego->BackBox(90);
9621 }
9622 }
9623 if (Hoption.System == kCARTESIAN) {
9624 fLego->InitMoveScreen(-1.1,1.1);
9626 if (Hoption.FrontBox) fLego->FrontBox(90);
9627 }
9628 if (!Hoption.Axis && !Hoption.Same) {
9629 TGaxis axis;
9630 PaintLegoAxis(&axis, 90);
9631 }
9632
9634
9635 fLego.reset();
9636}
9637
9638////////////////////////////////////////////////////////////////////////////////
9639/// Control function to draw a table using Delaunay triangles.
9640
9642{
9643
9644 TGraphDelaunay2D *dt = nullptr;
9645 TGraphDelaunay *dtOld = nullptr;
9646
9647 // Check if fH contains a TGraphDelaunay2D
9648 TList *hl = fH->GetListOfFunctions();
9649 dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
9650 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
9651 if (!dt && !dtOld) return;
9652
9653 // If needed, create a TGraph2DPainter
9654 if (!fGraph2DPainter)
9655 fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
9656
9657 // Define the 3D view
9658 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
9659 if (Hoption.Same) {
9660 TView *viewsame = gPad ? gPad->GetView() : nullptr;
9661 if (!viewsame) {
9662 Error("PaintTriangles", "no TView in current pad, do not use option SAME");
9663 return;
9664 }
9665 Double_t *rmin = viewsame->GetRmin();
9666 Double_t *rmax = viewsame->GetRmax();
9667 if (!rmin || !rmax) return;
9668 fXbuf[0] = rmin[0];
9669 fYbuf[0] = rmax[0];
9670 fXbuf[1] = rmin[1];
9671 fYbuf[1] = rmax[1];
9672 fXbuf[2] = rmin[2];
9673 fYbuf[2] = rmax[2];
9674 fH->SetMaximum(rmax[2]);
9675 fH->SetMinimum(rmin[2]);
9676 fH->GetXaxis()->SetRangeUser(rmin[0],rmax[0]);
9677 fH->GetYaxis()->SetRangeUser(rmin[1],rmax[1]);
9678 } else {
9679 fXbuf[0] = Hparam.xmin;
9680 fYbuf[0] = Hparam.xmax;
9681 fXbuf[1] = Hparam.ymin;
9682 fYbuf[1] = Hparam.ymax;
9683 fXbuf[2] = Hparam.zmin;
9684 fYbuf[2] = Hparam.zmax;
9685 }
9686
9687 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
9688 TView *view = gPad ? gPad->GetView() : nullptr;
9689 if (!view) {
9690 Error("PaintTriangles", "no TView in current pad");
9691 return;
9692 }
9693 Double_t thedeg = 90 - gPad->GetTheta();
9694 Double_t phideg = -90 - gPad->GetPhi();
9695 Double_t psideg = view->GetPsi();
9696 Int_t irep;
9697 view->SetView(phideg, thedeg, psideg, irep);
9698
9699 // Set color/style for back box
9700 fLego->SetFillStyle(gPad->GetFrameFillStyle());
9701 fLego->SetFillColor(gPad->GetFrameFillColor());
9702 fLego->TAttFill::Modify();
9703 Int_t backcolor = gPad->GetFrameFillColor();
9704 if (Hoption.System != kCARTESIAN) backcolor = 0;
9705 view->PadRange(backcolor);
9706 fLego->SetFillStyle(fH->GetFillStyle());
9707 fLego->SetFillColor(fH->GetFillColor());
9708 fLego->TAttFill::Modify();
9709
9710 // Paint the Back Box if needed
9711 if (Hoption.BackBox && !Hoption.Same) {
9712 fLego->InitMoveScreen(-1.1,1.1);
9713 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9715 fLego->BackBox(90);
9716 }
9717
9718 // Paint the triangles
9719 fGraph2DPainter->Paint(option);
9720
9721 // Paint the Front Box if needed
9722 if (Hoption.FrontBox) {
9723 fLego->InitMoveScreen(-1.1,1.1);
9725 fLego->FrontBox(90);
9726 }
9727
9728 // Paint the Axis if needed
9729 if (!Hoption.Axis && !Hoption.Same) {
9730 TGaxis axis;
9731 PaintLegoAxis(&axis, 90);
9732 }
9733
9735
9736 fLego.reset();
9737}
9738
9739////////////////////////////////////////////////////////////////////////////////
9740/// Define the color levels used to paint legos, surfaces etc..
9741
9743{
9744
9745 Int_t i, irep;
9746
9747 // Initialize the color levels
9748 if (ndivz >= 100) {
9749 Warning("PaintSurface", "too many color levels, %d >= 100, reset to 99", ndivz);
9750 ndivz = 99;
9751 }
9752 std::vector<Double_t> funlevel(ndivz+1);
9753 std::vector<Int_t> colorlevel(ndivz+1);
9754 Int_t theColor;
9755 Int_t ncolors = gStyle->GetNumberOfColors();
9756 for (i = 0; i < ndivz; ++i) {
9757 funlevel[i] = fH->GetContourLevelPad(i);
9758 theColor = Int_t((i+0.99)*Float_t(ncolors)/Float_t(ndivz));
9759 colorlevel[i] = gStyle->GetColorPalette(theColor);
9760 }
9761 colorlevel[ndivz] = gStyle->GetColorPalette(ncolors-1);
9762 fLego->ColorFunction(ndivz, funlevel.data(), colorlevel.data(), irep);
9763}
9764
9765////////////////////////////////////////////////////////////////////////////////
9766/// [Control function to draw 2D/3D histograms (tables).](\ref HP01c)
9767
9769{
9770
9771 // Fill Hparam structure with histo parameters
9772 if (!TableInit()) return;
9773
9774 // Draw histogram frame
9775 PaintFrame();
9776
9777 // If palette option not specified, delete a possible existing palette
9778 if (!Hoption.Zscale) {
9779 TObject *palette = fFunctions->FindObject("palette");
9780 if (palette) { fFunctions->Remove(palette); delete palette;}
9781 }
9782
9783 // Do not draw the histogram. Only the attached functions will be drawn.
9784 if (Hoption.Func == 2) {
9785 if (Hoption.Zscale) {
9786 Int_t ndiv = fH->GetContour();
9787 if (ndiv == 0 ) {
9788 ndiv = gStyle->GetNumberContours();
9789 fH->SetContour(ndiv);
9790 }
9791 PaintPalette();
9792 }
9793
9794 // Draw the histogram according to the option
9795 } else {
9796 if (fH->InheritsFrom(TH2Poly::Class()) && Hoption.Axis<=0) {
9797 if (Hoption.Fill) PaintTH2PolyBins("f");
9801 if (Hoption.Line) PaintTH2PolyBins("l");
9802 if (Hoption.Mark) PaintTH2PolyBins("P");
9803 } else if (Hoption.Axis<=0) {
9807 if (Hoption.Color) {
9810 }
9813 if (Hoption.Error >= 100) Paint2DErrors(option);
9815 }
9819 }
9820
9821 // Draw histogram title
9822 PaintTitle();
9823
9824 // Draw the axes
9825 if (!Hoption.Lego && !Hoption.Surf &&
9826 !Hoption.Tri && !(Hoption.Error >= 100)) PaintAxis(kFALSE);
9827
9828 TF1 *fit = nullptr;
9829 TIter next(fFunctions);
9830 while (auto obj = next()) {
9831 if (obj->InheritsFrom(TF1::Class())) {
9832 fit = (TF1*)obj;
9833 break;
9834 }
9835 }
9836 if ((Hoption.Same%10) != 1) {
9837 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
9838 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
9839 //ALWAYS executed on non-iOS platform.
9840 //On iOS, depends on mode.
9842 }
9843 }
9844 }
9845}
9846
9847////////////////////////////////////////////////////////////////////////////////
9848/// Control function to draw a TH2Poly bins' contours.
9849///
9850/// - option = "F" draw the bins as filled areas.
9851/// - option = "L" draw the bins as line.
9852/// - option = "P" draw the bins as markers.
9853
9855{
9856
9857 //Do not highlight the histogram, if its part was picked.
9858 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH) return;
9859
9860 TString opt = option;
9861 opt.ToLower();
9862 Bool_t line = kFALSE;
9863 Bool_t fill = kFALSE;
9864 Bool_t mark = kFALSE;
9865 if (opt.Contains("l")) line = kTRUE;
9866 if (opt.Contains("f")) fill = kTRUE;
9867 if (opt.Contains("p")) mark = kTRUE;
9868
9869 TH2PolyBin *b;
9870 Double_t z;
9871
9872 TIter next(((TH2Poly*)fH)->GetBins());
9873 TObject *obj, *poly;
9874
9875 while ((obj=next())) {
9876 b = (TH2PolyBin*)obj;
9877 z = b->GetContent();
9878 if (z==0 && Hoption.Zero) continue; // Do not draw empty bins in case of option "COL0 L"
9879 poly = b->GetPolygon();
9880
9881 // Paint the TGraph bins.
9882 if (poly->IsA() == TGraph::Class()) {
9883 TGraph *g = (TGraph*)poly;
9884 g->TAttLine::Modify();
9885 g->TAttMarker::Modify();
9886 g->TAttFill::Modify();
9887 if (line) {
9888 Int_t fs = g->GetFillStyle();
9889 Int_t db = gStyle->GetDrawBorder();
9890 g->SetFillStyle(0);
9892 g->Paint("F");
9893 gStyle->SetDrawBorder(db);
9894 g->SetFillStyle(fs);
9895 }
9896 if (fill) g->Paint("F");
9897 if (mark) g->Paint("P");
9898 }
9899
9900 // Paint the TMultiGraph bins.
9901 if (poly->IsA() == TMultiGraph::Class()) {
9902 TMultiGraph *mg = (TMultiGraph*)poly;
9903 TList *gl = mg->GetListOfGraphs();
9904 if (!gl) return;
9905 TGraph *g;
9906 TIter nextg(gl);
9907 while ((g = (TGraph*) nextg())) {
9908 g->TAttLine::Modify();
9909 g->TAttMarker::Modify();
9910 g->TAttFill::Modify();
9911 if (line) {
9912 Int_t fs = g->GetFillStyle();
9913 Int_t db = gStyle->GetDrawBorder();
9914 g->SetFillStyle(0);
9916 g->Paint("F");
9917 gStyle->SetDrawBorder(db);
9918 g->SetFillStyle(fs);
9919 }
9920 if (fill) g->Paint("F");
9921 if (mark) g->Paint("P");
9922 }
9923 }
9924 }
9925}
9926
9927////////////////////////////////////////////////////////////////////////////////
9928/// [Control function to draw a TH2Poly as a color plot.](\ref HP20a)
9929
9931{
9932
9933 //Do not highlight the histogram, if its part was picked.
9934 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
9935 return;
9936
9937 Int_t ncolors, color, theColor;
9938 Double_t z, zc;
9939 Double_t zmin = fH->GetMinimum();
9940 Double_t zmax = fH->GetMaximum();
9941 if (Hoption.Logz) {
9942 if (zmax > 0) {
9943 if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
9944 zmin = TMath::Log10(zmin);
9945 zmax = TMath::Log10(zmax);
9946 } else {
9947 return;
9948 }
9949 }
9950 Double_t dz = zmax - zmin;
9951
9952 // Initialize the levels on the Z axis
9953 ncolors = gStyle->GetNumberOfColors();
9954 Int_t ndiv = fH->GetContour();
9955 if (ndiv == 0 ) {
9956 ndiv = gStyle->GetNumberContours();
9957 fH->SetContour(ndiv);
9958 }
9959 Int_t ndivz = TMath::Abs(ndiv);
9960 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
9961 Double_t scale = ndivz/dz;
9962
9963 TIter next(((TH2Poly*)fH)->GetBins());
9964
9965 while (auto obj = next()) {
9966 TH2PolyBin *b = (TH2PolyBin*)obj;
9967 TObject *poly = b->GetPolygon();
9968
9969 z = b->GetContent();
9970 if (z==0 && Hoption.Zero) continue;
9971 if (Hoption.Logz) {
9972 if (z > 0) z = TMath::Log10(z);
9973 else z = zmin;
9974 }
9975 if (z < zmin) continue;
9976
9977 // Define the bin color.
9979 zc = fH->GetContourLevelPad(0);
9980 if (z < zc) continue;
9981 color = -1;
9982 for (Int_t k=0; k<ndiv; k++) {
9983 zc = fH->GetContourLevelPad(k);
9984 if (z < zc) {
9985 continue;
9986 } else {
9987 color++;
9988 }
9989 }
9990 } else {
9991 color = Int_t(0.01+(z-zmin)*scale);
9992 }
9993 theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
9994 if (theColor > ncolors-1) theColor = ncolors-1;
9995
9996 auto rootColor = gStyle->GetColorPalette(theColor);
9997
9998 // Paint the TGraph bins.
9999 if (poly->IsA() == TGraph::Class()) {
10000 TGraph *g = (TGraph*)poly;
10001 auto origin = g->GetFillColor();
10002 g->SetFillColor(rootColor);
10003 g->TAttFill::Modify();
10004 g->Paint("F");
10005 g->SetFillColor(origin);
10006 }
10007
10008 // Paint the TMultiGraph bins.
10009 if (poly->IsA() == TMultiGraph::Class()) {
10010 TMultiGraph *mg = (TMultiGraph*)poly;
10011 TIter nextg(mg->GetListOfGraphs());
10012 while (auto g = (TGraph*) nextg()) {
10013 auto origin = g->GetFillColor();
10014 g->SetFillColor(rootColor);
10015 g->TAttFill::Modify();
10016 g->Paint("F");
10017 g->SetFillColor(origin);
10018 }
10019 }
10020 }
10022}
10023
10024////////////////////////////////////////////////////////////////////////////////
10025/// [Control function to draw a TH2Poly as a scatter plot.](\ref HP20a)
10026
10028{
10029
10030 //Do not highlight the histogram, if its part was selected.
10031 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
10032 return;
10033
10034 Int_t k, loop, marker=0;
10035 Double_t z, xk,xstep, yk, ystep, xp, yp;
10036 Double_t scale = 1;
10037 Double_t zmin = fH->GetMinimum();
10038 Double_t zmax = fH->GetMaximum();
10039 if (Hoption.Logz) {
10040 if (zmax > 0) {
10041 if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
10042 zmin = TMath::Log10(zmin);
10043 zmax = TMath::Log10(zmax);
10044 } else {
10045 return;
10046 }
10047 }
10048 Double_t dz = zmax - zmin;
10049 scale = (kNMAX-1)/dz;
10050
10051
10052 // use an independent instance of a random generator
10053 // instead of gRandom to avoid conflicts and
10054 // to get same random numbers when drawing the same histogram
10055 TRandom2 random;
10056
10057 TH2PolyBin *b;
10058
10059 TIter next(((TH2Poly*)fH)->GetBins());
10060 TObject *obj, *poly;
10061
10062 Double_t maxarea = 0, a;
10063 while ((obj=next())) {
10064 b = (TH2PolyBin*)obj;
10065 a = b->GetArea();
10066 if (a>maxarea) maxarea = a;
10067 }
10068
10069 next.Reset();
10070
10071 while ((obj=next())) {
10072 b = (TH2PolyBin*)obj;
10073 poly = b->GetPolygon();
10074 z = b->GetContent();
10075 if (z < zmin) z = zmin;
10076 if (z > zmax) z = zmax;
10077 if (Hoption.Logz) {
10078 if (z > 0) z = TMath::Log10(z) - zmin;
10079 } else {
10080 z -= zmin;
10081 }
10082 k = Int_t((z*scale)*(b->GetArea()/maxarea));
10083 xk = b->GetXMin();
10084 yk = b->GetYMin();
10085 xstep = b->GetXMax()-xk;
10086 ystep = b->GetYMax()-yk;
10087
10088 // Paint the TGraph bins.
10089 if (poly->IsA() == TGraph::Class()) {
10090 TGraph *g = (TGraph*)poly;
10091 if (k <= 0 || z <= 0) continue;
10092 loop = 0;
10093 while (loop<k) {
10094 if (k+marker >= kNMAX) {
10095 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10096 marker=0;
10097 }
10098 xp = (random.Rndm()*xstep) + xk;
10099 yp = (random.Rndm()*ystep) + yk;
10100 if (g->IsInside(xp,yp)) {
10101 fXbuf[marker] = xp;
10102 fYbuf[marker] = yp;
10103 marker++;
10104 loop++;
10105 }
10106 }
10107 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10108 }
10109
10110 // Paint the TMultiGraph bins.
10111 if (poly->IsA() == TMultiGraph::Class()) {
10112 TMultiGraph *mg = (TMultiGraph*)poly;
10113 TList *gl = mg->GetListOfGraphs();
10114 if (!gl) return;
10115 if (k <= 0 || z <= 0) continue;
10116 loop = 0;
10117 while (loop<k) {
10118 if (k+marker >= kNMAX) {
10119 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10120 marker=0;
10121 }
10122 xp = (random.Rndm()*xstep) + xk;
10123 yp = (random.Rndm()*ystep) + yk;
10124 if (mg->IsInside(xp,yp)) {
10125 fXbuf[marker] = xp;
10126 fYbuf[marker] = yp;
10127 marker++;
10128 loop++;
10129 }
10130 }
10131 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10132 }
10133 }
10134 PaintTH2PolyBins("l");
10135}
10136
10137////////////////////////////////////////////////////////////////////////////////
10138/// [Control function to draw a TH2Poly as a text plot.](\ref HP20a)
10139
10141{
10142
10143 TLatex text;
10144 text.SetTextFont(gStyle->GetTextFont());
10145 text.SetTextColor(fH->GetMarkerColor());
10146 text.SetTextSize(0.02*fH->GetMarkerSize());
10147
10148 Double_t x, y, z, e, angle = 0;
10149 TString tt, tf;
10150 tf.Form("%s%s","%",gStyle->GetPaintTextFormat());
10151 if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
10152 Int_t opt = (Int_t)Hoption.Text/1000;
10153
10154 text.SetTextAlign(22);
10155 if (Hoption.Text == 1) angle = 0;
10156 text.SetTextAngle(angle);
10157 text.TAttText::Modify();
10158
10159 TH2PolyBin *b;
10160
10161 TIter next(((TH2Poly*)fH)->GetBins());
10162 TObject *obj, *p;
10163
10164 while ((obj=next())) {
10165 b = (TH2PolyBin*)obj;
10166 p = b->GetPolygon();
10167 x = (b->GetXMin()+b->GetXMax())/2;
10168 if (Hoption.Logx) {
10169 if (x > 0) x = TMath::Log10(x);
10170 else continue;
10171 }
10172 y = (b->GetYMin()+b->GetYMax())/2;
10173 if (Hoption.Logy) {
10174 if (y > 0) y = TMath::Log10(y);
10175 else continue;
10176 }
10177 z = b->GetContent();
10178 if (z < fH->GetMinimum() || (z == 0 && !Hoption.MinimumZero)) continue;
10179 if (opt==2) {
10180 e = fH->GetBinError(b->GetBinNumber());
10181 tf.Form("#splitline{%s%s}{#pm %s%s}",
10183 "%",gStyle->GetPaintTextFormat());
10184 tt.Form(tf.Data(),z,e);
10185 } else {
10186 tt.Form(tf.Data(),z);
10187 }
10188 if (opt==3) text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),p->GetName());
10189 else text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),tt.Data());
10190 }
10191
10192 PaintTH2PolyBins("l");
10193}
10194
10195////////////////////////////////////////////////////////////////////////////////
10196/// [Control function to draw a 1D/2D histograms with the bin values.](\ref HP15)
10197
10199{
10200
10201 TLatex text;
10202 text.SetTextFont(((int)gStyle->GetTextFont()/10)*10+2); // font precision must be 2
10203 text.SetTextColor(fH->GetMarkerColor());
10204 text.SetTextSize(0.02*fH->GetMarkerSize());
10205
10206 Double_t x, y, z, e, angle = 0;
10207 TString tt, tf;
10208 tf.Form("%s%s","%",gStyle->GetPaintTextFormat());
10209 if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
10210
10211 // 1D histograms
10212 if (fH->GetDimension() == 1) {
10213 Bool_t getentries = kFALSE;
10214 Double_t yt;
10215 TProfile *hp = (TProfile*)fH;
10216 if (Hoption.Text>2000 && fH->InheritsFrom(TProfile::Class())) {
10217 Hoption.Text = Hoption.Text-2000;
10218 getentries = kTRUE;
10219 }
10220 if (Hoption.Text == 1) angle = 90;
10221 text.SetTextAlign(11);
10222 if (angle == 90) text.SetTextAlign(12);
10223 if (angle == 0) text.SetTextAlign(21);
10224 text.TAttText::Modify();
10225 Double_t dt = 0.02*(gPad->GetY2()-gPad->GetY1());
10226 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10227 if (Hoption.Bar) {
10228 x = fH->GetXaxis()->GetBinLowEdge(i)+
10229 fH->GetXaxis()->GetBinWidth(i)*
10230 (fH->GetBarOffset()+0.5*fH->GetBarWidth());
10231 } else {
10232 x = fH->GetXaxis()->GetBinCenter(i);
10233 }
10234 y = fH->GetBinContent(i);
10235 yt = y;
10236 if (Hoption.MinimumZero && y<0) y = 0;
10237 if (getentries) yt = hp->GetBinEntries(i);
10238 if (yt == 0.) continue;
10239 tt.Form(tf.Data(),yt);
10240 if (Hoption.Logx) {
10241 if (x > 0) x = TMath::Log10(x);
10242 else continue;
10243 }
10244 if (Hoption.Logy) {
10245 if (y > 0) y = TMath::Log10(y);
10246 else continue;
10247 }
10248 if (y >= gPad->GetY2()) continue;
10249 if (y <= gPad->GetY1()) continue;
10250 text.PaintLatex(x,y+0.2*dt,angle,0.02*fH->GetMarkerSize(),tt.Data());
10251 }
10252
10253 // 2D histograms
10254 } else {
10255 Double_t zmin = Hparam.zmin;
10256 if (Hoption.Logz) zmin = TMath::Power(10,Hparam.zmin);
10257
10258 text.SetTextAlign(22);
10259 if (Hoption.Text == 1) angle = 0;
10260 text.SetTextAngle(angle);
10261 text.TAttText::Modify();
10262 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
10263 y = fYaxis->GetBinCenter(j);
10264 if (Hoption.Logy) {
10265 if (y > 0) y = TMath::Log10(y);
10266 else continue;
10267 }
10268 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10269 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
10270 x = fXaxis->GetBinCenter(i);
10271 if (Hoption.Logx) {
10272 if (x > 0) x = TMath::Log10(x);
10273 else continue;
10274 }
10275 if (!IsInside(x,y)) continue;
10276 z = fH->GetBinContent(bin);
10277 if (z < zmin || (z == 0 && !Hoption.MinimumZero)) continue;
10278 if (Hoption.Text>2000) {
10279 e = fH->GetBinError(bin);
10280 tf.Form("#splitline{%s%s}{#pm %s%s}",
10282 "%",gStyle->GetPaintTextFormat());
10283 tt.Form(tf.Data(),z,e);
10284 } else {
10285 tt.Form(tf.Data(),z);
10286 }
10287 text.PaintLatex(x,y+fH->GetBarOffset()*fYaxis->GetBinWidth(j),
10288 angle,0.02*fH->GetMarkerSize(),tt.Data());
10289 }
10290 }
10291 }
10292}
10293
10294////////////////////////////////////////////////////////////////////////////////
10295/// [Control function to draw a 3D implicit functions.](\ref HP27)
10296
10298{
10299
10300 Int_t irep;
10301
10302 TAxis *xaxis = fH->GetXaxis();
10303 TAxis *yaxis = fH->GetYaxis();
10304 TAxis *zaxis = fH->GetZaxis();
10305
10306 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
10307 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
10308 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
10309 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
10310 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
10311 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
10312
10313 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
10314
10315 TView *view = gPad ? gPad->GetView() : nullptr;
10316 if (!view) {
10317 Error("PaintTF3", "no TView in current pad");
10318 return;
10319 }
10320 Double_t thedeg = 90 - gPad->GetTheta();
10321 Double_t phideg = -90 - gPad->GetPhi();
10322 Double_t psideg = view->GetPsi();
10323 view->SetView(phideg, thedeg, psideg, irep);
10324
10325 fLego->InitMoveScreen(-1.1,1.1);
10326
10327 if (Hoption.BackBox) {
10328 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
10330 fLego->BackBox(90);
10331 }
10332
10334
10335 fLego->ImplicitFunction(fCurrentF3, fXbuf.data(), fYbuf.data(), fH->GetNbinsX(),
10336 fH->GetNbinsY(),
10337 fH->GetNbinsZ(), "BF");
10338
10339 if (Hoption.FrontBox) {
10340 fLego->InitMoveScreen(-1.1,1.1);
10342 fLego->FrontBox(90);
10343 }
10344 if (!Hoption.Axis && !Hoption.Same) {
10345 TGaxis axis;
10346 PaintLegoAxis(&axis, 90);
10347 }
10348
10349 PaintTitle();
10350
10351 fLego.reset();
10352}
10353
10354/////////////////////////////////////////////////////////////new TGaxis///////////////////
10355/// Draw the histogram title
10356///
10357/// The title is drawn according to the title alignment returned by
10358/// `GetTitleAlign()`. It is a 2 digits integer): hv
10359///
10360/// where `h` is the horizontal alignment and `v` is the
10361/// vertical alignment.
10362///
10363/// - `h` can get the values 1 2 3 for left, center, and right
10364/// - `v` can get the values 1 2 3 for bottom, middle and top
10365///
10366/// for instance the default alignment is: 13 (left top)
10367
10369{
10370 // probably best place for calls PaintHighlightBin
10371 // calls after paint histo (1D or 2D) and before paint title and stats
10372 if (!gPad->GetView()) PaintHighlightBin();
10373
10374 if (Hoption.Same) return;
10375 if (fH->TestBit(TH1::kNoTitle)) return;
10376 Int_t nt = strlen(fH->GetTitle());
10377 TPaveText *title = nullptr;
10378 TObject *obj;
10379 TIter next(gPad->GetListOfPrimitives());
10380 while ((obj = next())) {
10381 if (!obj->InheritsFrom(TPaveText::Class())) continue;
10382 title = (TPaveText*)obj;
10383 if (strcmp(title->GetName(),"title")) {title = nullptr; continue;}
10384 break;
10385 }
10386 if (nt == 0 || gStyle->GetOptTitle() <= 0) {
10387 if (title) delete title;
10388 return;
10389 }
10390 Double_t ht = gStyle->GetTitleH();
10391 Double_t wt = gStyle->GetTitleW();
10392
10393 if (ht <= 0) {
10394 if (gStyle->GetTitleFont("")%10 == 3) {
10395 Double_t hw = (Double_t) TMath::Max(gPad->GetPadWidth(), gPad->GetPadHeight());
10396 if (hw > 0)
10397 ht = 1.1 * (gStyle->GetTitleSize("")/hw);
10398 } else {
10399 ht = 1.1*gStyle->GetTitleFontSize();
10400 }
10401 }
10402 if (ht <= 0) ht = 0.05;
10403 if (wt <= 0) {
10404 TLatex l;
10405 l.SetTextSize(ht);
10406 l.SetTitle(fH->GetTitle());
10407 // adjustment in case the title has several lines (#splitline)
10408 ht = TMath::Max(ht, 1.2*l.GetYsize()/(gPad->GetY2() - gPad->GetY1()));
10409 Double_t wndc = l.GetXsize()/(gPad->GetX2() - gPad->GetX1());
10410 wt = TMath::Min(0.7, 0.02+wndc);
10411 }
10412 if (title) {
10413 TText *t0 = (TText*)title->GetLine(0);
10414 if (t0) {
10415 if (!strcmp(t0->GetTitle(),fH->GetTitle())) return;
10416 t0->SetTitle(fH->GetTitle());
10417 if (wt > 0) title->SetX2NDC(title->GetX1NDC()+wt);
10418 }
10419 return;
10420 }
10421
10422 Int_t talh = gStyle->GetTitleAlign()/10;
10423 if (talh < 1) talh = 1; else if (talh > 3) talh = 3;
10424 Int_t talv = gStyle->GetTitleAlign()%10;
10425 if (talv < 1) talv = 1; else if (talv > 3) talv = 3;
10427 xpos = gStyle->GetTitleX();
10428 ypos = gStyle->GetTitleY();
10429 if (talh == 2) xpos = xpos-wt/2.;
10430 if (talh == 3) xpos = xpos-wt;
10431 if (talv == 2) ypos = ypos+ht/2.;
10432 if (talv == 1) ypos = ypos+ht;
10433
10434 TPaveText *ptitle = new TPaveText(xpos, ypos-ht, xpos+wt, ypos,"blNDC");
10435
10436 // box with the histogram title
10438 ptitle->SetFillStyle(gStyle->GetTitleStyle());
10439 ptitle->SetName("title");
10442 ptitle->SetTextFont(gStyle->GetTitleFont(""));
10443 if (gStyle->GetTitleFont("")%10 > 2)
10445 ptitle->AddText(fH->GetTitle());
10446 ptitle->SetBit(kCanDelete);
10447 ptitle->Draw();
10448 ptitle->Paint("blNDC");
10449
10450 if(!gPad->IsEditable()) delete ptitle;
10451}
10452
10453////////////////////////////////////////////////////////////////////////////////
10454/// Process message `mess`.
10455
10456void THistPainter::ProcessMessage(const char *mess, const TObject *obj)
10457{
10458 if (!strcmp(mess,"SetF3")) {
10459 fCurrentF3 = (TF3 *)obj;
10460 }
10461}
10462
10463////////////////////////////////////////////////////////////////////////////////
10464/// Static function.
10465///
10466/// Convert Right Ascension, Declination to X,Y using an AITOFF projection.
10467/// This procedure can be used to create an all-sky map in Galactic
10468/// coordinates with an equal-area Aitoff projection. Output map
10469/// coordinates are zero longitude centered.
10470/// Also called Hammer-Aitoff projection (first presented by Ernst von Hammer in 1892)
10471///
10472/// source: GMT
10473///
10474/// code from Ernst-Jan Buis
10475
10477{
10478
10479 Double_t x, y;
10480
10481 Double_t alpha2 = (l/2)*TMath::DegToRad();
10482 Double_t delta = b*TMath::DegToRad();
10483 Double_t r2 = TMath::Sqrt(2.);
10484 Double_t f = 2*r2/TMath::Pi();
10485 Double_t cdec = TMath::Cos(delta);
10486 Double_t denom = TMath::Sqrt(1. + cdec*TMath::Cos(alpha2));
10487 x = cdec*TMath::Sin(alpha2)*2.*r2/denom;
10488 y = TMath::Sin(delta)*r2/denom;
10489 x *= TMath::RadToDeg()/f;
10490 y *= TMath::RadToDeg()/f;
10491 // x *= -1.; // for a skymap swap left<->right
10492 Al = x;
10493 Ab = y;
10494
10495 return 0;
10496}
10497
10498////////////////////////////////////////////////////////////////////////////////
10499/// Static function
10500///
10501/// Probably the most famous of the various map projections, the Mercator projection
10502/// takes its name from Mercator who presented it in 1569. It is a cylindrical, conformal projection
10503/// with no distortion along the equator.
10504/// The Mercator projection has been used extensively for world maps in which the distortion towards
10505/// the polar regions grows rather large, thus incorrectly giving the impression that, for example,
10506/// Greenland is larger than South America. In reality, the latter is about eight times the size of
10507/// Greenland. Also, the Former Soviet Union looks much bigger than Africa or South America. One may wonder
10508/// whether this illusion has had any influence on U.S. foreign policy.' (Source: GMT)
10509/// code from Ernst-Jan Buis
10510
10512{
10513
10514 Al = l;
10516 Ab = TMath::Log(aid);
10517 return 0;
10518}
10519
10520////////////////////////////////////////////////////////////////////////////////
10521/// Static function code for sinusoidal projection
10522/// from Ernst-Jan Buis
10523/// Source https://en.wikipedia.org/wiki/Sinusoidal_projection
10524
10526{
10527
10528 Al = l*cos(b*TMath::DegToRad());
10529 Ab = b;
10530 return 0;
10531}
10532
10533////////////////////////////////////////////////////////////////////////////////
10534/// Static function code for parabolic projection
10535/// from Ernst-Jan Buis
10536
10538{
10539
10540 Al = l*(2.*TMath::Cos(2*b*TMath::DegToRad()/3) - 1);
10541 Ab = 180*TMath::Sin(b*TMath::DegToRad()/3);
10542 return 0;
10543}
10544
10545////////////////////////////////////////////////////////////////////////////////
10546/// Static function.
10547///
10548/// Convert Right Ascension, Declination to X,Y using an MOLLWEIDE projection.
10549/// This procedure can be used to create an all-sky map in Galactic
10550/// coordinates with an equal-area Mollweide projection. Output map
10551/// coordinates are zero longitude centered.
10552/// It is also known as the Babinet projection, homalographic projection, homolographic projection, and elliptical projection.
10553/// Source: https://en.wikipedia.org/wiki/Mollweide_projection
10554///
10555/// code from Marco Meyer-Conde
10556
10558{
10559
10560 Double_t theta0 = b * TMath::DegToRad(), theta = theta0;
10561
10562 for (int i = 0; i < 100; i++) {
10563 Double_t num = 2 * theta + TMath::Sin(2 * theta) - TMath::Pi() * TMath::Sin(theta0);
10564 Double_t den = 4 * TMath::Power(TMath::Cos(theta), 2);
10565
10566 if (den < 1e-20) {
10567 theta = theta0;
10568 break;
10569 }
10570
10571 theta -= num / den;
10572
10573 if (TMath::Abs(num / den) < 1e-4) break;
10574 }
10575
10576 Al = l * TMath::Cos(theta);
10577 Ab = 90 * TMath::Sin(theta);
10578
10579 return 0;
10580}
10581
10582////////////////////////////////////////////////////////////////////////////////
10583/// Recompute the histogram range following graphics operations.
10584
10586{
10587
10588 if (Hoption.Same) return;
10589
10590 // Compute x,y range
10592 xmax = Hparam.xmax,
10593 ymin = Hparam.ymin,
10594 ymax = Hparam.ymax,
10595 xscale = 1;
10596
10597 std::function<Int_t(Double_t,Double_t,Double_t&,Double_t&)> func;
10598
10599 if (Hoption.Proj == 1) {
10600 func = ProjectAitoff2xy;
10601 xscale = 0.9999;
10602 } else if (Hoption.Proj == 2) {
10603 if (Hparam.ymin <= -90 || Hparam.ymax >= 90) {
10604 Warning("Mercator Projection", "Latitude out of range %f or %f", Hparam.ymin, Hparam.ymax);
10605 Hoption.Proj = 0;
10606 } else {
10609 }
10610 } else if (Hoption.Proj == 3) {
10611 func = ProjectSinusoidal2xy;
10612 } else if (Hoption.Proj == 4) {
10613 func = ProjectParabolic2xy;
10614 } else if (Hoption.Proj == 5) {
10615 func = ProjectMollweide2xy;
10616 }
10617
10618 if (func) {
10619 Double_t xmin_aid, ymin_aid, xmax_aid, ymax_aid;
10620
10621 func(Hparam.xmin, Hparam.ymin, xmin_aid, ymin_aid);
10622 func(Hparam.xmin, Hparam.ymax, xmin, ymax_aid);
10623 func(Hparam.xmax, Hparam.ymax, xmax_aid, ymax);
10624 func(Hparam.xmax, Hparam.ymin, xmax, ymin);
10625
10626 if (xmin > xmin_aid) xmin = xmin_aid;
10627 if (ymin > ymin_aid) ymin = ymin_aid;
10628 if (xmax < xmax_aid) xmax = xmax_aid;
10629 if (ymax < ymax_aid) ymax = ymax_aid;
10630 if (Hparam.ymin < 0 && Hparam.ymax > 0) {
10631 // there is an 'equator', check its range in the plot..
10632 func(Hparam.xmin*xscale, 0, xmin_aid, ymin_aid);
10633 func(Hparam.xmax*xscale, 0, xmax_aid, ymin_aid);
10634 if (xmin > xmin_aid) xmin = xmin_aid;
10635 if (xmax < xmax_aid) xmax = xmax_aid;
10636 }
10637 if (Hparam.xmin < 0 && Hparam.xmax > 0) {
10638 func(0, Hparam.ymin, xmin_aid, ymin_aid);
10639 func(0, Hparam.ymax, xmax_aid, ymax_aid);
10640 if (ymin > ymin_aid) ymin = ymin_aid;
10641 if (ymax < ymax_aid) ymax = ymax_aid;
10642 }
10643 }
10644
10645 Hparam.xmin = xmin;
10646 Hparam.xmax = xmax;
10647 Hparam.ymin = ymin;
10648 Hparam.ymax = ymax;
10649
10650 Double_t dx = xmax-xmin;
10651 Double_t dy = ymax-ymin;
10652 Double_t dxr = dx/(1 - gPad->GetLeftMargin() - gPad->GetRightMargin());
10653 Double_t dyr = dy/(1 - gPad->GetBottomMargin() - gPad->GetTopMargin());
10654
10655 // Range() could change the size of the pad pixmap and therefore should
10656 // be called before the other paint routines
10657 gPad->Range(xmin - dxr*gPad->GetLeftMargin(),
10658 ymin - dyr*gPad->GetBottomMargin(),
10659 xmax + dxr*gPad->GetRightMargin(),
10660 ymax + dyr*gPad->GetTopMargin());
10661 gPad->RangeAxis(xmin, ymin, xmax, ymax);
10662}
10663
10664////////////////////////////////////////////////////////////////////////////////
10665/// Set current histogram to `h`
10666
10668{
10669
10670 if (h == nullptr) return;
10671 fH = h;
10672 fXaxis = h->GetXaxis();
10673 fYaxis = h->GetYaxis();
10674 fZaxis = h->GetZaxis();
10676}
10677
10678////////////////////////////////////////////////////////////////////////////////
10679/// Initialize various options to draw 2D histograms.
10680
10682{
10683
10684 static const char *where = "TableInit";
10685
10686 Int_t first, last;
10687 Double_t yMARGIN= gStyle->GetHistTopMargin();
10688 Double_t zmin, zmax;
10689 Int_t maximum = 0;
10690 Int_t minimum = 0;
10691 if (fH->GetMaximumStored() != -1111) maximum = 1;
10692 if (fH->GetMinimumStored() != -1111) minimum = 1;
10693
10694 // ----------------- Compute X axis parameters
10695 first = fXaxis->GetFirst();
10696 last = fXaxis->GetLast();
10697 Hparam.xlast = last;
10698 Hparam.xfirst = first;
10703
10704 // if log scale in X, replace xmin,max by the log
10705 if (Hoption.Logx) {
10706 // find the first edge of a bin that is > 0
10707 if (Hparam.xlowedge <=0 ) {
10710 }
10711 if (Hparam.xmin <=0 || Hparam.xmax <=0) {
10712 Error(where, "cannot set X axis to log scale");
10713 return 0;
10714 }
10716 if (Hparam.xfirst < first) Hparam.xfirst = first;
10718 if (Hparam.xlast > last) Hparam.xlast = last;
10721 }
10722
10723 // ----------------- Compute Y axis parameters
10724 first = fYaxis->GetFirst();
10725 last = fYaxis->GetLast();
10726 Hparam.ylast = last;
10727 Hparam.yfirst = first;
10730 if (!Hparam.ybinsize) Hparam.ybinsize = 1;
10733
10734 // if log scale in Y, replace ymin,max by the log
10735 if (Hoption.Logy) {
10736 if (Hparam.ylowedge <=0 ) {
10739 }
10740 if (Hparam.ymin <=0 || Hparam.ymax <=0) {
10741 Error(where, "cannot set Y axis to log scale");
10742 return 0;
10743 }
10745 if (Hparam.yfirst < first) Hparam.yfirst = first;
10747 if (Hparam.ylast > last) Hparam.ylast = last;
10750 }
10751
10752
10753 // ----------------- Compute Z axis parameters
10754 Double_t bigp = TMath::Power(10,32);
10755 zmax = -bigp;
10756 zmin = bigp;
10757 Double_t c1, e1;
10758 Double_t allchan = 0;
10759 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
10760 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10761 c1 = fH->GetBinContent(i,j);
10762 zmax = TMath::Max(zmax,c1);
10763 if (Hoption.Error) {
10764 e1 = fH->GetBinError(i,j);
10765 zmax = TMath::Max(zmax,c1+e1);
10766 }
10767 zmin = TMath::Min(zmin,c1);
10768 allchan += c1;
10769 }
10770 }
10771
10772 // Take into account maximum , minimum
10773
10774 if (maximum) zmax = fH->GetMaximumStored();
10775 if (minimum) zmin = fH->GetMinimumStored();
10776 if (Hoption.Logz && zmax < 0) {
10777 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10778 return 0;
10779 } else if (Hoption.Logz && zmin>=0 && zmax==0) { // empty histogram in log scale
10780 zmin = 0.01;
10781 zmax = 10.;
10782 }
10783 if (zmin >= zmax) {
10784 if (Hoption.Logz) {
10785 if (zmax > 0) zmin = 0.001*zmax;
10786 else {
10787 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10788 return 0;
10789 }
10790 }
10791 }
10792
10793 // take into account normalization factor
10794 Hparam.allchan = allchan;
10795 Double_t factor = allchan;
10796 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
10797 if (allchan) factor /= allchan;
10798 if (factor == 0) factor = 1;
10799 Hparam.factor = factor;
10800 zmax = factor*zmax;
10801 zmin = factor*zmin;
10802 c1 = zmax;
10803 if (TMath::Abs(zmin) > TMath::Abs(c1)) c1 = zmin;
10804
10805 // For log scales, histogram coordinates are log10(ymin) and
10806 // log10(ymax). Final adjustment (if not option "Same")
10807 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
10808 // Maximum and Minimum are not defined.
10809 if (Hoption.Logz) {
10810 if (zmin <= 0) {
10811 zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
10812 fH->SetMinimum(zmin);
10813 }
10814 zmin = TMath::Log10(zmin);
10815 if (!minimum) zmin += TMath::Log10(0.5);
10816 zmax = TMath::Log10(zmax);
10817 if (!maximum) zmax += TMath::Log10(2*(0.9/0.95));
10818 goto LZMIN;
10819 }
10820
10821 // final adjustment of YMAXI for linear scale (if not option "Same"):
10822 // decrease histogram height to MAX% of allowed height if HMAXIM
10823 // has not been called.
10824 // MAX% is the value in percent which has been set in HPLSET
10825 // (default is 90%).
10826 if (!maximum) {
10827 zmax += yMARGIN*(zmax-zmin);
10828 }
10829
10830 // final adjustment of ymin for linear scale.
10831 // if minimum is not set , then ymin is set to zero if >0
10832 // or to ymin - yMARGIN if <0.
10833 if (!minimum) {
10834 if (Hoption.MinimumZero) {
10835 if (zmin >= 0) zmin = 0;
10836 else zmin -= yMARGIN*(zmax-zmin);
10837 } else {
10838 Double_t dzmin = yMARGIN*(zmax-zmin);
10839 if (zmin >= 0 && (zmin-dzmin <= 0)) zmin = 0;
10840 else zmin -= dzmin;
10841 }
10842 }
10843
10844LZMIN:
10845 Hparam.zmin = zmin;
10846 Hparam.zmax = zmax;
10847
10848 // Set bar offset and width
10851
10852 return 1;
10853}
10854
10855////////////////////////////////////////////////////////////////////////////////
10856/// This function returns the best format to print the error value (e)
10857/// knowing the parameter value (v) and the format (f) used to print it.
10858
10860{
10861
10862 static TString ef;
10863 TString tf, tv;
10864
10865 // print v with the format f in tv.
10866 tf.Form("%s%s","%",f);
10867 tv.Form(tf.Data(),v);
10868
10869 // Analyse tv.
10870 int ie = tv.Index("e");
10871 int iE = tv.Index("E");
10872 int id = tv.Index(".");
10873
10874 // v has been printed with the exponent notation.
10875 // There is 2 cases, the exponent is positive or negative
10876 if (ie >= 0 || iE >= 0) {
10877 if (tv.Index("+") >= 0) {
10878 if (e < 1) {
10879 ef.Form("%s.1f","%");
10880 } else {
10881 if (ie >= 0) {
10882 ef.Form("%s.%de","%",ie-id-1);
10883 } else {
10884 ef.Form("%s.%dE","%",iE-id-1);
10885 }
10886 }
10887 } else {
10888 if (ie >= 0) {
10889 ef.Form("%s.%de","%",ie-id-1);
10890 } else {
10891 ef.Form("%s.%dE","%",iE-id-1);
10892 }
10893 }
10894
10895 // There is not '.' in tv. e will be printed with one decimal digit.
10896 } else if (id < 0) {
10897 ef.Form("%s.1f","%");
10898
10899 // There is a '.' in tv and no exponent notation. e's decimal part will
10900 // have the same number of digits as v's one.
10901 } else {
10902 ef.Form("%s.%df","%",tv.Length()-id-1);
10903 }
10904
10905 return ef.Data();
10906}
10907
10908
10909////////////////////////////////////////////////////////////////////////////////
10910/// Return projection kind from option string
10911
10913{
10914 TString opt = option;
10915 opt.ToLower();
10916 Int_t projection = 0;
10917 if (opt.BeginsWith("xy"))
10918 projection = 4;
10919 else if (opt.BeginsWith("yx"))
10920 projection = 5;
10921 else if (opt.BeginsWith("xz"))
10922 projection = 6;
10923 else if (opt.BeginsWith("zx"))
10924 projection = 7;
10925 else if (opt.BeginsWith("yz"))
10926 projection = 8;
10927 else if (opt.BeginsWith("zy"))
10928 projection = 9;
10929 else if (opt.BeginsWith("x"))
10930 projection = 1;
10931 else if (opt.BeginsWith("y"))
10932 projection = 2;
10933 else if (opt.BeginsWith("z"))
10934 projection = 3;
10935 return projection;
10936}
10937
10938
10939////////////////////////////////////////////////////////////////////////////////
10940/// Set projection.
10941
10943{
10944 if (fShowProjection2) {
10945 auto name2 = TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2);
10946 auto c2 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name2.Data()));
10947 if (c2) c2->Close();
10948 fShowProjection2 = 0;
10949 }
10950 if (fShowProjection) {
10951 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10952 auto c1 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name1.Data()));
10953 if (c1) c1->Close();
10954 fShowProjection = 0;
10955 }
10956
10957 if (nbins <= 0)
10958 return;
10959
10960 if ((fH->GetDimension() == 3) && (gPad->GetGLDevice() != -1)) {
10961 Error("SetShowProjection", "TH3 projections do not work in GL mode");
10962 return;
10963 }
10964
10965 Int_t projection = DetectProjectionKind(option);
10966 if (projection == 0)
10967 return;
10968
10969 // exclude x or xy from option, rest use as histogram draw option
10970 fShowOption = option + (projection < 4 ? 1 : 2);
10971 fShowProjection = projection + 100 * nbins;
10972 fShowProjection2 = 0;
10973
10974 gROOT->MakeDefCanvas();
10975 gPad->SetName(TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection).Data());
10976 gPad->SetGrid();
10977}
10978
10979////////////////////////////////////////////////////////////////////////////////
10980/// Set projection XY.
10981
10982void THistPainter::SetShowProjectionXY(const char *option, Int_t nbinsY, Int_t nbinsX)
10983{
10984 if (fShowProjection2) {
10985 auto name2 = TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2);
10986 auto c2 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name2.Data()));
10987 if (c2) c2->Close();
10988 fShowProjection2 = 0;
10989 }
10990 if (fShowProjection) {
10991 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10992 auto c1 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name1.Data()));
10993 if (c1) c1->Close();
10994 fShowProjection = 0;
10995 }
10996
10997 if ((nbinsX <= 0) || (nbinsY <= 0))
10998 return;
10999
11000 if ((fH->GetDimension() == 3) && (gPad->GetGLDevice() != -1)) {
11001 Error("SetShowProjectionXY", "TH3 projections do not work in GL mode");
11002 return;
11003 }
11004
11005 Int_t projection = DetectProjectionKind(option);
11006 if (projection == 0)
11007 return;
11008
11009 // exclude x or xy from option, rest use as histogram draw option
11010 fShowOption = option + (projection < 4 ? 1 : 2);
11011 fShowProjection = projection + 100*nbinsY;
11012 fShowProjection2 = projection + 100*nbinsX;
11013
11014 gROOT->MakeDefCanvas();
11015 gPad->SetName(TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection).Data());
11016 gPad->SetGrid();
11017 gROOT->MakeDefCanvas();
11018 gPad->SetName(TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2).Data());
11019 gPad->SetGrid();
11020}
11021
11022
11023////////////////////////////////////////////////////////////////////////////////
11024/// Show projection onto X.
11025
11027{
11028 if (!gPad)
11029 return;
11030
11031 Int_t nbins = (Int_t)fShowProjection/100;
11032
11033 // Erase old position and draw a line at current position
11034 Double_t uxmin = gPad->GetUxmin();
11035 Double_t uxmax = gPad->GetUxmax();
11036 Float_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
11037 Int_t biny1 = fH->GetYaxis()->FindBin(y);
11038 Int_t biny2 = TMath::Min(biny1+nbins-1, fH->GetYaxis()->GetNbins());
11039 Double_t py1 = gPad->YtoPad(fH->GetYaxis()->GetBinLowEdge(biny1));
11040 Double_t py2 = gPad->YtoPad(fH->GetYaxis()->GetBinUpEdge(biny2));
11041
11042 gPad->PaintBox(uxmin,py1,uxmax,py2,"iprojX");
11043 gPad->UpdateAsync();
11044
11045 // Create or set the new canvas proj x
11046 TVirtualPad::TContext ctxt(true);
11047 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
11048 auto c = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name1.Data()));
11049 if (!c) {
11051 return;
11052 }
11053
11054 c->Clear();
11055 c->cd();
11056 c->SetLogy(ctxt.GetSaved()->GetLogz());
11057 c->SetLogx(ctxt.GetSaved()->GetLogx());
11058
11059 // Draw slice corresponding to mouse position
11060 TString prjName = TString::Format("slice_px_of_%s",fH->GetName());
11061 if (auto hp = ((TH2*)fH)->ProjectionX(prjName, biny1, biny2)) {
11062 hp->SetFillColor(38);
11063 // apply a patch from Oliver Freyermuth to set the title in the projection
11064 // using the range of the projected Y values
11065 if (biny1 == biny2) {
11066 Double_t valueFrom = fH->GetYaxis()->GetBinLowEdge(biny1);
11067 Double_t valueTo = fH->GetYaxis()->GetBinUpEdge(biny1);
11068 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11069 Int_t valuePrecision = -TMath::Nint(TMath::Log10(valueTo-valueFrom))+1;
11070 if (fH->GetYaxis()->GetLabels() != nullptr) {
11071 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf] %s", biny1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetYaxis()->GetBinLabel(biny1)));
11072 } else {
11073 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf]", biny1, valuePrecision, valueFrom, valuePrecision, valueTo));
11074 }
11075 } else {
11076 Double_t valueFrom = fH->GetYaxis()->GetBinLowEdge(biny1);
11077 Double_t valueTo = fH->GetYaxis()->GetBinUpEdge(biny2);
11078 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11079 // biny1 is used here to get equal precision no matter how large the binrange is,
11080 // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
11081 Int_t valuePrecision = -TMath::Nint(TMath::Log10(fH->GetYaxis()->GetBinUpEdge(biny1)-valueFrom))+1;
11082 if (fH->GetYaxis()->GetLabels() != nullptr) {
11083 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)));
11084 } else {
11085 hp->SetTitle(TString::Format("ProjectionX of biny=[%d,%d] [y=%.*lf..%.*lf]", biny1, biny2, valuePrecision, valueFrom, valuePrecision, valueTo));
11086 }
11087 }
11088 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11089 hp->SetYTitle(((TH2*)fH)->GetZaxis()->GetTitle() ? ((TH2*)fH)->GetZaxis()->GetTitle() : "Number of Entries");
11090 c->Add(hp, fShowOption);
11091 c->UpdateAsync();
11092 }
11093}
11094
11095////////////////////////////////////////////////////////////////////////////////
11096/// Show projection onto Y.
11097
11099{
11100 if (!gPad)
11101 return;
11102
11103 Int_t nbins = (Int_t)fShowProjection/100;
11104 if (fShowProjection2)
11105 nbins = (Int_t)fShowProjection2/100;
11106
11107 Double_t uymin = gPad->GetUymin();
11108 Double_t uymax = gPad->GetUymax();
11109 Float_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
11110 Int_t binx1 = fH->GetXaxis()->FindBin(x);
11111 Int_t binx2 = TMath::Min(binx1+nbins-1, fH->GetXaxis()->GetNbins());
11112 Double_t px1 = gPad->XtoPad(fH->GetXaxis()->GetBinLowEdge(binx1));
11113 Double_t px2 = gPad->XtoPad(fH->GetXaxis()->GetBinUpEdge(binx2));
11114
11115 gPad->PaintBox(px1, uymin, px2, uymax, "iprojY");
11116 gPad->UpdateAsync();
11117
11118 // Create or set the new canvas proj y
11119 TVirtualPad::TContext ctxt(true);
11120
11121 TString name2 = fShowProjection2 ? TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2)
11122 : TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
11123
11124 auto c = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name2.Data()));
11125 if (!c) {
11127 return;
11128 }
11129
11130 c->Clear();
11131 c->cd();
11132 c->SetLogy(ctxt.GetSaved()->GetLogz());
11133 c->SetLogx(ctxt.GetSaved()->GetLogy());
11134
11135 // Draw slice corresponding to mouse position
11136 TString prjName = TString::Format("slice_py_of_%s",fH->GetName());
11137 if (auto hp = ((TH2*)fH)->ProjectionY(prjName, binx1, binx2)) {
11138 hp->SetFillColor(38);
11139 // apply a patch from Oliver Freyermuth to set the title in the projection
11140 // using the range of the projected X values
11141 if (binx1 == binx2) {
11142 Double_t valueFrom = fH->GetXaxis()->GetBinLowEdge(binx1);
11143 Double_t valueTo = fH->GetXaxis()->GetBinUpEdge(binx1);
11144 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11145 Int_t valuePrecision = -TMath::Nint(TMath::Log10(valueTo-valueFrom))+1;
11146 if (fH->GetXaxis()->GetLabels()) {
11147 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf] [%s]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetXaxis()->GetBinLabel(binx1)));
11148 } else {
11149 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo));
11150 }
11151 } else {
11152 Double_t valueFrom = fH->GetXaxis()->GetBinLowEdge(binx1);
11153 Double_t valueTo = fH->GetXaxis()->GetBinUpEdge(binx2);
11154 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11155 // binx1 is used here to get equal precision no matter how large the binrange is,
11156 // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
11157 Int_t valuePrecision = -TMath::Nint(TMath::Log10(fH->GetXaxis()->GetBinUpEdge(binx1)-valueFrom))+1;
11158 if (fH->GetXaxis()->GetLabels()) {
11159 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)));
11160 } else {
11161 hp->SetTitle(TString::Format("ProjectionY of binx=[%d,%d] [x=%.*lf..%.*lf]", binx1, binx2, valuePrecision, valueFrom, valuePrecision, valueTo));
11162 }
11163 }
11164 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11165 hp->SetYTitle(((TH2*)fH)->GetZaxis()->GetTitle() ? ((TH2*)fH)->GetZaxis()->GetTitle() : "Number of Entries");
11166 c->Add(hp, fShowProjection2 ? "hbar" + fShowOption : fShowOption);
11167 c->UpdateAsync();
11168 }
11169}
11170
11171////////////////////////////////////////////////////////////////////////////////
11172/// Show projection (specified by `fShowProjection`) of a `TH3`.
11173/// The drawing option for the projection is in `fShowOption`.
11174///
11175/// First implementation: R.Brun
11176///
11177/// Full implementation: Tim Tran (timtran@jlab.org) April 2006
11178///
11179/// Redesign: S. Linev September 2026
11180
11182{
11183 Int_t nbins = fShowProjection / 100; //decode nbins
11184 Int_t kind = fShowProjection % 100; // projection kinds
11185
11186 if (fH->GetDimension() < 3) {
11187 if (fShowProjection2 % 100 == 1) {
11188 ShowProjectionY(px, py);
11189 }
11190 if (fShowProjection % 100 == 1) {
11191 ShowProjectionX(px, py);
11192 return;
11193 }
11194 if (fShowProjection % 100 == 2) {
11195 ShowProjectionY(px, py);
11196 return;
11197 }
11198 }
11199
11200 auto &parent = *gPad;
11201
11202 // 3D protection does not work with GL painters
11203 if (parent.GetGLDevice() != -1)
11204 return;
11205
11206 auto view = parent.GetView();
11207 if (!view)
11208 return;
11209
11210 // check that ranges are set
11211 if ((parent.GetUxmin() == parent.GetUxmax()) || (parent.GetUymin() == parent.GetUymax()))
11212 return;
11213
11214 // calculated vertices
11215 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};
11216
11217 auto cname = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
11218 auto c = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(cname));
11219 auto h3 = dynamic_cast<TH3 *>(fH);
11220
11221 if (!c || !h3) {
11222 fShowProjection = 0;
11223 return;
11224 }
11225
11226 TAxis *xaxis = fH->GetXaxis();
11227 TAxis *yaxis = fH->GetYaxis();
11228 TAxis *zaxis = fH->GetZaxis();
11229
11230 static constexpr Int_t iMin = -111;
11231 static constexpr Int_t iMax = -11;
11232 static constexpr Int_t kMaxDist = 50; // maximal distance to detect bin
11233
11234 auto getx = [](TAxis *axis, Int_t indx) {
11235 return indx == iMin ? axis->GetBinLowEdge(axis->GetFirst())
11236 : (indx == iMax ? axis->GetBinUpEdge(axis->GetLast()) : axis->GetBinCenter(indx));
11237 };
11238
11239 auto findAxis = [&parent, px, py, xaxis, yaxis, zaxis, view, getx](Int_t &besti1, Int_t &besti2, char name) {
11240
11241 TAxis *axis1 = nullptr, *axis2 = nullptr;
11242 Int_t xindx = 0, yindx = 0, zindx = 0;
11243
11244 switch(name) {
11245 case 'x':
11246 axis1 = yaxis;
11247 axis2 = zaxis;
11248 xindx = TMath::Cos(view->GetLongitude() / 180. * TMath::Pi()) < 0 ? iMin : iMax;
11249 break;
11250 case 'y':
11251 axis1 = xaxis;
11252 axis2 = zaxis;
11253 yindx = TMath::Sin(view->GetLongitude() / 180. * TMath::Pi()) < 0 ? iMin : iMax;
11254 break;
11255 default:
11256 axis1 = xaxis;
11257 axis2 = yaxis;
11258 zindx = TMath::Cos(view->GetLatitude() / 180. * TMath::Pi()) > 0 ? iMax : iMin;
11259 break;
11260 }
11261
11262 Double_t best_dist = kMaxDist;
11263
11264 for (Int_t i1 = axis1->GetFirst(); i1 <= axis1->GetLast(); ++i1)
11265 for (Int_t i2 = axis2->GetFirst(); i2 <= axis2->GetLast(); ++i2) {
11266 switch(name) {
11267 case 'x': yindx = i1; zindx = i2; break;
11268 case 'y': xindx = i1; zindx = i2; break;
11269 default: xindx = i1; yindx = i2; break;
11270 }
11271 Double_t v[3] = {getx(xaxis, xindx), getx(yaxis, yindx), getx(zaxis, zindx)};
11272 Double_t ndc[3];
11273 view->WCtoNDC(v, ndc);
11274 Int_t px1 = parent.XtoAbsPixel(ndc[0]);
11275 Int_t py1 = parent.YtoAbsPixel(ndc[1]);
11276 Double_t distance = TMath::Sqrt(1. * (px1 - px) * (px1 - px) + 1. * (py1 - py) * (py1 - py));
11277 if (distance < best_dist) {
11278 best_dist = distance;
11279 besti1 = i1;
11280 besti2 = i2;
11281 }
11282 }
11283
11284 return best_dist < kMaxDist;
11285 };
11286
11287 auto convert = [view, getx, xaxis, yaxis, zaxis](Int_t ix, Int_t iy, Int_t iz,
11288 Double_t &resx, Double_t &resy) {
11289 Double_t vvv[3] = {getx(xaxis, ix), getx(yaxis, iy), getx(zaxis, iz)};
11290 Double_t uu[3];
11291 view->WCtoNDC(vvv, uu);
11292 resx = uu[0];
11293 resy = uu[1];
11294 };
11295
11296 auto draw_rects = [&parent, nbins, kind, &rect1x, &rect2x, &rect1y, &rect2y]() {
11297 rect1x[4] = rect1x[0];
11298 rect1y[4] = rect1y[0];
11299 rect2x[4] = rect2x[0];
11300 rect2y[4] = rect2y[0];
11301 if (kind > 3) {
11302 parent.PaintPolyLine(5, rect1x, rect1y, "iproj3_rect1");
11303 if (nbins > 1)
11304 parent.PaintPolyLine(5, rect2x, rect2y, "iproj3_rect2");
11305 } else {
11306 parent.PaintPolyLine(nbins > 1 ? 5 : 2, rect1x, rect1y, "iproj3_rect1");
11307 if (nbins > 1) {
11308 parent.PaintPolyLine(5, rect2x, rect2y, "iproj3_rect2");
11309 for (Int_t n = 0; n < 4; ++n) {
11310 Double_t xx[2] = {rect1x[n], rect2x[n]};
11311 Double_t yy[2] = {rect1y[n], rect2y[n]};
11312 parent.PaintPolyLine(2, xx, yy, TString::Format("iproj3_line%d", n).Data());
11313 }
11314 }
11315 }
11316 parent.UpdateAsync();
11317 };
11318
11319 Int_t binx = -1, biny = -1, binz = -1, binx2 = -1, biny2 = -1, binz2 = -1, dummy = -1;
11320
11321 auto extend_bin = [nbins](TAxis *axis, Int_t &bin) {
11322 Int_t bin2 = bin;
11323 if (nbins > 1) {
11324 bin2 = TMath::Min(bin + nbins / 2, axis->GetLast());
11325 bin = TMath::Max(bin2 - nbins + 1, axis->GetFirst());
11326 }
11327 return bin2;
11328 };
11329
11330 auto make_proj = [h3, &binx, &biny, &binz, &binx2, &biny2, &binz2, xaxis, yaxis, zaxis](const char *proj_kind) {
11331 Int_t firstX = xaxis->GetFirst();
11332 Int_t lastX = xaxis->GetLast();
11333 Int_t firstY = yaxis->GetFirst();
11334 Int_t lastY = yaxis->GetLast();
11335 Int_t firstZ = zaxis->GetFirst();
11336 Int_t lastZ = zaxis->GetLast();
11337 if (binx >= 0)
11338 xaxis->SetRange(binx, binx2);
11339 if (biny >= 0)
11340 yaxis->SetRange(biny, biny2);
11341 if (binz >= 0)
11342 zaxis->SetRange(binz, binz2);
11343 auto hp = h3->Project3D(proj_kind);
11344 if (binx >= 0)
11345 xaxis->SetRange(firstX,lastX);
11346 if (biny >= 0)
11347 yaxis->SetRange(firstY, lastY);
11348 if (binz >= 0)
11349 zaxis->SetRange(firstZ,lastZ);
11350 return hp;
11351 };
11352
11353 TVirtualPad::TContext ctxt(true);
11354
11355 switch (kind) {
11356 case 1: { // "x"
11357 if (!findAxis(biny, binz, 'x'))
11358 break;
11359
11360 biny2 = extend_bin(yaxis, biny);
11361 binz2 = extend_bin(zaxis, binz);
11362
11363 convert(iMin, biny, binz, rect1x[0], rect1y[0]);
11364 convert(iMax, biny, binz, rect1x[1], rect1y[1]);
11365 convert(iMax, biny, binz2, rect1x[2], rect1y[2]);
11366 convert(iMin, biny, binz2, rect1x[3], rect1y[3]);
11367 convert(iMin, biny2, binz, rect2x[0], rect2y[0]);
11368 convert(iMax, biny2, binz, rect2x[1], rect2y[1]);
11369 convert(iMax, biny2, binz2, rect2x[2], rect2y[2]);
11370 convert(iMin, biny2, binz2, rect2x[3], rect2y[3]);
11371
11372 draw_rects();
11373
11374 c->Clear();
11375
11376 if (auto hp = make_proj("x")) {
11377 hp->SetFillColor(38);
11378 if ((biny == biny2) && (binz == binz2))
11379 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny),
11380 binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
11381 else
11382 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),
11383 binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
11384 hp->SetXTitle(xaxis->GetTitle());
11385 hp->SetYTitle("Number of Entries");
11386 c->Add(hp, fShowOption);
11387 }
11388 break;
11389 }
11390
11391 case 2: { // "y"
11392 if (!findAxis(binx, binz, 'y'))
11393 break;
11394
11395 binx2 = extend_bin(xaxis, binx);
11396 binz2 = extend_bin(zaxis, binz);
11397
11398 convert(binx, iMin, binz, rect1x[0], rect1y[0]);
11399 convert(binx, iMax, binz, rect1x[1], rect1y[1]);
11400 convert(binx, iMax, binz2, rect1x[2], rect1y[2]);
11401 convert(binx, iMin, binz2, rect1x[3], rect1y[3]);
11402 convert(binx2, iMin, binz, rect2x[0], rect2y[0]);
11403 convert(binx2, iMax, binz, rect2x[1], rect2y[1]);
11404 convert(binx2, iMax, binz2, rect2x[2], rect2y[2]);
11405 convert(binx2, iMin, binz2, rect2x[3], rect2y[3]);
11406
11407 draw_rects();
11408
11409 c->Clear();
11410 if (auto hp = make_proj("y")) {
11411 hp->SetFillColor(38);
11412 if ((binx == binx2) && (binz == binz2))
11413 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
11414 binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
11415 else
11416 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),
11417 binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
11418 hp->SetXTitle(yaxis->GetTitle());
11419 hp->SetYTitle("Number of Entries");
11420 c->Add(hp, fShowOption);
11421 }
11422 break;
11423 }
11424
11425 case 3: { // "z"
11426 if (!findAxis(binx, biny, 'z'))
11427 break;
11428 binx2 = extend_bin(xaxis, binx);
11429 biny2 = extend_bin(yaxis, biny);
11430
11431 convert(binx, biny, iMin, rect1x[0], rect1y[0]);
11432 convert(binx, biny, iMax, rect1x[1], rect1y[1]);
11433 convert(binx, biny2, iMax, rect1x[2], rect1y[2]);
11434 convert(binx, biny2, iMin, rect1x[3], rect1y[3]);
11435 convert(binx2, biny, iMin, rect2x[0], rect2y[0]);
11436 convert(binx2, biny, iMax, rect2x[1], rect2y[1]);
11437 convert(binx2, biny2, iMax, rect2x[2], rect2y[2]);
11438 convert(binx2, biny2, iMin, rect2x[3], rect2y[3]);
11439
11440 draw_rects();
11441
11442 c->Clear();
11443 if (auto hp = make_proj("z")) {
11444 hp->SetFillColor(38);
11445 if ((binx == binx2) && (biny == biny2))
11446 hp->SetTitle(TString::Format("ProjectionZ of binx=%d [x=%.1f..%.1f] biny=%d [y=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
11447 biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny)));
11448 else
11449 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),
11450 biny, biny2, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny2) ) );
11451 hp->SetXTitle(zaxis->GetTitle());
11452 hp->SetYTitle("Number of Entries");
11453 c->Add(hp, fShowOption);
11454 }
11455 break;
11456 }
11457
11458 case 4: // "xy"
11459 case 5: { // "yx"
11460 if (!findAxis(dummy, binz, 'x') && !findAxis(dummy, binz, 'y'))
11461 break;
11462 binz2 = extend_bin(zaxis, binz);
11463
11464 convert(iMin, iMax, binz, rect1x[0], rect1y[0]);
11465 convert(iMax, iMax, binz, rect1x[1], rect1y[1]);
11466 convert(iMax, iMin, binz, rect1x[2], rect1y[2]);
11467 convert(iMin, iMin, binz, rect1x[3], rect1y[3]);
11468 if (binz != binz2) {
11469 convert(iMin, iMax, binz2, rect2x[0], rect2y[0]);
11470 convert(iMax, iMax, binz2, rect2x[1], rect2y[1]);
11471 convert(iMax, iMin, binz2, rect2x[2], rect2y[2]);
11472 convert(iMin, iMin, binz2, rect2x[3], rect2y[3]);
11473 }
11474
11475 draw_rects();
11476
11477 c->Clear();
11478
11479 if (auto hp = make_proj(kind == 4 ? "xy" : "yx")) {
11480 hp->SetFillColor(38);
11481 TString sbins = (binz == binz2) ? TString::Format("%d", binz) : TString::Format("[%d,%d]", binz, binz2);
11482 hp->SetTitle(TString::Format("Projection%s, binz=%s [z=%.1f..%.1f]", kind == 4 ? "XY" : "YX", sbins.Data(),
11483 zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2)));
11484 if (kind == 4) {
11485 hp->SetXTitle(yaxis->GetTitle());
11486 hp->SetYTitle(xaxis->GetTitle());
11487 } else {
11488 hp->SetXTitle(xaxis->GetTitle());
11489 hp->SetYTitle(yaxis->GetTitle());
11490 }
11491 hp->SetZTitle("Number of Entries");
11492 c->Add(hp, fShowOption);
11493 }
11494 break;
11495 }
11496
11497 case 6: // "xz"
11498 case 7: { // "zx"
11499 if (!findAxis(biny, dummy, 'x') && !findAxis(dummy, biny, 'z'))
11500 break;
11501
11502 biny2 = extend_bin(yaxis, biny);
11503
11504 convert(iMin, biny, iMax, rect1x[0], rect1y[0]);
11505 convert(iMax, biny, iMax, rect1x[1], rect1y[1]);
11506 convert(iMax, biny, iMin, rect1x[2], rect1y[2]);
11507 convert(iMin, biny, iMin, rect1x[3], rect1y[3]);
11508
11509 if (biny != biny2) {
11510 convert(iMin, biny2, iMax, rect2x[0], rect2y[0]);
11511 convert(iMax, biny2, iMax, rect2x[1], rect2y[1]);
11512 convert(iMax, biny2, iMin, rect2x[2], rect2y[2]);
11513 convert(iMin, biny2, iMin, rect2x[3], rect2y[3]);
11514 }
11515
11516 draw_rects();
11517
11518 c->Clear();
11519
11520 if (auto hp = make_proj(kind == 6 ? "xz" : "zx")) {
11521 hp->SetFillColor(38);
11522 TString sbins = (biny == biny2) ? TString::Format("%d", biny) : TString::Format("[%d,%d]", biny, biny2);
11523 hp->SetTitle(TString::Format("Projection%s, biny=%s [y=%.1f..%.1f]", kind == 6 ? "XZ" : "ZX", sbins.Data(),
11524 yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny2)));
11525 if (kind == 6) {
11526 hp->SetXTitle(zaxis->GetTitle());
11527 hp->SetYTitle(xaxis->GetTitle());
11528 } else {
11529 hp->SetXTitle(xaxis->GetTitle());
11530 hp->SetYTitle(zaxis->GetTitle());
11531 }
11532 hp->SetZTitle("Number of Entries");
11533 c->Add(hp, fShowOption);
11534 }
11535 break;
11536 }
11537
11538 case 8: // "yz"
11539 case 9: { // "zy"
11540 if (!findAxis(binx, dummy, 'y') && !findAxis(binx, dummy, 'z'))
11541 break;
11542
11543 binx2 = extend_bin(xaxis, binx);
11544
11545 convert(binx, iMax, iMin, rect1x[0], rect1y[0]);
11546 convert(binx, iMax, iMax, rect1x[1], rect1y[1]);
11547 convert(binx, iMin, iMax, rect1x[2], rect1y[2]);
11548 convert(binx, iMin, iMin, rect1x[3], rect1y[3]);
11549 if (binx != binx2) {
11550 convert(binx2, iMax, iMin, rect2x[0], rect2y[0]);
11551 convert(binx2, iMax, iMax, rect2x[1], rect2y[1]);
11552 convert(binx2, iMin, iMax, rect2x[2], rect2y[2]);
11553 convert(binx2, iMin, iMin, rect2x[3], rect2y[3]);
11554 }
11555
11556 draw_rects();
11557
11558 c->Clear();
11559 if (auto hp = make_proj(kind == 8 ? "yz" : "zy")) {
11560 hp->SetFillColor(38);
11561 TString sbins = (binx == binx2) ? TString::Format("%d", binx) : TString::Format("[%d,%d]", binx, binx2);
11562 hp->SetTitle(TString::Format("Projection%s of binx=%s [x=%.1f..%.f]", kind == 8 ? "YZ" : "ZY", sbins.Data(),
11563 xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx2)));
11564 if (kind == 8) {
11565 hp->SetXTitle(zaxis->GetTitle());
11566 hp->SetYTitle(yaxis->GetTitle());
11567 } else {
11568 hp->SetXTitle(yaxis->GetTitle());
11569 hp->SetYTitle(zaxis->GetTitle());
11570 }
11571 hp->SetZTitle("Number of Entries");
11572 c->Add(hp, fShowOption);
11573 }
11574 break;
11575 }
11576 }
11577 c->Update();
11578}
@ 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
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
Int_t fN
Definition TArray.h:38
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 void SetImageQuality(EImageQuality lquality)
Definition TAttImage.h:99
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:489
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:529
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:480
virtual const char * GetTimeFormatOnly() const
Return only the time format from the string fTimeFormat.
Definition TAxis.cxx:611
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:1097
virtual const char * GetTimeFormat() const
Definition TAxis.h:134
virtual void SetRange(Int_t first=0, Int_t last=0)
Set the viewing range for the axis using bin numbers.
Definition TAxis.cxx:1068
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width.
Definition TAxis.cxx:553
virtual Double_t GetBinUpEdge(Int_t bin) const
Return up edge of bin.
Definition TAxis.cxx:539
Int_t GetFirst() const
Return first bin on the axis i.e.
Definition TAxis.cxx:469
THashList * GetLabels() const
Definition TAxis.h:123
Create a Box.
Definition TBox.h:22
The candle plot painter class.
Definition TCandle.h:27
void SetLog(int x, int y, int z)
Definition TCandle.h:126
CandleOption
Definition TCandle.h:30
void SetHistoWidth(const Double_t width)
Definition TCandle.h:130
virtual void Paint(Option_t *option="")
Paint one candle with its current attributes.
Definition TCandle.cxx:665
Bool_t IsViolinScaled() const
Returns true if violin plot should be scaled.
Definition TCandle.cxx:190
Bool_t IsHorizontal() const
Definition TCandle.h:120
int ParseOption(char *optin)
Parsing of the option-string.
Definition TCandle.cxx:243
void SetOption(CandleOption opt)
Definition TCandle.h:125
void SetHistogram(TH1D *proj)
Definition TCandle.h:131
Bool_t IsCandleScaled() const
Returns true if candle plot should be scaled.
Definition TCandle.cxx:182
void SetCandleWidth(const Double_t width)
Definition TCandle.h:129
void SetAxisPosition(const Double_t candlePos)
Definition TCandle.h:127
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
void SetName(const char *name)
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
void Paint(Option_t *option="") override
Paint all objects in this collection.
The color creation and management class.
Definition TColor.h:22
virtual void SetRGB(Float_t r, Float_t g, Float_t b)
Initialize this color and its "dark" and "bright" associated colors.
Definition TColor.cxx:1868
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
virtual void GetRGB(Float_t &r, Float_t &g, Float_t &b) const
Definition TColor.h:55
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
void Paint(Option_t *option="") override
Paint this crown with its current attributes.
Definition TCrown.cxx:216
void SetYXRatio(Double_t v=1)
Definition TCrown.h:29
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
void Draw(Option_t *option="") override
Draw this histogram with options.
Definition TH1.cxx:3193
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()
Double_t Integral(Option_t *option="") const override
Return integral of bin contents.
Definition TH3.cxx:1419
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:30
static TImage * Create()
Create an image.
Definition TImage.cxx:34
virtual void SetImage(const Double_t *, UInt_t, UInt_t, TImagePalette *=nullptr)
Definition TImage.h:120
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.
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition TNamed.cxx:173
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
void Delete(Option_t *option="") override
Remove all objects from the array AND delete all heap based objects.
TObject * At(Int_t idx) const override
Definition TObjArray.h:170
TObject * FindObject(const char *name) const override
Find an object in this collection using its name.
void Add(TObject *obj) override
Definition TObjArray.h:68
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
virtual void Delete(Option_t *option="")
Delete this object.
Definition TObject.cxx:267
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
virtual TClass * IsA() const
Definition TObject.h:248
virtual void Paint(Option_t *option="")
This method must be overridden if a class wants to paint itself.
Definition TObject.cxx:630
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.
void Paint(Option_t *option="") override
Paint the palette.
void SetHistogram(TH1 *h)
TH1 * GetHistogram()
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.
void Draw(Option_t *option="") override
Draw this pavetext with its current attributes.
void Paint(Option_t *option="") override
Paint this pavetext with its current attributes.
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()
virtual Double_t GetBinEntries(Int_t bin) const
Return bin entries of a Profile2D histogram.
Profile Histogram.
Definition TProfile.h:32
virtual Double_t GetBinEntries(Int_t bin) const
Return bin entries of a Profile histogram.
Definition TProfile.cxx:864
static TClass * Class()
Random number generator class based on the maximally equidistributed combined Tausworthe generator by...
Definition TRandom2.h:27
Double_t Rndm() override
TausWorth generator from L'Ecuyer, uses as seed 3x32bits integers Use a mask of 0xffffffffUL to make ...
Definition TRandom2.cxx:56
Sequenceable collection abstract base class.
Basic string class.
Definition TString.h:137
Ssiz_t Length() const
Definition TString.h:426
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
TString & Remove(Ssiz_t pos)
Definition TString.h:695
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:1879
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.
virtual void Show()
small helper class to store/restore gPad context in TPad methods
Definition TVirtualPad.h:58
auto GetSaved() const
Definition TVirtualPad.h:66
Helper class to store interactive parameters for individual objects Should be used via MakeInteractiv...
Definition TVirtualPad.h:72
TVirtualPad is an abstract base class for the Pad and Canvas classes.
Definition TVirtualPad.h:53
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 void Close(Option_t *option="")=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