Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
THistPainter.cxx
Go to the documentation of this file.
1// @(#)root/histpainter:$Id$
2// Author: Rene Brun, Olivier Couet
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12#include <cstdlib>
13#include <cstring>
14#include <cstdio>
15#include <cctype>
16#include <iostream>
17
18#include "TROOT.h"
19#include "TSystem.h"
20#include "THistPainter.h"
21#include "TH2.h"
22#include "TH2Poly.h"
23#include "TH3.h"
24#include "TProfile.h"
25#include "TProfile2D.h"
26#include "THStack.h"
27#include "TF2.h"
28#include "TF3.h"
29#include "TCutG.h"
30#include "TMatrixDBase.h"
31#include "TMatrixFBase.h"
32#include "TVectorD.h"
33#include "TVectorF.h"
34#include "TCanvas.h"
35#include "TPad.h"
36#include "TPaveStats.h"
37#include "TFrame.h"
38#include "TLatex.h"
39#include "TPolyLine.h"
40#include "TPoints.h"
41#include "TStyle.h"
42#include "TGraph.h"
43#include "TMultiGraph.h"
44#include "TPie.h"
45#include "TGaxis.h"
46#include "TColor.h"
48#include "TGraph2D.h"
49#include "TGraph2DPainter.h"
50#include "TGraphDelaunay2D.h"
51#include "TView.h"
52#include "TMath.h"
53#include "TRandom2.h"
54#include "TObjArray.h"
55#define ROOT_Hoption_cxx
56#include "Hoption.h"
57#define ROOT_Hparam_cxx
58#include "Hparam.h"
59#include "TPluginManager.h"
60#include "TPaletteAxis.h"
61#include "TCrown.h"
62#include "TArrow.h"
63#include "TVirtualPadPainter.h"
64#include "TVirtualPadEditor.h"
65#include "TVirtualX.h"
66#include "TEnv.h"
67#include "TPoint.h"
68#include "TImage.h"
69#include "TCandle.h"
70#include "strlcpy.h"
71
72/*! \class THistPainter
73 \ingroup Histpainter
74 \brief The histogram painter class. Implements all histograms' drawing's options.
75
76- [Introduction](\ref HP00)
77- [Histograms' plotting options](\ref HP01)
78 - [Options supported for 1D and 2D histograms](\ref HP01a)
79 - [Options supported for 1D histograms](\ref HP01b)
80 - [Options supported for 2D histograms](\ref HP01c)
81 - [Options supported for 3D histograms](\ref HP01d)
82 - [Options supported for histograms' stacks (THStack)](\ref HP01e)
83- [Setting the Style](\ref HP02)
84- [Setting line, fill, marker, and text attributes](\ref HP03)
85- [Setting Tick marks on the histogram axis](\ref HP04)
86- [Giving titles to the X, Y and Z axis](\ref HP05)
87- [The option SAME](\ref HP060)
88 - [Limitations](\ref HP060a)
89- [Colors automatically picked in palette](\ref HP061)
90- [Superimposing two histograms with different scales in the same pad](\ref HP06)
91- [Statistics Display](\ref HP07)
92- [Fit Statistics](\ref HP08)
93- [The error bars options](\ref HP09)
94- [The bar chart option](\ref HP100)
95- [The BAR and HBAR options](\ref HP10)
96- [The SCATter plot option (legacy draw option)](\ref HP11)
97- [The ARRow option](\ref HP12)
98- [The BOX option](\ref HP13)
99- [The COLor option (default for 2D and 3D histograms)](\ref HP14)
100- [The CANDLE and VIOLIN options](\ref HP140)
101 - [The CANDLE option](\ref HP140a)
102 - [The VIOLIN option](\ref HP140b)
103- [The TEXT and TEXTnn Option](\ref HP15)
104- [The CONTour options](\ref HP16)
105 - [The LIST option](\ref HP16a)
106 - [The AITOFF, MERCATOR, SINUSOIDAL and PARABOLIC options](\ref HP16b)
107- [The LEGO options](\ref HP17)
108- [The SURFace options](\ref HP18)
109- [Cylindrical, Polar, Spherical and PseudoRapidity/Phi options](\ref HP19)
110- [Base line for bar-charts and lego plots](\ref HP20)
111- [TH2Poly Drawing](\ref HP20a)
112- [The SPEC option](\ref HP21)
113- [Option Z : Adding the color palette on the right side of the pad](\ref HP22)
114- [Setting the color palette](\ref HP23)
115- [Drawing a sub-range of a 2-D histogram; the [cutg] option](\ref HP24)
116- [Drawing options for 3D histograms](\ref HP25)
117- [Drawing option for histograms' stacks](\ref HP26)
118- [Drawing of 3D implicit functions](\ref HP27)
119- [Associated functions drawing](\ref HP28)
120- [Drawing using OpenGL](\ref HP29)
121 - [General information: plot types and supported options](\ref HP29a)
122 - [TH3 as color boxes](\ref HP290)
123 - [TH3 as boxes (spheres)](\ref HP29b)
124 - [TH3 as iso-surface(s)](\ref HP29c)
125 - [TF3 (implicit function)](\ref HP29d)
126 - [Parametric surfaces](\ref HP29e)
127 - [Interaction with the plots](\ref HP29f)
128 - [Selectable parts](\ref HP29g)
129 - [Rotation and zooming](\ref HP29h)
130 - [Panning](\ref HP29i)
131 - [Box cut](\ref HP29j)
132 - [Plot specific interactions (dynamic slicing etc.)](\ref HP29k)
133 - [Surface with option GLSURF](\ref HP29l)
134 - [TF3](\ref HP29m)
135 - [Box](\ref HP29n)
136 - [Iso](\ref HP29o)
137 - [Parametric plot](\ref HP29p)
138- [Highlight mode for histogram](\ref HP30)
139 - [Highlight mode and user function](\ref HP30a)
140
141
142\anchor HP00
143## Introduction
144
145
146Histograms are drawn via the `THistPainter` class. Each histogram has a
147pointer to its own painter (to be usable in a multithreaded program). When the
148canvas has to be redrawn, the `Paint` function of each objects in the
149pad is called. In case of histograms, `TH1::Paint` invokes directly
150`THistPainter::Paint`.
151
152To draw a histogram `h` it is enough to do:
153
154 h->Draw();
155
156`h` can be of any kind: 1D, 2D or 3D. To choose how the histogram will
157be drawn, the `Draw()` method can be invoked with an option. For instance
158to draw a 2D histogram as a lego plot it is enough to do:
159
160 h->Draw("lego");
161
162`THistPainter` offers many options to paint 1D, 2D and 3D histograms.
163
164When the `Draw()` method of a histogram is called for the first time
165(`TH1::Draw`), it creates a `THistPainter` object and saves a
166pointer to this "painter" as a data member of the histogram. The
167`THistPainter` class specializes in the drawing of histograms. It is
168separated from the histogram so that one can have histograms without the
169graphics overhead, for example in a batch program. Each histogram having its own
170painter (rather than a central singleton painter painting all histograms), allows
171two histograms to be drawn in two threads without overwriting the painter's
172values.
173
174When a displayed histogram is filled again, there is no need to call the
175`Draw()` method again; the image will be refreshed the next time the
176pad will be updated.
177
178A pad is updated after one of these three actions:
179
1801. a carriage control on the ROOT command line,
1812. a click inside the pad,
1823. a call to `TPad::Update`.
183
184
185By default a call to `TH1::Draw()` clears the pad of all objects
186before drawing the new image of the histogram. One can use the `SAME`
187option to leave the previous display intact and superimpose the new histogram.
188The same histogram can be drawn with different graphics options in different
189pads.
190
191When a displayed histogram is deleted, its image is automatically removed
192from the pad.
193
194To create a copy of the histogram when drawing it, one can use
195`TH1::DrawClone()`. This will clone the histogram and allow to change
196and delete the original one without affecting the clone.
197
198
199\anchor HP01
200### Histograms' plotting options
201
202
203Most options can be concatenated with or without spaces or commas, for example:
204
205 h->Draw("E1 SAME");
206
207The options are not case sensitive:
208
209 h->Draw("e1 same");
210
211
212The default drawing option can be set with `TH1::SetOption` and retrieve
213using `TH1::GetOption`:
214
215 root [0] h->Draw(); // Draw "h" using the standard histogram representation.
216 root [1] h->Draw("E"); // Draw "h" using error bars
217 root [3] h->SetOption("E"); // Change the default drawing option for "h"
218 root [4] h->Draw(); // Draw "h" using error bars
219 root [5] h->GetOption(); // Retrieve the default drawing option for "h"
220 (const Option_t* 0xa3ff948)"E"
221
222
223\anchor HP01a
224#### Options supported for 1D and 2D histograms
225
226| Option | Description |
227|----------|-------------------------------------------------------------------|
228| "E" | Draw error bars. |
229| "AXIS" | Draw only axis. |
230| "AXIG" | Draw only grid (if the grid is requested). |
231| \anchor OPTHIST "HIST" | When an histogram has errors it is visualized by default with error bars. To visualize it without errors use the option "HIST" together with the required option (eg "hist same c"). The "HIST" option can also be used to plot only the histogram and not the associated function(s). |
232| "FUNC" | When an histogram has a fitted function, this option allows to draw the fit result only. |
233| "SAME" | Superimpose on previous picture in the same pad. |
234| "SAMES" | Same as "SAME" and draw the statistics box|
235| "PFC" | Palette Fill Color: histogram's fill color is taken in the current palette. |
236| "PLC" | Palette Line Color: histogram's line color is taken in the current palette. |
237| "PMC" | Palette Marker Color: histogram's marker color is taken in the current palette. |
238| "LEGO" | Draw a lego plot with hidden line removal. |
239| "LEGO1" | Draw a lego plot with hidden surface removal. |
240| "LEGO2" | Draw a lego plot using colors to show the cell contents When the option "0" is used with any LEGO option, the empty bins are not drawn.|
241| "LEGO3" | Draw a lego plot with hidden surface removal, like LEGO1 but the border lines of each lego-bar are not drawn.|
242| "LEGO4" | Draw a lego plot with hidden surface removal, like LEGO1 but without the shadow effect on each lego-bar.|
243| "TEXT" | Draw bin contents as text (format set via `gStyle->SetPaintTextFormat`).|
244| "TEXTnn" | Draw bin contents as text at angle nn (0 < nn <= 90). |
245| "X+" | The X-axis is drawn on the top side of the plot. |
246| "Y+" | The Y-axis is drawn on the right side of the plot. |
247| "MIN0" | Set minimum value for the Y axis to 0, equivalent to gStyle->SetHistMinimumZero(). |
248
249
250\anchor HP01b
251#### Options supported for 1D histograms
252
253| Option | Description |
254|----------|-------------------------------------------------------------------|
255| " " | Default. |
256| "AH" | Draw histogram without axis. "A" can be combined with any drawing option. For instance, "AC" draws the histogram as a smooth Curve without axis.|
257| "][" | When this option is selected the first and last vertical lines of the histogram are not drawn.|
258| "B" | Bar chart option.|
259| "BAR" | Like option "B", but bars can be drawn with a 3D effect.|
260| "HBAR" | Like option "BAR", but bars are drawn horizontally.|
261| "C" | Draw a smooth Curve through the histogram bins.|
262| "E0" | Draw error bars. Markers are drawn for bins with 0 contents. Combined with E1 or E2 it avoids error bars clipping|
263| "E1" | Draw error bars with perpendicular lines at the edges.|
264| "E2" | Draw error bars with rectangles.|
265| "E3" | Draw a fill area through the end points of the vertical error bars.|
266| "E4" | Draw a smoothed filled area through the end points of the error bars.|
267| "E5" | Like E3 but ignore the bins with 0 contents.|
268| "E6" | Like E4 but ignore the bins with 0 contents.|
269| "X0" | When used with one of the "E" option, it suppress the error bar along X as `gStyle->SetErrorX(0)` would do.|
270| "L" | Draw a line through the bin contents.|
271| "P" | Draw current marker at each bin except empty bins.|
272| "P*" | Draw a star marker at each bin except empty bins.|
273| "P0" | Draw current marker at each bin including empty bins.|
274| "PIE" | Draw histogram as a Pie Chart.|
275| "*H" | Draw histogram with a * at each bin.|
276| "LF2" | Draw histogram like with option "L" but with a fill area. Note that "L" draws also a fill area if the hist fill color is set but the fill area corresponds to the histogram contour.|
277
278
279
280\anchor HP01c
281#### Options supported for 2D histograms
282
283| Option | Description |
284|--------------|------------------------------------------------------------------|
285| " " | Default (color plot).|
286| "ARR" | Arrow mode. Shows gradient between adjacent cells.|
287| "BOX" | A box is drawn for each cell with surface proportional to the content's absolute value. A negative content is marked with a X. |
288| "BOX1" | A button is drawn for each cell with surface proportional to content's absolute value. A sunken button is drawn for negative values a raised one for positive.|
289| "COL" | A box is drawn for each cell with a color scale varying with contents. All the none empty bins (bins with content and error equal to 0) are painted. Empty bins are not painted unless some bins have a negative content because in that case the null bins might be not empty. `TProfile2D` histograms are handled differently because, for this type of 2D histograms, it is possible to know if an empty bin has been filled or not. So even if all the bins' contents are positive some empty bins might be painted. And vice versa, if some bins have a negative content some empty bins might be not painted (default).|
290| "COL1" | Same as "COL" but in case of histogram with negative content the empty bins are not drawn.
291| "COLZ" | Same as "COL". In addition the color palette is also drawn.|
292| "COL2" | Alternative rendering algorithm to "COL". Can significantly improve rendering performance for large, non-sparse 2-D histograms.|
293| "COLZ2" | Same as "COL2". In addition the color palette is also drawn.|
294| "Z CJUST" | In combination with colored options "COL","CONT0" etc: Justify labels in the color palette at color boundaries. For more details see `TPaletteAxis`|
295| "CANDLE" | Draw a candle plot along X axis.|
296| "CANDLEX" | Same as "CANDLE".|
297| "CANDLEY" | Draw a candle plot along Y axis.|
298| "CANDLEXn" | Draw a candle plot along X axis. Different candle-styles with n from 1 to 6.|
299| "CANDLEYn" | Draw a candle plot along Y axis. Different candle-styles with n from 1 to 6.|
300| "VIOLIN" | Draw a violin plot along X axis.|
301| "VIOLINX" | Same as "VIOLIN".|
302| "VIOLINY" | Draw a violin plot along Y axis.|
303| "VIOLINXn" | Draw a violin plot along X axis. Different violin-styles with n being 1 or 2.|
304| "VIOLINYn" | Draw a violin plot along Y axis. Different violin-styles with n being 1 or 2.|
305| "CONT" | Draw a contour plot (same as CONT0).|
306| "CONT0" | Draw a contour plot using surface colors to distinguish contours.|
307| "CONT1" | Draw a contour plot using line styles to distinguish contours.|
308| "CONT2" | Draw a contour plot using the same line style for all contours.|
309| "CONT3" | Draw a contour plot using fill area colors.|
310| "CONT4" | Draw a contour plot using surface colors (SURF option at theta = 0).|
311| "LIST" | Generate a list of TGraph objects for each contour.|
312| "SAME0" | Same as "SAME" but do not use the z-axis range of the first plot. |
313| "SAMES0" | Same as "SAMES" but do not use the z-axis range of the first plot. |
314| "CYL" | Use Cylindrical coordinates. The X coordinate is mapped on the angle and the Y coordinate on the cylinder length.|
315| "POL" | Use Polar coordinates. The visible X range mapped on the angle and the visible Y coordinate on the radius.|
316| "POLF" | Fixed Polar coordinates. The histogram X coordinate mapped on the angle and the Y coordinate on the radius.|
317| "POLN" | Natural Polar coordinates. The X coordinate directly represent angle in radian and the Y coordinate is the radius.|
318| "SPH" | Use Spherical coordinates. The X coordinate is mapped on the latitude and the Y coordinate on the longitude.|
319| "PSR" | Use PseudoRapidity/Phi coordinates. The X coordinate is mapped on Phi.|
320| "SURF" | Draw a surface plot with hidden line removal.|
321| "SURF1" | Draw a surface plot with hidden surface removal.|
322| "SURF2" | Draw a surface plot using colors to show the cell contents.|
323| "SURF3" | Same as SURF with in addition a contour view drawn on the top.|
324| "SURF4" | Draw a surface using Gouraud shading.|
325| "SURF5" | Same as SURF3 but only the colored contour is drawn. Used with option CYL, SPH or PSR it allows to draw colored contours on a sphere, a cylinder or a in pseudo rapidity space. In cartesian or polar coordinates, option SURF3 is used.|
326| "AITOFF" | Draw a contour via an AITOFF projection.|
327| "MERCATOR" | Draw a contour via an Mercator projection.|
328| "SINUSOIDAL" | Draw a contour via an Sinusoidal projection.|
329| "PARABOLIC" | Draw a contour via an Parabolic projection.|
330| "MOLLWEIDE" | Draw a contour via an Mollweide projection.|
331| "LEGO9" | Draw the 3D axis only. Mainly needed for internal use |
332| "FB" | With LEGO or SURFACE, suppress the Front-Box.|
333| "BB" | With LEGO or SURFACE, suppress the Back-Box.|
334| "A" | With LEGO or SURFACE, suppress the axis.|
335| "SCAT" | Draw a scatter-plot (legacy draw option).|
336| "[cutg]" | Draw only the sub-range selected by the TCutG named "cutg".|
337
338
339
340\anchor HP01d
341#### Options supported for 3D histograms
342
343| Option | Description |
344|----------|-------------------------------------------------------------------|
345| " " | Default (color plot).|
346| "ISO" | Draw a Gouraud shaded 3d iso surface through a 3d histogram. It paints one surface at the value computed as follow: `SumOfWeights/(NbinsX*NbinsY*NbinsZ)`.|
347| "BOX" | Draw a for each cell with volume proportional to the content's absolute value. An hidden line removal algorithm is used|
348| "BOX1" | Same as BOX but an hidden surface removal algorithm is used|
349| "BOX2" | The boxes' colors are picked in the current palette according to the bins' contents|
350| "BOX2Z" | Same as "BOX2". In addition the color palette is also drawn.|
351| "BOX3" | Same as BOX1, but the border lines of each lego-bar are not drawn.|
352| "LEGO" | Same as `BOX`.|
353
354\anchor HP01e
355#### Options supported for histograms' stacks (`THStack`)
356
357| Option | Description |
358|------------|-----------------------------------------------------------------|
359| " " | Default, the histograms are drawn on top of each other (as lego plots for 2D histograms).|
360| "NOSTACK" | Histograms in the stack are all paint in the same pad as if the option `SAME` had been specified.|
361| "NOSTACKB" | Histograms are drawn next to each other as bar charts.|
362| "PADS" | The current pad/canvas is subdivided into a number of pads equal to the number of histograms in the stack and each histogram is paint into a separate pad.|
363| "PADSn" | Like PADS but the current pad/canvas is subdivided into a `n` columns, automatically calculating the number of rows.|
364| "PFC" | Palette Fill Color: stack's fill color is taken in the current palette. |
365| "PLC" | Palette Line Color: stack's line color is taken in the current palette. |
366| "PMC" | Palette Marker Color: stack's marker color is taken in the current palette. |
367
368
369
370\anchor HP02
371### Setting the Style
372
373
374Histograms use the current style (`gStyle`). When one changes the current
375style and would like to propagate the changes to the histogram,
376`TH1::UseCurrentStyle` should be called. Call `UseCurrentStyle` on
377each histogram is needed.
378
379To force all the histogram to use the current style use:
380
381 gROOT->ForceStyle();
382
383All the histograms read after this call will use the current style.
384
385
386\anchor HP03
387### Setting line, fill, marker, and text attributes
388
389
390The histogram classes inherit from the attribute classes:
391`TAttLine`, `TAttFill` and `TAttMarker`.
392See the description of these classes for the list of options.
393
394
395\anchor HP04
396### Setting Tick marks on the histogram axis
397
398
399The `TPad::SetTicks` method specifies the type of tick marks on the axis.
400If ` tx = gPad->GetTickx()` and `ty = gPad->GetTicky()` then:
401
402 tx = 1; tick marks on top side are drawn (inside)
403 tx = 2; tick marks and labels on top side are drawn
404 ty = 1; tick marks on right side are drawn (inside)
405 ty = 2; tick marks and labels on right side are drawn
406
407By default only the left Y axis and X bottom axis are drawn
408(`tx = ty = 0`)
409
410`TPad::SetTicks(tx,ty)` allows to set these options.
411See also The `TAxis` functions to set specific axis attributes.
412
413In case multiple color filled histograms are drawn on the same pad, the fill
414area may hide the axis tick marks. One can force a redraw of the axis over all
415the histograms by calling:
416
417 gPad->RedrawAxis();
418
419
420\anchor HP05
421### Giving titles to the X, Y and Z axis
422
423
424 h->GetXaxis()->SetTitle("X axis title");
425 h->GetYaxis()->SetTitle("Y axis title");
426
427The histogram title and the axis titles can be any `TLatex` string.
428The titles are part of the persistent histogram.
429
430
431\anchor HP060
432### The option "SAME"
433
434
435By default, when an histogram is drawn, the current pad is cleared before
436drawing. In order to keep the previous drawing and draw on top of it the
437option `SAME` should be use. The histogram drawn with the option
438`SAME` uses the coordinates system available in the current pad.
439
440This option can be used alone or combined with any valid drawing option but
441some combinations must be use with care.
442
443\anchor HP060a
444#### Limitations
445
446- It does not work when combined with the `LEGO` and `SURF` options unless the
447 histogram plotted with the option `SAME` has exactly the same
448 ranges on the X, Y and Z axis as the currently drawn histogram. To superimpose
449 lego plots [histograms' stacks](\ref HP26) should be used.
450
451
452\anchor HP061
453### Colors automatically picked in palette
454
455\since **ROOT version 6.09/01**
456
457When several histograms are painted in the same canvas thanks to the option "SAME"
458or via a `THStack` it might be useful to have an easy and automatic way to choose
459their color. The simplest way is to pick colors in the current active color
460palette. Palette coloring for histogram is activated thanks to the options `PFC`
461(Palette Fill Color), `PLC` (Palette Line Color) and `PMC` (Palette Marker Color).
462When one of these options is given to `TH1::Draw` the histogram get its color
463from the current color palette defined by `gStyle->SetPalette(...)`. The color
464is determined according to the number of objects having palette coloring in
465the current pad.
466
467Begin_Macro(source)
468../../../tutorials/hist/hist005_TH1_palettecolor.C
469End_Macro
470
471Begin_Macro(source)
472../../../tutorials/hist/hist027_THStack_palette_color.C
473End_Macro
474
475Begin_Macro(source)
476../../../tutorials/hist/hist025_THStack_2d_palette_color.C
477End_Macro
478
479\anchor HP06
480### Superimposing two histograms with different scales in the same pad
481
482
483The following example creates two histograms, the second histogram is the bins
484integral of the first one. It shows a procedure to draw the two histograms in
485the same pad and it draws the scale of the second histogram using a new vertical
486axis on the right side. See also the tutorial `transpad.C` for a variant
487of this example.
488
489Begin_Macro(source)
490{
491 auto c1 = new TCanvas("c1","c1",600,400);
492 // create/fill draw h1
493 gStyle->SetOptStat(kFALSE);
494 auto h1 = new TH1F("h1","Superimposing two histograms with different scales",100,-3,3);
495 Int_t i;
496 for (i=0;i<10000;i++) h1->Fill(gRandom->Gaus(0,1));
497 h1->Draw();
498 c1->Update();
499
500 // create hint1 filled with the bins integral of h1
501 auto hint1 = new TH1F("hint1","h1 bins integral",100,-3,3);
502 float sum = 0.f;
503 for (i=1;i<=100;i++) {
504 sum += h1->GetBinContent(i);
505 hint1->SetBinContent(i,sum);
506 }
507
508 // scale hint1 to the pad coordinates
509 float rightmax = 1.1*hint1->GetMaximum();
510 float scale = gPad->GetUymax()/rightmax;
511 hint1->SetLineColor(kRed);
512 hint1->Scale(scale);
513 hint1->Draw("same");
514
515 // draw an axis on the right side
516 auto axis = new TGaxis(gPad->GetUxmax(),gPad->GetUymin(),
517 gPad->GetUxmax(), gPad->GetUymax(),0,rightmax,510,"+L");
518 axis->SetLineColor(kRed);
519 axis->SetTextColor(kRed);
520 axis->Draw();
521}
522End_Macro
523
524
525\anchor HP07
526### Statistics Display
527
528
529The type of information shown in the histogram statistics box can be selected
530with:
531
532 gStyle->SetOptStat(mode);
533
534The `mode` has up to nine digits that can be set to on (1 or 2), off (0).
535
536 mode = ksiourmen (default = 000001111)
537 k = 1; kurtosis printed
538 k = 2; kurtosis and kurtosis error printed
539 s = 1; skewness printed
540 s = 2; skewness and skewness error printed
541 i = 1; integral of bins printed
542 i = 2; integral of bins with option "width" printed
543 o = 1; number of overflows printed
544 u = 1; number of underflows printed
545 r = 1; standard deviation printed
546 r = 2; standard deviation and standard deviation error printed
547 m = 1; mean value printed
548 m = 2; mean and mean error values printed
549 e = 1; number of entries printed
550 n = 1; name of histogram is printed
551
552For example:
553
554 gStyle->SetOptStat(11);
555
556displays only the name of histogram and the number of entries, whereas:
557
558 gStyle->SetOptStat(1101);
559
560displays the name of histogram, mean value and standard deviation.
561
562<b>WARNING 1:</b> never do:
563
564 gStyle->SetOptStat(0001111);
565
566but instead do:
567
568 gStyle->SetOptStat(1111);
569
570because `0001111` will be taken as an octal number!
571
572<b>WARNING 2:</b> for backward compatibility with older versions
573
574 gStyle->SetOptStat(1);
575
576is taken as:
577
578 gStyle->SetOptStat(1111)
579
580To print only the name of the histogram do:
581
582 gStyle->SetOptStat(1000000001);
583
584<b>NOTE</b> that in case of 2D histograms, when selecting only underflow
585(10000) or overflow (100000), the statistics box will show all combinations
586of underflow/overflows and not just one single number.
587
588The parameter mode can be any combination of the letters `kKsSiIourRmMen`
589
590 k : kurtosis printed
591 K : kurtosis and kurtosis error printed
592 s : skewness printed
593 S : skewness and skewness error printed
594 i : integral of bins printed
595 I : integral of bins with option "width" printed
596 o : number of overflows printed
597 u : number of underflows printed
598 r : standard deviation printed
599 R : standard deviation and standard deviation error printed
600 m : mean value printed
601 M : mean value mean error values printed
602 e : number of entries printed
603 n : name of histogram is printed
604
605For example, to print only name of histogram and number of entries do:
606
607 gStyle->SetOptStat("ne");
608
609To print only the name of the histogram do:
610
611 gStyle->SetOptStat("n");
612
613The default value is:
614
615 gStyle->SetOptStat("nemr");
616
617When a histogram is painted, a `TPaveStats` object is created and added
618to the list of functions of the histogram. If a `TPaveStats` object
619already exists in the histogram list of functions, the existing object is just
620updated with the current histogram parameters.
621
622Once a histogram is painted, the statistics box can be accessed using
623`h->FindObject("stats")`. In the command line it is enough to do:
624
625 Root > h->Draw()
626 Root > TPaveStats *st = (TPaveStats*)h->FindObject("stats")
627
628because after `h->Draw()` the histogram is automatically painted. But
629in a script file the painting should be forced using `gPad->Update()`
630in order to make sure the statistics box is created:
631
632 h->Draw();
633 gPad->Update();
634 TPaveStats *st = (TPaveStats*)h->FindObject("stats");
635
636Without `gPad->Update()` the line `h->FindObject("stats")` returns a null pointer.
637
638When a histogram is drawn with the option `SAME`, the statistics box
639is not drawn. To force the statistics box drawing with the option
640`SAME`, the option `SAMES` must be used.
641If the new statistics box hides the previous statistics box, one can change
642its position with these lines (`h` being the pointer to the histogram):
643
644 Root > TPaveStats *st = (TPaveStats*)h->FindObject("stats")
645 Root > st->SetX1NDC(newx1); //new x start position
646 Root > st->SetX2NDC(newx2); //new x end position
647
648To change the type of information for an histogram with an existing
649`TPaveStats` one should do:
650
651 st->SetOptStat(mode);
652
653Where `mode` has the same meaning than when calling `gStyle->SetOptStat(mode)`
654(see above).
655
656One can delete the statistics box for a histogram `TH1* h` with:
657
658 h->SetStats(0)
659
660and activate it again with:
661
662 h->SetStats(1).
663
664Labels used in the statistics box ("Mean", "Std Dev", ...) can be changed from
665`$ROOTSYS/etc/system.rootrc` or `.rootrc` (look for the string `Hist.Stats.`).
666
667
668\anchor HP08
669### Fit Statistics
670
671
672The type of information about fit parameters printed in the histogram statistics
673box can be selected via the parameter mode. The parameter mode can be
674`= pcev` (default `= 0111`)
675
676 p = 1; print Probability
677 c = 1; print Chisquare/Number of degrees of freedom
678 e = 1; print errors (if e=1, v must be 1)
679 v = 1; print name/values of parameters
680
681Example:
682
683 gStyle->SetOptFit(1011);
684
685print fit probability, parameter names/values and errors.
686
6871. When `v = 1` is specified, only the non-fixed parameters are shown.
6882. When `v = 2` all parameters are shown.
689
690Note: `gStyle->SetOptFit(1)` means "default value", so it is equivalent
691to `gStyle->SetOptFit(111)`
692
693
694\anchor HP09
695### The error bars options
696
697
698| Option | Description |
699|----------|-------------------------------------------------------------------|
700| "E" | Default. Shows only the error bars, not a marker.|
701| "E1" | Small lines are drawn at the end of the error bars.|
702| "E2" | Error rectangles are drawn.|
703| "E3" | A filled area is drawn through the end points of the vertical error bars.|
704| "E4" | A smoothed filled area is drawn through the end points of the vertical error bars.|
705| "E0" | Draw error bars. Markers are drawn for bins with 0 contents. Combined with E1 or E2 it avoids error bars clipping|
706| "E5" | Like E3 but ignore the bins with 0 contents.|
707| "E6" | Like E4 but ignore the bins with 0 contents.|
708| "X0" | When used with one of the "E" option, it suppress the error bar along X as `gStyle->SetErrorX(0)` would do.|
709
710Begin_Macro(source)
711{
712 auto c1 = new TCanvas("c1","c1",600,400);
713 auto he = new TH1F("he","Distribution drawn with error bars (option E1) ",100,-3,3);
714 for (int i=0; i<10000; i++) he->Fill(gRandom->Gaus(0,1));
715 gStyle->SetEndErrorSize(3);
716 gStyle->SetErrorX(1.);
717 he->SetMarkerStyle(20);
718 he->Draw("E1");
719}
720End_Macro
721
722The options "E3" and "E4" draw an error band through the end points of the
723vertical error bars. With "E4" the error band is smoothed. Because of the
724smoothing algorithm used some artefacts may appear at the end of the band
725like in the following example. In such cases "E3" should be used instead
726of "E4".
727
728Begin_Macro(source)
729{
730 auto ce4 = new TCanvas("ce4","ce4",600,400);
731 ce4->Divide(2,1);
732 auto he4 = new TH1F("he4","Distribution drawn with option E4",100,-3,3);
733 Int_t i;
734 for (i=0;i<10000;i++) he4->Fill(gRandom->Gaus(0,1));
735 he4->SetFillColor(kRed);
736 he4->GetXaxis()->SetRange(40,48);
737 ce4->cd(1);
738 he4->Draw("E4");
739 ce4->cd(2);
740 auto he3 = (TH1F*)he4->DrawClone("E3");
741 he3->SetTitle("Distribution drawn option E3");
742}
743End_Macro
744
7452D histograms can be drawn with error bars as shown is the following example:
746
747Begin_Macro(source)
748{
749 auto c2e = new TCanvas("c2e","c2e",600,400);
750 auto h2e = new TH2F("h2e","TH2 drawn with option E",40,-4,4,40,-20,20);
751 float px, py;
752 for (Int_t i = 0; i < 25000; i++) {
753 gRandom->Rannor(px,py);
754 h2e->Fill(px,5*py);
755 }
756 h2e->Draw("E");
757}
758End_Macro
759
760
761\anchor HP100
762### The bar chart option
763
764
765The option "B" allows to draw simple vertical bar charts.
766The bar width is controlled with `TH1::SetBarWidth()`,
767and the bar offset within the bin, with `TH1::SetBarOffset()`.
768These two settings are useful to draw several histograms on the
769same plot as shown in the following example:
770
771Begin_Macro(source)
772{
773 int i;
774 const Int_t nx = 8;
775 string os_X[nx] = {"8","32","128","512","2048","8192","32768","131072"};
776 float d_35_0[nx] = {0.75, -3.30, -0.92, 0.10, 0.08, -1.69, -1.29, -2.37};
777 float d_35_1[nx] = {1.01, -3.02, -0.65, 0.37, 0.34, -1.42, -1.02, -2.10};
778
779 auto cb = new TCanvas("cb","cb",600,400);
780 cb->SetGrid();
781
782 gStyle->SetHistMinimumZero();
783
784 auto h1b = new TH1F("h1b","Option B example",nx,0,nx);
785 h1b->SetFillColor(4);
786 h1b->SetBarWidth(0.4);
787 h1b->SetBarOffset(0.1);
788 h1b->SetStats(0);
789 h1b->SetMinimum(-5);
790 h1b->SetMaximum(5);
791
792 for (i=1; i<=nx; i++) {
793 h1b->SetBinContent(i, d_35_0[i-1]);
794 h1b->GetXaxis()->SetBinLabel(i,os_X[i-1].c_str());
795 }
796
797 h1b->Draw("b");
798
799 auto h2b = new TH1F("h2b","h2b",nx,0,nx);
800 h2b->SetFillColor(38);
801 h2b->SetBarWidth(0.4);
802 h2b->SetBarOffset(0.5);
803 h2b->SetStats(0);
804 for (i=1;i<=nx;i++) h2b->SetBinContent(i, d_35_1[i-1]);
805
806 h2b->Draw("b same");
807}
808End_Macro
809
810
811\anchor HP10
812### The "BAR" and "HBAR" options
813
814
815When the option `bar` or `hbar` is specified, a bar chart is drawn. A vertical
816bar-chart is drawn with the options `bar`, `bar0`, `bar1`, `bar2`, `bar3`, `bar4`.
817An horizontal bar-chart is drawn with the options `hbar`, `hbar0`, `hbar1`,
818`hbar2`, `hbar3`, `hbar4` (hist006_TH1_bar_charts.C).
819
820- The bar is filled with the histogram fill color.
821- The left side of the bar is drawn with a light fill color.
822- The right side of the bar is drawn with a dark fill color.
823- The percentage of the bar drawn with either the light or dark color is:
824 - 0% for option "(h)bar" or "(h)bar0"
825 - 10% for option "(h)bar1"
826 - 20% for option "(h)bar2"
827 - 30% for option "(h)bar3"
828 - 40% for option "(h)bar4"
829
830When an histogram has errors the option ["HIST"](\ref OPTHIST) together with the `(h)bar` option.
831
832Begin_Macro(source)
833../../../tutorials/hist/hist006_TH1_bar_charts.C
834End_Macro
835
836To control the bar width (default is the bin width) `TH1::SetBarWidth()`
837should be used.
838
839To control the bar offset (default is 0) `TH1::SetBarOffset()` should
840be used.
841
842These two parameters are useful when several histograms are plotted using
843the option `SAME`. They allow to plot the histograms next to each other.
844
845
846\anchor HP11
847### The SCATter plot option (legacy draw option)
848
849\attention
850Use of option `SCAT` has been deprecated. It was the default drawing option for 2D and
8513D histograms. The new default option is `COL` (heat-map).
852
853
854For each cell (i,j) a number of points proportional to the cell content is
855drawn. A maximum of `kNMAX` points per cell is drawn. If the maximum is above
856`kNMAX` contents are normalized to `kNMAX` (`kNMAX=2000`).
857If option is of the form `scat=ff`, (eg `scat=1.8`,
858`scat=1e-3`), then `ff` is used as a scale factor to compute the
859number of dots. `scat=1` is the default.
860
861By default the scatter plot is painted with a "dot marker" which not scalable
862(see the `TAttMarker` documentation). To change the marker size, a scalable marker
863type should be used. For instance a circle (marker style 20).
864
865Begin_Macro(source)
866{
867 auto c1 = new TCanvas("c1","c1",600,400);
868 auto hscat = new TH2F("hscat","Option SCATter example (default for 2D histograms) ",40,-4,4,40,-20,20);
869 float px, py;
870 for (Int_t i = 0; i < 25000; i++) {
871 gRandom->Rannor(px,py);
872 hscat->Fill(px,5*py);
873 hscat->Fill(3+0.5*px,2*py-10.);
874 }
875 hscat->Draw("scat=0.5"); // This a legacy draw option. Please consider using TScatter
876}
877End_Macro
878
879
880\anchor HP12
881### The ARRow option
882
883
884Shows gradient between adjacent cells. For each cell (i,j) an arrow is drawn
885The orientation of the arrow follows the cell gradient.
886
887Begin_Macro(source)
888{
889 auto c1 = new TCanvas("c1","c1",600,400);
890 auto harr = new TH2F("harr","Option ARRow example",20,-4,4,20,-20,20);
891 harr->SetLineColor(kRed);
892 float px, py;
893 for (Int_t i = 0; i < 25000; i++) {
894 gRandom->Rannor(px,py);
895 harr->Fill(px,5*py);
896 harr->Fill(3+0.5*px,2*py-10.,0.1);
897 }
898 harr->Draw("ARR");
899}
900End_Macro
901
902\since **ROOT version 6.17/01**
903
904The option `ARR` can be combined with the option `COL` or `COLZ`.
905
906Begin_Macro(source)
907{
908 auto c1 = new TCanvas("c1","c1",600,400);
909 auto harr = new TH2F("harr","Option ARR + COLZ example",20,-4,4,20,-20,20);
910 harr->SetStats(0);
911 float px, py;
912 for (Int_t i = 0; i < 25000; i++) {
913 gRandom->Rannor(px,py);
914 harr->Fill(px,5*py);
915 harr->Fill(3+0.5*px,2*py-10.,0.1);
916 }
917 harr->Draw("ARR COLZ");
918}
919End_Macro
920
921
922\anchor HP13
923### The BOX option
924
925
926For each cell (i,j) a box is drawn. The size (surface) of the box is
927proportional to the absolute value of the cell content.
928The cells with a negative content are drawn with a `X` on top of the box.
929
930Begin_Macro(source)
931{
932 auto c1 = new TCanvas("c1","c1",600,400);
933 auto hbox = new TH2F("hbox","Option BOX example",3,0,3,3,0,3);
934 hbox->SetFillColor(42);
935 hbox->Fill(0.5, 0.5, 1.);
936 hbox->Fill(0.5, 1.5, 4.);
937 hbox->Fill(0.5, 2.5, 3.);
938 hbox->Fill(1.5, 0.5, 2.);
939 hbox->Fill(1.5, 1.5, 12.);
940 hbox->Fill(1.5, 2.5, -6.);
941 hbox->Fill(2.5, 0.5, -4.);
942 hbox->Fill(2.5, 1.5, 6.);
943 hbox->Fill(2.5, 2.5, 0.5);
944 hbox->Draw("BOX");
945}
946End_Macro
947
948With option `BOX1` a button is drawn for each cell with surface
949proportional to content's absolute value. A sunken button is drawn for
950negative values a raised one for positive.
951
952Begin_Macro(source)
953{
954 auto c1 = new TCanvas("c1","c1",600,400);
955 auto hbox1 = new TH2F("hbox1","Option BOX1 example",3,0,3,3,0,3);
956 hbox1->SetFillColor(42);
957 hbox1->Fill(0.5, 0.5, 1.);
958 hbox1->Fill(0.5, 1.5, 4.);
959 hbox1->Fill(0.5, 2.5, 3.);
960 hbox1->Fill(1.5, 0.5, 2.);
961 hbox1->Fill(1.5, 1.5, 12.);
962 hbox1->Fill(1.5, 2.5, -6.);
963 hbox1->Fill(2.5, 0.5, -4.);
964 hbox1->Fill(2.5, 1.5, 6.);
965 hbox1->Fill(2.5, 2.5, 0.5);
966 hbox1->Draw("BOX1");
967}
968End_Macro
969
970When the option `SAME` (or "SAMES") is used with the option `BOX`,
971the boxes' sizes are computed taking the previous plots into account. The range
972along the Z axis is imposed by the first plot (the one without option
973`SAME`); therefore the order in which the plots are done is relevant.
974
975Begin_Macro(source)
976{
977 auto c1 = new TCanvas("c1","c1",600,400);
978 auto hb1 = new TH2F("hb1","Example of BOX plots with option SAME ",40,-3,3,40,-3,3);
979 auto hb2 = new TH2F("hb2","hb2",40,-3,3,40,-3,3);
980 auto hb3 = new TH2F("hb3","hb3",40,-3,3,40,-3,3);
981 auto hb4 = new TH2F("hb4","hb4",40,-3,3,40,-3,3);
982 for (Int_t i=0;i<1000;i++) {
983 double x,y;
984 gRandom->Rannor(x,y);
985 if (x>0 && y>0) hb1->Fill(x,y,4);
986 if (x<0 && y<0) hb2->Fill(x,y,3);
987 if (x>0 && y<0) hb3->Fill(x,y,2);
988 if (x<0 && y>0) hb4->Fill(x,y,1);
989 }
990 hb1->SetFillColor(1);
991 hb2->SetFillColor(2);
992 hb3->SetFillColor(3);
993 hb4->SetFillColor(4);
994 hb1->Draw("box");
995 hb2->Draw("box same");
996 hb3->Draw("box same");
997 hb4->Draw("box same");
998}
999End_Macro
1000
1001\since **ROOT version 6.17/01:**
1002
1003Sometimes the change of the range of the Z axis is unwanted, in which case, one
1004can use `SAME0` (or `SAMES0`) option to opt out of this change.
1005
1006Begin_Macro(source)
1007{
1008 auto h2 = new TH2F("h2"," ",10,0,10,10,20,30);
1009 auto hf = (TH2F*)h2->Clone("hf");
1010 h2->SetBit(TH1::kNoStats);
1011 hf->SetBit(TH1::kNoStats);
1012 h2->Fill(5,22);
1013 h2->Fill(5,23);
1014 h2->Fill(6,22);
1015 h2->Fill(6,23);
1016 hf->Fill(6,23);
1017 hf->Fill(6,23);
1018 hf->Fill(6,23);
1019 hf->Fill(6,23);
1020 hf->Fill(5,23);
1021
1022 auto hf_copy1 = hf->Clone("hf_copy1");
1023 TLatex lt;
1024
1025 auto cx = new TCanvas(); cx->Divide(2,1);
1026
1027 cx->cd(1);
1028 h2->Draw("box");
1029 hf->Draw("text colz same");
1030 lt.DrawLatexNDC(0.3,0.5,"SAME");
1031
1032 cx->cd(2);
1033 h2->Draw("box");
1034 hf_copy1->Draw("text colz same0");
1035 lt.DrawLatexNDC(0.3,0.5,"SAME0");
1036}
1037End_Macro
1038
1039
1040\anchor HP14
1041### The COLor option (default for 2D histograms)
1042
1043The magnitude of individual cell (i,j) is represented as a color picked in the current color palette.
1044This data visualization technique is often called a heat map (or heat-map).
1045
1046The color table used is defined in the current style.
1047
1048If the histogram's minimum and maximum are the same (flat histogram), the
1049mapping on colors is not possible, therefore nothing is painted. To paint a
1050flat histogram it is enough to set the histogram minimum
1051(`TH1::SetMinimum()`) different from the bins' content.
1052
1053The default number of color levels used to paint the cells is 20.
1054It can be changed with `TH1::SetContour()` or
1055`TStyle::SetNumberContours()`. The higher this number is, the smoother
1056is the color change between cells.
1057
1058The color palette in TStyle can be modified via `gStyle->SetPalette()`.
1059
1060All the non-empty bins are painted. Empty bins (bins with content and error equal to 0) are
1061not painted unless some bins have a negative content because in that case the null bins
1062might be not empty.
1063
1064`TProfile2D` histograms are handled differently because, for this type of 2D
1065histograms, it is possible to know if an empty bin has been filled or not. So even
1066if all the bins' contents are positive some empty bins might be painted. And vice versa,
1067if some bins have a negative content some empty bins might be not painted.
1068
1069Combined with the option `COL`, the option `Z` allows to
1070display the color palette defined by `gStyle->SetPalette()`.
1071
1072In the following example, the histogram has only positive bins; the empty
1073bins (containing 0) are not drawn.
1074
1075Begin_Macro(source)
1076{
1077 auto c1 = new TCanvas("c1","c1",600,400);
1078 auto hcol1 = new TH2F("hcol1","Option COLor example ",40,-4,4,40,-20,20);
1079 float px, py;
1080 for (Int_t i = 0; i < 25000; i++) {
1081 gRandom->Rannor(px,py);
1082 hcol1->Fill(px,5*py);
1083 }
1084 hcol1->Draw("COLZ");
1085}
1086End_Macro
1087
1088In the first plot of following example, the histogram has some negative bins;
1089the empty bins (containing 0) are drawn. In some cases one wants to not draw
1090empty bins (containing 0) of histograms having a negative minimum. The option
1091`1`, used to produce the second plot in the following picture, allows to do that.
1092
1093Begin_Macro(source)
1094{
1095 auto c1 = new TCanvas("c1","c1",600,600);
1096 c1->Divide(1,2);
1097 auto hcol23 = new TH2F("hcol23","Option COLZ example ",40,-4,4,40,-20,20);
1098 auto hcol24 = new TH2F("hcol24","Option COLZ1 example ",40,-4,4,40,-20,20);
1099 float px, py;
1100 for (Int_t i = 0; i < 25000; i++) {
1101 gRandom->Rannor(px,py);
1102 hcol23->Fill(px,5*py);
1103 hcol24->Fill(px,5*py);
1104 }
1105 hcol23->Fill(0.,0.,-200.);
1106 hcol24->Fill(0.,0.,-200.);
1107 c1->cd(1); hcol23->Draw("COLZ");
1108 c1->cd(2); hcol24->Draw("COLZ1");
1109}
1110End_Macro
1111
1112When the maximum of the histogram is set to a smaller value than the real maximum,
1113 the bins having a content between the new maximum and the real maximum are
1114painted with the color corresponding to the new maximum.
1115
1116When the minimum of the histogram is set to a greater value than the real minimum,
1117 the bins having a value between the real minimum and the new minimum are not drawn
1118 unless the option `0` is set.
1119In other words, option `COLZ0` forces the painting of bins with content < set minimum with
1120 a color corresponding to the set minimum. In contrast, option `COLZ` would not draw values
1121 smaller than the specified minimum. Note that both `COLZ` and `COLZ0` still do not draw
1122 empty bins, ie bins with `content == error == 0`, if the set min is not negative.
1123(Note that option `COLZ0` for TH2Poly has a different behavior than for TH2.)
1124
1125The following example illustrates the option `0` combined with the option `COL`.
1126
1127Begin_Macro(source)
1128{
1129 auto c1 = new TCanvas("c1","c1",600,600);
1130 c1->Divide(1,2);
1131 auto hcol21 = new TH2F("hcol21","Option COLZ",40,-4,4,40,-20,20);
1132 auto hcol22 = new TH2F("hcol22","Option COLZ0",40,-4,4,40,-20,20);
1133 float px, py;
1134 for (Int_t i = 0; i < 25000; i++) {
1135 gRandom->Rannor(px,py);
1136 hcol21->Fill(px,5*py);
1137 hcol22->Fill(px,5*py);
1138 }
1139 hcol21->SetBit(TH1::kNoStats);
1140 hcol22->SetBit(TH1::kNoStats);
1141 c1->cd(1); hcol21->Draw("COLZ");
1142 c1->cd(2); hcol22->Draw("COLZ0");
1143 hcol21->SetMaximum(100);
1144 hcol21->SetMinimum(40);
1145 hcol22->SetMaximum(100);
1146 hcol22->SetMinimum(40);
1147}
1148End_Macro
1149
1150Note that the behavior of `COLZ` is not symmetric: it does not draw values below the specified minimum,
1151but does draw values above the specified maximum by clipping them to the maximum color. In contrast, `COLZ0`
1152clips color on both lower and upper sides. Both `COLZ0` and `COLZ` exclude drawing empty bins (`content == error == 0`),
1153if the set minimum is not negative.
1154
1155\since **ROOT version 6.09/01:**
1156
1157When the option SAME (or "SAMES") is used with the option COL, the boxes' color
1158are computed taking the previous plots into account. The range along the Z axis
1159is imposed by the first plot (the one without option SAME); therefore the order
1160in which the plots are done is relevant. Same as [in the `BOX` option](\ref HP13), one can use
1161`SAME0` (or `SAMES0`) to opt out of this imposition.
1162
1163Begin_Macro(source)
1164{
1165 auto c = new TCanvas("c","Example of col plots with option SAME",200,10,700,500);
1166 auto h1 = new TH2F("h1","h1",40,-3,3,40,-3,3);
1167 auto h2 = new TH2F("h2","h2",40,-3,3,40,-3,3);
1168 auto h3 = new TH2F("h3","h3",40,-3,3,40,-3,3);
1169 auto h4 = new TH2F("h4","h4",40,-3,3,40,-3,3);
1170 h1->SetBit(TH1::kNoStats);
1171 for (Int_t i=0;i<5000;i++) {
1172 double x,y;
1173 gRandom->Rannor(x,y);
1174 if(x>0 && y>0) h1->Fill(x,y,4);
1175 if(x<0 && y<0) h2->Fill(x,y,3);
1176 if(x>0 && y<0) h3->Fill(x,y,2);
1177 if(x<0 && y>0) h4->Fill(x,y,1);
1178 }
1179 h1->Draw("colz");
1180 h2->Draw("col same");
1181 h3->Draw("col same");
1182 h4->Draw("col same");
1183}
1184End_Macro
1185
1186The option `COL` can be combined with the option `POL`:
1187
1188Begin_Macro(source)
1189{
1190 auto c1 = new TCanvas("c1","c1",600,400);
1191 auto hcol1 = new TH2F("hcol1","Option COLor combined with POL",40,-4,4,40,-4,4);
1192 float px, py;
1193 for (Int_t i = 0; i < 25000; i++) {
1194 gRandom->Rannor(px,py);
1195 hcol1->Fill(px,py);
1196 }
1197 hcol1->Draw("COLZPOL");
1198}
1199End_Macro
1200
1201\since **ROOT version 6.07/03:**
1202
1203A second rendering technique is also available with the COL2 and COLZ2 options.
1204
1205These options provide potential performance improvements compared to the standard
1206COL option. The performance comparison of the COL2 to the COL option depends on
1207the histogram and the size of the rendering region in the current pad. In general,
1208a small (approx. less than 100 bins per axis), sparsely populated TH2 will render
1209faster with the COL option.
1210
1211However, for larger histograms (approx. more than 100 bins per axis)
1212that are not sparse, the COL2 option will provide up to 20 times performance improvements.
1213For example, a 1000x1000 bin TH2 that is not sparse will render an order of magnitude
1214faster with the COL2 option.
1215
1216The COL2 option will also scale its performance based on the size of the
1217pixmap the histogram image is being rendered into. It also is much better optimized for
1218sessions where the user is forwarding X11 windows through an `ssh` connection.
1219
1220For the most part, the COL2 and COLZ2 options are a drop in replacement to the COL
1221and COLZ options. There is one major difference and that concerns the treatment of
1222bins with zero content. The COL2 and COLZ2 options color these bins the color of zero.
1223
1224COL2 option renders the histogram as a bitmap. Therefore it cannot be saved in vector
1225graphics file format like PostScript or PDF (an empty image will be generated). It can
1226be saved only in bitmap files like PNG format for instance.
1227
1228
1229\anchor HP140
1230### The CANDLE and VIOLIN options
1231
1232The mechanism behind Candle plots and Violin plots is very similar. Because of this they are
1233implemented in the same class TCandle. The keywords CANDLE or VIOLIN will initiate the drawing of
1234the corresponding plots. Followed by the keyword the user can select a plot direction (X or V for
1235vertical projections, or Y or H for horizontal projections) and/or predefined definitions
1236(1-6 for candles, 1-2 for violins). The order doesn't matter. Default is X and 1.
1237
1238Instead of using the predefined representations, the candle and violin parameters can be
1239changed individually. In that case the option have the following form:
1240
1241 CANDLEX(<option-string>)
1242 CANDLEY(<option-string>)
1243 VIOLINX(<option-string>)
1244 VIOLINY(<option-string>).
1245
1246All zeros at the beginning of `option-string` can be omitted.
1247
1248`option-string` consists eight values, defined as follow:
1249
1250 "CANDLEX(zhpawMmb)"
1251
1252Where:
1253
1254 - `b = 0`; no box drawn
1255 - `b = 1`; the box is drawn. As the candle-plot is also called a box-plot it
1256 makes sense in the very most cases to always draw the box
1257 - `b = 2`; draw a filled box with border
1258
1259 - `m = 0`; no median drawn
1260 - `m = 1`; median is drawn as a line
1261 - `m = 2`; median is drawn with errors (notches)
1262 - `m = 3`; median is drawn as a circle
1263
1264 - `M = 0`; no mean drawn
1265 - `M = 1`; mean is drawn as a dashed line
1266 - `M = 3`; mean is drawn as a circle
1267
1268 - `w = 0`; no whisker drawn
1269 - `w = 1`; whisker is drawn to end of distribution.
1270 - `w = 2`; whisker is drawn to max 1.5*iqr
1271
1272 - `a = 0`; no anchor drawn
1273 - `a = 1`; the anchors are drawn
1274
1275 - `p = 0`; no points drawn
1276 - `p = 1`; only outliers are drawn
1277 - `p = 2`; all datapoints are drawn
1278 - `p = 3`: all datapoints are drawn scattered
1279
1280 - `h = 0`; no histogram is drawn
1281 - `h = 1`; histogram at the left or bottom side is drawn
1282 - `h = 2`; histogram at the right or top side is drawn
1283 - `h = 3`; histogram at left and right or top and bottom (violin-style) is drawn
1284
1285 - `z = 0`; no zero indicator line is drawn
1286 - `z = 1`; zero indicator line is drawn.
1287
1288As one can see all individual options for both candle and violin plots can be accessed by this
1289mechanism. In deed the keywords CANDLE(<option-string>) and VIOLIN(<option-string>) have the same
1290meaning. So you can parametrise an option-string for a candle plot and use the keywords VIOLIN and
1291vice versa, if you wish.
1292
1293Using a logarithmic x- or y-axis is possible for candle and violin charts.
1294
1295\since **ROOT version 6.11/01**
1296
1297a logarithmic z-axis is possible, too but will only affect violin charts of course.
1298
1299\anchor HP140a
1300#### The CANDLE option
1301
1302<a href="http://en.wikipedia.org/wiki/Box_plot">A Candle plot</a> (also known as
1303a "box plot" or "whisker plot") was invented in 1977 by John Tukey. It is a convenient
1304way to describe graphically a data distribution (D) with only five numbers:
1305
1306 1. The minimum value of the distribution D (bottom or left whisker).
1307 2. The lower quartile (Q1): 25% of the data points in D are less than Q1 (bottom of the box).
1308 3. The median (M): 50% of the data points in D are less than M.
1309 4. The upper quartile (Q3): 75% of the data points in D are less than Q3 (top of the box).
1310 5. The maximum value of the distribution D (top or right whisker).
1311
1312In this implementation a TH2 is considered as a collection of TH1 along
1313X (option `CANDLE` or `CANDLEX`) or Y (option `CANDLEY`).
1314Each TH1 is represented as one candle.
1315
1316Begin_Macro(source)
1317../../../tutorials/hist/hist052_Graphics_candle_plot_whiskers.C
1318End_Macro
1319
1320The candle reduces the information coming from a whole distribution into few values.
1321Independently from the number of entries or the significance of the underlying distribution
1322a candle will always look like a candle. So candle plots should be used carefully in
1323particular with unknown distributions. The definition of a candle is based on
1324__unbinned data__. Here, candles are created from binned data. Because of this, the
1325deviation is connected to the bin width used. The calculation of the quantiles
1326normally done on unbinned data also. Because data are binned, this will
1327only work the best possible way within the resolution of one bin
1328
1329Because of all these facts one should take care that:
1330
1331 - there are enough points per candle
1332 - the bin width is small enough (more bins will increase the maximum
1333 available resolution of the quantiles although there will be some
1334 bins with no entries)
1335 - never make a candle-plot if the underlying distribution is double-distributed
1336 - only create candles of distributions that are more-or-less gaussian (the
1337 MPV should be not too far away from the mean).
1338
1339#### What a candle is made of
1340
1341\since **ROOT version 6.07/05**
1342
1343##### The box
1344The box displays the position of the inter-quantile-range of the underlying
1345distribution. The box contains 25% of the distribution below the median
1346and 25% of the distribution above the median. If the underlying distribution is large
1347enough and gaussian shaped the end-points of the box represent \f$ 0.6745\times\sigma \f$
1348(Where \f$ \sigma \f$ is the standard deviation of the gaussian). The width and
1349the position of the box can be modified by SetBarWidth() and SetBarOffset().
1350The +-25% quantiles are calculated by the GetQuantiles() methods.
1351
1352\since **ROOT version 6.11/01**
1353
1354Using the static function TCandle::SetBoxRange(double) the box definition will be
1355overwritten. E.g. using a box range of 0.68 will redefine the area of the lower box edge
1356to the upper box edge in order to cover 68% of the distribution illustrated by that candle.
1357The static function will affect all candle-charts in the running program.
1358Default is 0.5.
1359
1360Using the static function TCandle::SetScaledCandle(bool) the width of the box (and the
1361whole candle) can be influenced. Deactivated, the width is constant (to be set by
1362SetBarWidth() ). Activated, the width of the boxes will be scaled to each other based on the
1363amount of data in the corresponding candle, the maximum width can be influenced by
1364SetBarWidth(). The static function will affect all candle-charts in the running program.
1365Default is false. Scaling between multiple candle-charts (using "same" or THStack) is not
1366supported, yet
1367
1368##### The Median
1369For a sorted list of numbers, the median is the value in the middle of the list.
1370E.g. if a sorted list is made of five numbers "1,2,3,6,7" 3 will be the median
1371because it is in the middle of the list. If the number of entries is even the
1372average of the two values in the middle will be used. As histograms are binned
1373data, the situation is a bit more complex. The following example shows this:
1374
1375~~~ {.cpp}
1376void quantiles() {
1377 auto h = new TH1I("h","h",10,0,10);
1378 //h->Fill(3);
1379 //h->Fill(3);
1380 h->Fill(4);
1381 h->Draw();
1382 double p = 0.;
1383 double q = 0.;
1384 h->GetQuantiles(1,&q,&p);
1385
1386 cout << "Median is: " << q << std::endl;
1387}
1388~~~
1389
1390Here the bin-width is 1.0. If the two Fill(3) are commented out, as there are currently,
1391the example will return a calculated median of 4.5, because that's the bin center
1392of the bin in which the value 4.0 has been dropped. If the two Fill(3) are not
1393commented out, it will return 3.75, because the algorithm tries to evenly distribute
1394the individual values of a bin with bin content > 0. It means the sorted list
1395would be "3.25, 3.75, 4.5".
1396
1397The consequence is a median of 3.75. This shows how important it is to use a
1398small enough bin-width when using candle-plots on binned data.
1399If the distribution is large enough and gaussian shaped the median will be exactly
1400equal to the mean.
1401The median can be shown as a line or as a circle or not shown at all.
1402
1403In order to show the significance of the median notched candle plots apply a "notch" or
1404narrowing of the box around the median. The significance is defined by
1405\f$ 1.57\times\frac{iqr}{N} \f$ and will be represented as the size of the notch
1406(where iqr is the size of the box and N is the number of entries of the whole
1407distribution). Candle plots like these are usually called "notched candle plots".
1408
1409In case the significance of the median is greater that the size of the box, the
1410box will have an unnatural shape. Usually it means the chart has not enough data,
1411or that representing this uncertainty is not useful
1412
1413##### The Mean
1414The mean can be drawn as a dashed line or as a circle or not drawn at all.
1415The mean is the arithmetic average of the values in the distribution.
1416It is calculated using GetMean(). Because histograms are
1417binned data, the mean value can differ from a calculation on the raw-data.
1418If the distribution is large enough and gaussian shaped the mean will be
1419exactly the median.
1420
1421##### The Whiskers
1422The whiskers represent the part of the distribution not covered by the box.
1423The upper 25% and the lower 25% of the distribution are located within the whiskers.
1424Two representations are available.
1425
1426 - A simple one (using w=1) defining the lower whisker from the lowest data value
1427 to the bottom of the box, and the upper whisker from the top of the box to the
1428 highest data value. In this representation the whisker-lines are dashed.
1429 - A more complex one having a further restriction. The whiskers are still connected
1430 to the box but their length cannot exceed \f$ 1.5\times iqr \f$. So it might
1431 be that the outermost part of the underlying distribution will not be covered
1432 by the whiskers. Usually these missing parts will be represented by the outliers
1433 (see points). Of course the upper and the lower whisker may differ in length.
1434 In this representation the whiskers are drawn as solid lines.
1435
1436\since **ROOT version 6.11/01**
1437
1438Using the static function TCandle::SetWhiskerRange(double) the whisker definition w=1
1439will be overwritten. E.g. using a whisker-range of 0.95 and w=1 will redefine the area of
1440the lower whisker to the upper whisker in order to cover 95% of the distribution inside
1441that candle. The static function will affect all candle-charts in the running program.
1442Default is 1.
1443
1444If the distribution is large enough and gaussian shaped, the maximum length of
1445the whisker will be located at \f$ \pm 2.698 \sigma \f$ (when using the
14461.5*iqr-definition (w=2), where \f$ \sigma \f$ is the standard deviation
1447(see picture above). In that case 99.3% of the total distribution will be covered
1448by the box and the whiskers, whereas 0.7% are represented by the outliers.
1449
1450##### The Anchors
1451The anchors have no special meaning in terms of statistical calculation. They mark
1452the end of the whiskers and they have the width of the box. Both representation
1453with and without anchors are common.
1454
1455##### The Points
1456Depending on the configuration the points can have different meanings:
1457 - If p=1 the points represent the outliers. If they are shown, it means
1458 some parts of the underlying distribution are not covered by the whiskers.
1459 This can only occur when the whiskers are set to option w=2. Here the whiskers
1460 can have a maximum length of \f$ 1.5 \times iqr \f$. So any points outside the
1461 whiskers will be drawn as outliers. The outliers will be represented by crosses.
1462 - If p=2 all points in the distribution will be painted as crosses. This is
1463 useful for small datasets only (up to 10 or 20 points per candle).
1464 The outliers are shown along the candle. Because the underlying distribution
1465 is binned, is frequently occurs that a bin contains more than one value.
1466 Because of this the points will be randomly scattered within their bin along
1467 the candle axis. If the bin content for a bin is exactly 1 (usually
1468 this happens for the outliers) if will be drawn in the middle of the bin along
1469 the candle axis. As the maximum number of points per candle is limited by kNMax/2
1470 on very large datasets scaling will be performed automatically. In that case one
1471 would loose all outliers because they have usually a bin content of 1 (and a
1472 bin content between 0 and 1 after the scaling). Because of this all bin contents
1473 between 0 and 1 - after the scaling - will be forced to be 1.
1474 - As the drawing of all values on large datasets can lead to big amounts of crosses,
1475 one can show all values as a scatter plot instead by choosing p=3. The points will be
1476 drawn as dots and will be scattered within the width of the candle. The color
1477 of the points will be the color of the candle-chart.
1478
1479##### Other Options
1480Is is possible to combine all options of candle and violin plots with each other. E.g. a box-plot
1481with a histogram.
1482
1483#### How to use the candle-plots drawing option
1484
1485There are six predefined candle-plot representations:
1486
1487 - "CANDLEX1": Standard candle (whiskers cover the whole distribution)
1488 - "CANDLEX2": Standard candle with better whisker definition + outliers.
1489 It is a good compromise
1490 - "CANDLEX3": Like candle2 but with a mean as a circle.
1491 It is easier to distinguish mean and median
1492 - "CANDLEX4": Like candle3 but showing the uncertainty of the median as well
1493 (notched candle plots).
1494 For bigger datasets per candle
1495 - "CANDLEX5": Like candle2 but showing all data points.
1496 For very small datasets
1497 - "CANDLEX6": Like candle2 but showing all datapoints scattered.
1498 For huge datasets
1499
1500
1501The following picture shows how the six predefined representations look.
1502
1503Begin_Macro
1504{
1505 auto c1 = new TCanvas("c1","c1",700,800);
1506 c1->Divide(2,3);
1507 gStyle->SetOptStat(kFALSE);
1508
1509 auto hcandle = new TH2F("hcandle"," ",10,-4,4,40,-20,20);
1510 float px, py;
1511 for (Int_t i = 0; i < 15000; i++) {
1512 gRandom->Rannor(px,py);
1513 hcandle->Fill(px,5*py);
1514 }
1515 hcandle->SetMarkerSize(0.5);
1516
1517 TH2F *h2;
1518 for (Int_t i=1; i<7; i++) {
1519 c1->cd(i);
1520 h2 = (TH2F*)hcandle->DrawClone(Form("CANDLE%d",i));
1521 h2->SetTitle(Form("CANDLE%d",i));
1522 }
1523}
1524End_Macro
1525
1526
1527#### Example 1
1528Box and improved whisker, no mean, no median, no anchor no outliers
1529
1530 h1->Draw("CANDLEX(2001)");
1531
1532#### Example 2
1533A Candle-definition like "CANDLEX2" (New standard candle with better whisker definition + outliers)
1534
1535 h1->Draw("CANDLEX(112111)");
1536
1537#### Example 3
1538The following example shows how several candle plots can be super-imposed using
1539the option SAME. Note that the bar-width and bar-offset are active on candle plots.
1540Also the color, the line width, the size of the points and so on can be changed by the
1541standard attribute setting methods such as SetLineColor() SetLineWidth().
1542
1543Begin_Macro(source)
1544../../../tutorials/hist/hist049_Graphics_candle_plot.C
1545End_Macro
1546
1547\anchor HP140b
1548#### The VIOLIN option
1549
1550<a href="http://en.wikipedia.org/wiki/Violin_plot">A violin plot</a> is a candle plot
1551that also encodes the pdf information at each point.
1552
1553
1554Quartiles and mean are also represented at each point, with a marker
1555and two lines.
1556
1557In this implementation a TH2 is considered as a collection of TH1 along
1558X (option `VIOLIN` or `VIOLINX`) or Y (option `VIOLINY`).
1559
1560#### What a violin is made of
1561
1562\since **ROOT version 6.09/02**
1563
1564##### The histogram
1565The histogram is typically drawn to both directions with respect to the middle-line of the
1566corresponding bin. This can be achieved by using h=3. It is possible to draw a histogram only to
1567one side (h=1, or h=2).
1568The maximum number of bins in the histogram is limited to 500, if the number of bins in the used
1569histogram is higher it will be rebinned automatically. The maximum height of the histogram can
1570be modified by using SetBarWidth() and the position can be changed with SetBarOffset().
1571A solid fill style is recommended.
1572
1573\since **ROOT version 6.11/01**
1574
1575Using the static function TCandle::SetScaledViolin(bool) the height of the histogram or the
1576violin can be influenced. Activated, the height of the bins of the individual violins will be
1577scaled with respect to each other, the maximum height can be influenced by SetBarWidth().
1578Deactivated, the height of the bin with the maximum content of each individual violin is
1579set to a constant value using SetBarWidth(). The static function will affect all violin-charts
1580in the running program. Default is true. Scaling between multiple violin-charts
1581(using "same" or THStack) is not supported, yet.
1582
1583##### The zero indicator line
1584Typical for violin charts is a line in the background over the whole histogram indicating
1585the bins with zero entries. The zero indicator line can be activated with z=1. The line color
1586will always be the same as the fill-color of the histogram.
1587
1588##### The Mean
1589The Mean is illustrated with the same mechanism as used for candle plots. Usually a circle is used.
1590
1591##### Whiskers
1592The whiskers are illustrated by the same mechanism as used for candle plots. There is only one
1593difference. When using the simple whisker definition (w=1) and the zero indicator line (z=1), then
1594the whiskers will be forced to be solid (usually hashed)
1595
1596##### Points
1597The points are illustrated by the same mechanism as used for candle plots. E.g. VIOLIN2 uses
1598better whisker definition (w=2) and outliers (p=1).
1599
1600##### Other options
1601It is possible to combine all options of candle or violin plots with each other. E.g. a violin plot
1602including a box-plot.
1603
1604#### How to use the violin-plots drawing option
1605
1606There are two predefined violin-plot representations:
1607 - "VIOLINX1": Standard violin (histogram, mean, whisker over full distribution,
1608 zero indicator line)
1609 - "VIOLINX2": Line VIOLINX1 both with better whisker definition + outliers.
1610
1611A solid fill style is recommended for this plot (as opposed to a hollow or
1612hashed style).
1613
1614Begin_Macro(source)
1615{
1616 auto c1 = new TCanvas("c1","c1",600,400);
1617 Int_t nx(6), ny(40);
1618 double xmin(0.0), xmax(+6.0), ymin(0.0), ymax(+4.0);
1619 auto hviolin = new TH2F("hviolin", "Option VIOLIN example", nx, xmin, xmax, ny, ymin, ymax);
1620 TF1 f1("f1", "gaus", +0,0 +4.0);
1621 double x,y;
1622 for (Int_t iBin=1; iBin<hviolin->GetNbinsX(); ++iBin) {
1623 double xc = hviolin->GetXaxis()->GetBinCenter(iBin);
1624 f1.SetParameters(1, 2.0+TMath::Sin(1.0+xc), 0.2+0.1*(xc-xmin)/xmax);
1625 for(Int_t i=0; i<10000; ++i){
1626 x = xc;
1627 y = f1.GetRandom();
1628 hviolin->Fill(x, y);
1629 }
1630 }
1631 hviolin->SetFillColor(kGray);
1632 hviolin->SetMarkerStyle(20);
1633 hviolin->SetMarkerSize(0.5);
1634 hviolin->Draw("VIOLIN");
1635 c1->Update();
1636}
1637End_Macro
1638
1639The next example illustrates a time development of a certain value:
1640
1641Begin_Macro(source)
1642../../../tutorials/hist/hist047_Graphics_candle_decay.C
1643End_Macro
1644
1645
1646\anchor HP15
1647### The TEXT and TEXTnn Option
1648
1649
1650For each bin the content is printed. The text attributes are:
1651
1652- text font = current TStyle font (`gStyle->SetTextFont()`).
1653- text size = 0.02*padheight*markersize (if `h` is the histogram drawn
1654 with the option `TEXT` the marker size can be changed with
1655 `h->SetMarkerSize(markersize)`).
1656- text color = marker color.
1657
1658By default the format `g` is used. This format can be redefined
1659by calling `gStyle->SetPaintTextFormat()`.
1660
1661It is also possible to use `TEXTnn` in order to draw the text with
1662the angle `nn` (`0 < nn <= 90`).
1663
1664For 2D histograms the text is plotted in the center of each non empty cells.
1665It is possible to plot empty cells by calling `gStyle->SetHistMinimumZero()`
1666or providing MIN0 draw option. For 1D histogram the text is plotted at a y
1667position equal to the bin content.
1668
1669For 2D histograms when the option "E" (errors) is combined with the option
1670text ("TEXTE"), the error for each bin is also printed.
1671
1672Begin_Macro(source)
1673{
1674 auto c01 = new TCanvas("c01","c01",700,400);
1675 c01->Divide(2,1);
1676 auto htext1 = new TH1F("htext1","Option TEXT on 1D histograms ",10,-4,4);
1677 auto htext2 = new TH2F("htext2","Option TEXT on 2D histograms ",10,-4,4,10,-20,20);
1678 float px, py;
1679 for (Int_t i = 0; i < 25000; i++) {
1680 gRandom->Rannor(px,py);
1681 htext1->Fill(px,0.1);
1682 htext2->Fill(px,5*py,0.1);
1683 }
1684 gStyle->SetPaintTextFormat("4.1f m");
1685 htext2->SetMarkerSize(1.8);
1686 c01->cd(1);
1687 htext2->Draw("TEXT45");
1688 c01->cd(2);
1689 htext1->Draw();
1690 htext1->Draw("HIST TEXT0 SAME");
1691}
1692End_Macro
1693
1694\since **ROOT version 6.07/07:**
1695
1696In case several histograms are drawn on top ot each other (using option `SAME`),
1697the text can be shifted using `SetBarOffset()`. It specifies an offset for the
1698text position in each cell, in percentage of the bin width.
1699
1700Begin_Macro(source)
1701{
1702 auto c03 = new TCanvas("c03","c03",700,400);
1703 gStyle->SetOptStat(0);
1704 auto htext3 = new TH2F("htext3","Several 2D histograms drawn with option TEXT",10,-4,4,10,-20,20);
1705 auto htext4 = new TH2F("htext4","htext4",10,-4,4,10,-20,20);
1706 auto htext5 = new TH2F("htext5","htext5",10,-4,4,10,-20,20);
1707 float px, py;
1708 for (Int_t i = 0; i < 25000; i++) {
1709 gRandom->Rannor(px,py);
1710 htext3->Fill(4*px,20*py,0.1);
1711 htext4->Fill(4*px,20*py,0.5);
1712 htext5->Fill(4*px,20*py,1.0);
1713 }
1714 htext4->SetMarkerSize(1.8);
1715 htext5->SetMarkerSize(1.8);
1716 htext5->SetMarkerColor(kRed);
1717 htext4->SetBarOffset(0.2);
1718 htext5->SetBarOffset(-0.2);
1719 htext3->Draw("COL");
1720 htext4->Draw("TEXT SAME");
1721 htext5->Draw("TEXT SAME");
1722}
1723End_Macro
1724
1725In the case of profile histograms it is possible to print the number
1726of entries instead of the bin content. It is enough to combine the
1727option "E" (for entries) with the option "TEXT".
1728
1729Begin_Macro(source)
1730{
1731 auto c02 = new TCanvas("c02","c02",700,400);
1732 c02->Divide(2,1);
1733 gStyle->SetPaintTextFormat("g");
1734
1735 auto profile = new TProfile("profile","profile",10,0,10);
1736 profile->SetMarkerSize(2.2);
1737 profile->Fill(0.5,1);
1738 profile->Fill(1.5,2);
1739 profile->Fill(2.5,3);
1740 profile->Fill(3.5,4);
1741 profile->Fill(4.5,5);
1742 profile->Fill(5.5,5);
1743 profile->Fill(6.5,4);
1744 profile->Fill(7.5,3);
1745 profile->Fill(8.5,2);
1746 profile->Fill(9.5,1);
1747 c02->cd(1); profile->Draw("HIST TEXT0");
1748 c02->cd(2); profile->Draw("HIST TEXT0E");
1749}
1750End_Macro
1751
1752\anchor HP16
1753### The CONTour options
1754
1755
1756The following contour options are supported:
1757
1758| Option | Description |
1759|----------|-----------------------------------------------------------------------------|
1760| "CONT" | Draw a contour plot (same as CONT0). |
1761| "CONT0" | Draw a contour plot using surface colors to distinguish contours. |
1762| "CONT1" | Draw a contour plot using the line colors to distinguish contours. |
1763| "CONT2" | Draw a contour plot using the line styles (1 to 5) to distinguish contours. |
1764| "CONT3" | Draw a contour plot using the same line style for all contours. |
1765| "CONT4" | Draw a contour plot using surface colors (`SURF` option at theta = 0). |
1766
1767
1768The following example shows a 2D histogram plotted with the option
1769`CONTZ`. The option `CONT` draws a contour plot using surface
1770colors to distinguish contours. Combined with the option `CONT` (or
1771`CONT0`), the option `Z` allows to display the color palette
1772defined by `gStyle->SetPalette()`.
1773
1774Begin_Macro(source)
1775{
1776 auto c1 = new TCanvas("c1","c1",600,400);
1777 auto hcontz = new TH2F("hcontz","Option CONTZ example ",40,-4,4,40,-20,20);
1778 float px, py;
1779 for (Int_t i = 0; i < 25000; i++) {
1780 gRandom->Rannor(px,py);
1781 hcontz->Fill(px-1,5*py);
1782 hcontz->Fill(2+0.5*px,2*py-10.,0.1);
1783 }
1784 hcontz->Draw("CONTZ");
1785}
1786End_Macro
1787
1788The following example shows a 2D histogram plotted with the option
1789`CONT1Z`. The option `CONT1` draws a contour plot using the
1790line colors to distinguish contours. Combined with the option `CONT1`,
1791the option `Z` allows to display the color palette defined by
1792`gStyle->SetPalette()`.
1793
1794Begin_Macro(source)
1795{
1796 auto c1 = new TCanvas("c1","c1",600,400);
1797 auto hcont1 = new TH2F("hcont1","Option CONT1Z example ",40,-4,4,40,-20,20);
1798 float px, py;
1799 for (Int_t i = 0; i < 25000; i++) {
1800 gRandom->Rannor(px,py);
1801 hcont1->Fill(px-1,5*py);
1802 hcont1->Fill(2+0.5*px,2*py-10.,0.1);
1803 }
1804 hcont1->Draw("CONT1Z");
1805}
1806End_Macro
1807
1808The following example shows a 2D histogram plotted with the option
1809`CONT2`. The option `CONT2` draws a contour plot using the
1810line styles (1 to 5) to distinguish contours.
1811
1812Begin_Macro(source)
1813{
1814 auto c1 = new TCanvas("c1","c1",600,400);
1815 auto hcont2 = new TH2F("hcont2","Option CONT2 example ",40,-4,4,40,-20,20);
1816 float px, py;
1817 for (Int_t i = 0; i < 25000; i++) {
1818 gRandom->Rannor(px,py);
1819 hcont2->Fill(px-1,5*py);
1820 hcont2->Fill(2+0.5*px,2*py-10.,0.1);
1821 }
1822 hcont2->Draw("CONT2");
1823}
1824End_Macro
1825
1826The following example shows a 2D histogram plotted with the option
1827`CONT3`. The option `CONT3` draws contour plot using the same line style for
1828all contours.
1829
1830Begin_Macro(source)
1831{
1832 auto c1 = new TCanvas("c1","c1",600,400);
1833 auto hcont3 = new TH2F("hcont3","Option CONT3 example ",40,-4,4,40,-20,20);
1834 float px, py;
1835 for (Int_t i = 0; i < 25000; i++) {
1836 gRandom->Rannor(px,py);
1837 hcont3->Fill(px-1,5*py);
1838 hcont3->Fill(2+0.5*px,2*py-10.,0.1);
1839 }
1840 hcont3->SetLineStyle(kDotted);
1841 hcont3->Draw("CONT3");
1842}
1843End_Macro
1844
1845The following example shows a 2D histogram plotted with the option
1846`CONT4`. The option `CONT4` draws a contour plot using surface
1847colors to distinguish contours (`SURF` option at theta = 0). Combined
1848with the option `CONT` (or `CONT0`), the option `Z`
1849allows to display the color palette defined by `gStyle->SetPalette()`.
1850
1851Begin_Macro(source)
1852{
1853 auto c1 = new TCanvas("c1","c1",600,400);
1854 auto hcont4 = new TH2F("hcont4","Option CONT4Z example ",40,-4,4,40,-20,20);
1855 float px, py;
1856 for (Int_t i = 0; i < 25000; i++) {
1857 gRandom->Rannor(px,py);
1858 hcont4->Fill(px-1,5*py);
1859 hcont4->Fill(2+0.5*px,2*py-10.,0.1);
1860 }
1861 hcont4->Draw("CONT4Z");
1862}
1863End_Macro
1864
1865The default number of contour levels is 20 equidistant levels and can be changed
1866with `TH1::SetContour()` or `TStyle::SetNumberContours()`.
1867
1868\anchor HP16a
1869#### The LIST option
1870
1871When option `LIST` is specified together with option
1872`CONT`, the points used to draw the contours are saved in
1873`TGraph` objects:
1874
1875 h->Draw("CONT LIST");
1876 gPad->Update();
1877
1878The contour are saved in `TGraph` objects once the pad is painted.
1879Therefore to use this functionality in a macro, `gPad->Update()`
1880should be performed after the histogram drawing. Once the list is
1881built, the contours are accessible in the following way:
1882
1883 TObjArray *contours = (TObjArray*)gROOT->GetListOfSpecials()->FindObject("contours");
1884 Int_t ncontours = contours->GetSize();
1885 TList *list = (TList*)contours->At(i);
1886
1887Where `i` is a contour number, and list contains a list of
1888`TGraph` objects.
1889For one given contour, more than one disjoint polyline may be generated.
1890The number of TGraphs per contour is given by:
1891
1892 list->GetSize();
1893
1894To access the first graph in the list one should do:
1895
1896 TGraph *gr1 = (TGraph*)list->First();
1897
1898
1899The following example (hist102_TH2_contour_list.C) shows how to use this functionality.
1900
1901Begin_Macro(source)
1902../../../tutorials/hist/hist102_TH2_contour_list.C
1903End_Macro
1904
1905\anchor HP16b
1906#### The AITOFF, MERCATOR, SINUSOIDAL and PARABOLIC options
1907
1908The following options select the `CONT4` option and are useful for
1909sky maps or exposure maps (earth.C).
1910
1911| Option | Description |
1912|--------------|---------------------------------------------------------------|
1913| "AITOFF" | Draw a contour via an AITOFF projection.|
1914| "MERCATOR" | Draw a contour via an Mercator projection.|
1915| "SINUSOIDAL" | Draw a contour via an Sinusoidal projection.|
1916| "PARABOLIC" | Draw a contour via an Parabolic projection.|
1917
1918Begin_Macro(source)
1919../../../tutorials/visualisation/graphics/earth.C
1920End_Macro
1921
1922
1923\anchor HP17
1924### The LEGO options
1925
1926
1927In a lego plot the cell contents are drawn as 3-d boxes. The height of each box
1928is proportional to the cell content. The lego aspect is control with the
1929following options:
1930
1931| Option | Description |
1932|----------|-------------------------------------------------------------------|
1933| "LEGO" | Draw a lego plot using the hidden lines removal technique.|
1934| "LEGO1" | Draw a lego plot using the hidden surface removal technique.|
1935| "LEGO2" | Draw a lego plot using colors to show the cell contents.|
1936| "LEGO3" | Draw a lego plot with hidden surface removal, like LEGO1 but the border lines of each lego-bar are not drawn.|
1937| "LEGO4" | Draw a lego plot with hidden surface removal, like LEGO1 but without the shadow effect on each lego-bar.|
1938| "0" | When used with any LEGO option, the empty bins are not drawn.|
1939
1940
1941See the limitations with [the option "SAME"](\ref HP060a).
1942
1943Line attributes can be used in lego plots to change the edges' style.
1944
1945The following example shows a 2D histogram plotted with the option
1946`LEGO`. The option `LEGO` draws a lego plot using the hidden
1947lines removal technique.
1948
1949Begin_Macro(source)
1950{
1951 auto c2 = new TCanvas("c2","c2",600,400);
1952 auto hlego = new TH2F("hlego","Option LEGO example ",40,-4,4,40,-20,20);
1953 float px, py;
1954 for (Int_t i = 0; i < 25000; i++) {
1955 gRandom->Rannor(px,py);
1956 hlego->Fill(px-1,5*py);
1957 hlego->Fill(2+0.5*px,2*py-10.,0.1);
1958 }
1959 hlego->Draw("LEGO");
1960}
1961End_Macro
1962
1963The following example shows a 2D histogram plotted with the option
1964`LEGO1`. The option `LEGO1` draws a lego plot using the
1965hidden surface removal technique. Combined with any `LEGOn` option, the
1966option `0` allows to not drawn the empty bins.
1967
1968Begin_Macro(source)
1969{
1970 auto c2 = new TCanvas("c2","c2",600,400);
1971 auto hlego1 = new TH2F("hlego1","Option LEGO1 example (with option 0) ",40,-4,4,40,-20,20);
1972 float px, py;
1973 for (Int_t i = 0; i < 25000; i++) {
1974 gRandom->Rannor(px,py);
1975 hlego1->Fill(px-1,5*py);
1976 hlego1->Fill(2+0.5*px,2*py-10.,0.1);
1977 }
1978 hlego1->SetFillColor(kYellow);
1979 hlego1->Draw("LEGO1 0");
1980}
1981End_Macro
1982
1983The following example shows a 2D histogram plotted with the option
1984`LEGO3`. Like the option `LEGO1`, the option `LEGO3`
1985draws a lego plot using the hidden surface removal technique but doesn't draw
1986the border lines of each individual lego-bar. This is very useful for histograms
1987having many bins. With such histograms the option `LEGO1` gives a black
1988image because of the border lines. This option also works with stacked legos.
1989
1990Begin_Macro(source)
1991{
1992 auto c2 = new TCanvas("c2","c2",600,400);
1993 auto hlego3 = new TH2F("hlego3","Option LEGO3 example",40,-4,4,40,-20,20);
1994 float px, py;
1995 for (Int_t i = 0; i < 25000; i++) {
1996 gRandom->Rannor(px,py);
1997 hlego3->Fill(px-1,5*py);
1998 hlego3->Fill(2+0.5*px,2*py-10.,0.1);
1999 }
2000 hlego3->SetFillColor(kRed);
2001 hlego3->Draw("LEGO3");
2002}
2003End_Macro
2004
2005The following example shows a 2D histogram plotted with the option
2006`LEGO2`. The option `LEGO2` draws a lego plot using colors to
2007show the cell contents. Combined with the option `LEGO2`, the option
2008`Z` allows to display the color palette defined by
2009`gStyle->SetPalette()`.
2010
2011Begin_Macro(source)
2012{
2013 auto c2 = new TCanvas("c2","c2",600,400);
2014 auto hlego2 = new TH2F("hlego2","Option LEGO2Z example ",40,-4,4,40,-20,20);
2015 float px, py;
2016 for (Int_t i = 0; i < 25000; i++) {
2017 gRandom->Rannor(px,py);
2018 hlego2->Fill(px-1,5*py);
2019 hlego2->Fill(2+0.5*px,2*py-10.,0.1);
2020 }
2021 hlego2->Draw("LEGO2Z");
2022}
2023End_Macro
2024
2025
2026
2027\anchor HP18
2028### The "SURFace" options
2029
2030
2031In a surface plot, cell contents are represented as a mesh.
2032The height of the mesh is proportional to the cell content.
2033
2034| Option | Description |
2035|----------|-------------------------------------------------------------------|
2036| "SURF" | Draw a surface plot using the hidden line removal technique.|
2037| "SURF1" | Draw a surface plot using the hidden surface removal technique.|
2038| "SURF2" | Draw a surface plot using colors to show the cell contents.|
2039| "SURF3" | Same as `SURF` with an additional filled contour plot on top.|
2040| "SURF4" | Draw a surface using the Gouraud shading technique.|
2041| "SURF5" | Used with one of the options CYL, PSR and CYL this option allows to draw a filled contour plot.|
2042| "SURF6" | This option should not be used directly. It is used internally when the CONT is used with option the option SAME on a 3D plot.|
2043| "SURF7" | Same as `SURF2` with an additional line contour plot on top.|
2044
2045
2046
2047See the limitations with [the option "SAME"](\ref HP060a).
2048
2049The following example shows a 2D histogram plotted with the option
2050`SURF`. The option `SURF` draws a lego plot using the hidden
2051lines removal technique.
2052
2053Begin_Macro(source)
2054{
2055 auto c2 = new TCanvas("c2","c2",600,400);
2056 auto hsurf = new TH2F("hsurf","Option SURF example ",30,-4,4,30,-20,20);
2057 float px, py;
2058 for (Int_t i = 0; i < 25000; i++) {
2059 gRandom->Rannor(px,py);
2060 hsurf->Fill(px-1,5*py);
2061 hsurf->Fill(2+0.5*px,2*py-10.,0.1);
2062 }
2063 hsurf->Draw("SURF");
2064}
2065End_Macro
2066
2067The following example shows a 2D histogram plotted with the option
2068`SURF1`. The option `SURF1` draws a surface plot using the
2069hidden surface removal technique. Combined with the option `SURF1`,
2070the option `Z` allows to display the color palette defined by
2071`gStyle->SetPalette()`.
2072
2073Begin_Macro(source)
2074{
2075 auto c2 = new TCanvas("c2","c2",600,400);
2076 auto hsurf1 = new TH2F("hsurf1","Option SURF1 example ",30,-4,4,30,-20,20);
2077 float px, py;
2078 for (Int_t i = 0; i < 25000; i++) {
2079 gRandom->Rannor(px,py);
2080 hsurf1->Fill(px-1,5*py);
2081 hsurf1->Fill(2+0.5*px,2*py-10.,0.1);
2082 }
2083 hsurf1->Draw("SURF1");
2084}
2085End_Macro
2086
2087The following example shows a 2D histogram plotted with the option
2088`SURF2`. The option `SURF2` draws a surface plot using colors
2089to show the cell contents. Combined with the option `SURF2`, the option
2090`Z` allows to display the color palette defined by
2091`gStyle->SetPalette()`.
2092
2093Begin_Macro(source)
2094{
2095 auto c2 = new TCanvas("c2","c2",600,400);
2096 auto hsurf2 = new TH2F("hsurf2","Option SURF2 example ",30,-4,4,30,-20,20);
2097 float px, py;
2098 for (Int_t i = 0; i < 25000; i++) {
2099 gRandom->Rannor(px,py);
2100 hsurf2->Fill(px-1,5*py);
2101 hsurf2->Fill(2+0.5*px,2*py-10.,0.1);
2102 }
2103 hsurf2->Draw("SURF2");
2104}
2105End_Macro
2106
2107The following example shows a 2D histogram plotted with the option
2108`SURF3`. The option `SURF3` draws a surface plot using the
2109hidden line removal technique with, in addition, a filled contour view drawn on the
2110top. Combined with the option `SURF3`, the option `Z` allows
2111to display the color palette defined by `gStyle->SetPalette()`.
2112
2113Begin_Macro(source)
2114{
2115 auto c2 = new TCanvas("c2","c2",600,400);
2116 auto hsurf3 = new TH2F("hsurf3","Option SURF3 example ",30,-4,4,30,-20,20);
2117 float px, py;
2118 for (Int_t i = 0; i < 25000; i++) {
2119 gRandom->Rannor(px,py);
2120 hsurf3->Fill(px-1,5*py);
2121 hsurf3->Fill(2+0.5*px,2*py-10.,0.1);
2122 }
2123 hsurf3->Draw("SURF3");
2124}
2125End_Macro
2126
2127The following example shows a 2D histogram plotted with the option
2128`SURF4`. The option `SURF4` draws a surface using the Gouraud
2129shading technique.
2130
2131Begin_Macro(source)
2132{
2133 auto c2 = new TCanvas("c2","c2",600,400);
2134 auto hsurf4 = new TH2F("hsurf4","Option SURF4 example ",30,-4,4,30,-20,20);
2135 float px, py;
2136 for (Int_t i = 0; i < 25000; i++) {
2137 gRandom->Rannor(px,py);
2138 hsurf4->Fill(px-1,5*py);
2139 hsurf4->Fill(2+0.5*px,2*py-10.,0.1);
2140 }
2141 hsurf4->SetFillColor(kOrange);
2142 hsurf4->Draw("SURF4");
2143}
2144End_Macro
2145
2146The following example shows a 2D histogram plotted with the option
2147`SURF5 CYL`. Combined with the option `SURF5`, the option
2148`Z` allows to display the color palette defined by `gStyle->SetPalette()`.
2149
2150Begin_Macro(source)
2151{
2152 auto c2 = new TCanvas("c2","c2",600,400);
2153 auto hsurf5 = new TH2F("hsurf4","Option SURF5 example ",30,-4,4,30,-20,20);
2154 float px, py;
2155 for (Int_t i = 0; i < 25000; i++) {
2156 gRandom->Rannor(px,py);
2157 hsurf5->Fill(px-1,5*py);
2158 hsurf5->Fill(2+0.5*px,2*py-10.,0.1);
2159 }
2160 hsurf5->Draw("SURF5 CYL");
2161}
2162End_Macro
2163
2164The following example shows a 2D histogram plotted with the option
2165`SURF7`. The option `SURF7` draws a surface plot using the
2166hidden surfaces removal technique with, in addition, a line contour view drawn on the
2167top. Combined with the option `SURF7`, the option `Z` allows
2168to display the color palette defined by `gStyle->SetPalette()`.
2169
2170Begin_Macro(source)
2171{
2172 auto c2 = new TCanvas("c2","c2",600,400);
2173 auto hsurf7 = new TH2F("hsurf3","Option SURF7 example ",30,-4,4,30,-20,20);
2174 float px, py;
2175 for (Int_t i = 0; i < 25000; i++) {
2176 gRandom->Rannor(px,py);
2177 hsurf7->Fill(px-1,5*py);
2178 hsurf7->Fill(2+0.5*px,2*py-10.,0.1);
2179 }
2180 hsurf7->Draw("SURF7");
2181}
2182End_Macro
2183
2184As shown in the following example, when a contour plot is painted on top of a
2185surface plot using the option `SAME`, the contours appear in 3D on the
2186surface.
2187
2188Begin_Macro(source)
2189{
2190 auto c20=new TCanvas("c20","c20",600,400);
2191 int NBins = 50;
2192 double d = 2;
2193 auto hsc = new TH2F("hsc", "Surface and contour with option SAME ", NBins, -d, d, NBins, -d, d);
2194 for (int bx = 1; bx <= NBins; ++bx) {
2195 for (int by = 1; by <= NBins; ++by) {
2196 double x = hsc->GetXaxis()->GetBinCenter(bx);
2197 double y = hsc->GetYaxis()->GetBinCenter(by);
2198 hsc->SetBinContent(bx, by, exp(-x*x)*exp(-y*y));
2199 }
2200 }
2201 hsc->Draw("surf2");
2202 hsc->Draw("CONT1 SAME");
2203}
2204End_Macro
2205
2206
2207\anchor HP19
2208### Cylindrical, Polar, Spherical and PseudoRapidity/Phi options
2209
2210
2211Legos and surfaces plots are represented by default in Cartesian coordinates.
2212Combined with any `LEGOn` or `SURFn` options the following
2213options allow to draw a lego or a surface in other coordinates systems.
2214
2215| Option | Description |
2216|----------|-------------------------------------------------------------------|
2217| "CYL" | Use Cylindrical coordinates. The X coordinate is mapped on the angle and the Y coordinate on the cylinder length.|
2218| "POL" | Use Polar coordinates. The X coordinate is mapped on the angle and the Y coordinate on the radius.|
2219| "SPH" | Use Spherical coordinates. The X coordinate is mapped on the latitude and the Y coordinate on the longitude.|
2220| "PSR" | Use PseudoRapidity/Phi coordinates. The X coordinate is mapped on Phi.|
2221
2222
2223
2224<b>WARNING:</b> Axis are not drawn with these options.
2225
2226The following example shows the same histogram as a lego plot is the four
2227different coordinates systems.
2228
2229Begin_Macro(source)
2230{
2231 auto c3 = new TCanvas("c3","c3",600,400);
2232 c3->Divide(2,2);
2233 auto hlcc = new TH2F("hlcc","Cylindrical coordinates",20,-4,4,20,-20,20);
2234 float px, py;
2235 for (Int_t i = 0; i < 25000; i++) {
2236 gRandom->Rannor(px,py);
2237 hlcc->Fill(px-1,5*py);
2238 hlcc->Fill(2+0.5*px,2*py-10.,0.1);
2239 }
2240 hlcc->SetFillColor(kYellow);
2241 c3->cd(1); hlcc->Draw("LEGO1 CYL");
2242 c3->cd(2); auto hlpc = (TH2F*) hlcc->DrawClone("LEGO1 POL");
2243 hlpc->SetTitle("Polar coordinates");
2244 c3->cd(3); auto hlsc = (TH2F*) hlcc->DrawClone("LEGO1 SPH");
2245 hlsc->SetTitle("Spherical coordinates");
2246 c3->cd(4); auto hlprpc = (TH2F*) hlcc->DrawClone("LEGO1 PSR");
2247 hlprpc->SetTitle("PseudoRapidity/Phi coordinates");
2248}
2249End_Macro
2250
2251The following example shows the same histogram as a surface plot is the four different coordinates systems.
2252
2253Begin_Macro(source)
2254{
2255 auto c4 = new TCanvas("c4","c4",600,400);
2256 c4->Divide(2,2);
2257 auto hscc = new TH2F("hscc","Cylindrical coordinates",20,-4,4,20,-20,20);
2258 float px, py;
2259 for (Int_t i = 0; i < 25000; i++) {
2260 gRandom->Rannor(px,py);
2261 hscc->Fill(px-1,5*py);
2262 hscc->Fill(2+0.5*px,2*py-10.,0.1);
2263 }
2264 c4->cd(1); hscc->Draw("SURF1 CYL");
2265 c4->cd(2); auto hspc = (TH2F*) hscc->DrawClone("SURF1 POL");
2266 hspc->SetTitle("Polar coordinates");
2267 c4->cd(3); auto hssc = (TH2F*) hscc->DrawClone("SURF1 SPH");
2268 hssc->SetTitle("Spherical coordinates");
2269 c4->cd(4); auto hsprpc = (TH2F*) hscc->DrawClone("SURF1 PSR");
2270 hsprpc->SetTitle("PseudoRapidity/Phi coordinates");
2271}
2272End_Macro
2273
2274
2275\anchor HP20
2276### Base line for bar-charts and lego plots
2277
2278
2279By default the base line used to draw the boxes for bar-charts and lego plots is
2280the histogram minimum. It is possible to force this base line to be 0, using MIN0 draw
2281option or with the command:
2282
2283 gStyle->SetHistMinimumZero();
2284
2285Begin_Macro(source)
2286{
2287 auto c5 = new TCanvas("c5","c5",700,400);
2288 c5->Divide(2,1);
2289 auto hz1 = new TH1F("hz1","Bar-chart drawn from 0",20,-3,3);
2290 auto hz2 = new TH2F("hz2","Lego plot drawn from 0",20,-3,3,20,-3,3);
2291 Int_t i;
2292 double x,y;
2293 hz1->SetFillColor(kBlue);
2294 hz2->SetFillColor(kBlue);
2295 for (i=0;i<10000;i++) {
2296 x = gRandom->Gaus(0,1);
2297 y = gRandom->Gaus(0,1);
2298 if (x>0) {
2299 hz1->Fill(x,1);
2300 hz2->Fill(x,y,1);
2301 } else {
2302 hz1->Fill(x,-1);
2303 hz2->Fill(x,y,-2);
2304 }
2305 }
2306 c5->cd(1); hz1->Draw("bar2 min0");
2307 c5->cd(2); hz2->Draw("lego1 min0");
2308}
2309End_Macro
2310
2311This option also works for horizontal plots. The example given in the section
2312["The bar chart option"](\ref HP100) appears as follow:
2313
2314Begin_Macro(source)
2315{
2316 int i;
2317 const Int_t nx = 8;
2318 string os_X[nx] = {"8","32","128","512","2048","8192","32768","131072"};
2319 float d_35_0[nx] = {0.75, -3.30, -0.92, 0.10, 0.08, -1.69, -1.29, -2.37};
2320 float d_35_1[nx] = {1.01, -3.02, -0.65, 0.37, 0.34, -1.42, -1.02, -2.10};
2321
2322 auto cbh = new TCanvas("cbh","cbh",400,600);
2323 cbh->SetGrid();
2324
2325 auto h1bh = new TH1F("h1bh","Option HBAR centered on 0",nx,0,nx);
2326 h1bh->SetFillColor(4);
2327 h1bh->SetBarWidth(0.4);
2328 h1bh->SetBarOffset(0.1);
2329 h1bh->SetStats(0);
2330 h1bh->SetMinimum(-5);
2331 h1bh->SetMaximum(5);
2332
2333 for (i=1; i<=nx; i++) {
2334 h1bh->Fill(os_X[i-1].c_str(), d_35_0[i-1]);
2335 h1bh->GetXaxis()->SetBinLabel(i,os_X[i-1].c_str());
2336 }
2337
2338 h1bh->Draw("hbar min0");
2339
2340 auto h2bh = new TH1F("h2bh","h2bh",nx,0,nx);
2341 h2bh->SetFillColor(38);
2342 h2bh->SetBarWidth(0.4);
2343 h2bh->SetBarOffset(0.5);
2344 h2bh->SetStats(0);
2345 for (i=1;i<=nx;i++) h2bh->Fill(os_X[i-1].c_str(), d_35_1[i-1]);
2346
2347 h2bh->Draw("hbar min0 same");
2348}
2349End_Macro
2350
2351
2352\anchor HP20a
2353### TH2Poly Drawing
2354
2355
2356The following options are supported:
2357
2358| Option | Description |
2359|----------|-------------------------------------------------------------------|
2360| "SCAT" | Draw a scatter plot (legacy draw option).|
2361| "COL" | Draw a color plot. All the bins are painted even the empty bins (default).|
2362| "COLZ" | Same as "COL". In addition the color palette is also drawn.|
2363| "0" | When used with any COL options, the empty bins are not drawn.|
2364| "TEXT" | Draw bin contents as text (format set via `gStyle->SetPaintTextFormat`).|
2365| "TEXTN" | Draw bin names as text.|
2366| "TEXTnn" | Draw bin contents as text at angle nn (0 < nn <= 90).|
2367| "L" | Draw the bins boundaries as lines. The lines attributes are the TGraphs ones.|
2368| "P" | Draw the bins boundaries as markers. The markers attributes are the TGraphs ones.|
2369| "F" | Draw the bins boundaries as filled polygons. The filled polygons attributes are the TGraphs ones.|
2370
2371
2372
2373`TH2Poly` can be drawn as a color plot (option COL). `TH2Poly` bins can have any
2374shapes. The bins are defined as graphs. The following macro is a very simple
2375example showing how to book a TH2Poly and draw it.
2376
2377Begin_Macro(source)
2378{
2379 auto ch2p1 = new TCanvas("ch2p1","ch2p1",600,400);
2380 auto h2p = new TH2Poly();
2381 h2p->SetName("h2poly_name");
2382 h2p->SetTitle("h2poly_title");
2383 double px1[] = {0, 5, 6};
2384 double py1[] = {0, 0, 5};
2385 double px2[] = {0, -1, -1, 0};
2386 double py2[] = {0, 0, -1, 3};
2387 double px3[] = {4, 3, 0, 1, 2.4};
2388 double py3[] = {4, 3.7, 1, 3.7, 2.5};
2389 h2p->AddBin(3, px1, py1);
2390 h2p->AddBin(4, px2, py2);
2391 h2p->AddBin(5, px3, py3);
2392 h2p->Fill(0.1, 0.01, 3);
2393 h2p->Fill(-0.5, -0.5, 7);
2394 h2p->Fill(-0.7, -0.5, 1);
2395 h2p->Fill(1, 3, 1.5);
2396 double fx[] = {0.1, -0.5, -0.7, 1};
2397 double fy[] = {0.01, -0.5, -0.5, 3};
2398 double fw[] = {3, 1, 1, 1.5};
2399 h2p->FillN(4, fx, fy, fw);
2400 h2p->Draw("col");
2401}
2402End_Macro
2403
2404Rectangular bins are a frequent case. The special version of
2405the `AddBin` method allows to define them more easily like
2406shown in the following example (hist037_TH2Poly_boxes.C).
2407
2408Begin_Macro(source)
2409../../../tutorials/hist/hist037_TH2Poly_boxes.C
2410End_Macro
2411
2412One `TH2Poly` bin can be a list of polygons. Such bins are defined
2413by calling `AddBin` with a `TMultiGraph`. The following example
2414shows a such case:
2415
2416Begin_Macro(source)
2417{
2418 auto ch2p2 = new TCanvas("ch2p2","ch2p2",600,400);
2419
2420 Int_t i, bin;
2421 const Int_t nx = 48;
2422 const char *states [nx] = {
2423 "alabama", "arizona", "arkansas", "california",
2424 "colorado", "connecticut", "delaware", "florida",
2425 "georgia", "idaho", "illinois", "indiana",
2426 "iowa", "kansas", "kentucky", "louisiana",
2427 "maine", "maryland", "massachusetts", "michigan",
2428 "minnesota", "mississippi", "missouri", "montana",
2429 "nebraska", "nevada", "new_hampshire", "new_jersey",
2430 "new_mexico", "new_york", "north_carolina", "north_dakota",
2431 "ohio", "oklahoma", "oregon", "pennsylvania",
2432 "rhode_island", "south_carolina", "south_dakota", "tennessee",
2433 "texas", "utah", "vermont", "virginia",
2434 "washington", "west_virginia", "wisconsin", "wyoming"
2435 };
2436 Double_t pop[nx] = {
2437 4708708, 6595778, 2889450, 36961664, 5024748, 3518288, 885122, 18537969,
2438 9829211, 1545801, 12910409, 6423113, 3007856, 2818747, 4314113, 4492076,
2439 1318301, 5699478, 6593587, 9969727, 5266214, 2951996, 5987580, 974989,
2440 1796619, 2643085, 1324575, 8707739, 2009671, 19541453, 9380884, 646844,
2441 11542645, 3687050, 3825657, 12604767, 1053209, 4561242, 812383, 6296254,
2442 24782302, 2784572, 621760, 7882590, 6664195, 1819777, 5654774, 544270
2443 };
2444
2445 Double_t lon1 = -130;
2446 Double_t lon2 = -65;
2447 Double_t lat1 = 24;
2448 Double_t lat2 = 50;
2449 auto p = new TH2Poly("USA","USA Population",lon1,lon2,lat1,lat2);
2450
2451 TFile::SetCacheFileDir(".");
2452 auto f = TFile::Open("http://root.cern/files/usa.root", "CACHEREAD");
2453
2454 TMultiGraph *mg;
2455 TKey *key;
2456 TIter nextkey(gDirectory->GetListOfKeys());
2457 while ((key = (TKey*)nextkey())) {
2458 TObject *obj = key->ReadObj();
2459 if (obj->InheritsFrom("TMultiGraph")) {
2460 mg = (TMultiGraph*)obj;
2461 bin = p->AddBin(mg);
2462 }
2463 }
2464
2465 for (i=0; i<nx; i++) p->Fill(states[i], pop[i]);
2466
2467 gStyle->SetOptStat(11);
2468 p->Draw("COLZ L");
2469}
2470End_Macro
2471
2472`TH2Poly` histograms can also be plotted using the GL interface using
2473the option "GLLEGO".
2474
2475\since **ROOT version 6.09/01**
2476
2477In some cases it can be useful to not draw the empty bins. the option "0"
2478combined with the option "COL" and "COLZ" allows to do that.
2479
2480Begin_Macro(source)
2481{
2482 auto chc = new TCanvas("chc","chc",600,400);
2483
2484 auto hc = new TH2Poly();
2485 hc->Honeycomb(0,0,.1,25,25);
2486 hc->SetName("hc");
2487 hc->SetTitle("Option COLZ 0");
2488 TRandom ran;
2489 for (int i = 0; i<300; i++) hc->Fill(ran.Gaus(2.,1), ran.Gaus(2.,1));
2490 hc->Draw("colz 0");
2491}
2492End_Macro
2493
2494\anchor HP21
2495### The SPEC option
2496
2497
2498This option allows to use the `TSpectrum2Painter` tools. See the full
2499documentation in `TSpectrum2Painter::PaintSpectrum`.
2500
2501
2502\anchor HP22
2503### Option "Z" : Adding the color palette on the right side of the pad
2504
2505
2506When this option is specified, a color palette with an axis indicating the value
2507of the corresponding color is drawn on the right side of the picture. In case,
2508not enough space is left, one can increase the size of the right margin by
2509calling `TPad::SetRightMargin()`. The attributes used to display the
2510palette axis values are taken from the Z axis of the object. For example, to
2511set the labels size on the palette axis do:
2512
2513 hist->GetZaxis()->SetLabelSize().
2514
2515<b>WARNING:</b> The palette axis is always drawn vertically.
2516
2517
2518\anchor HP23
2519### Setting the color palette
2520
2521
2522To change the color palette `TStyle::SetPalette` should be used, eg:
2523
2524 gStyle->SetPalette(ncolors,colors);
2525
2526For example the option `COL` draws a 2D histogram with cells
2527represented by a box filled with a color index which is a function
2528of the cell content.
2529If the cell content is N, the color index used will be the color number
2530in `colors[N]`, etc. If the maximum cell content is greater than
2531`ncolors`, all cell contents are scaled to `ncolors`.
2532
2533If ` ncolors <= 0`, a default palette (see below) of 50 colors is
2534defined. This palette is recommended for pads, labels ...
2535
2536`if ncolors == 1 && colors == 0`, then a Pretty Palette with a
2537Spectrum Violet->Red is created with 50 colors. That's the default rain bow
2538palette.
2539
2540Other pre-defined palettes with 255 colors are available when `colors == 0`.
2541The following value of `ncolors` give access to:
2542
2543
2544 if ncolors = 51 and colors=0, a Deep Sea palette is used.
2545 if ncolors = 52 and colors=0, a Grey Scale palette is used.
2546 if ncolors = 53 and colors=0, a Dark Body Radiator palette is used.
2547 if ncolors = 54 and colors=0, a two-color hue palette palette is used.(dark blue through neutral gray to bright
2548yellow) if ncolors = 55 and colors=0, a Rain Bow palette is used. if ncolors = 56 and colors=0, an inverted Dark Body
2549Radiator palette is used.
2550
2551
2552If `ncolors > 0 && colors == 0`, the default palette is used with a maximum of ncolors.
2553
2554The default palette defines:
2555
2556- index 0 to 9 : shades of grey
2557- index 10 to 19 : shades of brown
2558- index 20 to 29 : shades of blue
2559- index 30 to 39 : shades of red
2560- index 40 to 49 : basic colors
2561
2562The color numbers specified in the palette can be viewed by selecting
2563the item `colors` in the `VIEW` menu of the canvas tool bar.
2564The red, green, and blue components of a color can be changed thanks to
2565`TColor::SetRGB()`.
2566
2567\since **ROOT version 6.19/01**
2568
2569As default labels and ticks are drawn by `TGAxis` at equidistant (lin or log)
2570points as controlled by SetNdivisions.
2571If option "CJUST" is given labels and ticks are justified at the
2572color boundaries defined by the contour levels.
2573For more details see `TPaletteAxis`
2574
2575\anchor HP24
2576### Drawing a sub-range of a 2D histogram; the [cutg] option
2577
2578
2579Using a `TCutG` object, it is possible to draw a sub-range of a 2D
2580histogram. One must create a graphical cut (mouse or C++) and specify the name
2581of the cut between `[]` in the `Draw()` option.
2582For example (fit2a.C), with a `TCutG` named `cutg`, one can call:
2583
2584 myhist->Draw("surf1 [cutg]");
2585
2586To invert the cut, it is enough to put a `-` in front of its name:
2587
2588 myhist->Draw("surf1 [-cutg]");
2589
2590It is possible to apply several cuts (`,` means logical AND):
2591
2592 myhist->Draw("surf1 [cutg1,cutg2]");
2593
2594Begin_Macro(source)
2595../../../tutorials/fit/fit2a.C
2596End_Macro
2597
2598\anchor HP25
2599### Drawing options for 3D histograms
2600
2601
2602| Option | Description |
2603|----------|-------------------------------------------------------------------|
2604| "SCAT" | Draw a scatter plot (legacy draw option).|
2605| "ISO" | Draw a Gouraud shaded 3d iso surface through a 3d histogram. It paints one surface at the value computed as follow: `SumOfWeights/(NbinsX*NbinsY*NbinsZ)`|
2606| "BOX" | Draw a for each cell with volume proportional to the content's absolute value. An hidden line removal algorithm is used|
2607| "BOX1" | Same as BOX but an hidden surface removal algorithm is used|
2608| "BOX2" | Same as "COL". The boxes' colors are picked in the current palette according to the bins' contents (default)|
2609| "BOX2Z" | Same as "BOX2". In addition the color palette is also drawn.|
2610| "BOX3" | Same as BOX1, but the border lines of each lego-bar are not drawn.|
2611
2612Note that instead of `BOX` one can also use `LEGO`.
2613
2614By default, 3D histograms are drawn as a colored box plots.
2615
2616The following example shows a 3D histogram plotted as a scatter plot.
2617
2618Begin_Macro(source)
2619{
2620 auto c06 = new TCanvas("c06","c06",600,400);
2621 gStyle->SetOptStat(kFALSE);
2622 auto h3scat = new TH3F("h3scat","Option SCAT",15,-2,2,15,-2,2,15,0,4);
2623 double x, y, z;
2624 for (Int_t i=0;i<10000;i++) {
2625 gRandom->Rannor(x, y);
2626 z = x*x + y*y;
2627 h3scat->Fill(x,y,z);
2628 }
2629 h3scat->Draw("SCAT"); // This a legacy draw option
2630}
2631End_Macro
2632
2633The following example shows a 3D histogram plotted with the option `BOX`.
2634
2635Begin_Macro(source)
2636{
2637 auto c16 = new TCanvas("c16","c16",600,400);
2638 gStyle->SetOptStat(kFALSE);
2639 auto h3box = new TH3F("h3box","Option BOX",15,-2,2,15,-2,2,15,0,4);
2640 double x, y, z;
2641 for (Int_t i=0;i<10000;i++) {
2642 gRandom->Rannor(x, y);
2643 z = x*x + y*y;
2644 h3box->Fill(x,y,z);
2645 }
2646 h3box->Draw("BOX");
2647}
2648End_Macro
2649
2650The following example shows a 3D histogram plotted with the option `BOX1`.
2651
2652Begin_Macro(source)
2653{
2654 auto c36 = new TCanvas("c36","c36",600,400);
2655 gStyle->SetOptStat(kFALSE);
2656 auto h3box = new TH3F("h3box","Option BOX1",10,-2.,2.,10,-2.,2.,10,-0.5,2.);
2657 double x, y, z;
2658 for (Int_t i=0;i<10000;i++) {
2659 gRandom->Rannor(x, y);
2660 z = abs(sin(x)/x + cos(y)*y);
2661 h3box->Fill(x,y,z);
2662 }
2663 h3box->SetFillColor(9);
2664 h3box->Draw("BOX1");
2665}
2666End_Macro
2667
2668The following example shows a 3D histogram plotted with the option `BOX2`.
2669
2670Begin_Macro(source)
2671{
2672 auto c56 = new TCanvas("c56","c56",600,400);
2673 gStyle->SetOptStat(kFALSE);
2674 auto h3box = new TH3F("h3box","Option BOX2 (default)",10,-2.,2.,10,-2.,2.,10,-0.5,2.);
2675 double x, y, z;
2676 for (Int_t i=0;i<10000;i++) {
2677 gRandom->Rannor(x, y);
2678 z = abs(sin(x)/x + cos(y)*y);
2679 h3box->Fill(x,y,z);
2680 }
2681 h3box->Draw("BOX2 Z");
2682}
2683End_Macro
2684
2685The following example shows a 3D histogram plotted with the option `BOX3`.
2686
2687Begin_Macro(source)
2688{
2689 auto c46 = new TCanvas("c46","c46",600,400);
2690 c46->SetFillColor(38);
2691 gStyle->SetOptStat(kFALSE);
2692 auto h3box = new TH3F("h3box","Option BOX3",15,-2,2,15,-2,2,15,0,4);
2693 double x, y, z;
2694 for (Int_t i=0;i<10000;i++) {
2695 gRandom->Rannor(x, y);
2696 z = x*x + y*y;
2697 h3box->Fill(x,y,z);
2698 }
2699 h3box->Draw("BOX3");
2700}
2701End_Macro
2702
2703For all the `BOX` options each bin is drawn as a 3D box with a volume proportional
2704to the absolute value of the bin content. The bins with a negative content are
2705drawn with a X on each face of the box as shown in the following example:
2706
2707Begin_Macro(source)
2708{
2709 auto c = new TCanvas("c","c",600,400);
2710 gStyle->SetOptStat(kFALSE);
2711 auto h3box = new TH3F("h3box","Option BOX1 with negative bins",3, 0., 4., 3, 0.,4., 3, 0., 4.);
2712 h3box->Fill(0., 2., 2., 10.);
2713 h3box->Fill(2., 2., 2., 5.);
2714 h3box->Fill(2., 2., .5, 2.);
2715 h3box->Fill(2., 2., 3., -1.);
2716 h3box->Fill(3., 2., 2., -10.);
2717 h3box->SetFillColor(8);
2718 h3box->Draw("box1");
2719}
2720End_Macro
2721
2722The following example shows a 3D histogram plotted with the option `ISO`.
2723
2724Begin_Macro(source)
2725{
2726 auto c26 = new TCanvas("c26","c26",600,400);
2727 gStyle->SetOptStat(kFALSE);
2728 auto h3iso = new TH3F("h3iso","Option ISO",15,-2,2,15,-2,2,15,0,4);
2729 double x, y, z;
2730 for (Int_t i=0;i<10000;i++) {
2731 gRandom->Rannor(x, y);
2732 z = x*x + y*y;
2733 h3iso->Fill(x,y,z);
2734 }
2735 h3iso->SetFillColor(kCyan);
2736 h3iso->Draw("ISO");
2737}
2738End_Macro
2739
2740
2741\anchor HP26
2742### Drawing option for histograms' stacks
2743
2744
2745Stacks of histograms are managed with the `THStack`. A `THStack`
2746is a collection of `TH1` (or derived) objects. For painting only the
2747`THStack` containing `TH1` only or
2748`THStack` containing `TH2` only will be considered.
2749
2750By default, histograms are shown stacked:
2751
27521. The first histogram is paint.
27532. The sum of the first and second, etc...
2754
2755If the option `NOSTACK` is specified, the histograms are all paint in
2756the same pad as if the option `SAME` had been specified. This allows to
2757compute X and Y scales common to all the histograms, like
2758`TMultiGraph` does for graphs.
2759
2760If the option `PADS` is specified, the current pad/canvas is subdivided into
2761a number of pads equal to the number of histograms and each histogram is paint
2762into a separate pad. With `PADSn`, the current pad/canvas is subdivided into
2763`n` columns, automatically calculating the number of rows.
2764
2765The following example shows various types of stacks (hist023_THStack_simple.C).
2766
2767Begin_Macro(source)
2768../../../tutorials/hist/hist023_THStack_simple.C
2769End_Macro
2770
2771The option `nostackb` allows to draw the histograms next to each
2772other as bar charts:
2773
2774Begin_Macro(source)
2775{
2776 auto cst0 = new TCanvas("cst0","cst0",600,400);
2777 auto hs = new THStack("hs","Stacked 1D histograms: option #font[82]{\"nostackb\"}");
2778
2779 auto h1 = new TH1F("h1","h1",10,-4,4);
2780 h1->FillRandom("gaus",20000);
2781 h1->SetFillColor(kRed);
2782 hs->Add(h1);
2783
2784 auto h2 = new TH1F("h2","h2",10,-4,4);
2785 h2->FillRandom("gaus",15000);
2786 h2->SetFillColor(kBlue);
2787 hs->Add(h2);
2788
2789 auto h3 = new TH1F("h3","h3",10,-4,4);
2790 h3->FillRandom("gaus",10000);
2791 h3->SetFillColor(kGreen);
2792 hs->Add(h3);
2793
2794 hs->Draw("nostackb");
2795 hs->GetXaxis()->SetNdivisions(-10);
2796 cst0->SetGridx();
2797}
2798End_Macro
2799
2800If at least one of the histograms in the stack has errors, the whole stack is
2801visualized by default with error bars. To visualize it without errors the
2802option `HIST` should be used.
2803
2804Begin_Macro(source)
2805{
2806 auto cst1 = new TCanvas("cst1","cst1",700,400);
2807 cst1->Divide(2,1);
2808
2809 auto hst11 = new TH1F("hst11", "", 20, -10, 10);
2810 hst11->Sumw2();
2811 hst11->FillRandom("gaus", 1000);
2812 hst11->SetFillColor(kViolet);
2813 hst11->SetLineColor(kViolet);
2814
2815 auto hst12 = new TH1F("hst12", "", 20, -10, 10);
2816 hst12->FillRandom("gaus", 500);
2817 hst12->SetFillColor(kBlue);
2818 hst12->SetLineColor(kBlue);
2819
2820 THStack st1("st1", "st1");
2821 st1.Add(hst11);
2822 st1.Add(hst12);
2823
2824 cst1->cd(1); st1.Draw();
2825 cst1->cd(2); st1.Draw("hist");
2826}
2827End_Macro
2828
2829\anchor HP27
2830### Drawing of 3D implicit functions
2831
2832
28333D implicit functions (`TF3`) can be drawn as iso-surfaces.
2834The implicit function f(x,y,z) = 0 is drawn in cartesian coordinates.
2835In the following example the options "FB" and "BB" suppress the
2836"Front Box" and "Back Box" around the plot.
2837
2838Begin_Macro(source)
2839{
2840 auto c2 = new TCanvas("c2","c2",600,400);
2841 auto f3 = new TF3("f3","sin(x*x+y*y+z*z-36)",-2,2,-2,2,-2,2);
2842 f3->SetClippingBoxOn(0,0,0);
2843 f3->SetFillColor(30);
2844 f3->SetLineColor(15);
2845 f3->Draw("FBBB");
2846}
2847End_Macro
2848
2849
2850\anchor HP28
2851### Associated functions drawing
2852
2853
2854An associated function is created by `TH1::Fit`. More than on fitted
2855function can be associated with one histogram (see `TH1::Fit`).
2856
2857A `TF1` object `f1` can be added to the list of associated
2858functions of an histogram `h` without calling `TH1::Fit`
2859simply doing:
2860
2861 h->GetListOfFunctions()->Add(f1);
2862
2863or
2864
2865 h->GetListOfFunctions()->Add(f1,someoption);
2866
2867To retrieve a function by name from this list, do:
2868
2869 TF1 *f1 = (TF1*)h->GetListOfFunctions()->FindObject(name);
2870
2871or
2872
2873 TF1 *f1 = h->GetFunction(name);
2874
2875Associated functions are automatically painted when an histogram is drawn.
2876To avoid the painting of the associated functions the option `HIST`
2877should be added to the list of the options used to paint the histogram.
2878
2879
2880\anchor HP29
2881### Drawing using OpenGL
2882
2883
2884The class `TGLHistPainter` allows to paint data set using the OpenGL 3D
2885graphics library. The plotting options start with `GL` keyword.
2886In addition, in order to inform canvases that OpenGL should be used to render
28873D representations, the following option should be set:
2888
2889 gStyle->SetCanvasPreferGL(true);
2890
2891
2892\anchor HP29a
2893#### General information: plot types and supported options
2894
2895The following types of plots are provided:
2896
2897For lego plots the supported options are:
2898
2899| Option | Description |
2900|----------|-------------------------------------------------------------------|
2901| "GLLEGO" | Draw a lego plot. It works also for `TH2Poly`.|
2902| "GLLEGO2"| Bins with color levels.|
2903| "GLLEGO3"| Cylindrical bars.|
2904
2905
2906
2907Lego painter in cartesian supports logarithmic scales for X, Y, Z.
2908In polar only Z axis can be logarithmic, in cylindrical only Y.
2909
2910For surface plots (`TF2` and `TH2`) the supported options are:
2911
2912| Option | Description |
2913|-----------|------------------------------------------------------------------|
2914| "GLSURF" | Draw a surface.|
2915| "GLSURF1" | Surface with color levels|
2916| "GLSURF2" | The same as "GLSURF1" but without polygon outlines.|
2917| "GLSURF3" | Color level projection on top of plot (works only in cartesian coordinate system).|
2918| "GLSURF4" | Same as "GLSURF" but without polygon outlines.|
2919
2920
2921
2922The surface painting in cartesian coordinates supports logarithmic scales along
2923X, Y, Z axis. In polar coordinates only the Z axis can be logarithmic,
2924in cylindrical coordinates only the Y axis.
2925
2926Additional options to SURF and LEGO - Coordinate systems:
2927
2928| Option | Description |
2929|----------|-------------------------------------------------------------------|
2930| " " | Default, cartesian coordinates system.|
2931| "POL" | Polar coordinates system.|
2932| "CYL" | Cylindrical coordinates system.|
2933| "SPH" | Spherical coordinates system.|
2934
2935
2936
2937\anchor HP290
2938#### TH3 as color boxes
2939
2940The supported option is:
2941
2942| Option | Description |
2943|----------|-------------------------------------------------------------------|
2944| "GLCOL" | H3 is drawn using semi-transparent colored boxes. See glvox1.C .|
2945
2946
2947
2948\anchor HP29b
2949#### TH3 as boxes (spheres)
2950
2951The supported options are:
2952
2953| Option | Description |
2954|----------|-------------------------------------------------------------------|
2955| "GLBOX" | TH3 as a set of boxes, size of box is proportional to bin content.|
2956| "GLBOX1" | The same as "glbox", but spheres are drawn instead of boxes.|
2957
2958
2959
2960\anchor HP29c
2961#### TH3 as iso-surface(s)
2962
2963The supported option is:
2964
2965| Option | Description |
2966|----------|-------------------------------------------------------------------|
2967| "GLISO" | TH3 is drawn using iso-surfaces.|
2968
2969
2970
2971\anchor HP29d
2972#### TF3 (implicit function)
2973
2974The supported option is:
2975
2976| Option | Description |
2977|----------|-------------------------------------------------------------------|
2978| "GL" | Draw a TF3.|
2979
2980
2981
2982\anchor HP29e
2983#### Parametric surfaces
2984
2985glparametric.C shows how to create parametric equations and visualize the surface.
2986
2987\anchor HP29f
2988#### Interaction with the plots
2989
2990All the interactions are implemented via standard methods
2991`DistancetoPrimitive()` and `ExecuteEvent()`. That's why all the
2992interactions with the OpenGL plots are possible only when the mouse cursor is
2993in the plot's area (the plot's area is the part of a the pad occupied by
2994gl-produced picture). If the mouse cursor is not above gl-picture, the standard
2995pad interaction is performed.
2996
2997\anchor HP29g
2998#### Selectable parts
2999
3000Different parts of the plot can be selected:
3001
3002- xoz, yoz, xoy back planes: When such a plane selected, it's highlighted in green
3003 if the dynamic slicing by this plane is supported, and it's highlighted in red,
3004 if the dynamic slicing is not supported.
3005- The plot itself:
3006 On surfaces, the selected surface is outlined in red. (TF3 and
3007 ISO are not outlined). On lego plots, the selected bin is
3008 highlighted. The bin number and content are displayed in pad's
3009 status bar. In box plots, the box or sphere is highlighted and
3010 the bin info is displayed in pad's status bar.
3011
3012
3013\anchor HP29h
3014#### Rotation and zooming
3015
3016
3017- Rotation:
3018 When the plot is selected, it can be rotated by pressing and
3019 holding the left mouse button and move the cursor.
3020- Zoom/Unzoom:
3021 Mouse wheel or 'j', 'J', 'k', 'K' keys.
3022
3023
3024\anchor HP29i
3025#### Panning
3026
3027The selected plot can be moved in a pad's area by pressing and
3028holding the left mouse button and the shift key.
3029
3030\anchor HP29j
3031#### Box cut
3032
3033Surface, iso, box, TF3 and parametric painters support box cut by
3034pressing the 'c' or 'C' key when the mouse cursor is in a plot's
3035area. That will display a transparent box, cutting away part of the
3036surface (or boxes) in order to show internal part of plot. This box
3037can be moved inside the plot's area (the full size of the box is
3038equal to the plot's surrounding box) by selecting one of the box
3039cut axes and pressing the left mouse button to move it.
3040
3041\anchor HP29k
3042#### Plot specific interactions (dynamic slicing etc.)
3043
3044Currently, all gl-plots support some form of slicing. When back plane
3045is selected (and if it's highlighted in green) you can press and hold
3046left mouse button and shift key and move this back plane inside
3047plot's area, creating the slice. During this "slicing" plot becomes
3048semi-transparent. To remove all slices (and projected curves for
3049surfaces) double click with left mouse button in a plot's area.
3050
3051\anchor HP29l
3052#### Surface with option "GLSURF"
3053
3054The surface profile is displayed on the slicing plane.
3055The profile projection is drawn on the back plane
3056by pressing `'p'` or `'P'` key.
3057
3058\anchor HP29m
3059#### TF3
3060
3061The contour plot is drawn on the slicing plane. For TF3 the color
3062scheme can be changed by pressing 's' or 'S'.
3063
3064\anchor HP29n
3065#### Box
3066
3067The contour plot corresponding to slice plane position is drawn in real time.
3068
3069\anchor HP29o
3070#### Iso
3071
3072Slicing is similar to "GLBOX" option.
3073
3074\anchor HP29p
3075#### Parametric plot
3076
3077No slicing. Additional keys: 's' or 'S' to change color scheme -
3078about 20 color schemes supported ('s' for "scheme"); 'l' or 'L' to
3079increase number of polygons ('l' for "level" of details), 'w' or 'W'
3080to show outlines ('w' for "wireframe").
3081
3082\anchor HP30
3083#### Highlight mode for histogram
3084
3085\since **ROOT version 6.15/01**
3086
3087\image html hlHisto3_top.gif "Highlight mode"
3088
3089Highlight mode is implemented for `TH1` (and for `TGraph`) class. When
3090highlight mode is on, mouse movement over the bin will be represented
3091graphically. Bin will be highlighted as "bin box" (presented by box
3092object). Moreover, any highlight (change of bin) emits signal
3093`TCanvas::Highlighted()` which allows the user to react and call their own
3094function. For a better understanding see also the tutorial `hist043` to `hist046`
3095located in `$ROOTSYS/tutorials/hist/`.
3096
3097Highlight mode is switched on/off by `TH1::SetHighlight()` function
3098or interactively from `TH1` context menu. `TH1::IsHighlight()` to verify
3099whether the highlight mode enabled or disabled, default it is disabled.
3100
3101~~~ {.cpp}
3102 root [0] .x $ROOTSYS/tutorials/hsimple.C
3103 root [1] hpx->SetHighlight(kTRUE) // or interactively from TH1 context menu
3104 root [2] hpx->IsHighlight()
3105 (bool) true
3106~~~
3107
3108\image html hlsimple_nofun.gif "Highlight mode for histogram"
3109
3110\anchor HP30a
3111#### Highlight mode and user function
3112
3113The user can use (connect) `TCanvas::Highlighted()` signal, which is always
3114emitted if there is a highlight bin and call user function via signal
3115and slot communication mechanism. `TCanvas::Highlighted()` is similar
3116`TCanvas::Picked()`
3117
3118- when selected object (histogram as a whole) is different from previous
3119then emit `Picked()` signal
3120- when selected (highlighted) bin from histogram is different from previous
3121then emit `Highlighted()` signal
3122
3123Any user function (or functions) has to be defined
3124`UserFunction(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)`.
3125In example (see below) has name `PrintInfo()`. All parameters of user
3126function are taken from
3127
3128 void TCanvas::Highlighted(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)
3129
3130- `pad` is pointer to pad with highlighted histogram
3131- `obj` is pointer to highlighted histogram
3132- `x` is highlighted x bin for 1D histogram
3133- `y` is highlighted y bin for 2D histogram (for 1D histogram not in use)
3134
3135Example how to create a connection from any `TCanvas` object to a user
3136`UserFunction()` slot (see also `TQObject::Connect()` for additional info)
3137
3138 TQObject::Connect("TCanvas", "Highlighted(TVirtualPad*,TObject*,Int_t,Int_t)",
3139 0, 0, "UserFunction(TVirtualPad*,TObject*,Int_t,Int_t)");
3140
3141or use non-static "simplified" function
3142`TCanvas::HighlightConnect(const char *slot)`
3143
3144 c1->HighlightConnect("UserFunction(TVirtualPad*,TObject*,Int_t,Int_t)");
3145
3146NOTE the signal and slot string must have a form
3147"(TVirtualPad*,TObject*,Int_t,Int_t)"
3148
3149 root [0] .x $ROOTSYS/tutorials/hsimple.C
3150 root [1] hpx->SetHighlight(kTRUE)
3151 root [2] .x hlprint.C
3152
3153file `hlprint.C`
3154~~~ {.cpp}
3155void PrintInfo(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)
3156{
3157 auto h = (TH1F *)obj;
3158 if (!h->IsHighlight()) // after highlight disabled
3159 h->SetTitle("highlight disable");
3160 else
3161 h->SetTitle(TString::Format("bin[%03d] (%5.2f) content %g", x,
3162 h->GetBinCenter(x), h->GetBinContent(x)));
3163 pad->Update();
3164}
3165
3166void hlprint()
3167{
3168 if (!gPad) return;
3169 gPad->GetCanvas()->HighlightConnect("PrintInfo(TVirtualPad*,TObject*,Int_t,Int_t)");
3170}
3171~~~
3172
3173\image html hlsimple.gif "Highlight mode and simple user function"
3174
3175For more complex demo please see for example tree200_temperature.C file.
3176
3177*/
3178
3180
3183
3184const Int_t kNMAX = 2000;
3185
3186const Int_t kMAXCONTOUR = 104;
3188
3189static std::unique_ptr<TBox> gXHighlightBox, gYHighlightBox; // highlight X and Y box
3190
3212
3213
3214////////////////////////////////////////////////////////////////////////////////
3215/// Default constructor.
3216
3218{
3219 fH = nullptr;
3220 fXaxis = nullptr;
3221 fYaxis = nullptr;
3222 fZaxis = nullptr;
3223 fFunctions = nullptr;
3224 fNcuts = 0;
3225 fStack = nullptr;
3226 fShowProjection = 0;
3227 fShowProjection2 = 0;
3228 fShowOption = "";
3229 for (int i=0; i<kMaxCuts; i++) {
3230 fCuts[i] = nullptr;
3231 fCutsOpt[i] = 0;
3232 }
3233 fXHighlightBin = -1;
3234 fYHighlightBin = -1;
3235 fCurrentF3 = nullptr;
3236
3237 gStringEntries = gEnv->GetValue("Hist.Stats.Entries", "Entries");
3238 gStringMean = gEnv->GetValue("Hist.Stats.Mean", "Mean");
3239 gStringMeanX = gEnv->GetValue("Hist.Stats.MeanX", "Mean x");
3240 gStringMeanY = gEnv->GetValue("Hist.Stats.MeanY", "Mean y");
3241 gStringMeanZ = gEnv->GetValue("Hist.Stats.MeanZ", "Mean z");
3242 gStringStdDev = gEnv->GetValue("Hist.Stats.StdDev", "Std Dev");
3243 gStringStdDevX = gEnv->GetValue("Hist.Stats.StdDevX", "Std Dev x");
3244 gStringStdDevY = gEnv->GetValue("Hist.Stats.StdDevY", "Std Dev y");
3245 gStringStdDevZ = gEnv->GetValue("Hist.Stats.StdDevZ", "Std Dev z");
3246 gStringUnderflow = gEnv->GetValue("Hist.Stats.Underflow", "Underflow");
3247 gStringOverflow = gEnv->GetValue("Hist.Stats.Overflow", "Overflow");
3248 gStringIntegral = gEnv->GetValue("Hist.Stats.Integral", "Integral");
3249 gStringIntegralBinWidth = gEnv->GetValue("Hist.Stats.IntegralBinWidth", "Integral(w)");
3250 gStringSkewness = gEnv->GetValue("Hist.Stats.Skewness", "Skewness");
3251 gStringSkewnessX = gEnv->GetValue("Hist.Stats.SkewnessX", "Skewness x");
3252 gStringSkewnessY = gEnv->GetValue("Hist.Stats.SkewnessY", "Skewness y");
3253 gStringSkewnessZ = gEnv->GetValue("Hist.Stats.SkewnessZ", "Skewness z");
3254 gStringKurtosis = gEnv->GetValue("Hist.Stats.Kurtosis", "Kurtosis");
3255 gStringKurtosisX = gEnv->GetValue("Hist.Stats.KurtosisX", "Kurtosis x");
3256 gStringKurtosisY = gEnv->GetValue("Hist.Stats.KurtosisY", "Kurtosis y");
3257 gStringKurtosisZ = gEnv->GetValue("Hist.Stats.KurtosisZ", "Kurtosis z");
3258}
3259
3260////////////////////////////////////////////////////////////////////////////////
3261/// destructor.
3262
3266
3267////////////////////////////////////////////////////////////////////////////////
3268/// Compute the distance from the point px,py to a line.
3269///
3270/// Compute the closest distance of approach from point px,py to elements of
3271/// an histogram. The distance is computed in pixels units.
3272///
3273/// Algorithm: Currently, this simple model computes the distance from the mouse
3274/// to the histogram contour only.
3275
3277{
3278
3279 Double_t defaultLabelSize = 0.04; // See TAttAxis.h for source of this value
3280
3281 const Int_t big = 9999;
3282 const Int_t kMaxDiff = 7;
3283
3284 if (fPie)
3285 return fPie->DistancetoPrimitive(px, py);
3286
3287 Double_t x = gPad->AbsPixeltoX(px);
3288 Double_t x1 = gPad->AbsPixeltoX(px+1);
3289
3290 Int_t puxmin = gPad->XtoAbsPixel(gPad->GetUxmin());
3291 Int_t puymin = gPad->YtoAbsPixel(gPad->GetUymin());
3292 Int_t puxmax = gPad->XtoAbsPixel(gPad->GetUxmax());
3293 Int_t puymax = gPad->YtoAbsPixel(gPad->GetUymax());
3294 Int_t curdist = big;
3296 Bool_t dsame;
3297 TObject *PadPointer = gPad->GetPadPointer();
3298 if (!PadPointer) return 0;
3299 TString doption = PadPointer->GetDrawOption();
3300 Double_t factor = 1;
3301 if (fH->GetNormFactor() != 0) {
3302 factor = fH->GetNormFactor()/fH->GetSumOfWeights();
3303 }
3304 // return if point is not in the histogram area
3305
3306 // If a 3D view exists, check distance to axis
3307 TView *view = gPad->GetView();
3308 Int_t d1,d2,d3;
3309 if (view && Hoption.Contour != 14) {
3310 Double_t ratio;
3311 d3 = view->GetDistancetoAxis(3, px, py, ratio);
3312 if (d3 <= kMaxDiff) {gPad->SetSelected(fZaxis); return 0;}
3313 d1 = view->GetDistancetoAxis(1, px, py, ratio);
3314 if (d1 <= kMaxDiff) {gPad->SetSelected(fXaxis); return 0;}
3315 d2 = view->GetDistancetoAxis(2, px, py, ratio);
3316 if (d2 <= kMaxDiff) {gPad->SetSelected(fYaxis); return 0;}
3317 if ( px > puxmin && px < puxmax && py > puymax && py < puymin) curdist = 1;
3318 goto FUNCTIONS;
3319 }
3320 // check if point is close to an axis
3321 doption.ToLower();
3322 dsame = kFALSE;
3323 if (doption.Contains("same")) dsame = kTRUE;
3324
3326 if (doption.Contains("y+")) {
3328 if (px <= xyaxis+dyaxis && px >= xyaxis && py >puymax && py < puymin) {
3329 if (!dsame) {
3330 if (gPad->IsVertical()) gPad->SetSelected(fYaxis);
3331 else gPad->SetSelected(fXaxis);
3332 return 0;
3333 }
3334 }
3335 } else {
3337 if (px >= xyaxis-dyaxis && px <= xyaxis && py >puymax && py < puymin) {
3338 if (!dsame) {
3339 if (gPad->IsVertical()) gPad->SetSelected(fYaxis);
3340 else gPad->SetSelected(fXaxis);
3341 return 0;
3342 }
3343 }
3344 }
3345
3347 if (doption.Contains("x+")) {
3349 if (py >= yxaxis-dxaxis && py <= yxaxis && px <puxmax && px > puxmin) {
3350 if (!dsame) {
3351 if (gPad->IsVertical()) gPad->SetSelected(fXaxis);
3352 else gPad->SetSelected(fYaxis);
3353 return 0;
3354 }
3355 }
3356 } else {
3358 if (yxaxis < puymin) yxaxis = puymin;
3360 if (!dsame) {
3361 if (gPad->IsVertical()) gPad->SetSelected(fXaxis);
3362 else gPad->SetSelected(fYaxis);
3363 return 0;
3364 }
3365 }
3366 }
3367
3368 if (fH->IsHighlight()) { // only if highlight is enable
3369 if ((px > puxmin) && (py < puymin) && (px < puxmax) && (py > puymax))
3370 HighlightBin(px, py);
3371 }
3372
3373 // if object is 2D or 3D return this object
3374 if (fH->GetDimension() == 2) {
3375 if (fH->InheritsFrom(TH2Poly::Class())) {
3376 TH2Poly *th2 = (TH2Poly*)fH;
3378 gPad->GetRangeAxis(xmin, ymin, xmax, ymax);
3379 Double_t pxu = gPad->AbsPixeltoX(px);
3380 Double_t pyu = gPad->AbsPixeltoY(py);
3381 if ((pxu>xmax) || (pxu < xmin) || (pyu>ymax) || (pyu < ymin)) {
3382 curdist = big;
3383 goto FUNCTIONS;
3384 } else {
3385 Int_t bin = th2->FindBin(pxu, pyu);
3386 if (bin>0) curdist = 1;
3387 else curdist = big;
3388 goto FUNCTIONS;
3389 }
3390 }
3391 Int_t delta2 = 5; //Give a margin of delta2 pixels to be in the 2-d area
3392 if ( px > puxmin + delta2
3393 && px < puxmax - delta2
3394 && py > puymax + delta2
3395 && py < puymin - delta2) {curdist =1; goto FUNCTIONS;}
3396 }
3397
3398 // point is inside histogram area. Find channel number
3399 if (gPad->IsVertical()) {
3400 Int_t bin = fXaxis->FindFixBin(gPad->PadtoX(x));
3401 Int_t binsup = fXaxis->FindFixBin(gPad->PadtoX(x1));
3402 Double_t binval = factor*fH->GetBinContent(bin);
3403 Int_t pybin = gPad->YtoAbsPixel(gPad->YtoPad(binval));
3404 if (binval == 0 && pybin < puymin) pybin = 10000;
3405 // special case if more than one bin for the pixel
3406 if (binsup-bin>1) {
3410 for (Int_t ibin=bin+1; ibin<binsup; ibin++) {
3414 }
3415 Int_t pybinmin = gPad->YtoAbsPixel(gPad->YtoPad(binvalmax));
3416 Int_t pybinmax = gPad->YtoAbsPixel(gPad->YtoPad(binvalmin));
3418 }
3419 if (bin != binsup) { // Mouse on bin border
3421 Int_t pybinsub = gPad->YtoAbsPixel(gPad->YtoPad(binsupval));
3422 if (py <= TMath::Max(pybinsub,pybin) && py >= TMath::Min(pybinsub,pybin) && pybin != 10000) return 0;
3423 }
3424 if (TMath::Abs(py - pybin) <= kMaxDiff) return TMath::Abs(py - pybin);
3425 } else {
3426 Double_t y = gPad->AbsPixeltoY(py);
3427 Double_t y1 = gPad->AbsPixeltoY(py+1);
3428 Int_t bin = fXaxis->FindFixBin(gPad->PadtoY(y));
3429 Int_t binsup = fXaxis->FindFixBin(gPad->PadtoY(y1));
3430 Double_t binval = factor*fH->GetBinContent(bin);
3431 Int_t pxbin = gPad->XtoAbsPixel(gPad->XtoPad(binval));
3432 if (binval == 0 && pxbin > puxmin) pxbin = 10000;
3433 // special case if more than one bin for the pixel
3434 if (binsup-bin>1) {
3438 for (Int_t ibin=bin+1; ibin<binsup; ibin++) {
3442 }
3443 Int_t pxbinmin = gPad->XtoAbsPixel(gPad->XtoPad(binvalmax));
3444 Int_t pxbinmax = gPad->XtoAbsPixel(gPad->XtoPad(binvalmin));
3446 }
3447 if (TMath::Abs(px - pxbin) <= kMaxDiff) return TMath::Abs(px - pxbin);
3448 }
3449 // Loop on the list of associated functions and user objects
3450FUNCTIONS:
3451 TObject *f;
3452 TIter next(fFunctions);
3453 while ((f = (TObject*) next())) {
3454 Int_t dist;
3455 if (f->InheritsFrom(TF1::Class())) dist = f->DistancetoPrimitive(-px,py);
3456 else dist = f->DistancetoPrimitive(px,py);
3457 if (dist < kMaxDiff) {gPad->SetSelected(f); return dist;}
3458 }
3459 return curdist;
3460}
3461
3462////////////////////////////////////////////////////////////////////////////////
3463/// Display a panel with all histogram drawing options.
3464
3466{
3467
3468 gCurrentHist = fH;
3469 if (!gPad) {
3470 Error("DrawPanel", "need to draw histogram first");
3471 return;
3472 }
3474 editor->Show();
3475 gROOT->ProcessLine(TString::Format("((TCanvas*)0x%zx)->Selected((TVirtualPad*)0x%zx,(TObject*)0x%zx,1)",
3476 (size_t)gPad->GetCanvas(), (size_t)gPad, (size_t)fH).Data());
3477}
3478
3479////////////////////////////////////////////////////////////////////////////////
3480/// Execute the actions corresponding to `event`.
3481///
3482/// This function is called when a histogram is clicked with the locator at
3483/// the pixel position px,py.
3484
3486{
3487
3488 if (!gPad) return;
3489
3490 static Int_t bin, px1, py1, px2, py2, pyold;
3491 static std::unique_ptr<TBox> zoombox;
3493
3494 Int_t bin1, bin2;
3495 Double_t xlow, xup, ylow, binval, x, baroffset, barwidth, binwidth;
3496 Bool_t opaque = gPad->OpaqueMoving();
3497
3498 if (!gPad->IsEditable()) return;
3499
3500 if (fPie) {
3501 fPie->ExecuteEvent(event, px, py);
3502 return;
3503 }
3504 // come here if we have a lego/surface in the pad
3505 TView *view = gPad->GetView();
3506
3507 if (!fShowProjection && view && !view->TestBit(kCannotRotate)) {
3508 view->ExecuteRotateView(event, px, py);
3509 return;
3510 }
3511
3512 TAxis *xaxis = fH->GetXaxis();
3513 TAxis *yaxis = fH->GetYaxis();
3514 Int_t dimension = fH->GetDimension();
3515
3516 // In case of option SAME the axis must be the ones of the first drawn histogram
3517 TString IsSame = fH->GetDrawOption();
3518 IsSame.ToLower();
3519 if (IsSame.Index("same")>=0) {
3520 TH1 *h1;
3521 TIter next(gPad->GetListOfPrimitives());
3522 while ((h1 = (TH1 *)next())) {
3523 if (!h1->InheritsFrom(TH1::Class())) continue;
3524 xaxis = h1->GetXaxis();
3525 yaxis = h1->GetYaxis();
3526 break;
3527 }
3528 }
3529
3530 Double_t factor = 1;
3531 if (fH->GetNormFactor() != 0) {
3532 factor = fH->GetNormFactor()/fH->GetSumOfWeights();
3533 }
3534
3535 switch (event) {
3536
3537 case kButton1Down:
3538
3539 if (!opaque) gVirtualX->SetLineColor(-1);
3540 fH->TAttLine::Modify();
3541
3542 if (opaque && dimension ==2) {
3543 zbx1 = gPad->AbsPixeltoX(px);
3544 zbx2 = gPad->AbsPixeltoX(px);
3545 zby1 = gPad->AbsPixeltoY(py);
3546 zby2 = gPad->AbsPixeltoY(py);
3547 px1 = px;
3548 py1 = py;
3549 if (gPad->GetLogx()) {
3550 zbx1 = TMath::Power(10,zbx1);
3551 zbx2 = TMath::Power(10,zbx2);
3552 }
3553 if (gPad->GetLogy()) {
3554 zby1 = TMath::Power(10,zby1);
3555 zby2 = TMath::Power(10,zby2);
3556 }
3557 if (zoombox) Error("ExecuteEvent", "Last zoom box was not deleted");
3558 zoombox = std::make_unique<TBox>(zbx1, zby1, zbx2, zby2);
3559 Int_t ci = TColor::GetColor("#7d7dff");
3560 TColor *zoomcolor = gROOT->GetColor(ci);
3561 if (!TCanvas::SupportAlpha() || !zoomcolor) zoombox->SetFillStyle(3002);
3562 else zoomcolor->SetAlpha(0.5);
3563 zoombox->SetFillColor(ci);
3564 zoombox->Draw();
3565 gPad->Modified();
3566 gPad->Update();
3567 }
3568 // No break !!!
3569
3570 case kMouseMotion:
3571
3572 if (fShowProjection) {ShowProjection3(px,py); break;}
3573
3574 gPad->SetCursor(kPointer);
3575 if (dimension ==1) {
3576 if (Hoption.Bar) {
3577 baroffset = fH->GetBarOffset();
3578 barwidth = fH->GetBarWidth();
3579 } else {
3580 baroffset = 0;
3581 barwidth = 1;
3582 }
3583 x = gPad->AbsPixeltoX(px);
3584 bin = fXaxis->FindFixBin(gPad->PadtoX(x));
3586 xlow = gPad->XtoPad(fXaxis->GetBinLowEdge(bin) + baroffset*binwidth);
3587 xup = gPad->XtoPad(xlow + barwidth*binwidth);
3588 ylow = gPad->GetUymin();
3589 px1 = gPad->XtoAbsPixel(xlow);
3590 px2 = gPad->XtoAbsPixel(xup);
3591 py1 = gPad->YtoAbsPixel(ylow);
3592 py2 = py;
3593 pyold = py;
3594 if (gROOT->GetEditHistograms()) gPad->SetCursor(kArrowVer);
3595 }
3596
3597 break;
3598
3599 case kButton1Motion:
3600
3601 if (dimension ==1) {
3602 if (gROOT->GetEditHistograms()) {
3603 if (!opaque) {
3604 gVirtualX->DrawBox(px1, py1, px2, py2,TVirtualX::kHollow); // Draw the old box
3605 py2 += py - pyold;
3606 gVirtualX->DrawBox(px1, py1, px2, py2,TVirtualX::kHollow); // Draw the new box
3607 pyold = py;
3608 } else {
3609 py2 += py - pyold;
3610 pyold = py;
3611 binval = gPad->PadtoY(gPad->AbsPixeltoY(py2))/factor;
3613 gPad->Modified(kTRUE);
3614 }
3615 }
3616 }
3617
3618 if (opaque && dimension ==2) {
3619 if (TMath::Abs(px1-px)>5 && TMath::Abs(py1-py)>5) {
3620 zbx2 = gPad->AbsPixeltoX(px);
3621 zby2 = gPad->AbsPixeltoY(py);
3622 if (gPad->GetLogx()) zbx2 = TMath::Power(10,zbx2);
3623 if (gPad->GetLogy()) zby2 = TMath::Power(10,zby2);
3624 if (zoombox) {
3625 zoombox->SetX2(zbx2);
3626 zoombox->SetY2(zby2);
3627 }
3628 gPad->Modified();
3629 gPad->Update();
3630 }
3631 }
3632
3633 break;
3634
3635 case kWheelUp:
3636
3637 if (dimension ==2) {
3638 bin1 = xaxis->GetFirst()+1;
3639 bin2 = xaxis->GetLast()-1;
3640 bin1 = TMath::Max(bin1, 1);
3641 bin2 = TMath::Min(bin2, xaxis->GetNbins());
3642 if (bin2>bin1) xaxis->SetRange(bin1,bin2);
3643 bin1 = yaxis->GetFirst()+1;
3644 bin2 = yaxis->GetLast()-1;
3645 bin1 = TMath::Max(bin1, 1);
3646 bin2 = TMath::Min(bin2, yaxis->GetNbins());
3647 if (bin2>bin1) yaxis->SetRange(bin1,bin2);
3648 }
3649 gPad->Modified();
3650 gPad->Update();
3651
3652 break;
3653
3654 case kWheelDown:
3655
3656 if (dimension == 2) {
3657 bin1 = xaxis->GetFirst()-1;
3658 bin2 = xaxis->GetLast()+1;
3659 bin1 = TMath::Max(bin1, 1);
3660 bin2 = TMath::Min(bin2, xaxis->GetNbins());
3661 const bool resetXaxisRange = bin1 == 1 && xaxis->GetFirst() == 1 && bin2 == xaxis->GetNbins() && xaxis->GetLast() == xaxis->GetNbins();
3662 if (bin2>bin1) xaxis->SetRange(bin1,bin2);
3663 if (resetXaxisRange) xaxis->ResetBit(TAxis::kAxisRange);
3664 bin1 = yaxis->GetFirst()-1;
3665 bin2 = yaxis->GetLast()+1;
3666 bin1 = TMath::Max(bin1, 1);
3667 bin2 = TMath::Min(bin2, yaxis->GetNbins());
3668 const bool resetYaxisRange = bin1 == 1 && yaxis->GetFirst() == 1 && bin2 == yaxis->GetNbins() && yaxis->GetLast() == yaxis->GetNbins();
3669 if (bin2>bin1) yaxis->SetRange(bin1,bin2);
3670 if (resetYaxisRange) yaxis->ResetBit(TAxis::kAxisRange);
3671 }
3672 gPad->Modified();
3673 gPad->Update();
3674
3675 break;
3676
3677 case kButton1Up:
3678 if (dimension ==1) {
3679 if (gROOT->GetEditHistograms()) {
3680 binval = gPad->PadtoY(gPad->AbsPixeltoY(py2))/factor;
3682 PaintInit(); // recalculate Hparam structure and recalculate range
3683 }
3684
3685 // might resize pad pixmap so should be called before any paint routine
3687 }
3688 if (opaque && dimension ==2) {
3689 if (zoombox) {
3690 Double_t x1 = TMath::Min(zoombox->GetX1(), zoombox->GetX2());
3691 Double_t x2 = TMath::Max(zoombox->GetX1(), zoombox->GetX2());
3692 Double_t y1 = TMath::Min(zoombox->GetY1(), zoombox->GetY2());
3693 Double_t y2 = TMath::Max(zoombox->GetY1(), zoombox->GetY2());
3694 x1 = TMath::Max(x1,xaxis->GetXmin());
3695 x2 = TMath::Min(x2,xaxis->GetXmax());
3696 y1 = TMath::Max(y1,yaxis->GetXmin());
3697 y2 = TMath::Min(y2,yaxis->GetXmax());
3698 if (x1<x2 && y1<y2) {
3699 xaxis->SetRangeUser(x1, x2);
3700 yaxis->SetRangeUser(y1, y2);
3701 }
3702 zoombox.reset();
3703 }
3704 }
3705 gPad->Modified(kTRUE);
3706 if (opaque) gVirtualX->SetLineColor(-1);
3707
3708 break;
3709
3710 case kButton1Locate:
3711
3712 ExecuteEvent(kButton1Down, px, py);
3713
3714 while (true) {
3715 px = py = 0;
3716 event = gVirtualX->RequestLocator(1, 1, px, py);
3717
3719
3720 if (event != -1) { // button is released
3721 ExecuteEvent(kButton1Up, px, py);
3722 return;
3723 }
3724 }
3725 }
3726}
3727
3728////////////////////////////////////////////////////////////////////////////////
3729/// Get a contour (as a list of TGraphs) using the Delaunay triangulation.
3730
3732{
3733 // Check if fH contains a TGraphDelaunay2D
3735 TGraphDelaunay2D *dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
3736 // try with the old painter
3737 TGraphDelaunay *dtOld = nullptr;
3738 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
3739
3740 if (!dt && !dtOld) return nullptr;
3741
3742 gCurrentHist = fH;
3743
3744 if (!fGraph2DPainter)
3745 ((THistPainter*)this)->fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
3746
3747 return fGraph2DPainter->GetContourList(contour);
3748}
3749
3750////////////////////////////////////////////////////////////////////////////////
3751/// Display the histogram info (bin number, contents, integral up to bin
3752/// corresponding to cursor position px,py.
3753
3755{
3756
3757 if (!gPad) return (char*)"";
3758
3759 Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
3760 Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
3761 Double_t x1 = gPad->PadtoX(gPad->AbsPixeltoX(px+1));
3763 drawOption.ToLower();
3766 if (fH->GetDimension() == 2) {
3767 if (gPad->GetView() || drawOption.Index("cont") >= 0) {
3768 uxmin=gPad->GetUxmin();
3769 uxmax=gPad->GetUxmax();
3772 x = xmin +(xmax-xmin)*(x-uxmin)/(uxmax-uxmin);
3773 uymin=gPad->GetUymin();
3774 uymax=gPad->GetUymax();
3777 y = ymin +(ymax-ymin)*(y-uymin)/(uymax-uymin);
3778 }
3779 }
3781 if (gPad->IsVertical()) {
3782 binx = fXaxis->FindFixBin(x);
3783 if (drawOption.Index("same") >= 0) {
3784 TH1 *h1;
3785 TIter next(gPad->GetListOfPrimitives());
3786 while ((h1 = (TH1 *)next())) {
3787 if (!h1->InheritsFrom(TH1::Class())) continue;
3788 binmin = h1->GetXaxis()->GetFirst();
3789 break;
3790 }
3791 } else {
3792 binmin = fXaxis->GetFirst();
3793 }
3795 // special case if more than 1 bin in x per pixel
3796 if (binx1-binx>1 && fH->GetDimension() == 1) {
3799 for (Int_t ibin=binx+1; ibin<binx1; ibin++) {
3803 binnear=ibin;
3804 }
3805 }
3806 binx = binnear;
3807 }
3808 } else {
3809 x1 = gPad->PadtoY(gPad->AbsPixeltoY(py+1));
3810 binx = fXaxis->FindFixBin(y);
3811 if (drawOption.Index("same") >= 0) {
3812 TH1 *h1;
3813 TIter next(gPad->GetListOfPrimitives());
3814 while ((h1 = (TH1 *)next())) {
3815 if (!h1->InheritsFrom(TH1::Class())) continue;
3816 binmin = h1->GetXaxis()->GetFirst();
3817 break;
3818 }
3819 } else {
3820 binmin = fXaxis->GetFirst();
3821 }
3823 // special case if more than 1 bin in x per pixel
3824 if (binx1-binx>1 && fH->GetDimension() == 1) {
3827 for (Int_t ibin=binx+1; ibin<binx1; ibin++) {
3831 binnear=ibin;
3832 }
3833 }
3834 binx = binnear;
3835 }
3836 }
3837 if (fH->GetDimension() == 1) {
3839 TProfile *tp = (TProfile*)fH;
3840 fObjectInfo.Form("(x=%g, y=%g, binx=%d, binc=%g, bine=%g, binn=%d)",
3842 (Int_t) tp->GetBinEntries(binx));
3843 }
3844 else {
3845 Double_t integ = 0;
3846 for (Int_t bin=binmin;bin<=binx;bin++) {integ += fH->GetBinContent(bin);}
3847 fObjectInfo.Form("(x=%g, y=%g, binx=%d, binc=%g, Sum=%g)",
3849 }
3850 } else if (fH->GetDimension() == 2) {
3851 if (fH->InheritsFrom(TH2Poly::Class())) {
3852 TH2Poly *th2 = (TH2Poly*)fH;
3853 biny = th2->FindBin(x,y);
3854 fObjectInfo.Form("%s (x=%g, y=%g, bin=%d, binc=%g)",
3855 th2->GetBinTitle(biny),x,y,biny,th2->GetBinContent(biny));
3856 }
3857 else if (fH->InheritsFrom(TProfile2D::Class())) {
3859 biny = fYaxis->FindFixBin(y);
3860 Int_t bin = fH->GetBin(binx,biny);
3861 fObjectInfo.Form("(x=%g, y=%g, binx=%d, biny=%d, binc=%g, bine=%g, binn=%d)",
3862 x, y, binx, biny, fH->GetBinContent(bin),
3863 fH->GetBinError(bin), (Int_t) tp->GetBinEntries(bin));
3864 } else {
3865 biny = fYaxis->FindFixBin(y);
3866 fObjectInfo.Form("(x=%g, y=%g, binx=%d, biny=%d, binc=%g bine=%g)",
3869 }
3870 } else {
3871 // 3d case: retrieving the x,y,z bin is not yet implemented
3872 // print just the x,y info
3873 fObjectInfo.Form("(x=%g, y=%g)",x,y);
3874 }
3875
3876 return (char *)fObjectInfo.Data();
3877}
3878
3879////////////////////////////////////////////////////////////////////////////////
3880/// Set highlight (enable/disable) mode for fH
3881
3883{
3884 if (fH->IsHighlight()) return;
3885
3886 fXHighlightBin = -1;
3887 fYHighlightBin = -1;
3888 // delete previous highlight box
3889 if (gXHighlightBox) gXHighlightBox.reset();
3890 if (gYHighlightBox) gYHighlightBox.reset();
3891 // emit Highlighted() signal (user can check on disabled)
3892 if (gPad->GetCanvas()) gPad->GetCanvas()->Highlighted(gPad, fH, fXHighlightBin, fYHighlightBin);
3893}
3894
3895////////////////////////////////////////////////////////////////////////////////
3896/// Check on highlight bin
3897
3899{
3900 // call from DistancetoPrimitive (only if highlight is enable)
3901
3902 Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
3903 Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
3906 if (!gPad->IsVertical()) binx = fXaxis->FindFixBin(y);
3907
3909 if (binx != fXHighlightBin) {
3911 changedBin = kTRUE;
3912 } else if (fH->GetDimension() == 1) return;
3913 if (biny != fYHighlightBin) {
3915 changedBin = kTRUE;
3916 }
3917 if (!changedBin) return;
3918
3919 // Info("HighlightBin", "histo: %p '%s'\txbin: %d, ybin: %d",
3920 // (void *)fH, fH->GetName(), fXHighlightBin, fYHighlightBin);
3921
3922 // paint highlight bin as box (recursive calls PaintHighlightBin)
3923 gPad->Modified(kTRUE);
3924 gPad->Update();
3925
3926 // emit Highlighted() signal
3927 if (gPad->GetCanvas()) gPad->GetCanvas()->Highlighted(gPad, fH, fXHighlightBin, fYHighlightBin);
3928}
3929
3930////////////////////////////////////////////////////////////////////////////////
3931/// Paint highlight bin as TBox object
3932
3934{
3935 // call from PaintTitle
3936
3937 if (!fH->IsHighlight()) return;
3938
3939 Double_t uxmin = gPad->GetUxmin();
3940 Double_t uxmax = gPad->GetUxmax();
3941 Double_t uymin = gPad->GetUymin();
3942 Double_t uymax = gPad->GetUymax();
3943 if (gPad->GetLogx()) {
3944 uxmin = TMath::Power(10.0, uxmin);
3945 uxmax = TMath::Power(10.0, uxmax);
3946 }
3947 if (gPad->GetLogy()) {
3948 uymin = TMath::Power(10.0, uymin);
3949 uymax = TMath::Power(10.0, uymax);
3950 }
3951
3952 // testing specific possibility (after zoom, draw with "same", log, etc.)
3954 if (gPad->IsVertical()) {
3956 if ((hcenter < uxmin) || (hcenter > uxmax)) return;
3957 } else {
3959 if ((hcenter < uymin) || (hcenter > uymax)) return;
3960 }
3961 if (fH->GetDimension() == 2) {
3963 if ((hcenter < uymin) || (hcenter > uymax)) return;
3964 }
3965
3966 // paint X highlight bin (for 1D or 2D)
3968 if (gPad->IsVertical()) {
3971 hby1 = uymin;
3972 hby2 = uymax;
3973 } else {
3974 hbx1 = uxmin;
3975 hbx2 = uxmax;
3978 }
3979
3980 if (!gXHighlightBox) {
3981 gXHighlightBox = std::make_unique<TBox>(hbx1, hby1, hbx2, hby2);
3982 gXHighlightBox->SetBit(kCannotPick);
3983 gXHighlightBox->SetFillColor(TColor::GetColor("#9797ff"));
3984 if (!TCanvas::SupportAlpha()) gXHighlightBox->SetFillStyle(3001);
3985 else gROOT->GetColor(gXHighlightBox->GetFillColor())->SetAlpha(0.5);
3986 }
3987 gXHighlightBox->SetX1(hbx1);
3988 gXHighlightBox->SetX2(hbx2);
3989 gXHighlightBox->SetY1(hby1);
3990 gXHighlightBox->SetY2(hby2);
3991 gXHighlightBox->Paint();
3992
3993 // Info("PaintHighlightBin", "histo: %p '%s'\txbin: %d, ybin: %d",
3994 // (void *)fH, fH->GetName(), fXHighlightBin, fYHighlightBin);
3995
3996 // paint Y highlight bin (only for 2D)
3997 if (fH->GetDimension() != 2) return;
3998 hbx1 = uxmin;
3999 hbx2 = uxmax;
4002
4003 if (!gYHighlightBox) {
4004 gYHighlightBox = std::make_unique<TBox>(hbx1, hby1, hbx2, hby2);
4005 gYHighlightBox->SetBit(kCannotPick);
4006 gYHighlightBox->SetFillColor(gXHighlightBox->GetFillColor());
4007 gYHighlightBox->SetFillStyle(gXHighlightBox->GetFillStyle());
4008 }
4009 gYHighlightBox->SetX1(hbx1);
4010 gYHighlightBox->SetX2(hbx2);
4011 gYHighlightBox->SetY1(hby1);
4012 gYHighlightBox->SetY2(hby2);
4013 gYHighlightBox->Paint();
4014}
4015
4016////////////////////////////////////////////////////////////////////////////////
4017/// Return `kTRUE` if the cell `ix`, `iy` is inside one of the graphical cuts.
4018
4020{
4021
4022 for (Int_t i=0;i<fNcuts;i++) {
4025 if (fCutsOpt[i] > 0) {
4026 if (!fCuts[i]->IsInside(x,y)) return kFALSE;
4027 } else {
4028 if (fCuts[i]->IsInside(x,y)) return kFALSE;
4029 }
4030 }
4031 return kTRUE;
4032}
4033
4034////////////////////////////////////////////////////////////////////////////////
4035/// Return `kTRUE` if the point `x`, `y` is inside one of the graphical cuts.
4036
4038{
4039
4040 for (Int_t i=0;i<fNcuts;i++) {
4041 if (fCutsOpt[i] > 0) {
4042 if (!fCuts[i]->IsInside(x,y)) return kFALSE;
4043 } else {
4044 if (fCuts[i]->IsInside(x,y)) return kFALSE;
4045 }
4046 }
4047 return kTRUE;
4048}
4049
4050////////////////////////////////////////////////////////////////////////////////
4051/// Decode string `choptin` and fill Hoption structure.
4052
4054{
4055
4056 char *l;
4057 char chopt[128];
4059 strlcpy(chopt,choptin,128);
4062
4070 Hoption.Candle = 0;
4071 Hoption.Polar = 0;
4072
4073 // special 2D options
4074 Hoption.List = 0;
4075 Hoption.Zscale = 0;
4076 Hoption.FrontBox = 1;
4077 Hoption.BackBox = 1;
4079
4080 Hoption.Zero = 0;
4081
4083
4084 //check for graphical cuts
4085 MakeCuts(chopt);
4086
4087 for (Int_t i=0;i<nch;i++) chopt[i] = toupper(chopt[i]);
4088 if (hdim > 1) Hoption.Color = 1; // Default drawing option for 2D and 3D histograms
4089 if (!nch) Hoption.Hist = 1;
4090 if (fFunctions->First()) Hoption.Func = 1;
4091 if (fH->GetSumw2N() && hdim == 1) Hoption.Error = 2;
4092
4093 char *l1 = strstr(chopt,"PFC"); // Automatic Fill Color
4094 char *l2 = strstr(chopt,"PLC"); // Automatic Line Color
4095 char *l3 = strstr(chopt,"PMC"); // Automatic Marker Color
4096 if (l1 || l2 || l3) {
4097 Int_t i = gPad->NextPaletteColor();
4098 if (l1) {memcpy(l1," ",3); fH->SetFillColor(i);}
4099 if (l2) {memcpy(l2," ",3); fH->SetLineColor(i);}
4100 if (l3) {memcpy(l3," ",3); fH->SetMarkerColor(i);}
4101 Hoption.Hist = 1; // Make sure something is drawn in case there is no drawing option specified.
4102 }
4103
4104 l = strstr(chopt,"MIN0");
4105 if (l) {
4106 Hoption.MinimumZero = 1;
4107 memcpy(l," ",4);
4108 }
4109
4110 l = strstr(chopt,"SPEC");
4111 if (l) {
4112 Hoption.Color = 0;
4113 memcpy(l," ",4);
4114 Int_t bs=0;
4115 l = strstr(chopt,"BF(");
4116 if (l) {
4117 if (sscanf(&l[3],"%d",&bs) > 0) {
4118 Int_t i=0;
4119 while (l[i]!=')') {
4120 l[i] = ' ';
4121 i++;
4122 }
4123 l[i] = ' ';
4124 }
4125 }
4126 Hoption.Spec = TMath::Max(1600,bs);
4127 return 1;
4128 }
4129
4130 l = strstr(chopt,"GL");
4131 if (l) {
4132 memcpy(l," ",2);
4133 }
4134 l = strstr(chopt,"X+");
4135 if (l) {
4136 Hoption.AxisPos = 10;
4137 memcpy(l," ",2);
4138 }
4139 l = strstr(chopt,"Y+");
4140 if (l) {
4141 Hoption.AxisPos += 1;
4142 memcpy(l," ",2);
4143 }
4144 if ((Hoption.AxisPos == 10 || Hoption.AxisPos == 1) && (nch == 2)) Hoption.Hist = 1;
4145 if (Hoption.AxisPos == 11 && nch == 4) Hoption.Hist = 1;
4146
4147 l = strstr(chopt,"SAMES");
4148 if (l) {
4149 if (nch == 5) Hoption.Hist = 1;
4150 Hoption.Same = 2;
4151 memcpy(l," ",5);
4152 if (l[5] == '0') { Hoption.Same += 10; l[5] = ' '; }
4153 }
4154 l = strstr(chopt,"SAME");
4155 if (l) {
4156 if (nch == 4) Hoption.Hist = 1;
4157 Hoption.Same = 1;
4158 memcpy(l," ",4);
4159 if (l[4] == '0') { Hoption.Same += 10; l[4] = ' '; }
4160 }
4161
4162 l = strstr(chopt,"SCAT");
4163 if (l) {
4164 Warning("MakeChopt","option SCAT is deprecated.");
4165 Hoption.Scat = 1;
4166 memcpy(l," ",4);
4167 Hoption.Color = 0;
4168 }
4169
4170 l = strstr(chopt,"PIE");
4171 if (l) {
4172 Hoption.Pie = 1;
4173 memcpy(l," ",3);
4174 }
4175
4176
4177 l = strstr(chopt,"CANDLE");
4178 if (l) {
4180 Hoption.Candle = candle.ParseOption(l);
4181 Hoption.Color = 0;
4182 }
4183
4184 l = strstr(chopt,"VIOLIN");
4185 if (l) {
4187 Hoption.Candle = candle.ParseOption(l);
4188 Hoption.Color = 0;
4189 }
4190
4191 l = strstr(chopt,"LEGO");
4192 if (l) {
4193 Hoption.Color = 0;
4194 Hoption.Lego = 1; memcpy(l," ",4);
4195 if (l[4] == '1') { Hoption.Lego = 11; l[4] = ' '; }
4196 if (l[4] == '2') { Hoption.Lego = 12; l[4] = ' '; }
4197 if (l[4] == '3') { Hoption.Lego = 13; l[4] = ' '; }
4198 if (l[4] == '4') { Hoption.Lego = 14; l[4] = ' '; }
4199 if (l[4] == '9') { Hoption.Lego = 19; l[4] = ' '; }
4200 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4201 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4202 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4203 }
4204
4205 l = strstr(chopt,"SURF");
4206 if (l) {
4207 Hoption.Color = 0;
4208 Hoption.Surf = 1; memcpy(l," ",4);
4209 if (l[4] == '1') { Hoption.Surf = 11; l[4] = ' '; }
4210 if (l[4] == '2') { Hoption.Surf = 12; l[4] = ' '; }
4211 if (l[4] == '3') { Hoption.Surf = 13; l[4] = ' '; }
4212 if (l[4] == '4') { Hoption.Surf = 14; l[4] = ' '; }
4213 if (l[4] == '5') { Hoption.Surf = 15; l[4] = ' '; }
4214 if (l[4] == '6') { Hoption.Surf = 16; l[4] = ' '; }
4215 if (l[4] == '7') { Hoption.Surf = 17; l[4] = ' '; }
4216 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4217 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4218 }
4219
4220 l = strstr(chopt,"TF3");
4221 if (l) {
4222 memcpy(l," ",3);
4223 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4224 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4225 }
4226
4227 l = strstr(chopt,"ISO");
4228 if (l) {
4229 memcpy(l," ",3);
4230 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4231 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4232 Hoption.Color = 0;
4233 }
4234
4235 l = strstr(chopt,"LIST"); if (l) { Hoption.List = 1; memcpy(l," ",4);}
4236
4237 l = strstr(chopt,"CONT");
4238 if (l) {
4239 memcpy(l," ",4);
4240 if (hdim>1) {
4241 Hoption.Color = 0;
4242 Hoption.Contour = 1;
4243 if (l[4] == '1') { Hoption.Contour = 11; l[4] = ' '; }
4244 if (l[4] == '2') { Hoption.Contour = 12; l[4] = ' '; }
4245 if (l[4] == '3') { Hoption.Contour = 13; l[4] = ' '; }
4246 if (l[4] == '4') { Hoption.Contour = 14; l[4] = ' '; }
4247 if (l[4] == '5') { Hoption.Contour = 15; l[4] = ' '; }
4248 } else {
4249 Hoption.Hist = 1;
4250 }
4251 }
4252 l = strstr(chopt,"HBAR");
4253 if (l) {
4254 Hoption.Hist = 0;
4255 Hoption.Bar = 20; memcpy(l," ",4);
4256 if (l[4] == '1') { Hoption.Bar = 21; l[4] = ' '; }
4257 if (l[4] == '2') { Hoption.Bar = 22; l[4] = ' '; }
4258 if (l[4] == '3') { Hoption.Bar = 23; l[4] = ' '; }
4259 if (l[4] == '4') { Hoption.Bar = 24; l[4] = ' '; }
4260 }
4261 l = strstr(chopt,"BAR");
4262 if (l) {
4263 Hoption.Hist = 0;
4264 Hoption.Bar = 10; memcpy(l," ",3);
4265 if (l[3] == '1') { Hoption.Bar = 11; l[3] = ' '; }
4266 if (l[3] == '2') { Hoption.Bar = 12; l[3] = ' '; }
4267 if (l[3] == '3') { Hoption.Bar = 13; l[3] = ' '; }
4268 if (l[3] == '4') { Hoption.Bar = 14; l[3] = ' '; }
4269 }
4270
4271 l = strstr(chopt,"ARR" );
4272 if (l) {
4273 memcpy(l," ", 3);
4274 if (hdim>1) {
4275 Hoption.Arrow = 1;
4276 Hoption.Color = 0;
4277 l = strstr(chopt,"COL"); if (l) { Hoption.Arrow = 2; memcpy(l," ",3); }
4278 l = strstr(chopt,"Z"); if (l) { Hoption.Zscale = 1; memcpy(l," ",1); }
4279 } else {
4280 Hoption.Hist = 1;
4281 }
4282 }
4283 l = strstr(chopt,"BOX" );
4284 if (l) {
4285 memcpy(l," ", 3);
4286 if (hdim>1) {
4287 Hoption.Color = 0;
4288 Hoption.Box = 1;
4289 if (l[3] == '1') { Hoption.Box = 11; l[3] = ' '; }
4290 if (l[3] == '2') { Hoption.Box = 12; l[3] = ' '; }
4291 if (l[3] == '3') { Hoption.Box = 13; l[3] = ' '; }
4292 } else {
4293 Hoption.Hist = 1;
4294 }
4295 }
4296 l = strstr(chopt,"TEXT");
4297 if (l) {
4298 Int_t angle;
4299 if (sscanf(&l[4],"%d",&angle) > 0) {
4300 if (angle < 0) angle=0;
4301 if (angle > 90) angle=90;
4302 Hoption.Text = 1000+angle;
4303 } else {
4304 Hoption.Text = 1;
4305 }
4306 memcpy(l," ", 4);
4307 l = strstr(chopt,"N");
4308 if (l && fH->InheritsFrom(TH2Poly::Class())) Hoption.Text = 3000 + (Hoption.Text != 1 ? Hoption.Text : 0);
4309 Hoption.Color = 0;
4310 }
4311 l = strstr(chopt,"COLZ");
4312 if (l) {
4313 memcpy(l," ",4);
4314 if (hdim > 1) {
4316 Hoption.Color = 1;
4317 Hoption.Zscale = 1;
4318 if (l[4] == '2') { Hoption.Color = 3; l[4] = ' '; }
4319 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4320 l = strstr(chopt,"1"); if (l) { Hoption.Color = 2; memcpy(l," ",1); }
4321 } else {
4322 Hoption.Hist = 1;
4323 }
4324 }
4325 l = strstr(chopt,"COL" );
4326 if (l) {
4327 memcpy(l," ", 3);
4328 if (hdim > 1) {
4330 Hoption.Color = 1;
4331 if (l[3] == '2') { Hoption.Color = 3; l[3] = ' '; }
4332 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4333 l = strstr(chopt,"1"); if (l) { Hoption.Color = 2; memcpy(l," ",1); }
4334 } else {
4335 Hoption.Hist = 1;
4336 }
4337 }
4338 l = strstr(chopt,"FUNC"); if (l) { Hoption.Func = 2; memcpy(l," ",4); Hoption.Hist = 0; }
4339 l = strstr(chopt,"HIST"); if (l) { Hoption.Hist = 2; memcpy(l," ",4); Hoption.Func = 0; Hoption.Error = 0;}
4340 l = strstr(chopt,"AXIS"); if (l) { Hoption.Axis = 1; memcpy(l," ",4); }
4341 l = strstr(chopt,"AXIG"); if (l) { Hoption.Axis = 2; memcpy(l," ",4); }
4342 l = strstr(chopt,"SCAT"); if (l) { Hoption.Scat = 1; memcpy(l," ",4); }
4343 l = strstr(chopt,"POLN"); if (l) { Hoption.System = kPOLAR; Hoption.Polar = 3; memcpy(l," ",4); }
4344 l = strstr(chopt,"POLF"); if (l) { Hoption.System = kPOLAR; Hoption.Polar = 2; memcpy(l," ",4); }
4345 l = strstr(chopt,"POL"); if (l) { Hoption.System = kPOLAR; Hoption.Polar = 1; memcpy(l," ",3); }
4346 l = strstr(chopt,"CYL"); if (l) { Hoption.System = kCYLINDRICAL; memcpy(l," ",3); }
4347 l = strstr(chopt,"SPH"); if (l) { Hoption.System = kSPHERICAL; memcpy(l," ",3); }
4348 l = strstr(chopt,"PSR"); if (l) { Hoption.System = kRAPIDITY; memcpy(l," ",3); }
4349
4350 l = strstr(chopt,"TRI");
4351 if (l) {
4352 if (!explicitColor) Hoption.Color = 0;
4353 Hoption.Tri = 1; memcpy(l," ",3);
4354 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4355 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4356 l = strstr(chopt,"ERR"); if (l) memcpy(l," ",3);
4357 }
4358
4359 l = strstr(chopt,"AITOFF");
4360 if (l) {
4361 Hoption.Proj = 1; memcpy(l," ",6); //Aitoff projection
4362 }
4363 l = strstr(chopt,"MERCATOR");
4364 if (l) {
4365 Hoption.Proj = 2; memcpy(l," ",8); //Mercator projection
4366 }
4367 l = strstr(chopt,"SINUSOIDAL");
4368 if (l) {
4369 Hoption.Proj = 3; memcpy(l," ",10); //Sinusoidal projection
4370 }
4371 l = strstr(chopt,"PARABOLIC");
4372 if (l) {
4373 Hoption.Proj = 4; memcpy(l," ",9); //Parabolic projection
4374 }
4375 l = strstr(chopt,"MOLLWEIDE");
4376 if (l) {
4377 Hoption.Proj = 5; memcpy(l," ",9); //Mollweide projection
4378 }
4379 if (Hoption.Proj > 0) {
4380 if (!explicitColor) Hoption.Color = 0;
4381 Hoption.Contour = 14;
4382 }
4383
4384 if (strstr(chopt,"A")) Hoption.Axis = -1;
4385 if (strstr(chopt,"B")) Hoption.Bar = 1;
4386 if (strstr(chopt,"C") && !strstr(chopt,"CJUST")) { Hoption.Curve =1; Hoption.Hist = -1;}
4387 if (strstr(chopt,"F")) Hoption.Fill =1;
4388 if (strstr(chopt,"][")) {Hoption.Off =1; Hoption.Hist =1;}
4389 if (strstr(chopt,"F2")) Hoption.Fill =2;
4390 if (strstr(chopt,"L")) { Hoption.Line =1; Hoption.Hist = -1;}
4391 if (strstr(chopt,"P")) { Hoption.Mark =1; Hoption.Hist = -1;}
4392 if (strstr(chopt,"Z")) Hoption.Zscale =1;
4393 if (strstr(chopt,"*")) Hoption.Star =1;
4394 if (strstr(chopt,"H")) Hoption.Hist =2;
4395 if (strstr(chopt,"P0")) Hoption.Mark =10;
4396
4397 if (fH->InheritsFrom(TH2Poly::Class())) {
4399 }
4400
4401 if (strstr(chopt,"E")) {
4402 if (hdim == 1) {
4403 Hoption.Error = 1;
4404 if (strstr(chopt,"E1")) Hoption.Error = 11;
4405 if (strstr(chopt,"E2")) Hoption.Error = 12;
4406 if (strstr(chopt,"E3")) Hoption.Error = 13;
4407 if (strstr(chopt,"E4")) Hoption.Error = 14;
4408 if (strstr(chopt,"E5")) Hoption.Error = 15;
4409 if (strstr(chopt,"E6")) Hoption.Error = 16;
4410 if (strstr(chopt,"E0")) Hoption.Error += 40;
4411 if (strstr(chopt,"X0")) {
4412 if (Hoption.Error == 1) Hoption.Error += 20;
4413 Hoption.Error += 10;
4414 }
4416 Hoption.Text += 2000;
4417 Hoption.Error = 0;
4418 }
4419 } else {
4420 if (Hoption.Error == 0) {
4421 Hoption.Error = 100;
4422 if (!explicitColor) Hoption.Color = 0;
4423 }
4424 if (Hoption.Text) {
4425 Hoption.Text += 2000;
4426 Hoption.Error = 0;
4427 }
4428 }
4429 }
4430
4431 if (Hoption.Surf == 15) {
4433 Hoption.Surf = 13;
4434 Warning("MakeChopt","option SURF5 is not supported in Cartesian and Polar modes");
4435 }
4436 }
4437
4438 // Copy options from current style
4439 Hoption.Logx = gPad->GetLogx();
4440 Hoption.Logy = gPad->GetLogy();
4441 Hoption.Logz = gPad->GetLogz();
4442
4443 // Check options incompatibilities
4444 if (Hoption.Bar == 1) Hoption.Hist = -1;
4445 return 1;
4446}
4447
4448////////////////////////////////////////////////////////////////////////////////
4449/// Decode string `choptin` and fill Graphical cuts structure.
4450
4452{
4453
4454 fNcuts = 0;
4455 char *left = (char*)strchr(choptin,'[');
4456 if (!left) return 0;
4457 char *right = (char*)strchr(choptin,']');
4458 if (!right) return 0;
4459 Int_t nch = right-left;
4460 if (nch < 2) return 0;
4461 char *cuts = left+1;
4462 *right = 0;
4463 char *comma, *minus;
4464 Int_t i;
4465 while (true) {
4466 comma = strchr(cuts,',');
4467 if (comma) *comma = 0;
4468 minus = strchr(cuts,'-');
4469 if (minus) cuts = minus+1;
4470 while (*cuts == ' ') cuts++;
4471 Int_t nc = strlen(cuts);
4472 while (cuts[nc-1] == ' ') {cuts[nc-1] = 0; nc--;}
4473 TIter next(gROOT->GetListOfSpecials());
4474 TCutG *cut=nullptr;
4475 TObject *obj;
4476 while ((obj = next())) {
4477 if (!obj->InheritsFrom(TCutG::Class())) continue;
4478 if (strcmp(obj->GetName(),cuts)) continue;
4479 cut = (TCutG*)obj;
4480 break;
4481 }
4482 if (cut) {
4483 fCuts[fNcuts] = cut;
4484 fCutsOpt[fNcuts] = 1;
4485 if (minus) fCutsOpt[fNcuts] = -1;
4486 fNcuts++;
4487 }
4488 if (!comma) break;
4489 cuts = comma+1;
4490 }
4491 for (i=0;i<=nch;i++) left[i] = ' ';
4492 return fNcuts;
4493}
4494
4495////////////////////////////////////////////////////////////////////////////////
4496/// [Control routine to paint any kind of histograms](\ref HP00)
4497
4499{
4500
4501 if (fH->GetBuffer()) fH->BufferEmpty(-1);
4502
4503 //For iOS: put the histogram on the top of stack of pickable objects.
4505
4506 gPad->SetVertical(kTRUE);
4507
4509 gCurrentHist = fH;
4510 TH1 *hsave = fH;
4512
4513 if (!MakeChopt(option)) return; //check options and fill Hoption structure
4514
4515 // Paint using TSpectrum2Painter
4516 if (Hoption.Spec) {
4517 if (!TableInit()) return;
4518 if (!TClass::GetClass("TSpectrum2Painter")) gSystem->Load("libSpectrumPainter");
4519 gROOT->ProcessLineFast(TString::Format("TSpectrum2Painter::PaintSpectrum((TH2F*)0x%zx,\"%s\",%d)",
4520 (size_t)fH, option, Hoption.Spec).Data());
4521 return;
4522 }
4523
4524 // Deflate the labels in case of alphanumeric labels
4528
4529 if (Hoption.Pie) {
4530 if (fH->GetDimension() == 1) {
4531 if (!fPie)
4532 fPie = std::make_unique<TPie>(fH);
4533 fPie->Paint(option);
4534 } else {
4535 Error("Paint", "Option PIE is for 1D histograms only");
4536 }
4537 return;
4538 } else {
4539 fPie.reset();
4540 }
4541
4542 fXbuf.resize(kNMAX);
4543 fYbuf.resize(kNMAX);
4544 if (fH->GetDimension() > 2) {
4545 PaintH3(option);
4547 if (Hoption.Func) {
4552 Hoption = hoptsave;
4553 Hparam = hparsave;
4554 }
4556 fXbuf.clear();
4557 fYbuf.clear();
4558 return;
4559 }
4560 TView *view = gPad->GetView();
4561 if (view) {
4562 if (!Hoption.Lego && !Hoption.Surf && !Hoption.Tri) {
4563 delete view;
4564 gPad->SetView(nullptr);
4565 }
4566 }
4567 if (fH->GetDimension() > 1 || Hoption.Lego || Hoption.Surf) {
4568 // In case of 1D histogram, Z axis becomes Y axis.
4569 Int_t logysav=0, logzsav=0;
4570 if (fH->GetDimension() == 1) {
4573 Hoption.Logz = 0;
4574 if (Hoption.Logy) {
4575 Hoption.Logz = 1;
4576 Hoption.Logy = 0;
4577 }
4578 }
4580 if (Hoption.Func) {
4585 Hoption = hoptsave;
4586 Hparam = hparsave;
4587 }
4590 fXbuf.clear();
4591 fYbuf.clear();
4592 if (fH->GetDimension() == 1) {
4595 }
4596 return;
4597 }
4598
4599 if (Hoption.Bar >= 20) {
4601 fXbuf.clear();
4602 fYbuf.clear();
4603 return;
4604 }
4605
4606 gPad->RangeAxisChanged(); //emit RangeAxisChanged() signal to sync axes
4607 // fill Hparam structure with histo parameters
4608 if (!PaintInit()) {
4609 fXbuf.clear();
4610 fYbuf.clear();
4611 return;
4612 }
4613
4614 // Picture surround (if new page) and page number (if requested).
4615 // Histogram surround (if not option "Same").
4616 PaintFrame();
4617
4618 // Paint histogram axis only
4619 Bool_t gridx = gPad->GetGridx();
4620 Bool_t gridy = gPad->GetGridy();
4621 if (Hoption.Axis > 0) {
4622 if (Hoption.Axis > 1) PaintAxis(kTRUE); //axis with grid
4623 else {
4624 if (gridx) gPad->SetGridx(0);
4625 if (gridy) gPad->SetGridy(0);
4627 if (gridx) gPad->SetGridx(1);
4628 if (gridy) gPad->SetGridy(1);
4629 }
4630 if ((Hoption.Same%10) ==1) Hoption.Same += 1;
4631 goto paintstat;
4632 }
4633 if (gridx || gridy) PaintAxis(kTRUE); // Draw the grid only
4634
4635 // test for options BAR or HBAR
4636 if (Hoption.Bar >= 10) {
4638 }
4639
4640 // do not draw histogram if error bars required
4641 if (!Hoption.Error) {
4642 if (Hoption.Hist && Hoption.Bar<10) PaintHist(option);
4643 }
4644
4645 // test for error bars or option E
4646 if (Hoption.Error) {
4648 if (Hoption.Hist == 2) PaintHist(option);
4649 }
4650
4652
4653 // test for associated function
4654 if (Hoption.Func) {
4659 Hoption = hoptsave;
4660 Hparam = hparsave;
4661 }
4662
4663 if (gridx) gPad->SetGridx(0);
4664 if (gridy) gPad->SetGridy(0);
4666 if (gridx) gPad->SetGridx(1);
4667 if (gridy) gPad->SetGridy(1);
4668
4669 PaintTitle(); // Draw histogram title
4670
4671 // Draw box with histogram statistics and/or fit parameters
4672paintstat:
4673 if ((Hoption.Same%10) != 1 && !fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
4674 TIter next(fFunctions);
4675 TObject *obj = nullptr;
4676 while ((obj = next())) {
4677 if (obj->InheritsFrom(TF1::Class())) break;
4678 obj = nullptr;
4679 }
4680
4681 //Stat is painted twice (first, it will be in canvas' list of primitives),
4682 //second, it will be here, this is not required on iOS.
4683 //Condition is ALWAYS true on a platform different from iOS.
4684 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode())
4685 PaintStat(gStyle->GetOptStat(),(TF1*)obj);
4686 }
4689 fXbuf.clear();
4690 fYbuf.clear();
4691}
4692
4693////////////////////////////////////////////////////////////////////////////////
4694/// [Control function to draw a table as an arrow plot](\ref HP12)
4695
4697{
4699 Double_t dx, dy, x1, x2, y1, y2, xc, yc, dxn, dyn;
4702 Double_t xrg = gPad->GetUxmin();
4703 Double_t yrg = gPad->GetUymin();
4704 Double_t xln = gPad->GetUxmax() - xrg;
4705 Double_t yln = gPad->GetUymax() - yrg;
4706 Double_t cx = (xln/Double_t(ncx))/2.;
4707 Double_t cy = (yln/Double_t(ncy))/2.;
4708 Double_t dn = 1.E-30;
4709
4710 auto arrow = new TArrow();
4711 arrow->SetAngle(30);
4712 arrow->SetFillStyle(1001);
4713 arrow->SetFillColor(fH->GetLineColor());
4714 arrow->SetLineColor(fH->GetLineColor());
4715 arrow->SetLineWidth(fH->GetLineWidth());
4716
4717 // Initialize the levels on the Z axis
4718 Int_t ncolors=0, ndivz=0;
4719 Double_t scale=0.;
4720 if (Hoption.Arrow>1) {
4722 Int_t ndiv = fH->GetContour();
4723 if (ndiv == 0 ) {
4724 ndiv = gStyle->GetNumberContours();
4725 fH->SetContour(ndiv);
4726 }
4727 ndivz = TMath::Abs(ndiv);
4728 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
4730 }
4731
4732 for (Int_t id=1;id<=2;id++) {
4733 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
4736 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
4737 xk = fXaxis->GetBinLowEdge(i);
4738 xstep = fXaxis->GetBinWidth(i);
4739 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
4740 if (i == Hparam.xfirst) {
4741 dx = fH->GetBinContent(i+1, j) - fH->GetBinContent(i, j);
4742 } else if (i == Hparam.xlast) {
4743 dx = fH->GetBinContent(i, j) - fH->GetBinContent(i-1, j);
4744 } else {
4745 dx = 0.5*(fH->GetBinContent(i+1, j) - fH->GetBinContent(i-1, j));
4746 }
4747 if (j == Hparam.yfirst) {
4748 dy = fH->GetBinContent(i, j+1) - fH->GetBinContent(i, j);
4749 } else if (j == Hparam.ylast) {
4750 dy = fH->GetBinContent(i, j) - fH->GetBinContent(i, j-1);
4751 } else {
4752 dy = 0.5*(fH->GetBinContent(i, j+1) - fH->GetBinContent(i, j-1));
4753 }
4754 if (id == 1) {
4757 } else if (id == 2) {
4758 xc = xrg + xln*(Double_t(i - Hparam.xfirst+1)-0.5)/Double_t(ncx);
4759 dxn = cx*dx/dn;
4760 x1 = xc - dxn;
4761 x2 = xc + dxn;
4762 yc = yrg + yln*(Double_t(j - Hparam.yfirst+1)-0.5)/Double_t(ncy);
4763 dyn = cy*dy/dn;
4764 y1 = yc - dyn;
4765 y2 = yc + dyn;
4766 if (Hoption.Arrow>1) {
4767 int color = Int_t(0.01+(fH->GetBinContent(i, j)-fH->GetMinimum())*scale);
4768 Int_t theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
4769 if (theColor > ncolors-1) theColor = ncolors-1;
4770 arrow->SetFillColor(gStyle->GetColorPalette(theColor));
4771 arrow->SetLineColor(gStyle->GetColorPalette(theColor));
4772 }
4773 if (TMath::Abs(x2-x1) > 0. || TMath::Abs(y2-y1) > 0.) {
4774 arrow->PaintArrow(x1, y1, x2, y2, 0.015, "|>");
4775 } else {
4776 arrow->PaintArrow(x1, y1, x2, y2, 0.005, "|>");
4777 }
4778 }
4779 }
4780 }
4781 }
4782
4784}
4785
4786////////////////////////////////////////////////////////////////////////////////
4787/// Draw axis (2D case) of an histogram.
4788///
4789/// If `drawGridOnly` is `TRUE`, only the grid is painted (if needed). This allows
4790/// to draw the grid and the axis separately. In `THistPainter::Paint` this
4791/// feature is used to make sure that the grid is drawn in the background and
4792/// the axis tick marks in the foreground of the pad.
4793
4795{
4796
4797 //On iOS, grid should not be pickable and can not be highlighted.
4798 //Condition is never true on a platform different from iOS.
4799 if (drawGridOnly && (gPad->PadInHighlightMode() || gPad->PadInSelectionMode()))
4800 return;
4801
4802 if (Hoption.Axis == -1) return;
4803 if (Hoption.Same && Hoption.Axis <= 0) return;
4804
4805 // Repainting alphanumeric labels axis on a plot done with
4806 // the option HBAR (horizontal) needs some adjustments.
4807 TAxis *xaxis = nullptr;
4808 TAxis *yaxis = nullptr;
4809 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4810 if (fXaxis->GetLabels() || fYaxis->GetLabels()) { // One axis has alphanumeric labels
4811 TIter next(gPad->GetListOfPrimitives());
4812 TObject *obj;
4813 // Check if the first TH1 of THStack in the pad is drawn with the option HBAR
4814 while ((obj = next())) {
4815 if (!obj->InheritsFrom(TH1::Class()) &&
4816 !obj->InheritsFrom(THStack::Class())) continue;
4817 TString opt = obj->GetDrawOption();
4818 opt.ToLower();
4819 // if drawn with HBAR, the axis should be inverted and the pad set to horizontal
4820 if (strstr(opt,"hbar")) {
4821 gPad->SetVertical(kFALSE);
4822 xaxis = fXaxis;
4823 yaxis = fYaxis;
4824 if (!strcmp(xaxis->GetName(),"xaxis")) {
4825 fXaxis = yaxis;
4826 fYaxis = xaxis;
4827 }
4828 }
4829 break;
4830 }
4831 }
4832 }
4833
4834 static char chopt[10] = "";
4835 Double_t gridl = 0;
4836 Int_t ndiv, ndivx, ndivy, nx1, nx2, ndivsave;
4837 Int_t useHparam = 0;
4841
4842 Double_t axmin = gPad->GetUxmin();
4843 Double_t axmax = gPad->GetUxmax();
4844 Double_t aymin = gPad->GetUymin();
4845 Double_t aymax = gPad->GetUymax();
4846 char *cw = nullptr;
4847 TGaxis axis;
4848
4849 // In case of option 'cont4' or in case of option 'same' over a 'cont4 plot'
4850 // Hparam must be use for the axis limits.
4851 if (Hoption.Contour == 14) useHparam = 1;
4852 if (Hoption.Same) {
4853 TObject *obj;
4854 TIter next(gPad->GetListOfPrimitives());
4855 while ((obj=next())) {
4856 if (strstr(obj->GetDrawOption(),"cont4")) {
4857 useHparam = 1;
4858 break;
4859 }
4860 }
4861 }
4862
4863 // Paint X axis
4864
4865 //To make X-axis selectable on iOS device.
4866 if (gPad->PadInSelectionMode())
4867 gPad->PushSelectableObject(fXaxis);
4868
4869 //This condition is ALWAYS true, unless it works on iOS (can be false on iOS).
4870 if (gPad->PadInSelectionMode() || !gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && gPad->GetSelected() == fXaxis)) {
4872 if (ndivx > 1000) {
4873 nx2 = ndivx/100;
4874 nx1 = TMath::Max(1, ndivx%100);
4875 ndivx = 100*nx2 + Int_t(Float_t(nx1)*gPad->GetAbsWNDC());
4876 }
4877 axis.SetTextAngle(0);
4879
4880 chopt[0] = 0;
4881 strlcat(chopt, "SDH",10);
4882 if (ndivx < 0) strlcat(chopt, "N",10);
4883 if (gPad->GetGridx()) {
4884 gridl = (aymax-aymin)/(gPad->GetY2() - gPad->GetY1());
4885 strlcat(chopt, "W",10);
4886 }
4887
4888 // Define X-Axis limits
4889 if (Hoption.Logx) {
4890 strlcat(chopt, "G",10);
4891 ndiv = TMath::Abs(ndivx);
4892 if (useHparam) {
4895 } else {
4896 umin = TMath::Power(10,axmin);
4897 umax = TMath::Power(10,axmax);
4898 }
4899 } else {
4900 ndiv = TMath::Abs(ndivx);
4901 if (useHparam) {
4902 umin = Hparam.xmin;
4903 umax = Hparam.xmax;
4904 } else {
4905 umin = axmin;
4906 umax = axmax;
4907 }
4908 }
4909
4910 // Display axis as time
4911 if (fXaxis->GetTimeDisplay()) {
4912 strlcat(chopt,"t",10);
4913 if (strlen(fXaxis->GetTimeFormatOnly()) == 0) {
4915 }
4916 }
4917
4918 // The main X axis can be on the bottom or on the top of the pad
4920 if (xAxisPos == 1) {
4921 // Main X axis top
4922 xAxisYPos1 = aymax;
4923 xAxisYPos2 = aymin;
4924 } else {
4925 // Main X axis bottom
4926 xAxisYPos1 = aymin;
4927 xAxisYPos2 = aymax;
4928 }
4929
4930 // Paint the main X axis (always)
4931 uminsave = umin;
4932 umaxsave = umax;
4933 ndivsave = ndiv;
4934 axis.SetOption(chopt);
4935 if (xAxisPos) {
4936 strlcat(chopt, "-",10);
4937 gridl = -gridl;
4938 }
4939 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4940 axis.SetLabelSize(0.);
4941 axis.SetTitle("");
4942 }
4945 umin, umax, ndiv, chopt, gridl, drawGridOnly);
4946
4947 // Paint additional X axis (if needed)
4948 // On iOS, this additional X axis is neither pickable, nor highlighted.
4949 // Additional checks PadInSelectionMode etc. does not effect non-iOS platform.
4950 if (gPad->GetTickx() && !gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
4951 if (xAxisPos) {
4952 cw=strstr(chopt,"-");
4953 *cw='z';
4954 } else {
4955 strlcat(chopt, "-",10);
4956 }
4957 if (gPad->GetTickx() < 2) strlcat(chopt, "U",10);
4958 if ((cw=strstr(chopt,"W"))) *cw='z';
4959 axis.SetTitle("");
4963 }
4964 }//End of "if pad in selection mode etc".
4965
4966 // Paint Y axis
4967 //On iOS, Y axis must pushed into the stack of selectable objects.
4968 if (gPad->PadInSelectionMode())
4969 gPad->PushSelectableObject(fYaxis);
4970
4971 //This conditions is ALWAYS true on a platform, different from iOS (on iOS can be true, can be false).
4972 if (gPad->PadInSelectionMode() || !gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && gPad->GetSelected() == fYaxis)) {
4975
4976 chopt[0] = 0;
4977 strlcat(chopt, "SDH",10);
4978 if (ndivy < 0) strlcat(chopt, "N",10);
4979 if (gPad->GetGridy()) {
4980 gridl = (axmax-axmin)/(gPad->GetX2() - gPad->GetX1());
4981 strlcat(chopt, "W",10);
4982 }
4983
4984 // Define Y-Axis limits
4985 if (Hoption.Logy) {
4986 strlcat(chopt, "G",10);
4987 ndiv = TMath::Abs(ndivy);
4988 if (useHparam) {
4991 } else {
4992 umin = TMath::Power(10,aymin);
4993 umax = TMath::Power(10,aymax);
4994 }
4995 } else {
4996 ndiv = TMath::Abs(ndivy);
4997 if (useHparam) {
4998 umin = Hparam.ymin;
4999 umax = Hparam.ymax;
5000 } else {
5001 umin = aymin;
5002 umax = aymax;
5003 }
5004 }
5005
5006 // Display axis as time
5007 if (fYaxis->GetTimeDisplay()) {
5008 strlcat(chopt,"t",10);
5009 if (strlen(fYaxis->GetTimeFormatOnly()) == 0) {
5011 }
5012 }
5013
5014 // The main Y axis can be on the left or on the right of the pad
5016 if (yAxisPos == 1) {
5017 // Main Y axis left
5018 yAxisXPos1 = axmax;
5019 yAxisXPos2 = axmin;
5020 } else {
5021 // Main Y axis right
5022 yAxisXPos1 = axmin;
5023 yAxisXPos2 = axmax;
5024 }
5025
5026 // Paint the main Y axis (always)
5027 uminsave = umin;
5028 umaxsave = umax;
5029 ndivsave = ndiv;
5030 axis.SetOption(chopt);
5031 if (yAxisPos) {
5032 strlcat(chopt, "+L",10);
5033 gridl = -gridl;
5034 }
5035 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
5036 axis.SetLabelSize(0.);
5037 axis.SetTitle("");
5038 }
5041 umin, umax, ndiv, chopt, gridl, drawGridOnly);
5042
5043 // Paint the additional Y axis (if needed)
5044 // Additional checks for pad mode are required on iOS: this "second" axis is
5045 // neither pickable, nor highlighted. Additional checks have no effect on non-iOS platform.
5046 if (gPad->GetTicky() && !gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
5047 if (gPad->GetTicky() < 2) {
5048 strlcat(chopt, "U",10);
5050 } else {
5051 strlcat(chopt, "+L",10);
5052 }
5053 if ((cw=strstr(chopt,"W"))) *cw='z';
5054 axis.SetTitle("");
5058 }
5059 }//End of "if pad is in selection mode etc."
5060
5061 // Reset the axis if they have been inverted in case of option HBAR
5062 if (xaxis) {
5063 fXaxis = xaxis;
5064 fYaxis = yaxis;
5065 }
5066}
5067
5068////////////////////////////////////////////////////////////////////////////////
5069/// [Draw a bar-chart in a normal pad.](\ref HP10)
5070
5072{
5073
5074 Int_t bar = Hoption.Bar - 10;
5078 TBox box;
5080 if (hcolor == gPad->GetFrameFillColor()) ++hcolor;
5082 box.SetFillColor(hcolor);
5083 box.SetFillStyle(hstyle);
5084 box.SetLineStyle(fH->GetLineStyle());
5085 box.SetLineColor(fH->GetLineColor());
5086 box.SetLineWidth(fH->GetLineWidth());
5087 for (Int_t bin=fXaxis->GetFirst();bin<=fXaxis->GetLast();bin++) {
5088 y = fH->GetBinContent(bin);
5089 xmin = gPad->XtoPad(fXaxis->GetBinLowEdge(bin));
5090 xmax = gPad->XtoPad(fXaxis->GetBinUpEdge(bin));
5091 ymin = gPad->GetUymin();
5092 ymax = gPad->YtoPad(y);
5093 if (ymax < gPad->GetUymin()) continue;
5094 if (ymax > gPad->GetUymax()) ymax = gPad->GetUymax();
5095 if (ymin < gPad->GetUymin()) ymin = gPad->GetUymin();
5096 if (Hoption.MinimumZero && ymin < 0)
5097 ymin=TMath::Min(0.,gPad->GetUymax());
5098 w = (xmax-xmin)*width;
5099 xmin += offset*(xmax-xmin);
5100 xmax = xmin + w;
5101 if (bar < 1) {
5102 box.PaintBox(xmin,ymin,xmax,ymax);
5103 } else {
5104 umin = xmin + bar*(xmax-xmin)/10.;
5105 umax = xmax - bar*(xmax-xmin)/10.;
5106 box.SetFillColor(TColor::GetColorBright(hcolor)); //bright
5107 box.PaintBox(xmin,ymin,umin,ymax);
5108 box.SetFillColor(hcolor);
5109 box.PaintBox(umin,ymin,umax,ymax);
5110 box.SetFillColor(TColor::GetColorDark(hcolor)); //dark
5111 box.PaintBox(umax,ymin,xmax,ymax);
5112 }
5113 }
5114}
5115
5116////////////////////////////////////////////////////////////////////////////////
5117/// [Draw a bar char in a rotated pad (X vertical, Y horizontal)](\ref HP10)
5118
5120{
5121
5122 gPad->SetVertical(kFALSE);
5123
5124 PaintInitH();
5125
5126 TAxis *xaxis = fXaxis;
5127 TAxis *yaxis = fYaxis;
5128 if (!strcmp(xaxis->GetName(),"xaxis")) {
5129 fXaxis = yaxis;
5130 fYaxis = xaxis;
5131 }
5132
5133 PaintFrame();
5135
5136 Int_t bar = Hoption.Bar - 20;
5140 TBox box;
5142 if (hcolor == gPad->GetFrameFillColor()) ++hcolor;
5144 box.SetFillColor(hcolor);
5145 box.SetFillStyle(hstyle);
5146 box.SetLineStyle(fH->GetLineStyle());
5147 box.SetLineColor(fH->GetLineColor());
5148 box.SetLineWidth(fH->GetLineWidth());
5149 for (Int_t bin=fYaxis->GetFirst();bin<=fYaxis->GetLast();bin++) {
5150 ymin = gPad->YtoPad(fYaxis->GetBinLowEdge(bin));
5151 ymax = gPad->YtoPad(fYaxis->GetBinUpEdge(bin));
5152 xmin = gPad->GetUxmin();
5153 xmax = gPad->XtoPad(fH->GetBinContent(bin));
5154 if (xmax < gPad->GetUxmin()) continue;
5155 if (xmax > gPad->GetUxmax()) xmax = gPad->GetUxmax();
5156 if (xmin < gPad->GetUxmin()) xmin = gPad->GetUxmin();
5157 if (Hoption.MinimumZero && xmin < 0)
5158 xmin=TMath::Min(0.,gPad->GetUxmax());
5159 w = (ymax-ymin)*width;
5160 ymin += offset*(ymax-ymin);
5161 ymax = ymin + w;
5162 if (bar < 1) {
5163 box.PaintBox(xmin,ymin,xmax,ymax);
5164 } else {
5165 umin = ymin + bar*(ymax-ymin)/10.;
5166 umax = ymax - bar*(ymax-ymin)/10.;
5167 box.SetFillColor(TColor::GetColorDark(hcolor)); //dark
5168 box.PaintBox(xmin,ymin,xmax,umin);
5169 box.SetFillColor(hcolor);
5170 box.PaintBox(xmin,umin,xmax,umax);
5171 box.SetFillColor(TColor::GetColorBright(hcolor)); //bright
5172 box.PaintBox(xmin,umax,xmax,ymax);
5173 }
5174 }
5175
5176 PaintTitle();
5177
5178 // Draw box with histogram statistics and/or fit parameters
5179 if ((Hoption.Same%10) != 1 && !fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
5180 TIter next(fFunctions);
5181 TObject *obj = nullptr;
5182 while ((obj = next())) {
5183 if (obj->InheritsFrom(TF1::Class())) break;
5184 obj = nullptr;
5185 }
5186 PaintStat(gStyle->GetOptStat(),(TF1*)obj);
5187 }
5188
5189 fXaxis = xaxis;
5190 fYaxis = yaxis;
5191}
5192
5193////////////////////////////////////////////////////////////////////////////////
5194/// [Control function to draw a 2D histogram as a box plot](\ref HP13)
5195
5197{
5198
5201 if (fH->GetFillColor() == 0) fH->SetFillStyle(0);
5202 if (Hoption.Box == 11) fH->SetFillStyle(1001);
5203 fH->TAttLine::Modify();
5204 fH->TAttFill::Modify();
5205
5206 Double_t z, xk,xstep, yk, ystep, xcent, ycent, xlow, xup, ylow, yup;
5207 Double_t ux1 = gPad->PixeltoX(1);
5208 Double_t ux0 = gPad->PixeltoX(0);
5209 Double_t uy1 = gPad->PixeltoY(1);
5210 Double_t uy0 = gPad->PixeltoY(0);
5211 Double_t dxmin = 0.51*(gPad->PadtoX(ux1)-gPad->PadtoX(ux0));
5212 Double_t dymin = 0.51*(gPad->PadtoY(uy0)-gPad->PadtoY(uy1));
5213
5214 Double_t zmin = TMath::Max(fH->GetMinimum(),0.);
5217 Double_t zminlin = zmin, zmaxlin = zmax;
5218
5219 // In case of option SAME, zmin and zmax values are taken from the
5220 // first plotted 2D histogram.
5221 if (Hoption.Same > 0 && Hoption.Same < 10) {
5222 TH2 *h2;
5223 TIter next(gPad->GetListOfPrimitives());
5224 while ((h2 = (TH2 *)next())) {
5225 if (!h2->InheritsFrom(TH2::Class())) continue;
5226 zmin = TMath::Max(h2->GetMinimum(), 0.);
5227 zmax = TMath::Max(TMath::Abs(h2->GetMaximum()),
5228 TMath::Abs(h2->GetMinimum()));
5229 zminlin = zmin;
5230 zmaxlin = zmax;
5231 if (Hoption.Logz) {
5232 if (zmin <= 0) {
5233 zmin = TMath::Log10(zmax*0.001);
5234 } else {
5235 zmin = TMath::Log10(zmin);
5236 }
5237 zmax = TMath::Log10(zmax);
5238 }
5239 break;
5240 }
5241 } else {
5242 if (Hoption.Logz) {
5243 if (zmin > 0) {
5244 zmin = TMath::Log10(zmin);
5245 zmax = TMath::Log10(zmax);
5246 } else {
5247 return;
5248 }
5249 }
5250 }
5251
5252 Double_t zratio, dz = zmax - zmin;
5254 if (fH->GetMinimum()<0) kZminNeg = kTRUE;
5256
5257 // Define the dark and light colors the "button style" boxes.
5258 Color_t color = fH->GetFillColor();
5259 Color_t light=0, dark=0;
5260 if (Hoption.Box == 11) {
5262 dark = TColor::GetColorDark(color);
5263 }
5264
5265 // Loop over all the bins and draw the boxes
5266 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
5269 ycent = 0.5*ystep;
5270 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
5271 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
5272 xk = fXaxis->GetBinLowEdge(i);
5273 xstep = fXaxis->GetBinWidth(i);
5274 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
5275 xcent = 0.5*xstep;
5277 kZNeg = kFALSE;
5278
5279 if (TMath::Abs(z) < zminlin) continue; // Can be the case with ...
5280 if (TMath::Abs(z) > zmaxlin) z = zmaxlin; // ... option Same
5281 if (kZminNeg && z==0) continue; // Do not draw empty bins if case of histo with negative bins.
5282
5283 if (z < 0) {
5284 if (Hoption.Logz) continue;
5285 z = -z;
5286 kZNeg = kTRUE;
5287 }
5288 if (Hoption.Logz) {
5289 if (z != 0) z = TMath::Log10(z);
5290 else z = zmin;
5291 }
5292
5293 if (dz == 0) continue;
5294 zratio = TMath::Sqrt((z-zmin)/dz);
5295 if (zratio == 0) continue;
5296
5297 xup = xcent*zratio + xk + xcent;
5298 xlow = 2*(xk + xcent) - xup;
5299 if (xup-xlow < dxmin) xup = xlow+dxmin;
5300 if (Hoption.Logx) {
5301 if (xup > 0) xup = TMath::Log10(xup);
5302 else continue;
5303 if (xlow > 0) xlow = TMath::Log10(xlow);
5304 else continue;
5305 }
5306
5307 yup = ycent*zratio + yk + ycent;
5308 ylow = 2*(yk + ycent) - yup;
5309 if (yup-ylow < dymin) yup = ylow+dymin;
5310 if (Hoption.Logy) {
5311 if (yup > 0) yup = TMath::Log10(yup);
5312 else continue;
5313 if (ylow > 0) ylow = TMath::Log10(ylow);
5314 else continue;
5315 }
5316
5317 xlow = TMath::Max(xlow, gPad->GetUxmin());
5318 ylow = TMath::Max(ylow, gPad->GetUymin());
5319 xup = TMath::Min(xup , gPad->GetUxmax());
5320 yup = TMath::Min(yup , gPad->GetUymax());
5321
5322 if (xlow >= xup) continue;
5323 if (ylow >= yup) continue;
5324
5325 if (Hoption.Box == 1) {
5326 fH->SetFillColor(color);
5327 fH->TAttFill::Modify();
5328 gPad->PaintBox(xlow, ylow, xup, yup);
5329 if (kZNeg) {
5330 gPad->PaintLine(xlow, ylow, xup, yup);
5331 gPad->PaintLine(xlow, yup, xup, ylow);
5332 }
5333 } else if (Hoption.Box == 11) {
5334 // Draw the center of the box
5335 fH->SetFillColor(color);
5336 fH->TAttFill::Modify();
5337 gPad->PaintBox(xlow, ylow, xup, yup);
5338
5339 // Draw top&left part of the box
5340 Double_t x[7], y[7];
5341 Double_t bwidth = 0.1;
5342 x[0] = xlow; y[0] = ylow;
5343 x[1] = xlow + bwidth*(xup-xlow); y[1] = ylow + bwidth*(yup-ylow);
5344 x[2] = x[1]; y[2] = yup - bwidth*(yup-ylow);
5345 x[3] = xup - bwidth*(xup-xlow); y[3] = y[2];
5346 x[4] = xup; y[4] = yup;
5347 x[5] = xlow; y[5] = yup;
5348 x[6] = xlow; y[6] = ylow;
5349 if (kZNeg) fH->SetFillColor(dark);
5350 else fH->SetFillColor(light);
5351 fH->TAttFill::Modify();
5352 gPad->PaintFillArea(7, x, y);
5353
5354 // Draw bottom&right part of the box
5355 x[0] = xlow; y[0] = ylow;
5356 x[1] = xlow + bwidth*(xup-xlow); y[1] = ylow + bwidth*(yup-ylow);
5357 x[2] = xup - bwidth*(xup-xlow); y[2] = y[1];
5358 x[3] = x[2]; y[3] = yup - bwidth*(yup-ylow);
5359 x[4] = xup; y[4] = yup;
5360 x[5] = xup; y[5] = ylow;
5361 x[6] = xlow; y[6] = ylow;
5362 if (kZNeg) fH->SetFillColor(light);
5363 else fH->SetFillColor(dark);
5364 fH->TAttFill::Modify();
5365 gPad->PaintFillArea(7, x, y);
5366 }
5367 }
5368 }
5369
5373 fH->TAttFill::Modify();
5374}
5375
5376
5377
5378////////////////////////////////////////////////////////////////////////////////
5379/// [Control function to draw a 2D histogram as a candle (box) plot or violin plot](\ref HP14)
5380
5382{
5383 TH1D *hproj = nullptr;
5384 TH2D *h2 = (TH2D*)fH;
5385
5388 myCandle.SetMarkerColor(fH->GetLineColor());
5389 myCandle.SetLineColor(fH->GetLineColor());
5390 myCandle.SetLineWidth(fH->GetLineWidth());
5391 myCandle.SetFillColor(fH->GetFillColor());
5392 myCandle.SetFillStyle(fH->GetFillStyle());
5393 myCandle.SetMarkerSize(fH->GetMarkerSize());
5394 myCandle.SetMarkerStyle(fH->GetMarkerStyle());
5396
5397 Bool_t swapXY = myCandle.IsHorizontal();
5398 const Double_t standardCandleWidth = 0.66;
5399 const Double_t standardHistoWidth = 0.8;
5400
5401 double allMaxContent = 0, allMaxIntegral = 0;
5402 if (myCandle.IsViolinScaled())
5404
5405 if (!swapXY) { // Vertical candle
5406 //Determining the slice with the maximum integral - if necessary
5407 if (myCandle.IsCandleScaled())
5408 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast; i++) {
5409 hproj = h2->ProjectionY("_px", i, i);
5410 if (hproj->Integral() > allMaxIntegral) allMaxIntegral = hproj->Integral();
5411 }
5412 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast; i++) {
5414 Double_t binWidth = fXaxis->GetBinWidth(i);
5415 hproj = h2->ProjectionY("_px", i, i);
5416 if (hproj->GetEntries() != 0) {
5418 Double_t offset = fH->GetBarOffset()*binWidth;
5419 double myMaxContent = hproj->GetBinContent(hproj->GetMaximumBin());
5420 double myIntegral = hproj->Integral();
5422 if (candleWidth > 0.999 && candleWidth < 1.001) {
5425 }
5426 if (Hoption.Logz && myMaxContent > 0) {
5428 if (myCandle.IsViolinScaled() && myMaxContent > 0 && allMaxContent > 0)
5430 } else if (myCandle.IsViolinScaled() && (allMaxContent > 0))
5432 if (myCandle.IsCandleScaled() && (allMaxIntegral > 0))
5434
5435 myCandle.SetAxisPosition(binPosX+binWidth/2. + offset);
5436 myCandle.SetCandleWidth(candleWidth*binWidth);
5437 myCandle.SetHistoWidth(histoWidth*binWidth);
5438 myCandle.SetHistogram(hproj);
5439 myCandle.Paint();
5440 }
5441 }
5442 } else { // Horizontal candle
5443 //Determining the slice with the maximum integral - if necessary
5444 if (myCandle.IsCandleScaled())
5445 for (Int_t i=Hparam.yfirst; i<=Hparam.ylast; i++) {
5446 hproj = h2->ProjectionX("_py", i, i);
5447 if (hproj->Integral() > allMaxIntegral) allMaxIntegral = hproj->Integral();
5448 }
5449 for (Int_t i=Hparam.yfirst; i<=Hparam.ylast; i++) {
5451 Double_t binWidth = fYaxis->GetBinWidth(i);
5452 hproj = h2->ProjectionX("_py", i, i);
5453 if (hproj->GetEntries() != 0) {
5455 Double_t offset = fH->GetBarOffset()*binWidth;
5456 double myMaxContent = hproj->GetBinContent(hproj->GetMaximumBin());
5457 double myIntegral = hproj->Integral();
5459 if (candleWidth > 0.999 && candleWidth < 1.001) {
5462 }
5463 if (Hoption.Logz && myMaxContent > 0) {
5465 if (myCandle.IsViolinScaled() && myMaxContent > 0 && allMaxContent > 0)
5467 } else if (myCandle.IsViolinScaled() && (allMaxContent > 0))
5469 if (myCandle.IsCandleScaled() && (allMaxIntegral > 0))
5471
5472 myCandle.SetAxisPosition(binPosY+binWidth/2. + offset);
5473 myCandle.SetCandleWidth(candleWidth*binWidth);
5474 myCandle.SetHistoWidth(histoWidth*binWidth);
5475 myCandle.SetHistogram(hproj);
5476 myCandle.Paint();
5477 }
5478 }
5479 }
5480 delete hproj;
5481}
5482
5483
5484
5485////////////////////////////////////////////////////////////////////////////////
5486/// Returns the rendering regions for an axis to use in the COL2 option
5487///
5488/// The algorithm analyses the size of the axis compared to the size of
5489/// the rendering region. It figures out the boundaries to use for each color
5490/// of the rendering region. Only one axis is computed here.
5491///
5492/// This allows for a single computation of the boundaries before iterating
5493/// through all of the bins.
5494///
5495/// \param pAxis the axis to consider
5496/// \param nPixels the number of pixels to render axis into
5497/// \param isLog whether the axis is log scale
5498
5499std::vector<THistRenderingRegion>
5501{
5502 std::vector<THistRenderingRegion> regions;
5503
5504 enum STRATEGY { Bins, Pixels } strategy;
5505
5506 Int_t nBins = (pAxis->GetLast() - pAxis->GetFirst() + 1);
5507
5508 if (nBins >= nPixels) {
5509 // more bins than pixels... we should loop over pixels and sample
5510 strategy = Pixels;
5511 } else {
5512 // fewer bins than pixels... we should loop over bins
5513 strategy = Bins;
5514 }
5515
5516 if (isLog) {
5517
5518 Double_t xMin = pAxis->GetBinLowEdge(pAxis->GetFirst());
5519 Int_t binOffset=0;
5520 while (xMin <= 0 && ((pAxis->GetFirst()+binOffset) != pAxis->GetLast()) ) {
5521 binOffset++;
5522 xMin = pAxis->GetBinLowEdge(pAxis->GetFirst()+binOffset);
5523 }
5524 if (xMin <= 0) {
5525 // this should cause an error if we have
5526 return regions;
5527 }
5528 Double_t xMax = pAxis->GetBinUpEdge(pAxis->GetLast());
5529
5530 if (strategy == Bins) {
5531 // logarithmic plot. we find the pixel for the bin
5532 // pixel = eta * log10(V) - alpha
5533 // where eta = nPixels/(log10(Vmax)-log10(Vmin))
5534 // and alpha = nPixels*log10(Vmin)/(log10(Vmax)-log10(Vmin))
5535 // and V is axis value
5536 Double_t eta = (nPixels-1.0)/(TMath::Log10(xMax) - TMath::Log10(xMin));
5537 Double_t offset = -1.0 * eta * TMath::Log10(xMin);
5538
5539 for (Int_t bin=pAxis->GetFirst()+binOffset; bin<=pAxis->GetLast(); bin++) {
5540
5541 // linear plot. we simply need to find the appropriate bin
5542 // for the
5543 Double_t xLowValue = pAxis->GetBinLowEdge(bin);
5544 Double_t xUpValue = pAxis->GetBinUpEdge(bin);
5547 THistRenderingRegion region = {std::make_pair(xPx0, xPx1),
5548 std::make_pair(bin, bin+1)};
5549 regions.push_back(region);
5550 }
5551
5552 } else {
5553
5554 // loop over pixels
5555
5556 Double_t beta = (TMath::Log10(xMax) - TMath::Log10(xMin))/(nPixels-1.0);
5557
5558 for (Int_t pixelIndex=0; pixelIndex<(nPixels-1); pixelIndex++) {
5559 // linear plot
5560 Int_t binLow = pAxis->FindBin(xMin*TMath::Power(10.0, beta*pixelIndex));
5561 Int_t binHigh = pAxis->FindBin(xMin*TMath::Power(10.0, beta*(pixelIndex+1)));
5562 THistRenderingRegion region = { std::make_pair(pixelIndex, pixelIndex+1),
5563 std::make_pair(binLow, binHigh)};
5564 regions.push_back(region);
5565 }
5566 }
5567 } else {
5568 // standard linear plot
5569
5570 if (strategy == Bins) {
5571 // loop over bins
5572 for (Int_t bin=pAxis->GetFirst(); bin<=pAxis->GetLast(); bin++) {
5573
5574 // linear plot. we simply need to find the appropriate bin
5575 // for the
5576 Int_t xPx0 = ((bin - pAxis->GetFirst()) * nPixels)/nBins;
5577 Int_t xPx1 = xPx0 + nPixels/nBins;
5578
5579 // make sure we don't compute beyond our bounds
5580 if (xPx1>= nPixels) xPx1 = nPixels-1;
5581
5582 THistRenderingRegion region = {std::make_pair(xPx0, xPx1),
5583 std::make_pair(bin, bin+1)};
5584 regions.push_back(region);
5585 }
5586 } else {
5587 // loop over pixels
5589 // linear plot
5590 Int_t binLow = (nBins*pixelIndex)/nPixels + pAxis->GetFirst();
5591 Int_t binHigh = binLow + nBins/nPixels;
5592 THistRenderingRegion region = { std::make_pair(pixelIndex, pixelIndex+1),
5593 std::make_pair(binLow, binHigh)};
5594 regions.push_back(region);
5595 }
5596 }
5597 }
5598
5599 return regions;
5600}
5601
5602////////////////////////////////////////////////////////////////////////////////
5603/// [Rendering scheme for the COL2 and COLZ2 options] (\ref HP14)
5604
5606{
5607
5608 if (Hoption.System != kCARTESIAN) {
5609 Error("THistPainter::PaintColorLevelsFast(Option_t*)",
5610 "Only cartesian coordinates supported by 'COL2' option. Using 'COL' option instead.");
5611 PaintColorLevels(nullptr);
5612 return;
5613 }
5614
5615 Double_t z;
5616
5617 // Use existing max or min values. If either is already set
5618 // the appropriate value to use.
5619 Double_t zmin = fH->GetMinimumStored();
5620 Double_t zmax = fH->GetMaximumStored();
5621 Double_t originalZMin = zmin;
5622 Double_t originalZMax = zmax;
5623 if ((zmin == -1111) && (zmax == -1111)) {
5624 fH->GetMinimumAndMaximum(zmin, zmax);
5625 fH->SetMinimum(zmin);
5626 fH->SetMaximum(zmax);
5627 } else if (zmin == -1111) {
5628 zmin = fH->GetMinimum();
5629 fH->SetMinimum(zmin);
5630 } else if (zmax == -1111) {
5631 zmax = fH->GetMaximum();
5632 fH->SetMaximum(zmax);
5633 }
5634
5635 Double_t dz = zmax - zmin;
5636 if (dz <= 0) { // Histogram filled with a constant value
5637 zmax += 0.1*TMath::Abs(zmax);
5638 zmin -= 0.1*TMath::Abs(zmin);
5639 dz = zmax - zmin;
5640 }
5641
5642 if (Hoption.Logz) {
5643 if (zmin > 0) {
5644 zmin = TMath::Log10(zmin);
5645 zmax = TMath::Log10(zmax);
5646 dz = zmax - zmin;
5647 } else {
5648 Error("THistPainter::PaintColorLevelsFast(Option_t*)",
5649 "Cannot plot logz because bin content is less than 0.");
5650 return;
5651 }
5652 }
5653
5654 // Initialize the levels on the Z axis
5655 Int_t ndiv = fH->GetContour();
5656 if (ndiv == 0 ) {
5657 ndiv = gStyle->GetNumberContours();
5658 fH->SetContour(ndiv);
5659 }
5660 std::vector<Double_t> colorBounds(ndiv);
5661 std::vector<Double_t> contours(ndiv, 0);
5662 if (!fH->TestBit(TH1::kUserContour)) {
5663 fH->SetContour(ndiv);
5664 } else {
5665 fH->GetContour(contours.data());
5666 }
5667
5668 Double_t step = 1.0/ndiv;
5669 for (Int_t i=0; i<ndiv; ++i) {
5670 colorBounds[i] = step*i;
5671 }
5672
5673 auto pFrame = gPad->GetFrame();
5674 Int_t px0 = gPad->XtoPixel(pFrame->GetX1());
5675 Int_t px1 = gPad->XtoPixel(pFrame->GetX2());
5676 Int_t py0 = gPad->YtoPixel(pFrame->GetY1());
5677 Int_t py1 = gPad->YtoPixel(pFrame->GetY2());
5678 Int_t nXPixels = px1-px0;
5679 Int_t nYPixels = py0-py1; // y=0 is at the top of the screen
5680
5681 std::vector<Double_t> buffer(nXPixels*nYPixels, 0);
5682
5685 if (xRegions.empty() || yRegions.empty()) {
5686 Error("THistPainter::PaintColorLevelFast(Option_t*)",
5687 "Encountered error while computing rendering regions.");
5688 return;
5689 }
5690
5693 Double_t minValue = 1.;
5694 Double_t maxValue = 0.;
5695 for (auto& yRegion : yRegions) {
5696 for (auto& xRegion : xRegions ) {
5697
5698 const auto& xBinRange = xRegion.fBinRange;
5699 const auto& yBinRange = yRegion.fBinRange;
5700
5701 // sample the range
5702 z = fH->GetBinContent(xBinRange.second-1, yBinRange.second-1);
5703
5704 if (Hoption.Logz) {
5705 if (z > 0) z = TMath::Log10(z);
5706 else z = zmin;
5707 }
5708
5709 // obey the user's max and min values if they were set
5710 if (z > zmax) z = zmax;
5711 if (z < zmin) z = zmin;
5712
5714 // contours are absolute values
5715 auto index = TMath::BinarySearch(contours.size(), contours.data(), z);
5716 z = colorBounds[index];
5717 } else {
5718 Int_t index = 0;
5719 if (dz != 0) {
5720 index = 0.001 + ((z - zmin)/dz)*ndiv;
5721 }
5722
5723 if (index == static_cast<Int_t>(colorBounds.size())) {
5724 index--;
5725 }
5726
5727 // Do a little bookkeeping to use later for getting libAfterImage to produce
5728 // the correct colors
5729 if (index == 0) {
5730 minExists = kTRUE;
5731 } else if (index == static_cast<Int_t>(colorBounds.size()-1)) {
5732 maxExists = kTRUE;
5733 }
5734
5735 z = colorBounds[index];
5736
5737 if (z < minValue) {
5738 minValue = z;
5739 }
5740 if (z > maxValue) {
5741 maxValue = z;
5742 }
5743 }
5744
5745 // fill in the actual pixels
5746 const auto& xPixelRange = xRegion.fPixelRange;
5747 const auto& yPixelRange = yRegion.fPixelRange;
5748 for (Int_t xPx = xPixelRange.first; xPx <= xPixelRange.second; ++xPx) {
5749 for (Int_t yPx = yPixelRange.first; yPx <= yPixelRange.second; ++yPx) {
5751 buffer[pixel] = z;
5752 }
5753 }
5754 } // end px loop
5755 } // end py loop
5756
5757 // This is a bit of a hack to ensure that we span the entire color range and
5758 // don't screw up the colors for a sparse histogram. No one will notice that I set a
5759 // single pixel on the edge of the image to a different color. This is even more
5760 // true because the chosen pixels will be covered by the axis.
5761 if (minValue != maxValue) {
5762 if ( !minExists) {
5763 buffer.front() = 0;
5764 }
5765
5766 if ( !maxExists) {
5767 buffer[buffer.size()-nXPixels] = 0.95;
5768 }
5769 }
5770
5771 // Generate the TImage
5774 pImage->SetImageQuality(TAttImage::kImgBest);
5775 pImage->SetImage(buffer.data(), nXPixels, nYPixels, pPalette);
5776 delete pPalette;
5777
5778 auto pp = gPad->GetPainter();
5779 if (pp)
5780 pp->DrawImage(pImage, px0, py1);
5781
5782 delete pImage;
5783
5784 if (Hoption.Zscale)
5785 PaintPalette();
5786
5787 // Reset the maximum and minimum values to their original values
5788 // when this function was called. If we don't do this, an initial
5789 // value of -1111 will be replaced with the true max or min values.
5792}
5793
5794////////////////////////////////////////////////////////////////////////////////
5795/// [Control function to draw a 2D histogram as a color plot.](\ref HP14)
5796
5798{
5799 Double_t z, e, zc, xk, xstep, yk, ystep, xlow, xup, ylow, yup;
5800
5801 Double_t zmin = fH->GetMinimum();
5802 Double_t zmax = fH->GetMaximum();
5803
5804 Double_t dz = zmax - zmin;
5805 if (dz <= 0) { // Histogram filled with a constant value
5806 zmax += 0.1*TMath::Abs(zmax);
5807 zmin -= 0.1*TMath::Abs(zmin);
5808 dz = zmax - zmin;
5809 }
5810
5811 // In case of option SAME, zmin and zmax values are taken from the
5812 // first plotted 2D histogram.
5813 if (Hoption.Same > 0 && Hoption.Same < 10) {
5814 TH2 *h2;
5815 TIter next(gPad->GetListOfPrimitives());
5816 while ((h2 = (TH2 *)next())) {
5817 if (!h2->InheritsFrom(TH2::Class())) continue;
5818 zmin = h2->GetMinimum();
5819 zmax = h2->GetMaximum();
5820 fH->SetMinimum(zmin);
5821 fH->SetMaximum(zmax);
5822 if (Hoption.Logz) {
5823 if (zmin <= 0) {
5824 zmin = TMath::Log10(zmax*0.001);
5825 } else {
5826 zmin = TMath::Log10(zmin);
5827 }
5828 zmax = TMath::Log10(zmax);
5829 }
5830 dz = zmax - zmin;
5831 break;
5832 }
5833 } else {
5834 if (Hoption.Logz) {
5835 if (zmin > 0) {
5836 zmin = TMath::Log10(zmin);
5837 zmax = TMath::Log10(zmax);
5838 dz = zmax - zmin;
5839 } else {
5840 return;
5841 }
5842 }
5843 }
5844
5847 fH->SetFillStyle(1001);
5848 fH->TAttFill::Modify();
5849
5850 // Initialize the levels on the Z axis
5852 Int_t ndiv = fH->GetContour();
5853 if (ndiv == 0) {
5854 ndiv = gStyle->GetNumberContours();
5855 fH->SetContour(ndiv);
5856 }
5857 Int_t ndivz = TMath::Abs(ndiv);
5858 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
5859 Double_t scale = (dz ? ndivz / dz : 1.0);
5860
5861 Double_t xmin = gPad->GetUxmin();
5862 Double_t xmax = gPad->GetUxmax();
5863 Double_t ymin = gPad->GetUymin();
5864 Double_t ymax = gPad->GetUymax();
5865
5866 // range used for polar coordinates
5867 Double_t pxmin = xmin, pxmax = xmax, pymin = ymin, pymax = ymax, pkr = 0.5;
5868 if ((Hoption.System == kPOLAR) && (Hoption.Polar == 2)) {
5869 pxmin = fXaxis->GetXmin();
5870 pxmax = fXaxis->GetXmax();
5871 if (Hoption.Logx) {
5872 if (pxmax <= 0)
5873 return;
5875 if (pxmin <= 0)
5876 pxmin = pxmax - 5;
5877 else
5879 }
5880 pkr = 0.45; // makes fixed range more pretty
5881 pymin = fYaxis->GetXmin();
5882 pymax = fYaxis->GetXmax();
5883 if (Hoption.Logy) {
5884 if (pymax <= 0)
5885 return;
5887 if (pymin <= 0)
5888 pymin = pymax - 5;
5889 else
5891 } else if ((pymax > 0) && (pymin > 0)) {
5892 // force minimal radius to 0 to display natural polar graphics
5893 pymin = 0;
5894 }
5895 }
5896
5897 if ((Hoption.System == kPOLAR) && (Hoption.Polar == 3)) {
5898 // do not touch boundaries when draw without axis histogram
5899 if (!Hoption.Same)
5900 pkr = 0.45;
5901 // for natural coordinates force minimal radius to 0
5902 if (!Hoption.Logy && (pymax > 0))
5903 pymin = 0;
5904 }
5905
5906 Int_t color;
5907 TProfile2D* prof2d = dynamic_cast<TProfile2D*>(fH);
5908 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
5911 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
5912 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
5913 xk = fXaxis->GetBinLowEdge(i);
5914 xstep = fXaxis->GetBinWidth(i);
5915 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
5916 z = fH->GetBinContent(bin);
5917 e = fH->GetBinError(bin);
5918 // if fH is a profile histogram do not draw empty bins
5919 if (prof2d) {
5920 const Double_t binEntries = prof2d->GetBinEntries(bin);
5921 if (binEntries == 0)
5922 continue;
5923 } else {
5924 // don't draw the empty bins for non-profile histograms
5925 // with positive content
5926 if (z == 0 && e == 0) {
5927 if (zmin >= 0 || Hoption.Logz) continue;
5928 if (Hoption.Color == 2) continue;
5929 }
5930 }
5931
5932 if (Hoption.Logz)
5933 z = z > 0 ? TMath::Log10(z) : zmin;
5934 if (z < zmin && !Hoption.Zero)
5935 continue;
5936 xup = xk + xstep;
5937 xlow = xk;
5938 if (Hoption.Logx) {
5939 if ((xup <= 0) || (xlow <= 0))
5940 continue;
5941 xup = TMath::Log10(xup);
5942 xlow = TMath::Log10(xlow);
5943 }
5944 yup = yk + ystep;
5945 ylow = yk;
5946 if (Hoption.Logy) {
5947 if ((yup <= 0) || (ylow <= 0))
5948 continue;
5949 yup = TMath::Log10(yup);
5950 ylow = TMath::Log10(ylow);
5951 }
5952 if ((xup < xmin) || (yup < ymin) || (xlow > xmax) || (ylow > ymax))
5953 continue;
5954 if (xlow < xmin)
5955 xlow = xmin;
5956 if (ylow < ymin)
5957 ylow = ymin;
5958 if (xup > xmax)
5959 xup = xmax;
5960 if (yup > ymax)
5961 yup = ymax;
5962
5964 zc = fH->GetContourLevelPad(0);
5965 if (z < zc) continue;
5966 color = -1;
5967 for (Int_t k=0; k<ndiv; k++) {
5968 zc = fH->GetContourLevelPad(k);
5969 if (z < zc) {
5970 continue;
5971 } else {
5972 color++;
5973 }
5974 }
5975 } else {
5976 color = Hoption.Zero ? Int_t(0.01+(std::max(z, zmin)-zmin)*scale) : Int_t(0.01+(z-zmin)*scale);
5977 }
5978
5979 Int_t theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
5980 if (theColor > ncolors-1)
5981 theColor = ncolors-1;
5983 if (Hoption.System != kPOLAR) {
5985 fH->TAttFill::Modify();
5986 gPad->PaintBox(xlow, ylow, xup, yup);
5987 } else {
5988 Double_t midx = (xmin + xmax) / 2;
5989 Double_t midy = (ymin + ymax) / 2;
5990 Double_t rx = xmax - xmin;
5991 Double_t ry = ymax - ymin;
5992 Double_t a1, a2;
5993
5994 if (Hoption.Polar == 3) {
5995 a1 = xlow / TMath::Pi() * 180;
5996 a2 = xup / TMath::Pi() * 180;
5997 } else {
5998 a1 = ((xlow - pxmin) / (pxmax - pxmin) - 0.5) * 360;
5999 a2 = ((xup - pxmin) / (pxmax - pxmin) - 0.5) * 360;
6000 }
6001 Double_t r1 = (ylow - pymin) / (pymax - pymin) * rx * pkr;
6002 Double_t r2 = (yup - pymin) / (pymax - pymin) * rx * pkr;
6003
6004 TCrown crown(midx, midy, r1, r2, a1, a2);
6005 crown.SetYXRatio(rx > 0 ? ry / rx : 1);
6006 crown.SetFillColor(fillColor);
6007 crown.SetLineColor(fH->GetLineColor());
6008 crown.SetLineWidth(fH->GetLineWidth());
6009 crown.SetLineStyle(fH->GetLineStyle());
6010 crown.Paint();
6011 }
6012 }
6013 }
6014
6016
6019 fH->TAttFill::Modify();
6020
6021}
6022
6023////////////////////////////////////////////////////////////////////////////////
6024/// [Control function to draw a 2D histogram as a contour plot.](\ref HP16)
6025
6027{
6028
6029 Int_t i, j, count, ncontour, icol, n, lj, m, ix, jx, ljfill;
6030 Int_t itars, mode, ir[4];
6031 Double_t xsave, ysave, thesave,phisave,x[4], y[4], zc[4];
6032
6033 if (Hoption.Contour == 14) {
6034 Hoption.Surf = 12;
6035 Hoption.Axis = 1;
6036 thesave = gPad->GetTheta();
6037 phisave = gPad->GetPhi();
6038 gPad->SetPhi(0.);
6039 gPad->SetTheta(90.);
6041 gPad->SetPhi(phisave);
6042 gPad->SetTheta(thesave);
6043 TView *view = gPad->GetView();
6044 if (view) view->SetBit(kCannotRotate); //tested in ExecuteEvent
6045 PaintAxis();
6046 return;
6047 }
6048
6049 if (Hoption.Same) {
6050 // If the contour is painted on a 3d plot, the contour lines are
6051 // paint in 3d too.
6052 TObject *obj;
6053 TIter next(gPad->GetListOfPrimitives());
6054 while ((obj=next())) {
6055 if (strstr(obj->GetDrawOption(),"surf") ||
6056 strstr(obj->GetDrawOption(),"lego") ||
6057 strstr(obj->GetDrawOption(),"tri")) {
6058 Hoption.Surf = 16;
6060 return;
6061 }
6062 }
6063 }
6064
6065 if (Hoption.Contour == 15) {
6066 TGraphDelaunay2D *dt = nullptr;
6067 TGraphDelaunay *dtOld = nullptr;
6069 dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
6070 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
6071 if (!dt && !dtOld) return;
6072 if (!fGraph2DPainter)
6073 fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
6074 fGraph2DPainter->Paint(option);
6075 return;
6076 }
6077
6078 gPad->SetBit(TGraph::kClipFrame);
6079
6080 std::vector<Double_t> levels(2*kMAXCONTOUR);
6081 std::vector<Double_t> xarr(2*kMAXCONTOUR);
6082 std::vector<Double_t> yarr(2*kMAXCONTOUR);
6083 std::vector<Int_t> itarr(2*kMAXCONTOUR);
6084
6085 Int_t npmax = 0;
6086 for (i=0;i<2*kMAXCONTOUR;i++) itarr[i] = 0;
6087
6088 ncontour = fH->GetContour();
6089 if (ncontour == 0) {
6092 }
6093 if (ncontour > kMAXCONTOUR) {
6094 Warning("PaintContour", "maximum number of contours is %d, asked for %d",
6097 }
6099
6100 for (i=0;i<ncontour;i++) levels[i] = fH->GetContourLevelPad(i);
6104 if (Hoption.Contour == 13) {
6105 fH->TAttLine::Modify();
6106 }
6107
6108 std::vector<std::unique_ptr<TPolyLine>> polys;
6109 TObjArray *contours = nullptr;
6110 TList *list = nullptr;
6111 TGraph *graph = nullptr;
6112 std::vector<Int_t> np;
6113 if (Hoption.Contour == 1 || (Hoption.List && (Hoption.Contour == 11 || Hoption.Contour == 12 || Hoption.Contour == 13))) {
6114 np.resize(ncontour);
6115 for (i=0;i<ncontour;i++)
6116 np[i] = 0;
6117 for (i=0;i<ncontour;i++)
6118 polys.emplace_back(std::make_unique<TPolyLine>(100));
6119 if (Hoption.List == 1) {
6120 contours = (TObjArray*)gROOT->GetListOfSpecials()->FindObject("contours");
6121 if (contours) {
6122 gROOT->GetListOfSpecials()->Remove(contours);
6123 count = contours->GetSize();
6124 for (i=0;i<count;i++) {
6125 list = (TList*)contours->At(i);
6126 if (list) list->Delete();
6127 }
6128 contours->Delete();
6129 delete contours;
6130 }
6132 contours->SetName("contours");
6133 gROOT->GetListOfSpecials()->Add(contours);
6134 for (i=0;i<ncontour;i++) {
6135 list = new TList();
6136 contours->Add(list);
6137 }
6138 }
6139 }
6143
6144 Int_t k,ipoly;
6145 for (j=Hparam.yfirst; j<Hparam.ylast; j++) {
6146 y[0] = fYaxis->GetBinCenter(j);
6147 y[1] = y[0];
6148 y[2] = fYaxis->GetBinCenter(j+1);
6149 y[3] = y[2];
6150 for (i=Hparam.xfirst; i<Hparam.xlast; i++) {
6151 zc[0] = fH->GetBinContent(i, j);
6152 zc[1] = fH->GetBinContent(i+1, j);
6153 zc[2] = fH->GetBinContent(i+1, j+1);
6154 zc[3] = fH->GetBinContent(i, j+1);
6155 if (!IsInside(fXaxis->GetBinCenter(i),fYaxis->GetBinCenter(j))) continue;
6156 if (Hoption.Logz) {
6157 if (zc[0] > 0) zc[0] = TMath::Log10(zc[0]);
6158 else zc[0] = Hparam.zmin;
6159 if (zc[1] > 0) zc[1] = TMath::Log10(zc[1]);
6160 else zc[1] = Hparam.zmin;
6161 if (zc[2] > 0) zc[2] = TMath::Log10(zc[2]);
6162 else zc[2] = Hparam.zmin;
6163 if (zc[3] > 0) zc[3] = TMath::Log10(zc[3]);
6164 else zc[3] = Hparam.zmin;
6165 }
6166 for (k=0;k<4;k++) {
6167 ir[k] = TMath::BinarySearch(ncontour, levels.data(), zc[k]);
6168 }
6169 if (ir[0] != ir[1] || ir[1] != ir[2] || ir[2] != ir[3] || ir[3] != ir[0]) {
6170 x[0] = fXaxis->GetBinCenter(i);
6171 x[3] = x[0];
6172 x[1] = fXaxis->GetBinCenter(i+1);
6173 x[2] = x[1];
6174 if (zc[0] <= zc[1]) n = 0; else n = 1;
6175 if (zc[2] <= zc[3]) m = 2; else m = 3;
6176 if (zc[n] > zc[m]) n = m;
6177 n++;
6178 lj=1;
6179 for (ix=1;ix<=4;ix++) {
6180 m = n%4 + 1;
6181 ljfill = PaintContourLine(zc[n-1],ir[n-1],x[n-1],y[n-1],zc[m-1],
6182 ir[m-1],x[m-1],y[m-1], xarr.data()+lj-1,yarr.data()+lj-1,itarr.data()+lj-1, levels.data());
6183 lj += 2*ljfill;
6184 n = m;
6185 }
6186
6187 if (zc[0] <= zc[1]) n = 0; else n = 1;
6188 if (zc[2] <= zc[3]) m = 2; else m = 3;
6189 if (zc[n] > zc[m]) n = m;
6190 n++;
6191 lj=2;
6192 for (ix=1;ix<=4;ix++) {
6193 if (n == 1) m = 4;
6194 else m = n-1;
6195 ljfill = PaintContourLine(zc[n-1],ir[n-1],x[n-1],y[n-1],zc[m-1],
6196 ir[m-1],x[m-1],y[m-1],xarr.data()+lj-1,yarr.data()+lj-1,itarr.data()+lj-1, levels.data());
6197 lj += 2*ljfill;
6198 n = m;
6199 }
6200
6201 // Re-order endpoints
6202
6203 count = 0;
6204 for (ix=1; ix<=lj-5; ix +=2) {
6205 //count = 0;
6206 while (itarr[ix-1] != itarr[ix]) {
6207 xsave = xarr[ix];
6208 ysave = yarr[ix];
6209 itars = itarr[ix];
6210 for (jx=ix; jx<=lj-5; jx +=2) {
6211 xarr[jx] = xarr[jx+2];
6212 yarr[jx] = yarr[jx+2];
6213 itarr[jx] = itarr[jx+2];
6214 }
6215 xarr[lj-3] = xsave;
6216 yarr[lj-3] = ysave;
6217 itarr[lj-3] = itars;
6218 if (count > 100) break;
6219 count++;
6220 }
6221 }
6222
6223 if (count > 100) continue;
6224 for (ix=1; ix<=lj-2; ix +=2) {
6225 theColor = Int_t((itarr[ix-1]+0.99)*Float_t(ncolors)/Float_t(ndivz));
6227 if (Hoption.Contour == 11) {
6229 }
6230 if (Hoption.Contour == 12) {
6231 mode = icol%5;
6232 if (mode == 0) mode = 5;
6234 }
6235 if (Hoption.Contour != 1) {
6236 fH->TAttLine::Modify();
6237 gPad->PaintPolyLine(2,xarr.data()+ix-1,yarr.data()+ix-1);
6238 if ((Hoption.Contour != 11 && Hoption.Contour != 12 && Hoption.Contour != 13) || !Hoption.List)
6239 continue;
6240 }
6241
6242 ipoly = itarr[ix-1];
6243 if (ipoly >=0 && ipoly <ncontour) {
6244 polys[ipoly]->SetPoint(np[ipoly] ,xarr[ix-1],yarr[ix-1]);
6245 polys[ipoly]->SetPoint(np[ipoly]+1,xarr[ix], yarr[ix]);
6246 np[ipoly] += 2;
6247 if (npmax < np[ipoly]) npmax = np[ipoly];
6248 }
6249 }
6250 } // end of if (ir[0]
6251 } //end of for (i
6252 } //end of for (j
6253
6255 std::vector<Double_t> xp, yp;
6257 Int_t istart;
6258 Int_t first = ncontour;
6259 std::vector<Int_t> polysort;
6261 if (Hoption.Contour != 1) {
6262 if (!Hoption.List || (Hoption.Contour != 11 && Hoption.Contour != 12 && Hoption.Contour != 13))
6263 goto theEND;
6264 }
6265
6266 //The 2 points line generated above are now sorted/merged to generate
6267 //a list of consecutive points.
6268 // If the option "List" has been specified, the list of points is saved
6269 // in the form of TGraph objects in the ROOT list of special objects.
6270 xmin = gPad->GetUxmin();
6271 ymin = gPad->GetUymin();
6272 xp.resize(2*npmax);
6273 yp.resize(2*npmax);
6274 polysort.resize(ncontour);
6275 //find first positive contour
6276 for (ipoly=0;ipoly<ncontour;ipoly++) {
6277 if (levels[ipoly] >= 0) {first = ipoly; break;}
6278 }
6279 //store negative contours from 0 to minimum, then all positive contours
6280 k = 0;
6281 for (ipoly=first-1;ipoly>=0;ipoly--) {polysort[k] = ipoly; k++;}
6282 for (ipoly=first;ipoly<ncontour;ipoly++) {polysort[k] = ipoly; k++;}
6283 // if Contour==1 we can now draw sorted contours, otherwise (11,12,13) just store
6284 contListNb = 0;
6285 if (Hoption.Contour == 1) fH->SetFillStyle(1001);
6286 for (k=0;k<ncontour;k++) {
6287 ipoly = polysort[k];
6288 if (Hoption.List) list = (TList*)contours->At(contListNb);
6289 contListNb++;
6290 if (np[ipoly] == 0)
6291 continue;
6292 Double_t *xx = polys[ipoly]->GetX();
6293 Double_t *yy = polys[ipoly]->GetY();
6294 istart = 0;
6295 while (true) {
6296 iminus = npmax;
6297 iplus = iminus+1;
6298 xp[iminus]= xx[istart]; yp[iminus] = yy[istart];
6299 xp[iplus] = xx[istart+1]; yp[iplus] = yy[istart+1];
6300 xx[istart] = xmin; yy[istart] = ymin;
6301 xx[istart+1] = xmin; yy[istart+1] = ymin;
6302 while (true) {
6303 nadd = 0;
6304 for (i=2;i<np[ipoly];i+=2) {
6305 if ((iplus < 2*npmax-1) && (xx[i] == xp[iplus]) && (yy[i] == yp[iplus])) {
6306 iplus++;
6307 xp[iplus] = xx[i+1]; yp[iplus] = yy[i+1];
6308 xx[i] = xmin; yy[i] = ymin;
6309 xx[i+1] = xmin; yy[i+1] = ymin;
6310 nadd++;
6311 }
6312 if ((iminus > 0) && (xx[i+1] == xp[iminus]) && (yy[i+1] == yp[iminus])) {
6313 iminus--;
6314 xp[iminus] = xx[i]; yp[iminus] = yy[i];
6315 xx[i] = xmin; yy[i] = ymin;
6316 xx[i+1] = xmin; yy[i+1] = ymin;
6317 nadd++;
6318 }
6319 }
6320 if (nadd == 0) break;
6321 }
6324 if (Hoption.Contour == 1) {
6325 if (ndivz > 1) fH->SetFillColor(icol);
6326 fH->TAttFill::Modify();
6327 gPad->PaintFillArea(iplus-iminus+1,xp.data()+iminus,yp.data()+iminus);
6328 }
6329 if (Hoption.List) {
6330 graph = new TGraph(iplus-iminus+1,xp.data()+iminus,yp.data()+iminus);
6331 if (Hoption.Contour == 1)
6332 graph->SetFillColor(icol);
6333 else if (Hoption.Contour == 11)
6334 graph->SetLineColor(icol);
6335 else if (Hoption.Contour == 12) {
6336 mode = icol%5;
6337 if (mode == 0) mode = 5;
6338 graph->SetLineStyle(mode);
6339 }
6340 graph->SetLineWidth(fH->GetLineWidth());
6341 list->Add(graph);
6342 }
6343 //check if more points are left
6344 istart = 0;
6345 for (i=2;i<np[ipoly];i+=2) {
6346 if (xx[i] != xmin && yy[i] != ymin) {
6347 istart = i;
6348 break;
6349 }
6350 }
6351 if (istart == 0) break;
6352 }
6353 }
6354
6355theEND:
6356 gPad->ResetBit(TGraph::kClipFrame);
6361}
6362
6363////////////////////////////////////////////////////////////////////////////////
6364/// Fill the matrix `xarr` and `yarr` for Contour Plot.
6365
6369{
6370
6371 Bool_t vert;
6373 Int_t n, i, icount;
6374
6375 if (x1 == x2) {
6376 vert = kTRUE;
6377 tlen = y2 - y1;
6378 } else {
6379 vert = kFALSE;
6380 tlen = x2 - x1;
6381 }
6382
6383 n = icont1 +1;
6384 tdif = elev2 - elev1;
6385 i = 0;
6386 icount = 0;
6387 while (n <= icont2 && i <= kMAXCONTOUR/2 -3) {
6388 //elev = fH->GetContourLevel(n);
6389 elev = levels[n];
6390 diff = elev - elev1;
6391 pdif = diff/tdif;
6392 xlen = tlen*pdif;
6393 if (vert) {
6394 if (Hoption.Logx)
6395 xarr[i] = TMath::Log10(x1);
6396 else
6397 xarr[i] = x1;
6398 if (Hoption.Logy)
6399 yarr[i] = TMath::Log10(y1 + xlen);
6400 else
6401 yarr[i] = y1 + xlen;
6402 } else {
6403 if (Hoption.Logx)
6404 xarr[i] = TMath::Log10(x1 + xlen);
6405 else
6406 xarr[i] = x1 + xlen;
6407 if (Hoption.Logy)
6408 yarr[i] = TMath::Log10(y1);
6409 else
6410 yarr[i] = y1;
6411 }
6412 itarr[i] = n;
6413 icount++;
6414 i +=2;
6415 n++;
6416 }
6417 return icount;
6418}
6419
6420////////////////////////////////////////////////////////////////////////////////
6421/// [Draw 1D histograms error bars.](\ref HP09)
6422
6424{
6425
6426 // On iOS, we do not highlight histogram, if it's not picked at the moment
6427 // (but part of histogram (axis or pavestat) was picked, that's why this code
6428 // is called at all. This conditional statement never executes on non-iOS platform.
6429 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH) return;
6430
6431 const Int_t kBASEMARKER=8;
6432 Double_t xp, yp, ex1, ex2, ey1, ey2;
6433 Double_t delta;
6435 Double_t xi1, xi2, xi3, xi4, yi1, yi2, yi3, yi4;
6437 Double_t logxmin = 0;
6438 Double_t logymin = 0;
6439 Double_t offset = 0.;
6440 Double_t width = 0.;
6441 Int_t i, k, npoints, first, last, fixbin;
6442 Int_t if1 = 0;
6443 Int_t if2 = 0;
6447 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};
6448 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};
6449
6450 std::vector<Double_t> xline, yline, xsegm, ysegm, xmarker, ymarker;
6452 if (Hoption.Error >= 40) {Hoption.Error -=40; option0 = 1;}
6453 if (Int_t(Hoption.Error/10) == 2) {optionEX0 = 1; Hoption.Error -= 10;}
6454 if (Hoption.Error == 31) {optionEX0 = 1; Hoption.Error = 1;}
6455 if (Hoption.Error == 11) option1 = 1;
6456 if (Hoption.Error == 12) option2 = 1;
6457 if (Hoption.Error == 13) option3 = 1;
6458 if (Hoption.Error == 14) {option4 = 1; option3 = 1;}
6459 if (Hoption.Error == 15) {optionI0 = 1; option3 = 1;}
6460 if (Hoption.Error == 16) {optionI0 = 1; option4 = 1; option3 = 1;}
6461 if (option2+option3 == 0) optionE = 1;
6462 if (Hoption.Error == 0) optionE = 0;
6463 if (fXaxis->GetXbins()->fN) fixbin = 0;
6464 else fixbin = 1;
6465
6466 offset = fH->GetBarOffset();
6467 width = fH->GetBarWidth();
6468
6470 if (optionEX0) {
6471 xerror = 0;
6472 } else {
6473 xerror = gStyle->GetErrorX();
6474 }
6476 if (errormarker == 1) symbolsize = 0.01;
6478 if (errormarker >= 20 && errormarker <= 49) {
6479 sbasex *= cxx[errormarker-20];
6480 sbasey *= cyy[errormarker-20];
6481 }
6482 // set the graphics attributes
6483
6484 fH->TAttLine::Modify();
6485 fH->TAttFill::Modify();
6486 fH->TAttMarker::Modify();
6487
6488 // set the first and last bin
6489
6490 Double_t factor = Hparam.factor;
6491 first = Hparam.xfirst;
6492 last = Hparam.xlast;
6493 npoints = last - first +1;
6494 xmin = gPad->GetUxmin();
6495 xmax = gPad->GetUxmax();
6496 ymin = gPad->GetUymin();
6497 ymax = gPad->GetUymax();
6498
6499 xsegm.reserve(1024);
6500 ysegm.reserve(1024);
6501 if (!xsegm.capacity() || !ysegm.capacity()) {
6502 Error("PaintErrors", "out of memory for lines painting");
6503 return;
6504 }
6505
6506 auto flush_segmentes = [&]() {
6507 if (xsegm.size() > 0) {
6508 gPad->PaintSegments(xsegm.size()/2, xsegm.data(), ysegm.data());
6509 xsegm.clear();
6510 ysegm.clear();
6511 }
6512 };
6513
6515 xsegm.emplace_back(x1);
6516 xsegm.emplace_back(x2);
6517 ysegm.emplace_back(y1);
6518 ysegm.emplace_back(y2);
6519 if (xsegm.size() == xsegm.capacity())
6521 };
6522
6523 auto flush_markers = [&]() {
6524 if (xmarker.size() > 0) {
6525 gPad->PaintPolyMarker(xmarker.size(), xmarker.data(), ymarker.data());
6526 xmarker.clear();
6527 ymarker.clear();
6528 }
6529 };
6530
6531 auto add_marker = [&](Double_t x, Double_t y) {
6532 if (xmarker.capacity() == 0) {
6533 xmarker.reserve(256);
6534 ymarker.reserve(256);
6535 }
6536
6537 xmarker.emplace_back(x);
6538 ymarker.emplace_back(y);
6539 if (xmarker.size() == xmarker.capacity()) {
6541 flush_markers();
6542 }
6543 };
6544
6545
6546 if (option3) {
6547 xline.resize(2*npoints);
6548 yline.resize(2*npoints);
6549 if ((npoints > 0) && (xline.empty() || yline.empty())) {
6550 Error("PaintErrors", "too many points, out of memory");
6551 return;
6552 }
6553 if1 = 1;
6554 if2 = 2*npoints;
6555 }
6556
6557 // compute the offset of the error bars due to the symbol size
6558 s2x = gPad->PixeltoX(Int_t(0.5*sbasex)) - gPad->PixeltoX(0);
6559 s2y =-gPad->PixeltoY(Int_t(0.5*sbasey)) + gPad->PixeltoY(0);
6560
6561 // compute size of the lines at the end of the error bars
6563 bxsize = gPad->PixeltoX(dxend) - gPad->PixeltoX(0);
6564 bysize =-gPad->PixeltoY(dxend) + gPad->PixeltoY(0);
6565
6566
6567 if (fixbin) {
6569 else xp = Hparam.xmin + 0.5*Hparam.xbinsize;
6570 } else {
6571 delta = fH->GetBinWidth(first);
6572 xp = fH->GetBinLowEdge(first) + 0.5*delta;
6573 }
6574
6575 // if errormarker = 0 or symbolsize = 0. no symbol is drawn
6578
6579 // ---------------------- Loop over the points---------------------
6580 for (k=first; k<=last; k++) {
6581
6582 // get the data
6583 // xp = X position of the current point
6584 // yp = Y position of the current point
6585 // ex1 = Low X error
6586 // ex2 = Up X error
6587 // ey1 = Low Y error
6588 // ey2 = Up Y error
6589 // (xi,yi) = Error bars coordinates
6590
6591 // apply offset on errors for bar histograms
6592 Double_t xminTmp = gPad->XtoPad(fXaxis->GetBinLowEdge(k));
6593 Double_t xmaxTmp = gPad->XtoPad(fXaxis->GetBinUpEdge(k));
6594 if (Hoption.Logx) {
6597 }
6600 xmaxTmp = xminTmp + w;
6601 xp = (xminTmp+xmaxTmp)/2.;
6602
6603 if (Hoption.Logx) {
6604 if (xp <= 0) goto L30;
6605 if (xp < logxmin) goto L30;
6606 if (xp > TMath::Power(10,xmax)) break;
6607 } else {
6608 if (xp < xmin) goto L30;
6609 if (xp > xmax) break;
6610 }
6611 yp = factor*fH->GetBinContent(k);
6612 if (optionI0 && yp==0) goto L30;
6613 if (fixbin) {
6615 } else {
6616 delta = fH->GetBinWidth(k);
6617 ex1 = xerror*delta;
6618 }
6619 if (fH->GetBinErrorOption() == TH1::kNormal) {
6620 ey1 = factor*fH->GetBinError(k);
6621 ey2 = ey1;
6622 } else {
6623 ey1 = factor*fH->GetBinErrorLow(k);
6624 ey2 = factor*fH->GetBinErrorUp(k);
6625 }
6626 ex2 = ex1;
6627
6628 xi4 = xp;
6629 xi3 = xp;
6630 xi2 = xp + ex2;
6631 xi1 = xp - ex1;
6632
6633 yi1 = yp;
6634 yi2 = yp;
6635 yi3 = yp - ey1;
6636 yi4 = yp + ey2;
6637
6638 // take the LOG if necessary
6639 if (Hoption.Logx) {
6644 }
6645 if (Hoption.Logy) {
6650 }
6651
6652 // test if error bars are not outside the limits
6653 // otherwise they are truncated
6654
6659
6660 // test if the marker is on the frame limits. If "Yes", the
6661 // marker will not be drawn and the error bars will be readjusted.
6662
6663 drawmarker = kTRUE;
6664 if (!option0 && !option3) {
6665 if (Hoption.Logy && yp < logymin) goto L30;
6666 if (yi1 < ymin || yi1 > ymax) goto L30;
6667 if (Hoption.Error != 0 && yp == 0 && ey1 <= 0) drawmarker = kFALSE;
6668 }
6670
6671 // draw the error rectangles
6672 if (option2) {
6673 if ((yi3 >= ymax) || (yi4 <= ymin))
6674 goto L30;
6675 gPad->PaintBox(xi1,yi3,xi2,yi4);
6676 }
6677
6678 // keep points for fill area drawing
6679 if (option3) {
6680 xline[if1-1] = xi3;
6681 xline[if2-1] = xi3;
6682 yline[if1-1] = yi4;
6683 yline[if2-1] = yi3;
6684 if1++;
6685 if2--;
6686 }
6687
6688 // draw the error bars
6689 if (Hoption.Logy && yp < logymin)
6691 if (optionE && drawmarker) {
6692 if ((yi3 < yi1 - s2y) && (yi3 < ymax))
6694 if ((yi1 + s2y < yi4) && (yi4 > ymin))
6696 // don't duplicate the horizontal line
6697 if (Hoption.Hist != 2) {
6699 if (xi1 < xi3 - s2x)
6701 if (xi3 + s2x < xi2)
6703 }
6704 }
6705 }
6706 if (optionE && !drawmarker && (ey1 != 0 || ey2 !=0)) {
6707 if ((yi3 < yi1) && (yi3 < ymax))
6709 if ((yi1 < yi4) && (yi4 > ymin))
6711 // don't duplicate the horizontal line
6712 if (Hoption.Hist != 2) {
6714 if (xi1 < xi3)
6716 if (xi3 < xi2)
6718 }
6719 }
6720 }
6721
6722 // draw line at the end of the error bars
6723
6724 if (option1 && drawmarker) {
6725
6731 if (xi1 < xi3-s2x)
6733 if (xi2 > xi3+s2x)
6735 }
6736 }
6737
6738 // draw the marker
6739
6740 if (drawmarker)
6741 add_marker(xi3, yi1);
6742
6743L30:
6744 if (fixbin) xp += Hparam.xbinsize;
6745 else {
6746 if (k < last) {
6747 delta = fH->GetBinWidth(k+1);
6748 xp = fH->GetBinLowEdge(k+1) + 0.5*delta;
6749 }
6750 }
6751 } //end of for loop
6752
6754
6755 flush_markers();
6756
6757
6758 // draw the filled area
6759
6760 if (option3) {
6761 TGraph graph;
6762 graph.SetLineStyle(fH->GetLineStyle());
6763 graph.SetLineColor(fH->GetLineColor());
6764 graph.SetLineWidth(fH->GetLineWidth());
6765 graph.SetFillStyle(fH->GetFillStyle());
6766 graph.SetFillColor(fH->GetFillColor());
6767 Int_t logx = gPad->GetLogx();
6768 Int_t logy = gPad->GetLogy();
6769 gPad->SetLogx(0);
6770 gPad->SetLogy(0);
6771
6772 // In some cases the number of points in the fill area is smaller than
6773 // 2*npoints. In such cases the array xline and yline must be arranged
6774 // before being plotted. The next loop does that.
6775 if (if2 > npoints) {
6776 for (i=1; i<if1; i++) {
6777 xline[if1-2+i] = xline[if2-1+i];
6778 yline[if1-2+i] = yline[if2-1+i];
6779 }
6780 npoints = if1-1;
6781 }
6782 if (option4) graph.PaintGraph(2*npoints,xline.data(),yline.data(),"FC");
6783 else graph.PaintGraph(2*npoints,xline.data(),yline.data(),"F");
6784 gPad->SetLogx(logx);
6785 gPad->SetLogy(logy);
6786 }
6787}
6788
6789////////////////////////////////////////////////////////////////////////////////
6790/// Draw 2D histograms errors.
6791
6793{
6794
6795 fH->TAttMarker::Modify();
6796 fH->TAttLine::Modify();
6797
6798 // Define the 3D view
6799 fXbuf[0] = Hparam.xmin;
6800 fYbuf[0] = Hparam.xmax;
6801 fXbuf[1] = Hparam.ymin;
6802 fYbuf[1] = Hparam.ymax;
6803 fXbuf[2] = Hparam.zmin;
6804 fYbuf[2] = Hparam.zmax*(1. + gStyle->GetHistTopMargin());
6805 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
6806 TView *view = gPad ? gPad->GetView() : nullptr;
6807 if (!view) {
6808 Error("Paint2DErrors", "no TView in current pad");
6809 return;
6810 }
6811 Double_t thedeg = 90 - gPad->GetTheta();
6812 Double_t phideg = -90 - gPad->GetPhi();
6813 Double_t psideg = view->GetPsi();
6814 Int_t irep;
6815 view->SetView(phideg, thedeg, psideg, irep);
6816
6817 // Set color/style for back box
6818 fLego->SetFillStyle(gPad->GetFrameFillStyle());
6819 fLego->SetFillColor(gPad->GetFrameFillColor());
6820 fLego->TAttFill::Modify();
6821 Int_t backcolor = gPad->GetFrameFillColor();
6822 if (Hoption.System != kCARTESIAN) backcolor = 0;
6823 view->PadRange(backcolor);
6824 fLego->SetFillStyle(fH->GetFillStyle());
6825 fLego->SetFillColor(fH->GetFillColor());
6826 fLego->TAttFill::Modify();
6827
6828 // Paint the Back Box if needed
6829 if (Hoption.BackBox && !Hoption.Same && !Hoption.Lego && !Hoption.Surf) {
6830 fLego->InitMoveScreen(-1.1,1.1);
6831 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
6833 fLego->BackBox(90);
6834 }
6835
6836 // Paint the Errors
6837 Double_t x, ex, x1, x2;
6838 Double_t y, ey, y1, y2;
6839 Double_t z, ez1, ez2, z1, z2;
6840 Double_t temp1[3],temp2[3];
6842 if (Hoption.Error == 110) {
6843 xyerror = 0;
6844 } else {
6846 }
6847
6849 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
6850 y = fYaxis->GetBinCenter(j);
6852 y1 = y-ey;
6853 y2 = y+ey;
6854 if (Hoption.Logy) {
6855 if (y > 0) y = TMath::Log10(y);
6856 else continue;
6857 if (y1 > 0) y1 = TMath::Log10(y1);
6858 else y1 = Hparam.ymin;
6859 if (y2 > 0) y2 = TMath::Log10(y2);
6860 else y2 = Hparam.ymin;
6861 }
6864 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
6865 xk = fXaxis->GetBinLowEdge(i);
6866 xstep = fXaxis->GetBinWidth(i);
6867 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
6868 Int_t bin = fH->GetBin(i,j);
6869 x = fXaxis->GetBinCenter(i);
6871 x1 = x-ex;
6872 x2 = x+ex;
6873 if (Hoption.Logx) {
6874 if (x > 0) x = TMath::Log10(x);
6875 else continue;
6876 if (x1 > 0) x1 = TMath::Log10(x1);
6877 else x1 = Hparam.xmin;
6878 if (x2 > 0) x2 = TMath::Log10(x2);
6879 else x2 = Hparam.xmin;
6880 }
6881 z = fH->GetBinContent(bin);
6882 if (fH->GetBinErrorOption() == TH1::kNormal) {
6883 ez1 = fH->GetBinError(bin);
6884 ez2 = ez1;
6885 }
6886 else {
6888 ez2 = fH->GetBinErrorUp(bin);
6889 }
6890 z1 = z - ez1;
6891 z2 = z + ez2;
6892 if (Hoption.Logz) {
6893 if (z > 0) z = TMath::Log10(z);
6894 else z = Hparam.zmin;
6895 if (z1 > 0) z1 = TMath::Log10(z1);
6896 else z1 = Hparam.zmin;
6897 if (z2 > 0) z2 = TMath::Log10(z2);
6898 else z2 = Hparam.zmin;
6899
6900 }
6901 if (z <= Hparam.zmin) continue;
6902 if (z > Hparam.zmax) z = Hparam.zmax;
6903
6904 temp1[0] = x1;
6905 temp1[1] = y;
6906 temp1[2] = z;
6907 temp2[0] = x2;
6908 temp2[1] = y;
6909 temp2[2] = z;
6910 gPad->PaintLine3D(temp1, temp2);
6911 temp1[0] = x;
6912 temp1[1] = y1;
6913 temp1[2] = z;
6914 temp2[0] = x;
6915 temp2[1] = y2;
6916 temp2[2] = z;
6917 gPad->PaintLine3D(temp1, temp2);
6918 temp1[0] = x;
6919 temp1[1] = y;
6920 temp1[2] = z1;
6921 temp2[0] = x;
6922 temp2[1] = y;
6923 temp2[2] = z2;
6924 gPad->PaintLine3D(temp1, temp2);
6925 temp1[0] = x;
6926 temp1[1] = y;
6927 temp1[2] = z;
6928 view->WCtoNDC(temp1, &temp2[0]);
6929 gPad->PaintPolyMarker(1, &temp2[0], &temp2[1]);
6930 }
6931 }
6932
6933 // Paint the Front Box if needed
6934 if (Hoption.FrontBox) {
6935 fLego->InitMoveScreen(-1.1,1.1);
6937 fLego->FrontBox(90);
6938 }
6939
6940 // Paint the Axis if needed
6941 if (!Hoption.Axis && !Hoption.Same && !Hoption.Lego && !Hoption.Surf) {
6942 TGaxis axis;
6943 PaintLegoAxis(&axis, 90);
6944 }
6945
6946 fLego.reset();
6947}
6948
6949////////////////////////////////////////////////////////////////////////////////
6950/// Calculate range and clear pad (canvas).
6951
6953{
6954
6955 if (Hoption.Same) return;
6956
6958
6959 if (Hoption.Lego || Hoption.Surf || Hoption.Tri ||
6960 Hoption.Contour == 14 || Hoption.Error >= 100) {
6961 TObject *frame = gPad->FindObject("TFrame");
6962 if (frame) gPad->Remove(frame);
6963 return;
6964 }
6965
6966 //The next statement is always executed on non-iOS platform,
6967 //on iOS depends on pad mode.
6968 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode())
6969 gPad->PaintPadFrame(Hparam.xmin,Hparam.ymin,Hparam.xmax,Hparam.ymax);
6970}
6971
6972////////////////////////////////////////////////////////////////////////////////
6973/// [Paint functions associated to an histogram.](\ref HP28")
6974
6976{
6977 auto lnk = fFunctions->FirstLink();
6978
6979 while (lnk) {
6980 auto obj = lnk->GetObject();
6982 if (obj->InheritsFrom(TF2::Class())) {
6983 if (!obj->TestBit(TF2::kNotDraw)) {
6984 if (Hoption.Lego || Hoption.Surf || Hoption.Error >= 100) {
6985 TF2 *f2 = (TF2*)obj;
6986 f2->SetMinimum(fH->GetMinimum());
6987 f2->SetMaximum(fH->GetMaximum());
6988 f2->SetRange(fH->GetXaxis()->GetXmin(), fH->GetYaxis()->GetXmin(), fH->GetXaxis()->GetXmax(), fH->GetYaxis()->GetXmax() );
6989 f2->Paint("surf same");
6990 } else {
6991 obj->Paint("cont3 same");
6992 }
6993 }
6994 } else if (obj->InheritsFrom(TF1::Class())) {
6995 if (!obj->TestBit(TF1::kNotDraw)) obj->Paint("lsame");
6996 } else {
6997 //Let's make this 'function' selectable on iOS device (for example, it can be TPaveStat).
6998 gPad->PushSelectableObject(obj);
6999
7000 //The next statement is ALWAYS executed on non-iOS platform, on iOS it depends on pad's mode
7001 //and picked object.
7002 if (!gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && obj == gPad->GetSelected()))
7003 obj->Paint(lnk->GetOption());
7004 }
7005 lnk = lnk->Next();
7006 }
7007}
7008
7009////////////////////////////////////////////////////////////////////////////////
7010/// [Control routine to draw 1D histograms](\ref HP01b)
7011
7013{
7014
7015 //On iOS: do not highlight hist, if part of it was selected.
7016 //Never executes on non-iOS platform.
7017 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
7018 return;
7019
7020 static char chopth[17];
7021
7023 Int_t i, j, first, last, nbins, fixbin;
7024 Double_t c1, yb;
7025 yb = 0;
7026
7027 strlcpy(chopth, " ",17);
7028
7031 Double_t baroffset = fH->GetBarOffset();
7032 Double_t barwidth = fH->GetBarWidth();
7035 gStyle->SetBarOffset(baroffset);
7036 gStyle->SetBarWidth(barwidth);
7037
7038 // Create "LIFE" structure to keep current histogram status
7039
7040 first = Hparam.xfirst;
7041 last = Hparam.xlast;
7042 nbins = last - first + 1;
7043
7044 std::vector<Double_t> keepx, keepy;
7045 if (fXaxis->GetXbins()->fN) fixbin = 0;
7046 else fixbin = 1;
7047 if (fixbin) keepx.resize(2);
7048 else keepx.resize(nbins+1);
7049 keepy.resize(nbins);
7050 Double_t logymin = 0;
7052
7053 // Loop on histogram bins
7054
7055 for (j=first; j<=last;j++) {
7057 if (TMath::Abs(ymax-ymin) > 0) {
7059 else yb = c1;
7060 }
7061 if (!Hoption.Line) {
7062 yb = TMath::Max(yb, ymin);
7063 yb = TMath::Min(yb, ymax);
7064 }
7065 keepy[j-first] = yb;
7066 }
7067
7068 // Draw histogram according to value of FillStyle and FillColor
7069
7070 if (fixbin) { keepx[0] = Hparam.xmin; keepx[1] = Hparam.xmax; }
7071 else {
7072 for (i=0; i<nbins; i++) keepx[i] = fXaxis->GetBinLowEdge(i+first);
7073 keepx[nbins] = fXaxis->GetBinUpEdge(nbins-1+first);
7074 }
7075
7076 // Prepare Fill area (systematic with option "Bar").
7077
7079 htype = oldhtype;
7080 if (Hoption.Bar) {
7081 if (htype == 0 || htype == 1000) htype = 1001;
7082 }
7083
7085
7086 // Code option for GrapHist
7087
7088 if (Hoption.Line) chopth[0] = 'L';
7089 if (Hoption.Star) chopth[1] = '*';
7090 if (Hoption.Mark) chopth[2] = 'P';
7091 if (Hoption.Mark == 10) chopth[3] = '0';
7093 if (Hoption.Curve) chopth[3] = 'C';
7094 if (Hoption.Hist > 0) chopth[4] = 'H';
7095 else if (Hoption.Bar) chopth[5] = 'B';
7096 if (Hoption.Logy) chopth[6] = '1';
7097 if (fH->GetFillColor() && htype) {
7098 if (Hoption.Hist > 0 || Hoption.Curve || Hoption.Line) {
7099 chopth[7] = 'F';
7100 }
7101 }
7102 }
7103 if (!fixbin && strlen(chopth)) {
7104 chopth[8] = 'N';
7105 }
7106
7107 if (Hoption.Fill == 2) chopth[13] = '2';
7108
7109 // Option LOGX
7110
7111 if (Hoption.Logx) {
7112 chopth[9] = 'G';
7113 chopth[10] = 'X';
7114 if (fixbin) {
7115 keepx[0] = TMath::Power(10,keepx[0]);
7116 keepx[1] = TMath::Power(10,keepx[1]);
7117 }
7118 }
7119
7120 if (Hoption.Off) {
7121 chopth[11] = ']';
7122 chopth[12] = '[';
7123 }
7124
7125 // Draw the histogram
7126
7127 TGraph graph;
7128 graph.SetLineWidth(lw);
7129 graph.SetLineStyle(fH->GetLineStyle());
7130 graph.SetLineColor(fH->GetLineColor());
7131 graph.SetFillStyle(htype);
7132 graph.SetFillColor(fH->GetFillColor());
7134 graph.SetMarkerSize(fH->GetMarkerSize());
7137
7138 graph.PaintGrapHist(nbins, keepx.data(), keepy.data() ,chopth);
7139
7142
7144}
7145
7146////////////////////////////////////////////////////////////////////////////////
7147/// [Control function to draw a 3D histograms.](\ref HP01d)
7148
7150{
7151
7152 TString cmd;
7153 TString opt = option;
7154 opt.ToLower();
7155 Int_t irep;
7156 Float_t NEntries = fH->GetEntries();
7157
7158 if (fCurrentF3 || strstr(opt,"tf3")) {
7159 PaintTF3();
7160 return;
7161 }
7162
7163 if (NEntries > 0) {
7164 if (Hoption.Box || Hoption.Lego || Hoption.Color) {
7165 if (Hoption.Box == 11 || Hoption.Lego == 11) {
7166 PaintH3Box(1);
7167 } else if (Hoption.Box == 12 || Hoption.Lego == 12 || Hoption.Color == 1) {
7168 PaintH3Box(2);
7169 } else if (Hoption.Box == 13 || Hoption.Lego == 13) {
7170 PaintH3Box(3);
7171 } else {
7173 }
7174 return;
7175 }
7176
7177 if (strstr(opt,"iso")) {
7178 PaintH3Iso();
7179 return;
7180 }
7181 }
7182
7183 TView *view = gPad ? gPad->GetView() : nullptr;
7184 if (!view) return;
7185
7186 if (strstr(opt,"fb")) Hoption.FrontBox = 0;
7187 if (strstr(opt,"bb")) Hoption.BackBox = 0;
7188
7189 Double_t thedeg = 90 - gPad->GetTheta();
7190 Double_t phideg = -90 - gPad->GetPhi();
7191 Double_t psideg = view->GetPsi();
7192 view->SetView(phideg, thedeg, psideg, irep);
7193
7194 if(NEntries > 0) { // Paint as 3D scatter plot
7195 cmd.Form("TPolyMarker3D::PaintH3((TH1 *)0x%zx,\"%s\");",(size_t)fH,option);
7196 gROOT->ProcessLine(cmd.Data());
7197 } else {
7198 TAxis* xAxis = fH->GetXaxis();
7199 TAxis* yAxis = fH->GetYaxis();
7200 TAxis* zAxis = fH->GetZaxis();
7201 Double_t xmin = xAxis->GetXmin();
7202 Double_t xmax = xAxis->GetXmax();
7203 Double_t ymin = yAxis->GetXmin();
7204 Double_t ymax = yAxis->GetXmax();
7205 Double_t zmin = zAxis->GetXmin();
7206 Double_t zmax = zAxis->GetXmax();
7207 view->SetRange(xmin, ymin, zmin, xmax, ymax, zmax); // Set the axis limits (Xmin, Ymin, Zmin, Xmax, Ymax, Zmax)
7208 }
7209
7210 if (Hoption.Same) return;
7211
7212 // Draw axis
7213 view->SetOutlineToCube();
7214 TSeqCollection *ol = view->GetOutline();
7215 if (ol && Hoption.BackBox && Hoption.FrontBox) ol->Paint(option);
7217
7218 if (!Hoption.Axis && !Hoption.Same) {
7219 TGaxis axis;
7220 PaintLegoAxis(&axis, 90);
7221 }
7222
7223 // Draw palette. In case of 4D plot with TTree::Draw() the palette should
7224 // be painted with the option colz.
7225 if (fH->GetDrawOption() && strstr(opt,"colz")) {
7226 Int_t ndiv = fH->GetContour();
7227 if (ndiv == 0 ) {
7228 ndiv = gStyle->GetNumberContours();
7229 fH->SetContour(ndiv);
7230 }
7231 PaintPalette();
7232 }
7233
7234 // Draw title
7235 PaintTitle();
7236
7237 //Draw stats and fit results
7238 TF1 *fit = nullptr;
7239 TIter next(fFunctions);
7240 while (auto obj = next()) {
7241 if (obj->InheritsFrom(TF1::Class())) {
7242 fit = (TF1*)obj;
7243 break;
7244 }
7245 }
7246 if ((Hoption.Same%10) != 1) {
7247 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7249 }
7250 }
7251
7252}
7253
7254////////////////////////////////////////////////////////////////////////////////
7255/// Compute histogram parameters used by the drawing routines.
7256
7258{
7259
7260 if (fH->GetDimension() > 1 || Hoption.Lego || Hoption.Surf) return 1;
7261
7262 Int_t i;
7263 static const char *where = "PaintInit";
7265 Int_t maximum = 0;
7266 Int_t minimum = 0;
7267 if (fH->GetMaximumStored() != -1111) maximum = 1;
7268 if (fH->GetMinimumStored() != -1111) minimum = 1;
7269
7270 // Compute X axis parameters
7271
7272 Int_t last = fXaxis->GetLast();
7273 Int_t first = fXaxis->GetFirst();
7276 Hparam.xlast = last;
7277 Hparam.xfirst = first;
7280
7281 // if log scale in X, replace xmin,max by the log
7282 if (Hoption.Logx) {
7283 if (Hparam.xmax<=0) {
7284 Error(where, "cannot set X axis to log scale");
7285 return 0;
7286 }
7287 if (Hparam.xlowedge <=0 ) {
7288 if (Hoption.Same) {
7289 TH1* h1 = nullptr;
7290 TObject *obj;
7291 TIter next(gPad->GetListOfPrimitives());
7292 while ((obj = (TObject *)next())) {
7293 if (obj->InheritsFrom(TH1::Class())) { h1 = (TH1*)(obj) ; break; }
7294 if (obj->InheritsFrom(THStack::Class())) { h1 = ((THStack*)(obj))->GetHistogram() ; break; }
7295 if (obj->InheritsFrom(TGraph::Class())) { h1 = ((TGraph*)(obj))->GetHistogram() ; break; }
7296 if (obj->InheritsFrom(TMultiGraph::Class())) { h1 = ((TMultiGraph*)(obj))->GetHistogram(); break; }
7297 if (obj->InheritsFrom(TGraph2D::Class())) { h1 = ((TGraph2D*)(obj))->GetHistogram(); break; }
7298 if (obj->InheritsFrom(TF1::Class())) { h1 = ((TF1*)(obj))->GetHistogram(); break; }
7299 }
7300 if (h1) {
7302 } else {
7303 Error(where, "undefined user's coordinates. Cannot use option SAME");
7304 return 0;
7305 }
7306 } else {
7307 for (i=first; i<=last; i++) {
7308 Double_t binLow = fXaxis->GetBinLowEdge(i);
7309 if (binLow>0) {
7310 Hparam.xlowedge = binLow;
7311 break;
7312 }
7313 if (binLow == 0 && fH->GetBinContent(i) !=0) {
7314 Hparam.xlowedge = fXaxis->GetBinUpEdge(i)*0.001;
7315 break;
7316 }
7317 }
7318 if (Hparam.xlowedge<=0) {
7319 Error(where, "cannot set X axis to log scale");
7320 return 0;
7321 }
7322 }
7324 }
7329 if (Hparam.xlast > last) Hparam.xlast = last;
7330 if (Hparam.xfirst < first) Hparam.xfirst = first;
7331 }
7332
7333 // Compute Y axis parameters
7334 Double_t bigp = TMath::Power(10,32);
7335 Double_t ymax = -bigp;
7336 Double_t ymin = bigp;
7337 Double_t c1, e1;
7338 Double_t xv[1];
7339 Double_t fval;
7340 TObject *f;
7341 TF1 *f1;
7342 Double_t allchan = 0;
7343 Int_t nonNullErrors = 0;
7344 TIter next(fFunctions);
7345 for (i=first; i<=last;i++) {
7346 c1 = fH->GetBinContent(i);
7347 if (std::isnan(c1) || std::isinf(c1))
7348 continue;
7350 if (Hoption.Logy) {
7351 if (c1 > 0) ymin = TMath::Min(ymin,c1);
7352 } else {
7354 }
7355 if (Hoption.Error) {
7357 e1 = fH->GetBinError(i);
7358 else
7359 e1 = fH->GetBinErrorUp(i);
7360 if (e1 > 0) nonNullErrors++;
7363 e1 = fH->GetBinErrorLow(i);
7364
7365 if (Hoption.Logy) {
7366 if (c1-e1>0.01*TMath::Abs(c1)) ymin = TMath::Min(ymin,c1-e1);
7367 } else {
7369 }
7370 }
7371 if (Hoption.Func) {
7372 xv[0] = fXaxis->GetBinCenter(i);
7373 while ((f = (TObject*) next())) {
7374 if (f->IsA() == TF1::Class()) {
7375 f1 = (TF1*)f;
7376 if (xv[0] < f1->GetXmin() || xv[0] > f1->GetXmax()) continue;
7377 fval = f1->Eval(xv[0],0,0);
7378 if (f1->GetMaximumStored() != -1111) fval = TMath::Min(f1->GetMaximumStored(), fval);
7380 if (Hoption.Logy) {
7381 if (c1 > 0 && fval > 0.3*c1) ymin = TMath::Min(ymin,fval);
7382 }
7383 }
7384 }
7385 next.Reset();
7386 }
7387 allchan += c1;
7388 }
7389 if (!nonNullErrors) {
7390 if (Hoption.Error) {
7391 if (!Hoption.Mark && !Hoption.Line && !Hoption.Star && !Hoption.Curve) Hoption.Hist = 2;
7392 Hoption.Error=0;
7393 }
7394 }
7395
7396
7397 // Take into account maximum , minimum
7398
7399 if (Hoption.Logy && ymin <= 0) {
7400 if (ymax >= 1) ymin = TMath::Max(.005,ymax*1e-10);
7401 else ymin = 0.001*ymax;
7402 }
7403
7404 Double_t xm = ymin;
7405 if (maximum) ymax = fH->GetMaximumStored();
7406 if (minimum) xm = fH->GetMinimumStored();
7407 if (Hoption.Logy && xm < 0) {
7408 Error(where, "log scale requested with a negative argument (%f)", xm);
7409 return 0;
7410 } else if (Hoption.Logy && xm>=0 && ymax==0) { // empty histogram in log scale
7411 ymin = 0.01;
7412 ymax = 10.;
7413 } else {
7414 ymin = xm;
7415 }
7416
7417 if (ymin >= ymax) {
7418 if (Hoption.Logy) {
7419 if (ymax > 0) ymin = 0.001*ymax;
7420 else {
7421 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", ymax);
7422 return 0;
7423 }
7424 }
7425 else {
7426 if (ymin > 0) {
7427 ymin = 0;
7428 ymax *= 2;
7429 } else if (ymin < 0) {
7430 ymax = 0;
7431 ymin *= 2;
7432 } else {
7433 ymin = 0;
7434 ymax = 1;
7435 }
7436 }
7437 }
7438
7439 // In some cases, mainly because of precision issues, ymin and ymax could almost equal.
7440 if (TMath::AreEqualRel(ymin,ymax,1E-15)) {
7441 ymin = ymin*(1-1E-14);
7442 ymax = ymax*(1+1E-14);
7443 }
7444
7445 // take into account normalization factor
7446 Hparam.allchan = allchan;
7447 Double_t factor = allchan;
7448 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
7449 if (allchan) factor /= allchan;
7450 if (factor == 0) factor = 1;
7451 Hparam.factor = factor;
7452 ymax = factor*ymax;
7453 ymin = factor*ymin;
7454 //just in case the norm factor is negative
7455 // this may happen with a positive norm factor and a negative integral !
7456 if (ymax < ymin) {
7457 Double_t temp = ymax;
7458 ymax = ymin;
7459 ymin = temp;
7460 }
7461
7462 // For log scales, histogram coordinates are LOG10(ymin) and
7463 // LOG10(ymax). Final adjustment (if not option "Same"
7464 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
7465 // Maximum and Minimum are not defined.
7466 if (Hoption.Logy) {
7467 if (ymin <=0 || ymax <=0) {
7468 Error(where, "Cannot set Y axis to log scale");
7469 return 0;
7470 }
7472 if (!minimum) ymin += TMath::Log10(0.5);
7474 if (!maximum) ymax += TMath::Log10(2*(0.9/0.95));
7475 if (!Hoption.Same) {
7476 Hparam.ymin = ymin;
7477 Hparam.ymax = ymax;
7478 }
7479 return 1;
7480 }
7481
7482 // final adjustment of ymin for linear scale.
7483 // if minimum is not set , then ymin is set to zero if >0
7484 // or to ymin - margin if <0.
7485 if (!minimum) {
7486 if (Hoption.MinimumZero) {
7487 if (ymin >= 0) ymin = 0;
7488 else ymin -= yMARGIN*(ymax-ymin);
7489 } else {
7491 if (ymin >= 0 && (ymin-dymin <= 0)) ymin = 0;
7492 else ymin -= dymin;
7493 }
7494 }
7495
7496 // final adjustment of YMAXI for linear scale (if not option "Same"):
7497 // decrease histogram height to MAX% of allowed height if HMAXIM
7498 // has not been called.
7499 if (!maximum) {
7500 ymax += yMARGIN*(ymax-ymin);
7501 }
7502
7503 Hparam.ymin = ymin;
7504 Hparam.ymax = ymax;
7505 return 1;
7506}
7507
7508////////////////////////////////////////////////////////////////////////////////
7509/// Compute histogram parameters used by the drawing routines for a rotated pad.
7510
7512{
7513
7514 static const char *where = "PaintInitH";
7516 Int_t maximum = 0;
7517 Int_t minimum = 0;
7518 if (fH->GetMaximumStored() != -1111) maximum = 1;
7519 if (fH->GetMinimumStored() != -1111) minimum = 1;
7520
7521 // Compute X axis parameters
7522
7523 Int_t last = fXaxis->GetLast();
7524 Int_t first = fXaxis->GetFirst();
7527 Hparam.xlast = last;
7528 Hparam.xfirst = first;
7531
7532 // if log scale in Y, replace ymin,max by the log
7533 if (Hoption.Logy) {
7534 if (Hparam.xlowedge <=0 ) {
7537 }
7538 if (Hparam.ymin <=0 || Hparam.ymax <=0) {
7539 Error(where, "cannot set Y axis to log scale");
7540 return 0;
7541 }
7546 if (Hparam.xlast > last) Hparam.xlast = last;
7547 }
7548
7549 // Compute Y axis parameters
7550 Double_t bigp = TMath::Power(10,32);
7551 Double_t xmax = -bigp;
7552 Double_t xmin = bigp;
7553 Double_t c1, e1;
7554 Double_t xv[1];
7555 Double_t fval;
7556 Int_t i;
7557 TObject *f;
7558 TF1 *f1;
7559 Double_t allchan = 0;
7560 TIter next(fFunctions);
7561 for (i=first; i<=last;i++) {
7562 c1 = fH->GetBinContent(i);
7565 if (Hoption.Error) {
7566 e1 = fH->GetBinError(i);
7569 }
7570 if (Hoption.Func) {
7571 xv[0] = fXaxis->GetBinCenter(i);
7572 while ((f = (TObject*) next())) {
7573 if (f->IsA() == TF1::Class()) {
7574 f1 = (TF1*)f;
7575 if (xv[0] < f1->GetXmin() || xv[0] > f1->GetXmax()) continue;
7576 fval = f1->Eval(xv[0],0,0);
7578 if (Hoption.Logy) {
7579 if (fval > 0.3*c1) xmin = TMath::Min(xmin,fval);
7580 }
7581 }
7582 }
7583 next.Reset();
7584 }
7585 allchan += c1;
7586 }
7587
7588 // Take into account maximum , minimum
7589
7590 if (Hoption.Logx && xmin <= 0) {
7591 if (xmax >= 1) xmin = TMath::Max(.5,xmax*1e-10);
7592 else xmin = 0.001*xmax;
7593 }
7594 Double_t xm = xmin;
7595 if (maximum) xmax = fH->GetMaximumStored();
7596 if (minimum) xm = fH->GetMinimumStored();
7597 if (Hoption.Logx && xm <= 0) {
7598 Error(where, "log scale requested with zero or negative argument (%f)", xm);
7599 return 0;
7600 }
7601 else xmin = xm;
7602 if (xmin >= xmax) {
7603 if (Hoption.Logx) {
7604 if (xmax > 0) xmin = 0.001*xmax;
7605 else {
7606 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", xmax);
7607 return 0;
7608 }
7609 }
7610 else {
7611 if (xmin > 0) {
7612 xmin = 0;
7613 xmax *= 2;
7614 } else if (xmin < 0) {
7615 xmax = 0;
7616 xmin *= 2;
7617 } else {
7618 xmin = 0;
7619 xmax = 1;
7620 }
7621 }
7622 }
7623
7624 // take into account normalization factor
7625 Hparam.allchan = allchan;
7626 Double_t factor = allchan;
7627 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
7628 if (allchan) factor /= allchan;
7629 if (factor == 0) factor = 1;
7630 Hparam.factor = factor;
7631 xmax = factor*xmax;
7632 xmin = factor*xmin;
7633
7634 // For log scales, histogram coordinates are LOG10(ymin) and
7635 // LOG10(ymax). Final adjustment (if not option "Same"
7636 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
7637 // Maximum and Minimum are not defined.
7638 if (Hoption.Logx) {
7639 if (xmin <=0 || xmax <=0) {
7640 Error(where, "Cannot set Y axis to log scale");
7641 return 0;
7642 }
7644 if (!minimum) xmin += TMath::Log10(0.5);
7646 if (!maximum) xmax += TMath::Log10(2*(0.9/0.95));
7647 if (!Hoption.Same) {
7648 Hparam.xmin = xmin;
7649 Hparam.xmax = xmax;
7650 }
7651 return 1;
7652 }
7653
7654 // final adjustment of ymin for linear scale.
7655 // if minimum is not set , then ymin is set to zero if >0
7656 // or to ymin - margin if <0.
7657 if (!minimum) {
7658 if (xmin >= 0) xmin = 0;
7659 else xmin -= yMARGIN*(xmax-xmin);
7660 }
7661
7662 // final adjustment of YMAXI for linear scale (if not option "Same"):
7663 // decrease histogram height to MAX% of allowed height if HMAXIM
7664 // has not been called.
7665 if (!maximum) {
7666 xmax += yMARGIN*(xmax-xmin);
7667 }
7668 Hparam.xmin = xmin;
7669 Hparam.xmax = xmax;
7670 return 1;
7671}
7672
7673////////////////////////////////////////////////////////////////////////////////
7674/// [Control function to draw a 3D histogram with boxes.](\ref HP25)
7675
7677{
7678 // Predefined box structure
7679 Double_t wxyz[8][3] = { {-1,-1,-1}, {1,-1,-1}, {1,1,-1}, {-1,1,-1},
7680 {-1,-1, 1}, {1,-1, 1}, {1,1, 1}, {-1,1, 1} };
7681 Int_t iface[6][4] = { {0,3,2,1}, {4,5,6,7},
7682 {0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7} };
7683
7684 // Define dimensions of world space
7685 TAxis *xaxis = fH->GetXaxis();
7686 TAxis *yaxis = fH->GetYaxis();
7687 TAxis *zaxis = fH->GetZaxis();
7688
7689 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7690 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7691 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7692 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7693 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7694 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7695
7696 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7697
7698 // Set view
7699 TView *view = gPad ? gPad->GetView() : nullptr;
7700 if (!view) {
7701 Error("PaintH3", "no TView in current pad");
7702 return;
7703 }
7704 Double_t thedeg = 90 - gPad->GetTheta();
7705 Double_t phideg = -90 - gPad->GetPhi();
7706 Double_t psideg = view->GetPsi();
7707 Int_t irep;
7708 view->SetView(phideg, thedeg, psideg, irep);
7709
7710 Int_t backcolor = gPad->GetFrameFillColor();
7711 view->PadRange(backcolor);
7712
7713 // Draw back surfaces of frame box
7714 fLego->InitMoveScreen(-1.1,1.1);
7715 if (Hoption.BackBox) {
7716 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
7718 fLego->BackBox(90);
7719 }
7720
7722
7723 // Define order of drawing
7724 Double_t *tnorm = view->GetTnorm();
7725 if (!tnorm) return;
7726 Int_t incrx = (tnorm[ 8] < 0.) ? -1 : +1;
7727 Int_t incry = (tnorm[ 9] < 0.) ? -1 : +1;
7728 Int_t incrz = (tnorm[10] < 0.) ? -1 : +1;
7729 Int_t ix1 = (incrx == +1) ? xaxis->GetFirst() : xaxis->GetLast();
7730 Int_t iy1 = (incry == +1) ? yaxis->GetFirst() : yaxis->GetLast();
7731 Int_t iz1 = (incrz == +1) ? zaxis->GetFirst() : zaxis->GetLast();
7732 Int_t ix2 = (incrx == +1) ? xaxis->GetLast() : xaxis->GetFirst();
7733 Int_t iy2 = (incry == +1) ? yaxis->GetLast() : yaxis->GetFirst();
7734 Int_t iz2 = (incrz == +1) ? zaxis->GetLast() : zaxis->GetFirst();
7735
7736 // Set graphic attributes (colour, style, etc.)
7741
7742 fH->SetFillStyle(1001);
7743 fH->TAttFill::Modify();
7744 fH->TAttLine::Modify();
7747
7748 // Create bin boxes and draw
7752
7753 Double_t pmin[3], pmax[3], sxyz[8][3];
7754 for (Int_t ix = ix1; ix !=ix2+incrx; ix += incrx) {
7755 pmin[0] = xaxis->GetBinLowEdge(ix);
7756 pmax[0] = xaxis->GetBinUpEdge(ix);
7757 for (Int_t iy = iy1; iy != iy2+incry; iy += incry) {
7758 pmin[1] = yaxis->GetBinLowEdge(iy);
7759 pmax[1] = yaxis->GetBinUpEdge(iy);
7760 for (Int_t iz = iz1; iz != iz2+incrz; iz += incrz) {
7761 pmin[2] = zaxis->GetBinLowEdge(iz);
7762 pmax[2] = zaxis->GetBinUpEdge(iz);
7763 Double_t w = fH->GetBinContent(fH->GetBin(ix,iy,iz));
7764 Bool_t neg = kFALSE;
7765 Int_t n = 5;
7766 if (w<0) {
7767 w = -w;
7768 neg = kTRUE;
7769 }
7770 if (w < wmin) continue;
7771 if (w > wmax) w = wmax;
7772 Double_t scale = (TMath::Power((w-wmin)/(wmax-wmin),1./3.))/2.;
7773 if (scale == 0) continue;
7774 for (Int_t i=0; i<3; ++i) {
7775 Double_t c = (pmax[i] + pmin[i])*0.5;
7776 Double_t d = (pmax[i] - pmin[i])*scale;
7777 for (Int_t k=0; k<8; ++k) { // set bin box vertices
7778 sxyz[k][i] = wxyz[k][i]*d + c;
7779 }
7780 }
7781 for (Int_t k=0; k<8; ++k) { // transform to normalized space
7782 view->WCtoNDC(&sxyz[k][0],&sxyz[k][0]);
7783 }
7784 Double_t x[8], y[8]; // draw bin box faces
7785 for (Int_t k=0; k<6; ++k) {
7786 for (Int_t i=0; i<4; ++i) {
7787 Int_t iv = iface[k][i];
7788 x[i] = sxyz[iv][0];
7789 y[i] = sxyz[iv][1];
7790 }
7791 x[4] = x[0] ; y[4] = y[0];
7792 if (neg) {
7793 x[5] = x[2] ; y[5] = y[2];
7794 x[6] = x[3] ; y[6] = y[3];
7795 x[7] = x[1] ; y[7] = y[1];
7796 n = 8;
7797 } else {
7798 n = 5;
7799 }
7800 Double_t z = (x[2]-x[0])*(y[3]-y[1]) - (y[2]-y[0])*(x[3]-x[1]);
7801 if (z <= 0.) continue;
7802 if (iopt == 2) {
7803 theColor = ncolors*((w-wmin)/(wmax-wmin)) -1;
7805 } else {
7806 if (k == 3 || k == 5) {
7808 } else if (k == 0 || k == 1) {
7810 } else {
7812 }
7813 }
7814 fH->TAttFill::Modify();
7815 gPad->PaintFillArea(4, x, y);
7816 if (iopt != 3)gPad->PaintPolyLine(n, x, y);
7817 }
7818 }
7819 }
7820 }
7821
7822 // Draw front surfaces of frame box
7823 if (Hoption.FrontBox) fLego->FrontBox(90);
7824
7825 // Draw axis and title
7826 if (!Hoption.Axis && !Hoption.Same) {
7827 TGaxis axis;
7828 PaintLegoAxis(&axis, 90);
7829 }
7830 PaintTitle();
7831
7832 // Draw palette. if needed.
7833 if (Hoption.Zscale) {
7834 Int_t ndiv = fH->GetContour();
7835 if (ndiv == 0 ) {
7836 ndiv = gStyle->GetNumberContours();
7837 fH->SetContour(ndiv);
7838 }
7839 PaintPalette();
7840 }
7841
7842 //Draw stats and fit results
7843 TF1 *fit = nullptr;
7844 TIter next(fFunctions);
7845 while (auto obj = next()) {
7846 if (obj->InheritsFrom(TF1::Class())) {
7847 fit = (TF1*)obj;
7848 break;
7849 }
7850 }
7851 if ((Hoption.Same%10) != 1) {
7852 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7854 }
7855 }
7856
7857 fLego.reset();
7858
7861 fH->TAttFill::Modify();
7862}
7863
7864////////////////////////////////////////////////////////////////////////////////
7865/// [Control function to draw a 3D histogram with boxes.](\ref HP25)
7866
7868{
7869 // Predefined box structure
7870 Double_t wxyz[8][3] = {
7871 {-1,-1,-1}, {1,-1,-1}, {1,1,-1}, {-1,1,-1}, // bottom vertices
7872 {-1,-1, 1}, {1,-1, 1}, {1,1, 1}, {-1,1, 1} // top vertices
7873 };
7874 Int_t iface[6][4] = {
7875 {0,3,2,1}, {4,5,6,7}, // bottom and top faces
7876 {0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7} // side faces
7877 };
7878 Double_t normal[6][3] = {
7879 {0,0,-1}, {0,0,1}, // Z-, Z+
7880 {0,-1,0}, {1,0,0}, {0,1,0}, {-1,0,0} // Y-, X+, Y+, X-
7881 };
7882
7883 // Define dimensions of world space
7884 TAxis *xaxis = fH->GetXaxis();
7885 TAxis *yaxis = fH->GetYaxis();
7886 TAxis *zaxis = fH->GetZaxis();
7887
7888 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7889 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7890 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7891 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7892 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7893 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7894
7895 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7896
7897 // Set view
7898 TView *view = gPad ? gPad->GetView() : nullptr;
7899 if (!view) {
7900 Error("PaintH3", "no TView in current pad");
7901 return;
7902 }
7903 Double_t thedeg = 90 - gPad->GetTheta();
7904 Double_t phideg = -90 - gPad->GetPhi();
7905 Double_t psideg = view->GetPsi();
7906 Int_t irep;
7907 view->SetView(phideg, thedeg, psideg, irep);
7908
7909 Int_t backcolor = gPad->GetFrameFillColor();
7910 view->PadRange(backcolor);
7911
7912 // Draw front surfaces of frame box
7913 if (Hoption.FrontBox) {
7914 fLego->InitMoveScreen(-1.1,1.1);
7916 }
7917
7918 // Initialize hidden line removal algorithm "raster screen"
7919 fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
7920
7921 // Define order of drawing
7922 Double_t *tnorm = view->GetTnorm();
7923 if (!tnorm) return;
7924 Int_t incrx = (tnorm[ 8] < 0.) ? +1 : -1;
7925 Int_t incry = (tnorm[ 9] < 0.) ? +1 : -1;
7926 Int_t incrz = (tnorm[10] < 0.) ? +1 : -1;
7927 Int_t ix1 = (incrx == +1) ? xaxis->GetFirst() : xaxis->GetLast();
7928 Int_t iy1 = (incry == +1) ? yaxis->GetFirst() : yaxis->GetLast();
7929 Int_t iz1 = (incrz == +1) ? zaxis->GetFirst() : zaxis->GetLast();
7930 Int_t ix2 = (incrx == +1) ? xaxis->GetLast() : xaxis->GetFirst();
7931 Int_t iy2 = (incry == +1) ? yaxis->GetLast() : yaxis->GetFirst();
7932 Int_t iz2 = (incrz == +1) ? zaxis->GetLast() : zaxis->GetFirst();
7933
7934 // Set line attributes (colour, style, etc.)
7935 fH->TAttLine::Modify();
7936
7937 // Create bin boxes and draw
7938 const Int_t NTMAX = 100;
7939 Double_t tt[NTMAX][2];
7943 Double_t pmin[3], pmax[3], sxyz[8][3], pp[4][2];
7944 for (Int_t ix = ix1; ix !=ix2+incrx; ix += incrx) {
7945 pmin[0] = xaxis->GetBinLowEdge(ix);
7946 pmax[0] = xaxis->GetBinUpEdge(ix);
7947 for (Int_t iy = iy1; iy != iy2+incry; iy += incry) {
7948 pmin[1] = yaxis->GetBinLowEdge(iy);
7949 pmax[1] = yaxis->GetBinUpEdge(iy);
7950 for (Int_t iz = iz1; iz != iz2+incrz; iz += incrz) {
7951 pmin[2] = zaxis->GetBinLowEdge(iz);
7952 pmax[2] = zaxis->GetBinUpEdge(iz);
7953 Double_t w = fH->GetBinContent(fH->GetBin(ix,iy,iz));
7954 Bool_t neg = kFALSE;
7955 if (w<0) {
7956 w = -w;
7957 neg = kTRUE;
7958 }
7959 if (w < wmin) continue;
7960 if (w > wmax) w = wmax;
7961 Double_t scale = (TMath::Power((w-wmin)/(wmax-wmin),1./3.))/2.;
7962 if (scale == 0) continue;
7963 for (Int_t i=0; i<3; ++i) {
7964 Double_t c = (pmax[i] + pmin[i])*0.5;
7965 Double_t d = (pmax[i] - pmin[i])*scale;
7966 for (Int_t k=0; k<8; ++k) { // set bin box vertices
7967 sxyz[k][i] = wxyz[k][i]*d + c;
7968 }
7969 }
7970 for (Int_t k=0; k<8; ++k) { // transform to normalized space
7971 view->WCtoNDC(&sxyz[k][0],&sxyz[k][0]);
7972 }
7973 for (Int_t k=0; k<6; ++k) { // draw box faces
7974 Double_t zn;
7975 view->FindNormal(normal[k][0], normal[k][1], normal[k][2], zn);
7976 if (zn <= 0) continue;
7977 for (Int_t i=0; i<4; ++i) {
7978 Int_t ip = iface[k][i];
7979 pp[i][0] = sxyz[ip][0];
7980 pp[i][1] = sxyz[ip][1];
7981 }
7982 for (Int_t i=0; i<4; ++i) {
7983 Int_t i1 = i;
7984 Int_t i2 = (i == 3) ? 0 : i + 1;
7985 Int_t nt;
7986 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7987 Double_t xdel = pp[i2][0] - pp[i1][0];
7988 Double_t ydel = pp[i2][1] - pp[i1][1];
7989 Double_t x[2], y[2];
7990 for (Int_t it = 0; it < nt; ++it) {
7991 x[0] = pp[i1][0] + xdel*tt[it][0];
7992 y[0] = pp[i1][1] + ydel*tt[it][0];
7993 x[1] = pp[i1][0] + xdel*tt[it][1];
7994 y[1] = pp[i1][1] + ydel*tt[it][1];
7995 gPad->PaintPolyLine(2, x, y);
7996 }
7997 }
7998 if (neg) {
7999 Int_t i1 = 0;
8000 Int_t i2 = 2;
8001 Int_t nt;
8002 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
8003 Double_t xdel = pp[i2][0] - pp[i1][0];
8004 Double_t ydel = pp[i2][1] - pp[i1][1];
8005 Double_t x[2], y[2];
8006 for (Int_t it = 0; it < nt; ++it) {
8007 x[0] = pp[i1][0] + xdel*tt[it][0];
8008 y[0] = pp[i1][1] + ydel*tt[it][0];
8009 x[1] = pp[i1][0] + xdel*tt[it][1];
8010 y[1] = pp[i1][1] + ydel*tt[it][1];
8011 gPad->PaintPolyLine(2, x, y);
8012 }
8013 i1 = 1;
8014 i2 = 3;
8015 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
8016 xdel = pp[i2][0] - pp[i1][0];
8017 ydel = pp[i2][1] - pp[i1][1];
8018 for (Int_t it = 0; it < nt; ++it) {
8019 x[0] = pp[i1][0] + xdel*tt[it][0];
8020 y[0] = pp[i1][1] + ydel*tt[it][0];
8021 x[1] = pp[i1][0] + xdel*tt[it][1];
8022 y[1] = pp[i1][1] + ydel*tt[it][1];
8023 gPad->PaintPolyLine(2, x, y);
8024 }
8025 }
8026 fLego->FillPolygonBorder(4, &pp[0][0]); // update raster screen
8027 }
8028 }
8029 }
8030 }
8031
8032 // Draw frame box
8033 if (Hoption.BackBox) {
8034 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
8036 fLego->BackBox(90);
8037 }
8038
8039 if (Hoption.FrontBox) fLego->FrontBox(90);
8040
8041 // Draw axis and title
8042 if (!Hoption.Axis && !Hoption.Same) {
8043 TGaxis axis;
8044 PaintLegoAxis(&axis, 90);
8045 }
8046 PaintTitle();
8047
8048 //Draw stats and fit results
8049 TF1 *fit = nullptr;
8050 TIter next(fFunctions);
8051 while (auto obj = next()) {
8052 if (obj->InheritsFrom(TF1::Class())) {
8053 fit = (TF1*)obj;
8054 break;
8055 }
8056 }
8057 if ((Hoption.Same%10) != 1) {
8058 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
8060 }
8061 }
8062
8063 fLego.reset();
8064}
8065
8066////////////////////////////////////////////////////////////////////////////////
8067/// [Control function to draw a 3D histogram with Iso Surfaces.](\ref HP25)
8068
8070{
8071
8072 const Double_t ydiff = 1;
8073 const Double_t yligh1 = 10;
8074 const Double_t qa = 0.15;
8075 const Double_t qd = 0.15;
8076 const Double_t qs = 0.8;
8078 Int_t i, irep;
8079 Int_t nbcol = 28;
8080 Int_t icol1 = 201;
8081 Int_t ic1 = icol1;
8082 Int_t ic2 = ic1+nbcol;
8083 Int_t ic3 = ic2+nbcol;
8084
8085 TAxis *xaxis = fH->GetXaxis();
8086 TAxis *yaxis = fH->GetYaxis();
8087 TAxis *zaxis = fH->GetZaxis();
8088
8089 Int_t nx = fH->GetNbinsX();
8090 Int_t ny = fH->GetNbinsY();
8091 Int_t nz = fH->GetNbinsZ();
8092
8093 std::vector<Double_t> x(nx);
8094 std::vector<Double_t> y(ny);
8095 std::vector<Double_t> z(nz);
8096
8097 for (i=0; i<nx; i++) x[i] = xaxis->GetBinCenter(i+1);
8098 for (i=0; i<ny; i++) y[i] = yaxis->GetBinCenter(i+1);
8099 for (i=0; i<nz; i++) z[i] = zaxis->GetBinCenter(i+1);
8100
8101 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
8102 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
8103 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
8104 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
8105 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
8106 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
8107
8108 Double_t s[3];
8109 s[0] = fH->GetSumOfWeights()/(fH->GetNbinsX()*fH->GetNbinsY()*fH->GetNbinsZ());
8110 s[1] = 0.5*s[0];
8111 s[2] = 1.5*s[0];
8112
8113 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
8114
8115 TView *view = gPad ? gPad->GetView() : nullptr;
8116 if (!view) {
8117 Error("PaintH3Iso", "no TView in current pad");
8118 return;
8119 }
8120 Double_t thedeg = 90 - gPad->GetTheta();
8121 Double_t phideg = -90 - gPad->GetPhi();
8122 Double_t psideg = view->GetPsi();
8123 view->SetView(phideg, thedeg, psideg, irep);
8124
8125 Int_t backcolor = gPad->GetFrameFillColor();
8126 if (Hoption.System != kCARTESIAN) backcolor = 0;
8127 view->PadRange(backcolor);
8128
8129 Double_t dcol = 0.5/Double_t(nbcol);
8130 TColor *colref = gROOT->GetColor(fH->GetFillColor());
8131 if (!colref) {
8132 return;
8133 }
8134 Float_t r, g, b, hue, light, satur;
8135 colref->GetRGB(r,g,b);
8137 TColor *acol;
8138 for (Int_t col=0;col<nbcol;col++) {
8139 acol = gROOT->GetColor(col+icol1);
8140 TColor::HLStoRGB(hue, .4+col*dcol, satur, r, g, b);
8141 if (acol) acol->SetRGB(r, g, b);
8142 }
8143
8144 fLego->InitMoveScreen(-1.1,1.1);
8145
8146 if (Hoption.BackBox) {
8147 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
8149 fLego->BackBox(90);
8150 }
8151
8152 fLego->LightSource(0, ydiff, 0, 0, 0, irep);
8153 fLego->LightSource(1, yligh1, 1, 1, 1, irep);
8154 fLego->SurfaceProperty(qa, qd, qs, 1, irep);
8155 fmin = ydiff*qa;
8156 fmax = ydiff*qa + (yligh1+0.1)*(qd+qs);
8157 fLego->SetIsoSurfaceParameters(fmin, fmax, nbcol, ic1, ic2, ic3);
8158
8159 fLego->IsoSurface(1, s, nx, ny, nz, x.data(), y.data(), z.data(), "BF");
8160
8161 if (Hoption.FrontBox) {
8162 fLego->InitMoveScreen(-1.1,1.1);
8164 fLego->FrontBox(90);
8165 }
8166 if (!Hoption.Axis && !Hoption.Same) {
8167 TGaxis axis;
8168 PaintLegoAxis(&axis, 90);
8169 }
8170
8171 PaintTitle();
8172
8173 //Draw stats and fit results
8174 TF1 *fit = nullptr;
8175 TIter next(fFunctions);
8176 while (auto obj = next()) {
8177 if (obj->InheritsFrom(TF1::Class())) {
8178 fit = (TF1*)obj;
8179 break;
8180 }
8181 }
8182 if ((Hoption.Same%10) != 1) {
8183 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
8185 }
8186 }
8187
8188 fLego.reset();
8189}
8190
8191////////////////////////////////////////////////////////////////////////////////
8192/// [Control function to draw a 2D histogram as a lego plot.](\ref HP17)
8193
8195{
8196
8197 Int_t raster = 1;
8198 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
8199 Int_t nx = Hparam.xlast - Hparam.xfirst + 1;
8200 Int_t ny = Hparam.ylast - Hparam.yfirst + 1;
8201 Double_t zmin = Hparam.zmin;
8202 Double_t zmax = Hparam.zmax;
8207 Double_t dangle = 10*3.141592/180; //Delta angle for Rapidity option
8208 Double_t deltaz = TMath::Abs(zmin);
8209 if (deltaz == 0) deltaz = 1;
8210 if (zmin >= zmax) {
8211 zmin -= 0.5*deltaz;
8212 zmax += 0.5*deltaz;
8213 }
8214 Double_t z1c = zmin;
8215 Double_t z2c = zmin + (zmax-zmin)*(1+gStyle->GetHistTopMargin());
8216
8217 // Compute the lego limits and instantiate a lego object
8218 fXbuf[0] = -1;
8219 fYbuf[0] = 1;
8220 fXbuf[1] = -1;
8221 fYbuf[1] = 1;
8222 if (Hoption.System == kPOLAR) {
8223 fXbuf[2] = z1c;
8224 fYbuf[2] = z2c;
8225 } else if (Hoption.System == kCYLINDRICAL) {
8226 if (Hoption.Logy) {
8227 if (ylab1 > 0) fXbuf[2] = TMath::Log10(ylab1);
8228 else fXbuf[2] = 0;
8229 if (ylab2 > 0) fYbuf[2] = TMath::Log10(ylab2);
8230 else fYbuf[2] = 0;
8231 } else {
8232 fXbuf[2] = ylab1;
8233 fYbuf[2] = ylab2;
8234 }
8235 z1c = 0; z2c = 1;
8236 } else if (Hoption.System == kSPHERICAL) {
8237 fXbuf[2] = -1;
8238 fYbuf[2] = 1;
8239 z1c = 0; z2c = 1;
8240 } else if (Hoption.System == kRAPIDITY) {
8241 fXbuf[2] = -1/TMath::Tan(dangle);
8242 fYbuf[2] = 1/TMath::Tan(dangle);
8243 } else {
8244 fXbuf[0] = xlab1;
8245 fYbuf[0] = xlab2;
8246 fXbuf[1] = ylab1;
8247 fYbuf[1] = ylab2;
8248 fXbuf[2] = z1c;
8249 fYbuf[2] = z2c;
8250 raster = 0;
8251 }
8252
8253 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data(), Hoption.System);
8254
8255 Int_t nids = -1;
8256 TH1 * hid = nullptr;
8257 Color_t colormain = -1, colordark = -1;
8259
8260 // LEGO3 is like LEGO1 except that the black lines around each lego are not drawn.
8261 if (Hoption.Lego == 13) {
8262 Hoption.Lego = 11;
8263 fLego->SetMesh(0);
8264 }
8265 // LEGO4 is like LEGO1 except no shadows are drawn.
8266 if (Hoption.Lego == 14) {
8267 Hoption.Lego = 11;
8269 }
8270
8271 // Initialize the levels on the Z axis
8272 Int_t ndiv = fH->GetContour();
8273 if (ndiv == 0 ) {
8274 ndiv = gStyle->GetNumberContours();
8275 fH->SetContour(ndiv);
8276 }
8277 Int_t ndivz = TMath::Abs(ndiv);
8278 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
8279
8280 // Initialize colors
8281 if (!fStack) {
8282 fLego->SetEdgeAtt(fH->GetLineColor(),fH->GetLineStyle(),fH->GetLineWidth(),0);
8283 } else {
8284 for (Int_t id=0;id<=fStack->GetSize();id++) {
8285 hid = (TH1*)fStack->At((id==0)?id:id-1);
8286 fLego->SetEdgeAtt(hid->GetLineColor(),hid->GetLineStyle(),hid->GetLineWidth(),id);
8287 }
8288 }
8289
8290 if (Hoption.Lego == 11) {
8291 nids = 1;
8292 if (fStack) nids = fStack->GetSize();
8293 hid = fH;
8294 for (Int_t id=0;id<=nids;id++) {
8295 if (id > 0 && fStack) hid = (TH1*)fStack->At(id-1);
8296 colormain = hid->GetFillColor();
8297 if (colormain == 1) colormain = 17; //avoid drawing with black
8299 else colordark = colormain;
8300 fLego->SetColorMain(colormain,id);
8301 fLego->SetColorDark(colordark,id);
8302 if (id <= 1) fLego->SetColorMain(colormain,-1); // Set Bottom color
8303 if (id == nids) fLego->SetColorMain(colormain,99); // Set Top color
8304 }
8305 }
8306
8307 // Now ready to draw the lego plot
8308 Int_t irep = 0;
8309
8310 TView *view = gPad ? gPad->GetView() : nullptr;
8311 if (!view) {
8312 Error("PaintLego", "no TView in current pad");
8313 return;
8314 }
8315
8316 Double_t thedeg = 90 - gPad->GetTheta();
8317 Double_t phideg = -90 - gPad->GetPhi();
8318 Double_t psideg = view->GetPsi();
8319 view->SetView(phideg, thedeg, psideg, irep);
8320
8321 fLego->SetLineColor(kBlack); // zgrid color for lego1 & lego2
8322 fLego->SetFillStyle(fH->GetFillStyle());
8323
8324 // Set color/style for back box
8325 fLego->SetFillStyle(gPad->GetFrameFillStyle());
8326 fLego->SetFillColor(gPad->GetFrameFillColor());
8327 fLego->TAttFill::Modify();
8328
8329 Int_t backcolor = gPad->GetFrameFillColor();
8330 if (Hoption.System != kCARTESIAN) backcolor = 0;
8331 view->PadRange(backcolor);
8332
8333 fLego->SetFillStyle(fH->GetFillStyle());
8334 fLego->SetFillColor(fH->GetFillColor());
8335 fLego->TAttFill::Modify();
8336
8337 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
8338
8339 if (raster) fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
8340 else fLego->InitMoveScreen(-1.1,1.1);
8341
8342 if (Hoption.Lego == 19) {
8344 if (Hoption.BackBox) fLego->BackBox(90);
8345 if (Hoption.FrontBox) fLego->FrontBox(90);
8346 if (!Hoption.Axis) { TGaxis axis; PaintLegoAxis(&axis, 90); }
8347 return;
8348 }
8349
8350 if (Hoption.Lego == 11 || Hoption.Lego == 12) {
8353 fLego->BackBox(90);
8354 }
8355 }
8356
8357 if (Hoption.Lego == 12) DefineColorLevels(ndivz);
8358
8359 fLego->SetLegoFunction(&TPainter3dAlgorithms::LegoFunction);
8361 if (Hoption.Lego == 11) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode3);
8362 if (Hoption.Lego == 12) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode2);
8363 if (Hoption.System == kPOLAR) {
8364 if (Hoption.Lego == 1) fLego->LegoPolar(1,nx,ny,"FB");
8365 if (Hoption.Lego == 11) fLego->LegoPolar(1,nx,ny,"BF");
8366 if (Hoption.Lego == 12) fLego->LegoPolar(1,nx,ny,"BF");
8367 } else if (Hoption.System == kCYLINDRICAL) {
8368 if (Hoption.Lego == 1) fLego->LegoCylindrical(1,nx,ny,"FB");
8369 if (Hoption.Lego == 11) fLego->LegoCylindrical(1,nx,ny,"BF");
8370 if (Hoption.Lego == 12) fLego->LegoCylindrical(1,nx,ny,"BF");
8371 } else if (Hoption.System == kSPHERICAL) {
8372 if (Hoption.Lego == 1) fLego->LegoSpherical(0,1,nx,ny,"FB");
8373 if (Hoption.Lego == 11) fLego->LegoSpherical(0,1,nx,ny,"BF");
8374 if (Hoption.Lego == 12) fLego->LegoSpherical(0,1,nx,ny,"BF");
8375 } else if (Hoption.System == kRAPIDITY) {
8376 if (Hoption.Lego == 1) fLego->LegoSpherical(1,1,nx,ny,"FB");
8377 if (Hoption.Lego == 11) fLego->LegoSpherical(1,1,nx,ny,"BF");
8378 if (Hoption.Lego == 12) fLego->LegoSpherical(1,1,nx,ny,"BF");
8379 } else {
8380 if (Hoption.Lego == 1) {
8382 fLego->LegoCartesian(90,nx,ny,"FB");}
8383 if (Hoption.Lego == 11) fLego->LegoCartesian(90,nx,ny,"BF");
8384 if (Hoption.Lego == 12) fLego->LegoCartesian(90,nx,ny,"BF");
8385 }
8386
8387 if (Hoption.Lego == 1 || Hoption.Lego == 11) {
8390 fLego->BackBox(90);
8391 }
8392 }
8393 if (Hoption.System == kCARTESIAN) {
8394 fLego->InitMoveScreen(-1.1,1.1);
8396 if (Hoption.FrontBox) fLego->FrontBox(90);
8397 }
8398 if (!Hoption.Axis && !Hoption.Same) {
8399 TGaxis axis;
8400 PaintLegoAxis(&axis, 90);
8401 }
8403 fLego.reset();
8404}
8405
8406////////////////////////////////////////////////////////////////////////////////
8407/// Draw the axis for legos and surface plots.
8408
8410{
8411
8412 static Double_t epsil = 0.001;
8413
8416 Double_t r[24] /* was [3][8] */;
8417 Int_t ndivx, ndivy, ndivz, i;
8418 Double_t x1[3], x2[3], y1[3], y2[3], z1[3], z2[3], av[24] /* was [3][8] */;
8419 static char chopax[8], chopay[8], chopaz[8];
8420 Int_t ix1, ix2, iy1, iy2, iz1, iz2;
8421 Double_t rad;
8422
8423 TView *view = gPad ? gPad->GetView() : nullptr;
8424 if (!view) {
8425 Error("PaintLegoAxis", "no TView in current pad");
8426 return;
8427 }
8428
8429 // In polar coordinates, draw a short line going from the external circle
8430 // corresponding to r = 1 up to r = 1.1
8431 if (Hoption.System == kPOLAR) {
8432 r[0] = 1;
8433 r[1] = 0;
8434 r[2] = 0;
8435 view->WCtoNDC(r, x1);
8436 r[0] = 1.1;
8437 r[1] = 0;
8438 r[2] = 0;
8439 view->WCtoNDC(r, x2);
8440 gPad->PaintLine(x1[0],x1[1],x2[0],x2[1]);
8441 return;
8442 }
8443
8444 if (Hoption.System != kCARTESIAN) return;
8445
8446 rad = TMath::ATan(1.) * 4. /180.;
8447 cosa = TMath::Cos(ang*rad);
8448 sina = TMath::Sin(ang*rad);
8449
8450 view->AxisVertex(ang, av, ix1, ix2, iy1, iy2, iz1, iz2);
8451 for (i = 1; i <= 8; ++i) {
8452 r[i*3 - 3] = av[i*3 - 3] + av[i*3 - 2]*cosa;
8453 r[i*3 - 2] = av[i*3 - 2]*sina;
8454 r[i*3 - 1] = av[i*3 - 1];
8455 }
8456
8457 view->WCtoNDC(&r[ix1*3 - 3], x1);
8458 view->WCtoNDC(&r[ix2*3 - 3], x2);
8459 view->WCtoNDC(&r[iy1*3 - 3], y1);
8460 view->WCtoNDC(&r[iy2*3 - 3], y2);
8461 view->WCtoNDC(&r[iz1*3 - 3], z1);
8462 view->WCtoNDC(&r[iz2*3 - 3], z2);
8463
8464 view->SetAxisNDC(x1, x2, y1, y2, z1, z2);
8465
8466 Double_t *rmin = view->GetRmin();
8467 Double_t *rmax = view->GetRmax();
8468 if (!rmin || !rmax) return;
8469
8470 // Initialize the axis options
8471 if (x1[0] > x2[0]) strlcpy(chopax, "SDH=+",8);
8472 else strlcpy(chopax, "SDH=-",8);
8473 if (y1[0] > y2[0]) strlcpy(chopay, "SDH=+",8);
8474 else strlcpy(chopay, "SDH=-",8);
8475 if (z2[1] > z1[1]) strlcpy(chopaz, "SDH=+",8);
8476 else strlcpy(chopaz, "SDH=-",8);
8477
8478 // Option LOG is required ?
8479 if (Hoption.Logx) strlcat(chopax,"G",8);
8480 if (Hoption.Logy) strlcat(chopay,"G",8);
8481 if (Hoption.Logz) strlcat(chopaz,"G",8);
8482
8483 // Initialize the number of divisions. If the
8484 // number of divisions is negative, option 'N' is required.
8488 if (ndivx < 0) {
8490 strlcat(chopax, "N",8);
8491 }
8492 if (ndivy < 0) {
8494 strlcat(chopay, "N",8);
8495 }
8496 if (ndivz < 0) {
8498 strlcat(chopaz, "N",8);
8499 }
8500
8501 // Set Axis attributes.
8502 // The variable SCALE rescales the VSIZ
8503 // in order to have the same label size for all angles.
8504
8505 axis->SetLineWidth(1);
8506
8507 // X axis drawing
8508 if (TMath::Abs(x1[0] - x2[0]) >= epsil || TMath::Abs(x1[1] - x2[1]) > epsil) {
8511 if (Hoption.Logx && !fH->InheritsFrom(TH3::Class())) {
8512 bmin = TMath::Power(10, rmin[0]);
8513 bmax = TMath::Power(10, rmax[0]);
8514 } else {
8515 bmin = rmin[0];
8516 bmax = rmax[0];
8517 }
8518 // Option time display is required ?
8519 if (fXaxis->GetTimeDisplay()) {
8520 strlcat(chopax,"t",8);
8521 if (strlen(fXaxis->GetTimeFormatOnly()) == 0) {
8523 } else {
8525 }
8526 }
8527 axis->SetOption(chopax);
8528 axis->PaintAxis(x1[0], x1[1], x2[0], x2[1], bmin, bmax, ndivx, chopax);
8529 }
8530
8531 // Y axis drawing
8532 if (TMath::Abs(y1[0] - y2[0]) >= epsil || TMath::Abs(y1[1] - y2[1]) > epsil) {
8535 if (fYaxis->GetTitleOffset() == 0) axis->SetTitleOffset(1.5);
8536
8537 if (fH->GetDimension() < 2) {
8538 strlcpy(chopay, "V=+UN",8);
8539 ndivy = 0;
8540 }
8541 if (TMath::Abs(y1[0] - y2[0]) < epsil) {
8542 y2[0] = y1[0];
8543 }
8544 if (Hoption.Logy && !fH->InheritsFrom(TH3::Class())) {
8545 bmin = TMath::Power(10, rmin[1]);
8546 bmax = TMath::Power(10, rmax[1]);
8547 } else {
8548 bmin = rmin[1];
8549 bmax = rmax[1];
8550 }
8551 // Option time display is required ?
8552 if (fYaxis->GetTimeDisplay()) {
8553 strlcat(chopay,"t",8);
8554 if (strlen(fYaxis->GetTimeFormatOnly()) == 0) {
8556 } else {
8558 }
8559 }
8560 axis->SetOption(chopay);
8561 axis->PaintAxis(y1[0], y1[1], y2[0], y2[1], bmin, bmax, ndivy, chopay);
8562 }
8563
8564 // Z axis drawing
8565 if (TMath::Abs(z1[0] - z2[0]) >= 100*epsil || TMath::Abs(z1[1] - z2[1]) > 100*epsil) {
8567 if (Hoption.Logz && !fH->InheritsFrom(TH3::Class())) {
8568 bmin = TMath::Power(10, rmin[2]);
8569 bmax = TMath::Power(10, rmax[2]);
8570 } else {
8571 bmin = rmin[2];
8572 bmax = rmax[2];
8573 }
8574 // Option time display is required ?
8575 if (fZaxis->GetTimeDisplay()) {
8576 strlcat(chopaz,"t",8);
8577 if (strlen(fZaxis->GetTimeFormatOnly()) == 0) {
8579 } else {
8581 }
8582 }
8583 axis->SetOption(chopaz);
8585 if (ztit.Index(";")>0) {
8586 ztit.Remove(ztit.Index(";"),ztit.Length());
8587 axis->SetTitle(ztit.Data());
8588 }
8589 axis->PaintAxis(z1[0], z1[1], z2[0], z2[1], bmin, bmax, ndivz, chopaz);
8590 }
8591
8592 //fH->SetLineStyle(1); /// otherwise fEdgeStyle[i] gets overwritten!
8593}
8594
8595////////////////////////////////////////////////////////////////////////////////
8596/// [Paint the color palette on the right side of the pad.](\ref HP22)
8597
8599{
8601 TView *view = gPad ? gPad->GetView() : nullptr;
8602 if (palette) {
8603 if (view) {
8604 if (!palette->TestBit(TPaletteAxis::kHasView)) {
8606 delete palette; palette = nullptr;
8607 }
8608 } else {
8609 if (palette->TestBit(TPaletteAxis::kHasView)) {
8611 delete palette; palette = nullptr;
8612 }
8613 }
8614 // make sure the histogram member of the palette is setup correctly. It may not be after a Clone()
8615 if (palette && !palette->GetHistogram()) palette->SetHistogram(fH);
8616 }
8617
8618 if (!palette) {
8619 Double_t xup = gPad->GetUxmax();
8620 Double_t x2 = gPad->PadtoX(gPad->GetX2());
8621 Double_t ymin = gPad->PadtoY(gPad->GetUymin());
8622 Double_t ymax = gPad->PadtoY(gPad->GetUymax());
8623 Double_t xr = 0.05*(gPad->GetX2() - gPad->GetX1());
8624 Double_t xmin = gPad->PadtoX(xup +0.1*xr);
8625 Double_t xmax = gPad->PadtoX(xup + xr);
8626 if (xmax > x2) xmax = gPad->PadtoX(gPad->GetX2()-0.01*xr);
8629 palette->Paint();
8630 }
8631}
8632
8633////////////////////////////////////////////////////////////////////////////////
8634/// [Control function to draw a 2D histogram as a scatter plot.](\ref HP11)
8635
8637{
8638
8639 fH->TAttMarker::Modify();
8640
8641 Int_t k, marker;
8642 Double_t dz, z, xk,xstep, yk, ystep;
8643 Double_t scale = 1;
8645 Double_t zmax = fH->GetMaximum();
8646 Double_t zmin = fH->GetMinimum();
8647 if (zmin == 0 && zmax == 0) return;
8648 if (zmin == zmax) {
8649 zmax += 0.1*TMath::Abs(zmax);
8650 zmin -= 0.1*TMath::Abs(zmin);
8651 }
8653 if (Hoption.Logz) {
8654 if (zmin > 0) zmin = TMath::Log10(zmin);
8655 else zmin = 0;
8656 if (zmax > 0) zmax = TMath::Log10(zmax);
8657 else zmax = 0;
8658 if (zmin == 0 && zmax == 0) return;
8659 dz = zmax - zmin;
8660 scale = 100/dz;
8661 if (ncells > 10000) scale /= 5;
8662 ltest = kTRUE;
8663 } else {
8664 dz = zmax - zmin;
8665 if (dz >= kNMAX || zmax < 1) {
8666 scale = (kNMAX-1)/dz;
8667 if (ncells > 10000) scale /= 5;
8668 ltest = kTRUE;
8669 }
8670 }
8671 if (fH->GetMinimumStored() == -1111) {
8673 if (Hoption.MinimumZero) {
8674 if (zmin >= 0) zmin = 0;
8675 else zmin -= yMARGIN*(zmax-zmin);
8676 } else {
8677 Double_t dzmin = yMARGIN*(zmax-zmin);
8678 if (zmin >= 0 && (zmin-dzmin <= 0)) zmin = 0;
8679 else zmin -= dzmin;
8680 }
8681 }
8682
8683 TString opt = option;
8684 opt.ToLower();
8685 if (opt.Contains("scat=")) {
8686 char optscat[100];
8687 strlcpy(optscat,opt.Data(),100);
8688 char *oscat = strstr(optscat,"scat=");
8689 char *blank = strstr(oscat," "); if (blank) *blank = 0;
8690 sscanf(oscat+5,"%lg",&scale);
8691 }
8692 // use an independent instance of a random generator
8693 // instead of gRandom to avoid conflicts and
8694 // to get same random numbers when drawing the same histogram
8696 marker=0;
8697 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
8700 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
8701 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
8702 xk = fXaxis->GetBinLowEdge(i);
8703 xstep = fXaxis->GetBinWidth(i);
8704 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
8705 z = fH->GetBinContent(bin);
8706 if (z < zmin) z = zmin;
8707 if (z > zmax) z = zmax;
8708 if (Hoption.Logz) {
8709 if (z > 0) z = TMath::Log10(z) - zmin;
8710 } else {
8711 z -= zmin;
8712 }
8713 if (z <= 0) continue;
8714 k = Int_t(z*scale);
8715 if (ltest) k++;
8716 if (k > 0) {
8717 for (Int_t loop=0; loop<k; loop++) {
8718 if (k+marker >= kNMAX) {
8719 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
8720 marker=0;
8721 }
8722 fXbuf[marker] = (random.Rndm()*xstep) + xk;
8723 fYbuf[marker] = (random.Rndm()*ystep) + yk;
8724 if (Hoption.Logx) {
8725 if (fXbuf[marker] > 0) fXbuf[marker] = TMath::Log10(fXbuf[marker]);
8726 else break;
8727 }
8728 if (Hoption.Logy) {
8729 if (fYbuf[marker] > 0) fYbuf[marker] = TMath::Log10(fYbuf[marker]);
8730 else break;
8731 }
8732 if (fXbuf[marker] < gPad->GetUxmin()) break;
8733 if (fYbuf[marker] < gPad->GetUymin()) break;
8734 if (fXbuf[marker] > gPad->GetUxmax()) break;
8735 if (fYbuf[marker] > gPad->GetUymax()) break;
8736 marker++;
8737 }
8738 }
8739 }
8740 }
8741 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
8742
8744}
8745
8746////////////////////////////////////////////////////////////////////////////////
8747/// Static function to paint special objects like vectors and matrices.
8748/// This function is called via `gROOT->ProcessLine` to paint these objects
8749/// without having a direct dependency of the graphics or histogramming
8750/// system.
8751
8753{
8754
8755 if (!obj) return;
8756 TDirectory::TContext ctx{nullptr}; // No self-registration to directories
8757
8758 if (obj->InheritsFrom(TMatrixFBase::Class())) {
8759 // case TMatrixF
8760 TH2F *R__TMatrixFBase = new TH2F((TMatrixFBase &)*obj);
8761 R__TMatrixFBase->SetBit(kCanDelete);
8762 R__TMatrixFBase->Draw(option);
8763
8764 } else if (obj->InheritsFrom(TMatrixDBase::Class())) {
8765 // case TMatrixD
8766 TH2D *R__TMatrixDBase = new TH2D((TMatrixDBase &)*obj);
8767 R__TMatrixDBase->SetBit(kCanDelete);
8768 R__TMatrixDBase->Draw(option);
8769
8770 } else if (obj->InheritsFrom(TVectorF::Class())) {
8771 //case TVectorF
8772 TH1F *R__TVectorF = new TH1F((TVectorF &)*obj);
8773 R__TVectorF->SetBit(kCanDelete);
8774 R__TVectorF->Draw(option);
8775
8776 } else if (obj->InheritsFrom(TVectorD::Class())) {
8777 //case TVectorD
8778 TH1D *R__TVectorD = new TH1D((TVectorD &)*obj);
8779 R__TVectorD->SetBit(kCanDelete);
8780 R__TVectorD->Draw(option);
8781 }
8782}
8783
8784////////////////////////////////////////////////////////////////////////////////
8785/// [Draw the statistics box for 1D and profile histograms.](\ref HP07)
8786
8788{
8789 TString tt, tf;
8790 Int_t dofit;
8791 TPaveStats *stats = nullptr;
8792 TIter next(fFunctions);
8793 while (auto obj = next()) {
8794 if (obj->InheritsFrom(TPaveStats::Class())) {
8795 stats = (TPaveStats*)obj;
8796 break;
8797 }
8798 }
8799
8800 if (stats && dostat) {
8801 dofit = stats->GetOptFit();
8802 dostat = stats->GetOptStat();
8803 } else {
8804 dofit = gStyle->GetOptFit();
8805 }
8806 if (!dofit) fit = nullptr;
8807 if (dofit == 1) dofit = 111;
8808 if (dostat == 1) dostat = 1111;
8809 Int_t print_name = dostat%10;
8810 Int_t print_entries = (dostat/10)%10;
8811 Int_t print_mean = (dostat/100)%10;
8812 Int_t print_stddev = (dostat/1000)%10;
8813 Int_t print_under = (dostat/10000)%10;
8814 Int_t print_over = (dostat/100000)%10;
8815 Int_t print_integral= (dostat/1000000)%10;
8816 Int_t print_skew = (dostat/10000000)%10;
8817 Int_t print_kurt = (dostat/100000000)%10;
8821 Int_t print_fval = dofit%10;
8822 Int_t print_ferrors = (dofit/10)%10;
8823 Int_t print_fchi2 = (dofit/100)%10;
8824 Int_t print_fprob = (dofit/1000)%10;
8826 if (fit) {
8827 if (print_fval < 2) nlinesf += fit->GetNumberFreeParameters();
8828 else nlinesf += fit->GetNpar();
8829 }
8831
8832 // Pavetext with statistics
8833 Bool_t done = kFALSE;
8834 if (!dostat && !fit) {
8835 if (stats) { fFunctions->Remove(stats); delete stats;}
8836 return;
8837 }
8839 if (fit) statw = 1.8*gStyle->GetStatW();
8841 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
8842 stath = 0.25*(nlines+nlinesf)*gStyle->GetStatH();
8843 }
8844 if (stats) {
8845 stats->Clear();
8846 done = kTRUE;
8847 } else {
8848 stats = new TPaveStats(
8851 gStyle->GetStatX(),
8852 gStyle->GetStatY(),"brNDC");
8853
8854 stats->SetParent(fH);
8855 stats->SetOptFit(dofit);
8856 stats->SetOptStat(dostat);
8857 stats->SetFillColor(gStyle->GetStatColor());
8858 stats->SetFillStyle(gStyle->GetStatStyle());
8860 stats->SetTextFont(gStyle->GetStatFont());
8861 if (gStyle->GetStatFont()%10 > 2)
8863 stats->SetFitFormat(gStyle->GetFitFormat());
8865 stats->SetName("stats");
8866
8868 stats->SetTextAlign(12);
8869 stats->SetBit(kCanDelete);
8870 stats->SetBit(kMustCleanup);
8871 }
8872 if (print_name) stats->AddText(fH->GetName());
8873 if (print_entries) {
8874 if (fH->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(fH->GetEntries()+0.5));
8875 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(fH->GetEntries()));
8876 stats->AddText(tt.Data());
8877 }
8878 if (print_mean) {
8879 if (print_mean == 1) {
8880 tf.Form("%s = %s%s",gStringMean.Data(),"%",stats->GetStatFormat());
8881 tt.Form(tf.Data(),fH->GetMean(1));
8882 } else {
8883 tf.Form("%s = %s%s #pm %s%s",gStringMean.Data(),"%",stats->GetStatFormat()
8884 ,"%",stats->GetStatFormat());
8885 tt.Form(tf.Data(),fH->GetMean(1),fH->GetMeanError(1));
8886 }
8887 stats->AddText(tt.Data());
8889 if (print_mean == 1) {
8890 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
8891 tt.Form(tf.Data(),fH->GetMean(2));
8892 } else {
8893 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
8894 ,"%",stats->GetStatFormat());
8895 tt.Form(tf.Data(),fH->GetMean(2),fH->GetMeanError(2));
8896 }
8897 stats->AddText(tt.Data());
8898 }
8899 }
8900 if (print_stddev) {
8901 if (print_stddev == 1) {
8902 tf.Form("%s = %s%s",gStringStdDev.Data(),"%",stats->GetStatFormat());
8903 tt.Form(tf.Data(),fH->GetStdDev(1));
8904 } else {
8905 tf.Form("%s = %s%s #pm %s%s",gStringStdDev.Data(),"%",stats->GetStatFormat()
8906 ,"%",stats->GetStatFormat());
8907 tt.Form(tf.Data(),fH->GetStdDev(1),fH->GetStdDevError(1));
8908 }
8909 stats->AddText(tt.Data());
8911 if (print_stddev == 1) {
8912 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
8913 tt.Form(tf.Data(),fH->GetStdDev(2));
8914 } else {
8915 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
8916 ,"%",stats->GetStatFormat());
8917 tt.Form(tf.Data(),fH->GetStdDev(2),fH->GetStdDevError(2));
8918 }
8919 stats->AddText(tt.Data());
8920 }
8921 }
8922 if (print_under) {
8923 tf.Form("%s = %s%s",gStringUnderflow.Data(),"%",stats->GetStatFormat());
8924 tt.Form(tf.Data(),fH->GetBinContent(0));
8925 stats->AddText(tt.Data());
8926 }
8927 if (print_over) {
8928 tf.Form("%s = %s%s",gStringOverflow.Data(),"%",stats->GetStatFormat());
8929 tt.Form(tf.Data(),fH->GetBinContent(fXaxis->GetNbins()+1));
8930 stats->AddText(tt.Data());
8931 }
8932 if (print_integral) {
8933 if (print_integral == 1) {
8934 tf.Form("%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
8935 tt.Form(tf.Data(),fH->Integral());
8936 } else {
8937 tf.Form("%s = %s%s",gStringIntegralBinWidth.Data(),"%",stats->GetStatFormat());
8938 tt.Form(tf.Data(),fH->Integral("width"));
8939 }
8940 stats->AddText(tt.Data());
8941 }
8942 if (print_skew) {
8943 if (print_skew == 1) {
8944 tf.Form("%s = %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat());
8945 tt.Form(tf.Data(),fH->GetSkewness(1));
8946 } else {
8947 tf.Form("%s = %s%s #pm %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat()
8948 ,"%",stats->GetStatFormat());
8949 tt.Form(tf.Data(),fH->GetSkewness(1),fH->GetSkewness(11));
8950 }
8951 stats->AddText(tt.Data());
8952 }
8953 if (print_kurt) {
8954 if (print_kurt == 1) {
8955 tf.Form("%s = %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat());
8956 tt.Form(tf.Data(),fH->GetKurtosis(1));
8957 } else {
8958 tf.Form("%s = %s%s #pm %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat()
8959 ,"%",stats->GetStatFormat());
8960 tt.Form(tf.Data(),fH->GetKurtosis(1),fH->GetKurtosis(11));
8961 }
8962 stats->AddText(tt.Data());
8963 }
8964
8965 // Draw Fit parameters
8966 if (fit) {
8967 Int_t ndf = fit->GetNDF();
8968 tf.Form("#chi^{2} / ndf = %s%s / %d","%",stats->GetFitFormat(),ndf);
8969 tt.Form(tf.Data(),fit->GetChisquare());
8970 if (print_fchi2) stats->AddText(tt.Data());
8971 if (print_fprob) {
8972 tf.Form("Prob = %s%s","%",stats->GetFitFormat());
8973 tt.Form(tf.Data(),TMath::Prob(fit->GetChisquare(),ndf));
8974 stats->AddText(tt.Data());
8975 }
8976 if (print_fval || print_ferrors) {
8978 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
8979 fit->GetParLimits(ipar,parmin,parmax);
8981 if (print_ferrors) {
8982 tf.Form("%-8s = %s%s #pm %s ", fit->GetParName(ipar), "%",stats->GetFitFormat(),
8983 GetBestFormat(fit->GetParameter(ipar), fit->GetParError(ipar), stats->GetFitFormat()));
8984 tt.Form(tf.Data(),fit->GetParameter(ipar)
8985 ,fit->GetParError(ipar));
8986 } else {
8987 tf.Form("%-8s = %s%s ",fit->GetParName(ipar), "%",stats->GetFitFormat());
8988 tt.Form(tf.Data(),fit->GetParameter(ipar));
8989 }
8990 stats->AddText(tt.Data());
8991 }
8992 }
8993 }
8994
8995 if (!done) fFunctions->Add(stats);
8996 stats->Paint(stats->GetOption());
8997}
8998
8999////////////////////////////////////////////////////////////////////////////////
9000/// [Draw the statistics box for 2D histograms.](\ref HP07)
9001
9003{
9004
9005 if (fH->GetDimension() != 2) return;
9006 TH2 *h2 = (TH2*)fH;
9007
9008 TString tt, tf;
9009 Int_t dofit;
9010 TPaveStats *stats = nullptr;
9011 TIter next(fFunctions);
9012 while (auto obj = next()) {
9013 if (obj->InheritsFrom(TPaveStats::Class())) {
9014 stats = (TPaveStats*)obj;
9015 break;
9016 }
9017 }
9018 if (stats && dostat) {
9019 dofit = stats->GetOptFit();
9020 dostat = stats->GetOptStat();
9021 } else {
9022 dofit = gStyle->GetOptFit();
9023 }
9024 if (dostat == 1) dostat = 1111;
9025 Int_t print_name = dostat%10;
9026 Int_t print_entries = (dostat/10)%10;
9027 Int_t print_mean = (dostat/100)%10;
9028 Int_t print_stddev = (dostat/1000)%10;
9029 Int_t print_under = (dostat/10000)%10;
9030 Int_t print_over = (dostat/100000)%10;
9031 Int_t print_integral= (dostat/1000000)%10;
9032 Int_t print_skew = (dostat/10000000)%10;
9033 Int_t print_kurt = (dostat/100000000)%10;
9035 if (print_under || print_over) nlines += 3;
9036
9037 // Pavetext with statistics
9038 if (!gStyle->GetOptFit()) fit = nullptr;
9039 Bool_t done = kFALSE;
9040 if (!dostat && !fit) {
9041 if (stats) { fFunctions->Remove(stats); delete stats;}
9042 return;
9043 }
9045 if (fit) statw = 1.8*gStyle->GetStatW();
9047 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
9048 stath = 0.25*nlines*gStyle->GetStatH();
9049 }
9050 if (fit) stath += gStyle->GetStatH();
9051 if (stats) {
9052 stats->Clear();
9053 done = kTRUE;
9054 } else {
9055 stats = new TPaveStats(
9058 gStyle->GetStatX(),
9059 gStyle->GetStatY(),"brNDC");
9060
9061 stats->SetParent(fH);
9062 stats->SetOptFit(dofit);
9063 stats->SetOptStat(dostat);
9064 stats->SetFillColor(gStyle->GetStatColor());
9065 stats->SetFillStyle(gStyle->GetStatStyle());
9067 stats->SetName("stats");
9068
9070 stats->SetTextAlign(12);
9071 stats->SetTextFont(gStyle->GetStatFont());
9072 if (gStyle->GetStatFont()%10 > 2)
9074 stats->SetFitFormat(gStyle->GetFitFormat());
9076 stats->SetBit(kCanDelete);
9077 stats->SetBit(kMustCleanup);
9078 }
9079 if (print_name) stats->AddText(h2->GetName());
9080 if (print_entries) {
9081 if (h2->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(h2->GetEntries()+0.5));
9082 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(h2->GetEntries()));
9083 stats->AddText(tt.Data());
9084 }
9085 if (print_mean) {
9086 if (print_mean == 1) {
9087 tf.Form("%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
9088 tt.Form(tf.Data(),h2->GetMean(1));
9089 stats->AddText(tt.Data());
9090 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
9091 tt.Form(tf.Data(),h2->GetMean(2));
9092 stats->AddText(tt.Data());
9093 } else {
9094 tf.Form("%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
9095 ,"%",stats->GetStatFormat());
9096 tt.Form(tf.Data(),h2->GetMean(1),h2->GetMeanError(1));
9097 stats->AddText(tt.Data());
9098 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
9099 ,"%",stats->GetStatFormat());
9100 tt.Form(tf.Data(),h2->GetMean(2),h2->GetMeanError(2));
9101 stats->AddText(tt.Data());
9102 }
9103 }
9104 if (print_stddev) {
9105 if (print_stddev == 1) {
9106 tf.Form("%s = %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat());
9107 tt.Form(tf.Data(),h2->GetStdDev(1));
9108 stats->AddText(tt.Data());
9109 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
9110 tt.Form(tf.Data(),h2->GetStdDev(2));
9111 stats->AddText(tt.Data());
9112 } else {
9113 tf.Form("%s = %s%s #pm %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat()
9114 ,"%",stats->GetStatFormat());
9115 tt.Form(tf.Data(),h2->GetStdDev(1),h2->GetStdDevError(1));
9116 stats->AddText(tt.Data());
9117 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
9118 ,"%",stats->GetStatFormat());
9119 tt.Form(tf.Data(),h2->GetStdDev(2),h2->GetStdDevError(2));
9120 stats->AddText(tt.Data());
9121 }
9122 }
9123 if (print_integral) {
9124 tf.Form("%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
9125 tt.Form(tf.Data(),fH->Integral());
9126 stats->AddText(tt.Data());
9127 }
9128 if (print_skew) {
9129 if (print_skew == 1) {
9130 tf.Form("%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
9131 tt.Form(tf.Data(),h2->GetSkewness(1));
9132 stats->AddText(tt.Data());
9133 tf.Form("%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
9134 tt.Form(tf.Data(),h2->GetSkewness(2));
9135 stats->AddText(tt.Data());
9136 } else {
9137 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
9138 ,"%",stats->GetStatFormat());
9139 tt.Form(tf.Data(),h2->GetSkewness(1),h2->GetSkewness(11));
9140 stats->AddText(tt.Data());
9141 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
9142 ,"%",stats->GetStatFormat());
9143 tt.Form(tf.Data(),h2->GetSkewness(2),h2->GetSkewness(12));
9144 stats->AddText(tt.Data());
9145 }
9146 }
9147 if (print_kurt) {
9148 if (print_kurt == 1) {
9149 tf.Form("%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
9150 tt.Form(tf.Data(),h2->GetKurtosis(1));
9151 stats->AddText(tt.Data());
9152 tf.Form("%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
9153 tt.Form(tf.Data(),h2->GetKurtosis(2));
9154 stats->AddText(tt.Data());
9155 } else {
9156 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
9157 ,"%",stats->GetStatFormat());
9158 tt.Form(tf.Data(),h2->GetKurtosis(1),h2->GetKurtosis(11));
9159 stats->AddText(tt.Data());
9160 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
9161 ,"%",stats->GetStatFormat());
9162 tt.Form(tf.Data(),h2->GetKurtosis(2),h2->GetKurtosis(12));
9163 stats->AddText(tt.Data());
9164 }
9165 }
9166 if (print_under || print_over) {
9167 //get 3*3 under/overflows for 2d hist
9168 Double_t unov[9];
9169
9170 Int_t cellsX = h2->GetXaxis()->GetNbins() + 1;
9171 Int_t cellsY = h2->GetYaxis()->GetNbins() + 1;
9172 Int_t firstX = std::max(1, h2->GetXaxis()->GetFirst());
9173 Int_t firstY = std::max(1, h2->GetYaxis()->GetFirst());
9174 Int_t lastX = std::min(h2->GetXaxis()->GetLast(), h2->GetXaxis()->GetNbins());
9175 Int_t lastY = std::min(h2->GetYaxis()->GetLast(), h2->GetYaxis()->GetNbins());
9176
9177 unov[0] = h2->Integral( 0, firstX-1, lastY+1, cellsY );
9178 unov[1] = h2->Integral(firstX , lastX , lastY+1, cellsY );
9179 unov[2] = h2->Integral(lastX+1, cellsX , lastY+1, cellsY );
9180 unov[3] = h2->Integral( 0, firstX-1, firstY , lastY );
9181 unov[4] = h2->Integral(firstX , lastX , firstY , lastY );
9182 unov[5] = h2->Integral(lastX+1, cellsX , firstY , lastY );
9183 unov[6] = h2->Integral( 0, firstX-1, 0, firstY-1);
9184 unov[7] = h2->Integral(firstX, lastX, 0, firstY-1);
9185 unov[8] = h2->Integral(lastX+1, cellsX , 0, firstY-1);
9186
9187 tt.Form("%g|%g|%g\n", unov[0], unov[1], unov[2]);
9188 stats->AddText(tt.Data());
9189 tt.Form("%g|%g|%g\n", unov[3], unov[4], unov[5]);
9190 stats->AddText(tt.Data());
9191 tt.Form("%g|%g|%g\n", unov[6], unov[7], unov[8]);
9192 stats->AddText(tt.Data());
9193 }
9194
9195 // Draw Fit parameters
9196 if (fit) {
9197 Int_t ndf = fit->GetNDF();
9198 tt.Form("#chi^{2} / ndf = %6.4g / %d",fit->GetChisquare(),ndf);
9199 stats->AddText(tt.Data());
9200 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
9201 tt.Form("%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
9202 ,fit->GetParameter(ipar)
9203 ,fit->GetParError(ipar));
9204 stats->AddText(tt.Data());
9205 }
9206 }
9207
9208 if (!done) fFunctions->Add(stats);
9209 stats->Paint(stats->GetOption());
9210}
9211
9212////////////////////////////////////////////////////////////////////////////////
9213/// [Draw the statistics box for 3D histograms.](\ref HP07)
9214
9216{
9217
9218 if (fH->GetDimension() != 3) return;
9219 TH3 *h3 = (TH3*)fH;
9220
9221 TString tt, tf;
9222 Int_t dofit;
9223 TPaveStats *stats = nullptr;
9224 TIter next(fFunctions);
9225 while (auto obj = next()) {
9226 if (obj->InheritsFrom(TPaveStats::Class())) {
9227 stats = (TPaveStats*)obj;
9228 break;
9229 }
9230 }
9231 if (stats && dostat) {
9232 dofit = stats->GetOptFit();
9233 dostat = stats->GetOptStat();
9234 } else {
9235 dofit = gStyle->GetOptFit();
9236 }
9237 if (dostat == 1) dostat = 1111;
9238 Int_t print_name = dostat%10;
9239 Int_t print_entries = (dostat/10)%10;
9240 Int_t print_mean = (dostat/100)%10;
9241 Int_t print_stddev = (dostat/1000)%10;
9242 Int_t print_under = (dostat/10000)%10;
9243 Int_t print_over = (dostat/100000)%10;
9244 Int_t print_integral= (dostat/1000000)%10;
9245 Int_t print_skew = (dostat/10000000)%10;
9246 Int_t print_kurt = (dostat/100000000)%10;
9248 if (print_under || print_over) nlines += 3;
9249
9250 // Pavetext with statistics
9251 if (!gStyle->GetOptFit()) fit = nullptr;
9252 Bool_t done = kFALSE;
9253 if (!dostat && !fit) {
9254 if (stats) { fFunctions->Remove(stats); delete stats;}
9255 return;
9256 }
9258 if (fit) statw = 1.8*gStyle->GetStatW();
9260 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
9261 stath = 0.25*nlines*gStyle->GetStatH();
9262 }
9263 if (fit) stath += gStyle->GetStatH();
9264 if (stats) {
9265 stats->Clear();
9266 done = kTRUE;
9267 } else {
9268 stats = new TPaveStats(
9271 gStyle->GetStatX(),
9272 gStyle->GetStatY(),"brNDC");
9273
9274 stats->SetParent(fH);
9275 stats->SetOptFit(dofit);
9276 stats->SetOptStat(dostat);
9277 stats->SetFillColor(gStyle->GetStatColor());
9278 stats->SetFillStyle(gStyle->GetStatStyle());
9280 stats->SetName("stats");
9281
9283 stats->SetTextAlign(12);
9284 stats->SetTextFont(gStyle->GetStatFont());
9285 stats->SetFitFormat(gStyle->GetFitFormat());
9287 stats->SetBit(kCanDelete);
9288 stats->SetBit(kMustCleanup);
9289 }
9290 if (print_name) stats->AddText(h3->GetName());
9291 if (print_entries) {
9292 if (h3->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(h3->GetEntries()+0.5));
9293 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(h3->GetEntries()+0.5));
9294 stats->AddText(tt.Data());
9295 }
9296 if (print_mean) {
9297 if (print_mean == 1) {
9298 tf.Form("%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
9299 tt.Form(tf.Data(),h3->GetMean(1));
9300 stats->AddText(tt.Data());
9301 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
9302 tt.Form(tf.Data(),h3->GetMean(2));
9303 stats->AddText(tt.Data());
9304 tf.Form("%s = %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat());
9305 tt.Form(tf.Data(),h3->GetMean(3));
9306 stats->AddText(tt.Data());
9307 } else {
9308 tf.Form("%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
9309 ,"%",stats->GetStatFormat());
9310 tt.Form(tf.Data(),h3->GetMean(1),h3->GetMeanError(1));
9311 stats->AddText(tt.Data());
9312 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
9313 ,"%",stats->GetStatFormat());
9314 tt.Form(tf.Data(),h3->GetMean(2),h3->GetMeanError(2));
9315 stats->AddText(tt.Data());
9316 tf.Form("%s = %s%s #pm %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat()
9317 ,"%",stats->GetStatFormat());
9318 tt.Form(tf.Data(),h3->GetMean(3),h3->GetMeanError(3));
9319 stats->AddText(tt.Data());
9320 }
9321 }
9322 if (print_stddev) {
9323 if (print_stddev == 1) {
9324 tf.Form("%s = %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat());
9325 tt.Form(tf.Data(),h3->GetStdDev(1));
9326 stats->AddText(tt.Data());
9327 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
9328 tt.Form(tf.Data(),h3->GetStdDev(2));
9329 stats->AddText(tt.Data());
9330 tf.Form("%s = %s%s",gStringStdDevZ.Data(),"%",stats->GetStatFormat());
9331 tt.Form(tf.Data(),h3->GetStdDev(3));
9332 stats->AddText(tt.Data());
9333 } else {
9334 tf.Form("%s = %s%s #pm %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat()
9335 ,"%",stats->GetStatFormat());
9336 tt.Form(tf.Data(),h3->GetStdDev(1),h3->GetStdDevError(1));
9337 stats->AddText(tt.Data());
9338 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
9339 ,"%",stats->GetStatFormat());
9340 tt.Form(tf.Data(),h3->GetStdDev(2),h3->GetStdDevError(2));
9341 stats->AddText(tt.Data());
9342 tf.Form("%s = %s%s #pm %s%s",gStringStdDevZ.Data(),"%",stats->GetStatFormat()
9343 ,"%",stats->GetStatFormat());
9344 tt.Form(tf.Data(),h3->GetStdDev(3),h3->GetStdDevError(3));
9345 stats->AddText(tt.Data());
9346 }
9347 }
9348 if (print_integral) {
9349 tt.Form("%s = %6.4g",gStringIntegral.Data(),h3->Integral());
9350 stats->AddText(tt.Data());
9351 }
9352 if (print_skew) {
9353 if (print_skew == 1) {
9354 tf.Form("%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
9355 tt.Form(tf.Data(),h3->GetSkewness(1));
9356 stats->AddText(tt.Data());
9357 tf.Form("%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
9358 tt.Form(tf.Data(),h3->GetSkewness(2));
9359 stats->AddText(tt.Data());
9360 tf.Form("%s = %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat());
9361 tt.Form(tf.Data(),h3->GetSkewness(3));
9362 stats->AddText(tt.Data());
9363 } else {
9364 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
9365 ,"%",stats->GetStatFormat());
9366 tt.Form(tf.Data(),h3->GetSkewness(1),h3->GetSkewness(11));
9367 stats->AddText(tt.Data());
9368 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
9369 ,"%",stats->GetStatFormat());
9370 tt.Form(tf.Data(),h3->GetSkewness(2),h3->GetSkewness(12));
9371 stats->AddText(tt.Data());
9372 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat()
9373 ,"%",stats->GetStatFormat());
9374 tt.Form(tf.Data(),h3->GetSkewness(3),h3->GetSkewness(13));
9375 stats->AddText(tt.Data());
9376 }
9377 }
9378 if (print_kurt) {
9379 if (print_kurt == 1) {
9380 tf.Form("%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
9381 tt.Form(tf.Data(),h3->GetKurtosis(1));
9382 stats->AddText(tt.Data());
9383 tf.Form("%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
9384 tt.Form(tf.Data(),h3->GetKurtosis(2));
9385 stats->AddText(tt.Data());
9386 tf.Form("%s = %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat());
9387 tt.Form(tf.Data(),h3->GetKurtosis(3));
9388 stats->AddText(tt.Data());
9389 } else {
9390 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
9391 ,"%",stats->GetStatFormat());
9392 tt.Form(tf.Data(),h3->GetKurtosis(1),h3->GetKurtosis(11));
9393 stats->AddText(tt.Data());
9394 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
9395 ,"%",stats->GetStatFormat());
9396 tt.Form(tf.Data(),h3->GetKurtosis(2),h3->GetKurtosis(12));
9397 stats->AddText(tt.Data());
9398 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat()
9399 ,"%",stats->GetStatFormat());
9400 tt.Form(tf.Data(),h3->GetKurtosis(3),h3->GetKurtosis(13));
9401 stats->AddText(tt.Data());
9402 }
9403 }
9404 if (print_under || print_over) {
9405 // no underflow - overflow printing for a 3D histogram
9406 // one would need a 3D table
9407 }
9408
9409 // Draw Fit parameters
9410 if (fit) {
9411 Int_t ndf = fit->GetNDF();
9412 tt.Form("#chi^{2} / ndf = %6.4g / %d",fit->GetChisquare(),ndf);
9413 stats->AddText(tt.Data());
9414 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
9415 tt.Form("%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
9416 ,fit->GetParameter(ipar)
9417 ,fit->GetParError(ipar));
9418 stats->AddText(tt.Data());
9419 }
9420 }
9421
9422 if (!done) fFunctions->Add(stats);
9423 stats->Paint(stats->GetOption());
9424}
9425
9426////////////////////////////////////////////////////////////////////////////////
9427/// [Control function to draw a 2D histogram as a surface plot.](\ref HP18)
9428
9430{
9431
9432 const Double_t ydiff = 1;
9433 const Double_t yligh1 = 10;
9434 const Double_t qa = 0.15;
9435 const Double_t qd = 0.15;
9436 const Double_t qs = 0.8;
9438 Int_t raster = 0;
9439 Int_t irep = 0;
9440
9441 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
9444 Double_t zmin = Hparam.zmin;
9445 Double_t zmax = Hparam.zmax;
9450 Double_t dangle = 10*3.141592/180; //Delta angle for Rapidity option
9451 Double_t deltaz = TMath::Abs(zmin);
9452 if (deltaz == 0) deltaz = 1;
9453 if (zmin >= zmax) {
9454 zmin -= 0.5*deltaz;
9455 zmax += 0.5*deltaz;
9456 }
9457 Double_t z1c = zmin;
9458 Double_t z2c = zmin + (zmax-zmin)*(1+gStyle->GetHistTopMargin());
9459 // Compute the lego limits and instantiate a lego object
9460 fXbuf[0] = -1;
9461 fYbuf[0] = 1;
9462 fXbuf[1] = -1;
9463 fYbuf[1] = 1;
9464 if (Hoption.System >= kPOLAR && (Hoption.Surf == 1 || Hoption.Surf == 13)) raster = 1;
9465 if (Hoption.System == kPOLAR) {
9466 fXbuf[2] = z1c;
9467 fYbuf[2] = z2c;
9468 } else if (Hoption.System == kCYLINDRICAL) {
9469 if (Hoption.Logy) {
9470 if (ylab1 > 0) fXbuf[2] = TMath::Log10(ylab1);
9471 else fXbuf[2] = 0;
9472 if (ylab2 > 0) fYbuf[2] = TMath::Log10(ylab2);
9473 else fYbuf[2] = 0;
9474 } else {
9475 fXbuf[2] = ylab1;
9476 fYbuf[2] = ylab2;
9477 }
9478 z1c = 0; z2c = 1;
9479 } else if (Hoption.System == kSPHERICAL) {
9480 fXbuf[2] = -1;
9481 fYbuf[2] = 1;
9482 z1c = 0; z2c = 1;
9483 } else if (Hoption.System == kRAPIDITY) {
9484 fXbuf[2] = -1/TMath::Tan(dangle);
9485 fYbuf[2] = 1/TMath::Tan(dangle);
9486 } else {
9487 fXbuf[0] = xlab1;
9488 fYbuf[0] = xlab2;
9489 fXbuf[1] = ylab1;
9490 fYbuf[1] = ylab2;
9491 fXbuf[2] = z1c;
9492 fYbuf[2] = z2c;
9493 }
9494
9495 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data(), Hoption.System);
9496 fLego->SetEdgeAtt(fH->GetLineColor(),fH->GetLineStyle(),fH->GetLineWidth(),0);
9497 fLego->SetFillColor(fH->GetFillColor());
9498
9499 // Initialize the levels on the Z axis
9500 Int_t ndiv = fH->GetContour();
9501 if (ndiv == 0 ) {
9502 ndiv = gStyle->GetNumberContours();
9503 fH->SetContour(ndiv);
9504 }
9505 Int_t ndivz = TMath::Abs(ndiv);
9506 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
9507
9508 if (Hoption.Surf == 13 || Hoption.Surf == 15) fLego->SetMesh(3);
9509 if (Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) fLego->SetMesh(0);
9510
9511 // Close the surface in case of non cartesian coordinates.
9512
9513 if (Hoption.System != kCARTESIAN) {nx++; ny++;}
9514
9515 // Now ready to draw the surface plot
9516
9517 TView *view = gPad ? gPad->GetView() : nullptr;
9518 if (!view) {
9519 Error("PaintSurface", "no TView in current pad");
9520 return;
9521 }
9522
9523 Double_t thedeg = 90 - gPad->GetTheta();
9524 Double_t phideg = -90 - gPad->GetPhi();
9525 Double_t psideg = view->GetPsi();
9526 view->SetView(phideg, thedeg, psideg, irep);
9527
9528 // Set color/style for back box
9529 if (Hoption.Same) {
9530 fLego->SetFillStyle(0);
9531 fLego->SetFillColor(1);
9532 } else {
9533 fLego->SetFillStyle(gPad->GetFrameFillStyle());
9534 fLego->SetFillColor(gPad->GetFrameFillColor());
9535 }
9536 fLego->TAttFill::Modify();
9537
9538 Int_t backcolor = gPad->GetFrameFillColor();
9539 if (Hoption.System != kCARTESIAN) backcolor = 0;
9540 view->PadRange(backcolor);
9541
9542 fLego->SetFillStyle(fH->GetFillStyle());
9543 fLego->SetFillColor(fH->GetFillColor());
9544 fLego->TAttFill::Modify();
9545
9546 // Draw the filled contour on top
9548
9550 if (Hoption.Surf == 13 || Hoption.Surf == 15) {
9552 Hoption.Surf = 23;
9553 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9555 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"BF");
9556 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9557 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9558 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9559 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"BF");
9561 fLego->SetMesh(1);
9562 }
9563
9564 if (raster) fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
9565 else fLego->InitMoveScreen(-1.1,1.1);
9566
9567 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) {
9568 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9571 fLego->BackBox(90);
9572 }
9573 }
9574
9575 // Gouraud Shading surface
9576 if (Hoption.Surf == 14) {
9577 // Set light sources
9578 fLego->LightSource(0, ydiff, 0,0,0,irep);
9579 fLego->LightSource(1, yligh1 ,1,1,1,irep);
9580 fLego->SurfaceProperty(qa, qd, qs, 1, irep);
9581 fmin = ydiff*qa;
9582 fmax = fmin + (yligh1+0.1)*(qd+qs);
9583 Int_t nbcol = 28;
9584 icol1 = 201;
9585 Double_t dcol = 0.5/Double_t(nbcol);
9586 TColor *colref = gROOT->GetColor(fH->GetFillColor());
9587 if (!colref) return;
9589 colref->GetRGB(r,g,b);
9591 TColor *acol;
9592 for (Int_t col=0;col<nbcol;col++) {
9593 acol = gROOT->GetColor(col+icol1);
9595 if (acol) acol->SetRGB(r,g,b);
9596 }
9597 fLego->Spectrum(nbcol, fmin, fmax, icol1, 1, irep);
9598 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::GouraudFunction);
9600 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"BF");
9601 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9602 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9603 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9604 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"BF");
9605 } else if (Hoption.Surf == 15) {
9606 // The surface is not drawn in this case.
9607 } else {
9608 // Draw the surface
9609 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 16 || Hoption.Surf == 17) {
9611 } else {
9612 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9613 }
9614 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9615 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceRaster1);
9616 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode2);
9617 if (Hoption.System == kPOLAR) {
9618 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfacePolar(1,nx,ny,"FB");
9619 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfacePolar(1,nx,ny,"BF");
9620 } else if (Hoption.System == kCYLINDRICAL) {
9621 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceCylindrical(1,nx,ny,"FB");
9622 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9623 } else if (Hoption.System == kSPHERICAL) {
9624 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceSpherical(0,1,nx,ny,"FB");
9625 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9626 } else if (Hoption.System == kRAPIDITY) {
9627 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceSpherical(1,1,nx,ny,"FB");
9628 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9629 } else {
9630 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove1);
9631 if (Hoption.Surf == 16) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove3);
9632 if (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16) fLego->SurfaceCartesian(90,nx,ny,"FB");
9633 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCartesian(90,nx,ny,"BF");
9634 }
9635 }
9636
9637 // Paint the line contour on top for option SURF7
9638 if (Hoption.Surf == 17) {
9639 fLego->InitMoveScreen(-1.1,1.1);
9640 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9641 Hoption.Surf = 23;
9642 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9644 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"FB");
9645 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"FB");
9646 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"FB");
9647 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"FB");
9648 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"FB");
9649 }
9650
9651 if ((!Hoption.Same) &&
9652 (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16)) {
9655 fLego->BackBox(90);
9656 }
9657 }
9658 if (Hoption.System == kCARTESIAN) {
9659 fLego->InitMoveScreen(-1.1,1.1);
9661 if (Hoption.FrontBox) fLego->FrontBox(90);
9662 }
9663 if (!Hoption.Axis && !Hoption.Same) {
9664 TGaxis axis;
9665 PaintLegoAxis(&axis, 90);
9666 }
9667
9669
9670 fLego.reset();
9671}
9672
9673////////////////////////////////////////////////////////////////////////////////
9674/// Control function to draw a table using Delaunay triangles.
9675
9677{
9678
9679 TGraphDelaunay2D *dt = nullptr;
9680 TGraphDelaunay *dtOld = nullptr;
9681
9682 // Check if fH contains a TGraphDelaunay2D
9684 dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
9685 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
9686 if (!dt && !dtOld) return;
9687
9688 // If needed, create a TGraph2DPainter
9689 if (!fGraph2DPainter)
9690 fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
9691
9692 // Define the 3D view
9693 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
9694 if (Hoption.Same) {
9695 TView *viewsame = gPad ? gPad->GetView() : nullptr;
9696 if (!viewsame) {
9697 Error("PaintTriangles", "no TView in current pad, do not use option SAME");
9698 return;
9699 }
9700 Double_t *rmin = viewsame->GetRmin();
9701 Double_t *rmax = viewsame->GetRmax();
9702 if (!rmin || !rmax) return;
9703 fXbuf[0] = rmin[0];
9704 fYbuf[0] = rmax[0];
9705 fXbuf[1] = rmin[1];
9706 fYbuf[1] = rmax[1];
9707 fXbuf[2] = rmin[2];
9708 fYbuf[2] = rmax[2];
9709 fH->SetMaximum(rmax[2]);
9710 fH->SetMinimum(rmin[2]);
9711 fH->GetXaxis()->SetRangeUser(rmin[0],rmax[0]);
9712 fH->GetYaxis()->SetRangeUser(rmin[1],rmax[1]);
9713 } else {
9714 fXbuf[0] = Hparam.xmin;
9715 fYbuf[0] = Hparam.xmax;
9716 fXbuf[1] = Hparam.ymin;
9717 fYbuf[1] = Hparam.ymax;
9718 fXbuf[2] = Hparam.zmin;
9719 fYbuf[2] = Hparam.zmax;
9720 }
9721
9722 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
9723 TView *view = gPad ? gPad->GetView() : nullptr;
9724 if (!view) {
9725 Error("PaintTriangles", "no TView in current pad");
9726 return;
9727 }
9728 Double_t thedeg = 90 - gPad->GetTheta();
9729 Double_t phideg = -90 - gPad->GetPhi();
9730 Double_t psideg = view->GetPsi();
9731 Int_t irep;
9732 view->SetView(phideg, thedeg, psideg, irep);
9733
9734 // Set color/style for back box
9735 fLego->SetFillStyle(gPad->GetFrameFillStyle());
9736 fLego->SetFillColor(gPad->GetFrameFillColor());
9737 fLego->TAttFill::Modify();
9738 Int_t backcolor = gPad->GetFrameFillColor();
9739 if (Hoption.System != kCARTESIAN) backcolor = 0;
9740 view->PadRange(backcolor);
9741 fLego->SetFillStyle(fH->GetFillStyle());
9742 fLego->SetFillColor(fH->GetFillColor());
9743 fLego->TAttFill::Modify();
9744
9745 // Paint the Back Box if needed
9746 if (Hoption.BackBox && !Hoption.Same) {
9747 fLego->InitMoveScreen(-1.1,1.1);
9748 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9750 fLego->BackBox(90);
9751 }
9752
9753 // Paint the triangles
9754 fGraph2DPainter->Paint(option);
9755
9756 // Paint the Front Box if needed
9757 if (Hoption.FrontBox) {
9758 fLego->InitMoveScreen(-1.1,1.1);
9760 fLego->FrontBox(90);
9761 }
9762
9763 // Paint the Axis if needed
9764 if (!Hoption.Axis && !Hoption.Same) {
9765 TGaxis axis;
9766 PaintLegoAxis(&axis, 90);
9767 }
9768
9770
9771 fLego.reset();
9772}
9773
9774////////////////////////////////////////////////////////////////////////////////
9775/// Define the color levels used to paint legos, surfaces etc..
9776
9778{
9779
9780 Int_t i, irep;
9781
9782 // Initialize the color levels
9783 if (ndivz >= 100) {
9784 Warning("PaintSurface", "too many color levels, %d >= 100, reset to 99", ndivz);
9785 ndivz = 99;
9786 }
9787 std::vector<Double_t> funlevel(ndivz+1);
9788 std::vector<Int_t> colorlevel(ndivz+1);
9791 for (i = 0; i < ndivz; ++i) {
9793 theColor = Int_t((i+0.99)*Float_t(ncolors)/Float_t(ndivz));
9795 }
9797 fLego->ColorFunction(ndivz, funlevel.data(), colorlevel.data(), irep);
9798}
9799
9800////////////////////////////////////////////////////////////////////////////////
9801/// [Control function to draw 2D/3D histograms (tables).](\ref HP01c)
9802
9804{
9805
9806 // Fill Hparam structure with histo parameters
9807 if (!TableInit()) return;
9808
9809 // Draw histogram frame
9810 PaintFrame();
9811
9812 // If palette option not specified, delete a possible existing palette
9813 if (!Hoption.Zscale) {
9814 TObject *palette = fFunctions->FindObject("palette");
9815 if (palette) { fFunctions->Remove(palette); delete palette;}
9816 }
9817
9818 // Do not draw the histogram. Only the attached functions will be drawn.
9819 if (Hoption.Func == 2) {
9820 if (Hoption.Zscale) {
9821 Int_t ndiv = fH->GetContour();
9822 if (ndiv == 0 ) {
9823 ndiv = gStyle->GetNumberContours();
9824 fH->SetContour(ndiv);
9825 }
9826 PaintPalette();
9827 }
9828
9829 // Draw the histogram according to the option
9830 } else {
9831 if (fH->InheritsFrom(TH2Poly::Class()) && Hoption.Axis<=0) {
9832 if (Hoption.Fill) PaintTH2PolyBins("f");
9836 if (Hoption.Line) PaintTH2PolyBins("l");
9837 if (Hoption.Mark) PaintTH2PolyBins("P");
9838 } else if (Hoption.Axis<=0) {
9842 if (Hoption.Color) {
9845 }
9848 if (Hoption.Error >= 100) Paint2DErrors(option);
9850 }
9854 }
9855
9856 // Draw histogram title
9857 PaintTitle();
9858
9859 // Draw the axes
9860 if (!Hoption.Lego && !Hoption.Surf &&
9861 !Hoption.Tri && !(Hoption.Error >= 100)) PaintAxis(kFALSE);
9862
9863 TF1 *fit = nullptr;
9864 TIter next(fFunctions);
9865 while (auto obj = next()) {
9866 if (obj->InheritsFrom(TF1::Class())) {
9867 fit = (TF1*)obj;
9868 break;
9869 }
9870 }
9871 if ((Hoption.Same%10) != 1) {
9872 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
9873 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
9874 //ALWAYS executed on non-iOS platform.
9875 //On iOS, depends on mode.
9877 }
9878 }
9879 }
9880}
9881
9882////////////////////////////////////////////////////////////////////////////////
9883/// Control function to draw a TH2Poly bins' contours.
9884///
9885/// - option = "F" draw the bins as filled areas.
9886/// - option = "L" draw the bins as line.
9887/// - option = "P" draw the bins as markers.
9888
9890{
9891
9892 //Do not highlight the histogram, if its part was picked.
9893 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH) return;
9894
9895 TString opt = option;
9896 opt.ToLower();
9897 Bool_t line = kFALSE;
9898 Bool_t fill = kFALSE;
9899 Bool_t mark = kFALSE;
9900 if (opt.Contains("l")) line = kTRUE;
9901 if (opt.Contains("f")) fill = kTRUE;
9902 if (opt.Contains("p")) mark = kTRUE;
9903
9904 TH2PolyBin *b;
9905 Double_t z;
9906
9907 TIter next(((TH2Poly*)fH)->GetBins());
9908 TObject *obj, *poly;
9909
9910 while ((obj=next())) {
9911 b = (TH2PolyBin*)obj;
9912 z = b->GetContent();
9913 if (z==0 && Hoption.Zero) continue; // Do not draw empty bins in case of option "COL0 L"
9914 poly = b->GetPolygon();
9915
9916 // Paint the TGraph bins.
9917 if (poly->IsA() == TGraph::Class()) {
9918 TGraph *g = (TGraph*)poly;
9919 g->TAttLine::Modify();
9920 g->TAttMarker::Modify();
9921 g->TAttFill::Modify();
9922 if (line) {
9923 Int_t fs = g->GetFillStyle();
9925 g->SetFillStyle(0);
9927 g->Paint("F");
9929 g->SetFillStyle(fs);
9930 }
9931 if (fill) g->Paint("F");
9932 if (mark) g->Paint("P");
9933 }
9934
9935 // Paint the TMultiGraph bins.
9936 if (poly->IsA() == TMultiGraph::Class()) {
9938 TList *gl = mg->GetListOfGraphs();
9939 if (!gl) return;
9940 TGraph *g;
9941 TIter nextg(gl);
9942 while ((g = (TGraph*) nextg())) {
9943 g->TAttLine::Modify();
9944 g->TAttMarker::Modify();
9945 g->TAttFill::Modify();
9946 if (line) {
9947 Int_t fs = g->GetFillStyle();
9949 g->SetFillStyle(0);
9951 g->Paint("F");
9953 g->SetFillStyle(fs);
9954 }
9955 if (fill) g->Paint("F");
9956 if (mark) g->Paint("P");
9957 }
9958 }
9959 }
9960}
9961
9962////////////////////////////////////////////////////////////////////////////////
9963/// [Control function to draw a TH2Poly as a color plot.](\ref HP20a)
9964
9966{
9967
9968 //Do not highlight the histogram, if its part was picked.
9969 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
9970 return;
9971
9972 Int_t ncolors, color, theColor;
9973 Double_t z, zc;
9974 Double_t zmin = fH->GetMinimum();
9975 Double_t zmax = fH->GetMaximum();
9976 if (Hoption.Logz) {
9977 if (zmax > 0) {
9978 if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
9979 zmin = TMath::Log10(zmin);
9980 zmax = TMath::Log10(zmax);
9981 } else {
9982 return;
9983 }
9984 }
9985 Double_t dz = zmax - zmin;
9986
9987 // Initialize the levels on the Z axis
9989 Int_t ndiv = fH->GetContour();
9990 if (ndiv == 0 ) {
9991 ndiv = gStyle->GetNumberContours();
9992 fH->SetContour(ndiv);
9993 }
9994 Int_t ndivz = TMath::Abs(ndiv);
9995 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
9997
9998 TIter next(((TH2Poly*)fH)->GetBins());
9999
10000 while (auto obj = next()) {
10001 TH2PolyBin *b = (TH2PolyBin*)obj;
10002 TObject *poly = b->GetPolygon();
10003
10004 z = b->GetContent();
10005 if (z==0 && Hoption.Zero) continue;
10006 if (Hoption.Logz) {
10007 if (z > 0) z = TMath::Log10(z);
10008 else z = zmin;
10009 }
10010 if (z < zmin) continue;
10011
10012 // Define the bin color.
10014 zc = fH->GetContourLevelPad(0);
10015 if (z < zc) continue;
10016 color = -1;
10017 for (Int_t k=0; k<ndiv; k++) {
10018 zc = fH->GetContourLevelPad(k);
10019 if (z < zc) {
10020 continue;
10021 } else {
10022 color++;
10023 }
10024 }
10025 } else {
10026 color = Int_t(0.01+(z-zmin)*scale);
10027 }
10028 theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
10029 if (theColor > ncolors-1) theColor = ncolors-1;
10030
10032
10033 // Paint the TGraph bins.
10034 if (poly->IsA() == TGraph::Class()) {
10035 TGraph *g = (TGraph*)poly;
10036 auto origin = g->GetFillColor();
10037 g->SetFillColor(rootColor);
10038 g->TAttFill::Modify();
10039 g->Paint("F");
10040 g->SetFillColor(origin);
10041 }
10042
10043 // Paint the TMultiGraph bins.
10044 if (poly->IsA() == TMultiGraph::Class()) {
10047 while (auto g = (TGraph*) nextg()) {
10048 auto origin = g->GetFillColor();
10049 g->SetFillColor(rootColor);
10050 g->TAttFill::Modify();
10051 g->Paint("F");
10052 g->SetFillColor(origin);
10053 }
10054 }
10055 }
10057}
10058
10059////////////////////////////////////////////////////////////////////////////////
10060/// [Control function to draw a TH2Poly as a scatter plot.](\ref HP20a)
10061
10063{
10064
10065 //Do not highlight the histogram, if its part was selected.
10066 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
10067 return;
10068
10069 Int_t k, loop, marker=0;
10070 Double_t z, xk,xstep, yk, ystep, xp, yp;
10071 Double_t scale = 1;
10072 Double_t zmin = fH->GetMinimum();
10073 Double_t zmax = fH->GetMaximum();
10074 if (Hoption.Logz) {
10075 if (zmax > 0) {
10076 if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
10077 zmin = TMath::Log10(zmin);
10078 zmax = TMath::Log10(zmax);
10079 } else {
10080 return;
10081 }
10082 }
10083 Double_t dz = zmax - zmin;
10084 scale = (kNMAX-1)/dz;
10085
10086
10087 // use an independent instance of a random generator
10088 // instead of gRandom to avoid conflicts and
10089 // to get same random numbers when drawing the same histogram
10091
10092 TH2PolyBin *b;
10093
10094 TIter next(((TH2Poly*)fH)->GetBins());
10095 TObject *obj, *poly;
10096
10097 Double_t maxarea = 0, a;
10098 while ((obj=next())) {
10099 b = (TH2PolyBin*)obj;
10100 a = b->GetArea();
10101 if (a>maxarea) maxarea = a;
10102 }
10103
10104 next.Reset();
10105
10106 while ((obj=next())) {
10107 b = (TH2PolyBin*)obj;
10108 poly = b->GetPolygon();
10109 z = b->GetContent();
10110 if (z < zmin) z = zmin;
10111 if (z > zmax) z = zmax;
10112 if (Hoption.Logz) {
10113 if (z > 0) z = TMath::Log10(z) - zmin;
10114 } else {
10115 z -= zmin;
10116 }
10117 k = Int_t((z*scale)*(b->GetArea()/maxarea));
10118 xk = b->GetXMin();
10119 yk = b->GetYMin();
10120 xstep = b->GetXMax()-xk;
10121 ystep = b->GetYMax()-yk;
10122
10123 // Paint the TGraph bins.
10124 if (poly->IsA() == TGraph::Class()) {
10125 TGraph *g = (TGraph*)poly;
10126 if (k <= 0 || z <= 0) continue;
10127 loop = 0;
10128 while (loop<k) {
10129 if (k+marker >= kNMAX) {
10130 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10131 marker=0;
10132 }
10133 xp = (random.Rndm()*xstep) + xk;
10134 yp = (random.Rndm()*ystep) + yk;
10135 if (g->IsInside(xp,yp)) {
10136 fXbuf[marker] = xp;
10137 fYbuf[marker] = yp;
10138 marker++;
10139 loop++;
10140 }
10141 }
10142 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10143 }
10144
10145 // Paint the TMultiGraph bins.
10146 if (poly->IsA() == TMultiGraph::Class()) {
10148 TList *gl = mg->GetListOfGraphs();
10149 if (!gl) return;
10150 if (k <= 0 || z <= 0) continue;
10151 loop = 0;
10152 while (loop<k) {
10153 if (k+marker >= kNMAX) {
10154 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10155 marker=0;
10156 }
10157 xp = (random.Rndm()*xstep) + xk;
10158 yp = (random.Rndm()*ystep) + yk;
10159 if (mg->IsInside(xp,yp)) {
10160 fXbuf[marker] = xp;
10161 fYbuf[marker] = yp;
10162 marker++;
10163 loop++;
10164 }
10165 }
10166 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10167 }
10168 }
10169 PaintTH2PolyBins("l");
10170}
10171
10172////////////////////////////////////////////////////////////////////////////////
10173/// [Control function to draw a TH2Poly as a text plot.](\ref HP20a)
10174
10176{
10177
10178 TLatex text;
10179 text.SetTextFont(gStyle->GetTextFont());
10180 text.SetTextColor(fH->GetMarkerColor());
10181 text.SetTextSize(0.02*fH->GetMarkerSize());
10182
10183 Double_t x, y, z, e, angle = 0;
10184 TString tt, tf;
10185 tf.Form("%s%s","%",gStyle->GetPaintTextFormat());
10186 if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
10187 Int_t opt = (Int_t)Hoption.Text/1000;
10188
10189 text.SetTextAlign(22);
10190 if (Hoption.Text == 1) angle = 0;
10191 text.SetTextAngle(angle);
10192 text.TAttText::Modify();
10193
10194 TH2PolyBin *b;
10195
10196 TIter next(((TH2Poly*)fH)->GetBins());
10197 TObject *obj, *p;
10198
10199 while ((obj=next())) {
10200 b = (TH2PolyBin*)obj;
10201 p = b->GetPolygon();
10202 x = (b->GetXMin()+b->GetXMax())/2;
10203 if (Hoption.Logx) {
10204 if (x > 0) x = TMath::Log10(x);
10205 else continue;
10206 }
10207 y = (b->GetYMin()+b->GetYMax())/2;
10208 if (Hoption.Logy) {
10209 if (y > 0) y = TMath::Log10(y);
10210 else continue;
10211 }
10212 z = b->GetContent();
10213 if (z < fH->GetMinimum() || (z == 0 && !Hoption.MinimumZero)) continue;
10214 if (opt==2) {
10215 e = fH->GetBinError(b->GetBinNumber());
10216 tf.Form("#splitline{%s%s}{#pm %s%s}",
10218 "%",gStyle->GetPaintTextFormat());
10219 tt.Form(tf.Data(),z,e);
10220 } else {
10221 tt.Form(tf.Data(),z);
10222 }
10223 if (opt==3) text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),p->GetName());
10224 else text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),tt.Data());
10225 }
10226
10227 PaintTH2PolyBins("l");
10228}
10229
10230////////////////////////////////////////////////////////////////////////////////
10231/// [Control function to draw a 1D/2D histograms with the bin values.](\ref HP15)
10232
10234{
10235
10236 TLatex text;
10237 text.SetTextFont(((int)gStyle->GetTextFont()/10)*10+2); // font precision must be 2
10238 text.SetTextColor(fH->GetMarkerColor());
10239 text.SetTextSize(0.02*fH->GetMarkerSize());
10240
10241 Double_t x, y, z, e, angle = 0;
10242 TString tt, tf;
10243 tf.Form("%s%s","%",gStyle->GetPaintTextFormat());
10244 if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
10245
10246 // 1D histograms
10247 if (fH->GetDimension() == 1) {
10249 Double_t yt;
10250 TProfile *hp = (TProfile*)fH;
10251 if (Hoption.Text>2000 && fH->InheritsFrom(TProfile::Class())) {
10252 Hoption.Text = Hoption.Text-2000;
10253 getentries = kTRUE;
10254 }
10255 if (Hoption.Text == 1) angle = 90;
10256 text.SetTextAlign(11);
10257 if (angle == 90) text.SetTextAlign(12);
10258 if (angle == 0) text.SetTextAlign(21);
10259 text.TAttText::Modify();
10260 Double_t dt = 0.02*(gPad->GetY2()-gPad->GetY1());
10261 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10262 if (Hoption.Bar) {
10263 x = fH->GetXaxis()->GetBinLowEdge(i)+
10264 fH->GetXaxis()->GetBinWidth(i)*
10265 (fH->GetBarOffset()+0.5*fH->GetBarWidth());
10266 } else {
10267 x = fH->GetXaxis()->GetBinCenter(i);
10268 }
10269 y = fH->GetBinContent(i);
10270 yt = y;
10271 if (Hoption.MinimumZero && y<0) y = 0;
10272 if (getentries) yt = hp->GetBinEntries(i);
10273 if (yt == 0.) continue;
10274 tt.Form(tf.Data(),yt);
10275 if (Hoption.Logx) {
10276 if (x > 0) x = TMath::Log10(x);
10277 else continue;
10278 }
10279 if (Hoption.Logy) {
10280 if (y > 0) y = TMath::Log10(y);
10281 else continue;
10282 }
10283 if (y >= gPad->GetY2()) continue;
10284 if (y <= gPad->GetY1()) continue;
10285 text.PaintLatex(x,y+0.2*dt,angle,0.02*fH->GetMarkerSize(),tt.Data());
10286 }
10287
10288 // 2D histograms
10289 } else {
10290 Double_t zmin = Hparam.zmin;
10291 if (Hoption.Logz) zmin = TMath::Power(10,Hparam.zmin);
10292
10293 text.SetTextAlign(22);
10294 if (Hoption.Text == 1) angle = 0;
10295 text.SetTextAngle(angle);
10296 text.TAttText::Modify();
10297 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
10298 y = fYaxis->GetBinCenter(j);
10299 if (Hoption.Logy) {
10300 if (y > 0) y = TMath::Log10(y);
10301 else continue;
10302 }
10303 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10304 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
10305 x = fXaxis->GetBinCenter(i);
10306 if (Hoption.Logx) {
10307 if (x > 0) x = TMath::Log10(x);
10308 else continue;
10309 }
10310 if (!IsInside(x,y)) continue;
10311 z = fH->GetBinContent(bin);
10312 if (z < zmin || (z == 0 && !Hoption.MinimumZero)) continue;
10313 if (Hoption.Text>2000) {
10314 e = fH->GetBinError(bin);
10315 tf.Form("#splitline{%s%s}{#pm %s%s}",
10317 "%",gStyle->GetPaintTextFormat());
10318 tt.Form(tf.Data(),z,e);
10319 } else {
10320 tt.Form(tf.Data(),z);
10321 }
10322 text.PaintLatex(x,y+fH->GetBarOffset()*fYaxis->GetBinWidth(j),
10323 angle,0.02*fH->GetMarkerSize(),tt.Data());
10324 }
10325 }
10326 }
10327}
10328
10329////////////////////////////////////////////////////////////////////////////////
10330/// [Control function to draw a 3D implicit functions.](\ref HP27)
10331
10333{
10334
10335 Int_t irep;
10336
10337 TAxis *xaxis = fH->GetXaxis();
10338 TAxis *yaxis = fH->GetYaxis();
10339 TAxis *zaxis = fH->GetZaxis();
10340
10341 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
10342 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
10343 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
10344 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
10345 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
10346 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
10347
10348 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
10349
10350 TView *view = gPad ? gPad->GetView() : nullptr;
10351 if (!view) {
10352 Error("PaintTF3", "no TView in current pad");
10353 return;
10354 }
10355 Double_t thedeg = 90 - gPad->GetTheta();
10356 Double_t phideg = -90 - gPad->GetPhi();
10357 Double_t psideg = view->GetPsi();
10358 view->SetView(phideg, thedeg, psideg, irep);
10359
10360 fLego->InitMoveScreen(-1.1,1.1);
10361
10362 if (Hoption.BackBox) {
10363 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
10365 fLego->BackBox(90);
10366 }
10367
10369
10370 fLego->ImplicitFunction(fCurrentF3, fXbuf.data(), fYbuf.data(), fH->GetNbinsX(),
10371 fH->GetNbinsY(),
10372 fH->GetNbinsZ(), "BF");
10373
10374 if (Hoption.FrontBox) {
10375 fLego->InitMoveScreen(-1.1,1.1);
10377 fLego->FrontBox(90);
10378 }
10379 if (!Hoption.Axis && !Hoption.Same) {
10380 TGaxis axis;
10381 PaintLegoAxis(&axis, 90);
10382 }
10383
10384 PaintTitle();
10385
10386 fLego.reset();
10387}
10388
10389/////////////////////////////////////////////////////////////new TGaxis///////////////////
10390/// Draw the histogram title
10391///
10392/// The title is drawn according to the title alignment returned by
10393/// `GetTitleAlign()`. It is a 2 digits integer): hv
10394///
10395/// where `h` is the horizontal alignment and `v` is the
10396/// vertical alignment.
10397///
10398/// - `h` can get the values 1 2 3 for left, center, and right
10399/// - `v` can get the values 1 2 3 for bottom, middle and top
10400///
10401/// for instance the default alignment is: 13 (left top)
10402
10404{
10405 // probably best place for calls PaintHighlightBin
10406 // calls after paint histo (1D or 2D) and before paint title and stats
10407 if (!gPad->GetView()) PaintHighlightBin();
10408
10409 if (Hoption.Same) return;
10410 if (fH->TestBit(TH1::kNoTitle)) return;
10411 Int_t nt = strlen(fH->GetTitle());
10412 TPaveText *title = nullptr;
10413 TObject *obj;
10414 TIter next(gPad->GetListOfPrimitives());
10415 while ((obj = next())) {
10416 if (!obj->InheritsFrom(TPaveText::Class())) continue;
10417 title = (TPaveText*)obj;
10418 if (strcmp(title->GetName(),"title")) {title = nullptr; continue;}
10419 break;
10420 }
10421 if (nt == 0 || gStyle->GetOptTitle() <= 0) {
10422 if (title) delete title;
10423 return;
10424 }
10427
10428 if (ht <= 0) {
10429 if (gStyle->GetTitleFont("")%10 == 3) {
10430 Double_t hw = (Double_t) TMath::Max(gPad->GetPadWidth(), gPad->GetPadHeight());
10431 if (hw > 0)
10432 ht = 1.1 * (gStyle->GetTitleSize("")/hw);
10433 } else {
10434 ht = 1.1*gStyle->GetTitleFontSize();
10435 }
10436 }
10437 if (ht <= 0) ht = 0.05;
10438 if (wt <= 0) {
10439 TLatex l;
10440 l.SetTextSize(ht);
10441 l.SetTitle(fH->GetTitle());
10442 // adjustment in case the title has several lines (#splitline)
10443 ht = TMath::Max(ht, 1.2*l.GetYsize()/(gPad->GetY2() - gPad->GetY1()));
10444 Double_t wndc = l.GetXsize()/(gPad->GetX2() - gPad->GetX1());
10445 wt = TMath::Min(0.7, 0.02+wndc);
10446 }
10447 if (title) {
10448 TText *t0 = (TText*)title->GetLine(0);
10449 if (t0) {
10450 if (!strcmp(t0->GetTitle(),fH->GetTitle())) return;
10451 t0->SetTitle(fH->GetTitle());
10452 if (wt > 0) title->SetX2NDC(title->GetX1NDC()+wt);
10453 }
10454 return;
10455 }
10456
10458 if (talh < 1) talh = 1; else if (talh > 3) talh = 3;
10460 if (talv < 1) talv = 1; else if (talv > 3) talv = 3;
10462 xpos = gStyle->GetTitleX();
10463 ypos = gStyle->GetTitleY();
10464 if (talh == 2) xpos = xpos-wt/2.;
10465 if (talh == 3) xpos = xpos-wt;
10466 if (talv == 2) ypos = ypos+ht/2.;
10467 if (talv == 1) ypos = ypos+ht;
10468
10469 TPaveText *ptitle = new TPaveText(xpos, ypos-ht, xpos+wt, ypos,"blNDC");
10470
10471 // box with the histogram title
10472 ptitle->SetFillColor(gStyle->GetTitleFillColor());
10473 ptitle->SetFillStyle(gStyle->GetTitleStyle());
10474 ptitle->SetName("title");
10475 ptitle->SetBorderSize(gStyle->GetTitleBorderSize());
10476 ptitle->SetTextColor(gStyle->GetTitleTextColor());
10477 ptitle->SetTextFont(gStyle->GetTitleFont(""));
10478 if (gStyle->GetTitleFont("")%10 > 2)
10479 ptitle->SetTextSize(gStyle->GetTitleFontSize());
10480 ptitle->AddText(fH->GetTitle());
10481 ptitle->SetBit(kCanDelete);
10482 ptitle->Draw();
10483 ptitle->Paint("blNDC");
10484
10485 if(!gPad->IsEditable()) delete ptitle;
10486}
10487
10488////////////////////////////////////////////////////////////////////////////////
10489/// Process message `mess`.
10490
10491void THistPainter::ProcessMessage(const char *mess, const TObject *obj)
10492{
10493 if (!strcmp(mess,"SetF3")) {
10494 fCurrentF3 = (TF3 *)obj;
10495 }
10496}
10497
10498////////////////////////////////////////////////////////////////////////////////
10499/// Static function.
10500///
10501/// Convert Right Ascension, Declination to X,Y using an AITOFF projection.
10502/// This procedure can be used to create an all-sky map in Galactic
10503/// coordinates with an equal-area Aitoff projection. Output map
10504/// coordinates are zero longitude centered.
10505/// Also called Hammer-Aitoff projection (first presented by Ernst von Hammer in 1892)
10506///
10507/// source: GMT
10508///
10509/// code from Ernst-Jan Buis
10510
10512{
10513
10514 Double_t x, y;
10515
10517 Double_t delta = b*TMath::DegToRad();
10518 Double_t r2 = TMath::Sqrt(2.);
10519 Double_t f = 2*r2/TMath::Pi();
10520 Double_t cdec = TMath::Cos(delta);
10523 y = TMath::Sin(delta)*r2/denom;
10524 x *= TMath::RadToDeg()/f;
10525 y *= TMath::RadToDeg()/f;
10526 // x *= -1.; // for a skymap swap left<->right
10527 Al = x;
10528 Ab = y;
10529
10530 return 0;
10531}
10532
10533////////////////////////////////////////////////////////////////////////////////
10534/// Static function
10535///
10536/// Probably the most famous of the various map projections, the Mercator projection
10537/// takes its name from Mercator who presented it in 1569. It is a cylindrical, conformal projection
10538/// with no distortion along the equator.
10539/// The Mercator projection has been used extensively for world maps in which the distortion towards
10540/// the polar regions grows rather large, thus incorrectly giving the impression that, for example,
10541/// Greenland is larger than South America. In reality, the latter is about eight times the size of
10542/// Greenland. Also, the Former Soviet Union looks much bigger than Africa or South America. One may wonder
10543/// whether this illusion has had any influence on U.S. foreign policy.' (Source: GMT)
10544/// code from Ernst-Jan Buis
10545
10547{
10548
10549 Al = l;
10551 Ab = TMath::Log(aid);
10552 return 0;
10553}
10554
10555////////////////////////////////////////////////////////////////////////////////
10556/// Static function code for sinusoidal projection
10557/// from Ernst-Jan Buis
10558/// Source https://en.wikipedia.org/wiki/Sinusoidal_projection
10559
10561{
10562
10563 Al = l*cos(b*TMath::DegToRad());
10564 Ab = b;
10565 return 0;
10566}
10567
10568////////////////////////////////////////////////////////////////////////////////
10569/// Static function code for parabolic projection
10570/// from Ernst-Jan Buis
10571
10573{
10574
10575 Al = l*(2.*TMath::Cos(2*b*TMath::DegToRad()/3) - 1);
10576 Ab = 180*TMath::Sin(b*TMath::DegToRad()/3);
10577 return 0;
10578}
10579
10580////////////////////////////////////////////////////////////////////////////////
10581/// Static function.
10582///
10583/// Convert Right Ascension, Declination to X,Y using an MOLLWEIDE projection.
10584/// This procedure can be used to create an all-sky map in Galactic
10585/// coordinates with an equal-area Mollweide projection. Output map
10586/// coordinates are zero longitude centered.
10587/// It is also known as the Babinet projection, homalographic projection, homolographic projection, and elliptical projection.
10588/// Source: https://en.wikipedia.org/wiki/Mollweide_projection
10589///
10590/// code from Marco Meyer-Conde
10591
10593{
10594
10595 Double_t theta0 = b * TMath::DegToRad(), theta = theta0;
10596
10597 for (int i = 0; i < 100; i++) {
10598 Double_t num = 2 * theta + TMath::Sin(2 * theta) - TMath::Pi() * TMath::Sin(theta0);
10599 Double_t den = 4 * TMath::Power(TMath::Cos(theta), 2);
10600
10601 if (den < 1e-20) {
10602 theta = theta0;
10603 break;
10604 }
10605
10606 theta -= num / den;
10607
10608 if (TMath::Abs(num / den) < 1e-4) break;
10609 }
10610
10611 Al = l * TMath::Cos(theta);
10612 Ab = 90 * TMath::Sin(theta);
10613
10614 return 0;
10615}
10616
10617////////////////////////////////////////////////////////////////////////////////
10618/// Recompute the histogram range following graphics operations.
10619
10621{
10622
10623 if (Hoption.Same) return;
10624
10625 // Compute x,y range
10627 xmax = Hparam.xmax,
10628 ymin = Hparam.ymin,
10629 ymax = Hparam.ymax,
10630 xscale = 1;
10631
10632 std::function<Int_t(Double_t,Double_t,Double_t&,Double_t&)> func;
10633
10634 if (Hoption.Proj == 1) {
10635 func = ProjectAitoff2xy;
10636 xscale = 0.9999;
10637 } else if (Hoption.Proj == 2) {
10638 if (Hparam.ymin <= -90 || Hparam.ymax >= 90) {
10639 Warning("Mercator Projection", "Latitude out of range %f or %f", Hparam.ymin, Hparam.ymax);
10640 Hoption.Proj = 0;
10641 } else {
10644 }
10645 } else if (Hoption.Proj == 3) {
10646 func = ProjectSinusoidal2xy;
10647 } else if (Hoption.Proj == 4) {
10648 func = ProjectParabolic2xy;
10649 } else if (Hoption.Proj == 5) {
10650 func = ProjectMollweide2xy;
10651 }
10652
10653 if (func) {
10655
10659 func(Hparam.xmax, Hparam.ymin, xmax, ymin);
10660
10661 if (xmin > xmin_aid) xmin = xmin_aid;
10662 if (ymin > ymin_aid) ymin = ymin_aid;
10663 if (xmax < xmax_aid) xmax = xmax_aid;
10664 if (ymax < ymax_aid) ymax = ymax_aid;
10665 if (Hparam.ymin < 0 && Hparam.ymax > 0) {
10666 // there is an 'equator', check its range in the plot..
10667 func(Hparam.xmin*xscale, 0, xmin_aid, ymin_aid);
10668 func(Hparam.xmax*xscale, 0, xmax_aid, ymin_aid);
10669 if (xmin > xmin_aid) xmin = xmin_aid;
10670 if (xmax < xmax_aid) xmax = xmax_aid;
10671 }
10672 if (Hparam.xmin < 0 && Hparam.xmax > 0) {
10673 func(0, Hparam.ymin, xmin_aid, ymin_aid);
10674 func(0, Hparam.ymax, xmax_aid, ymax_aid);
10675 if (ymin > ymin_aid) ymin = ymin_aid;
10676 if (ymax < ymax_aid) ymax = ymax_aid;
10677 }
10678 }
10679
10680 Hparam.xmin = xmin;
10681 Hparam.xmax = xmax;
10682 Hparam.ymin = ymin;
10683 Hparam.ymax = ymax;
10684
10685 Double_t dx = xmax-xmin;
10686 Double_t dy = ymax-ymin;
10687 Double_t dxr = dx/(1 - gPad->GetLeftMargin() - gPad->GetRightMargin());
10688 Double_t dyr = dy/(1 - gPad->GetBottomMargin() - gPad->GetTopMargin());
10689
10690 // Range() could change the size of the pad pixmap and therefore should
10691 // be called before the other paint routines
10692 gPad->Range(xmin - dxr*gPad->GetLeftMargin(),
10693 ymin - dyr*gPad->GetBottomMargin(),
10694 xmax + dxr*gPad->GetRightMargin(),
10695 ymax + dyr*gPad->GetTopMargin());
10696 gPad->RangeAxis(xmin, ymin, xmax, ymax);
10697}
10698
10699////////////////////////////////////////////////////////////////////////////////
10700/// Set current histogram to `h`
10701
10703{
10704
10705 if (h == nullptr) return;
10706 fH = h;
10707 fXaxis = h->GetXaxis();
10708 fYaxis = h->GetYaxis();
10709 fZaxis = h->GetZaxis();
10711}
10712
10713////////////////////////////////////////////////////////////////////////////////
10714/// Initialize various options to draw 2D histograms.
10715
10717{
10718
10719 static const char *where = "TableInit";
10720
10721 Int_t first, last;
10723 Double_t zmin, zmax;
10724 Int_t maximum = 0;
10725 Int_t minimum = 0;
10726 if (fH->GetMaximumStored() != -1111) maximum = 1;
10727 if (fH->GetMinimumStored() != -1111) minimum = 1;
10728
10729 // ----------------- Compute X axis parameters
10730 first = fXaxis->GetFirst();
10731 last = fXaxis->GetLast();
10732 Hparam.xlast = last;
10733 Hparam.xfirst = first;
10738
10739 // if log scale in X, replace xmin,max by the log
10740 if (Hoption.Logx) {
10741 // find the first edge of a bin that is > 0
10742 if (Hparam.xlowedge <=0 ) {
10745 }
10746 if (Hparam.xmin <=0 || Hparam.xmax <=0) {
10747 Error(where, "cannot set X axis to log scale");
10748 return 0;
10749 }
10751 if (Hparam.xfirst < first) Hparam.xfirst = first;
10753 if (Hparam.xlast > last) Hparam.xlast = last;
10756 }
10757
10758 // ----------------- Compute Y axis parameters
10759 first = fYaxis->GetFirst();
10760 last = fYaxis->GetLast();
10761 Hparam.ylast = last;
10762 Hparam.yfirst = first;
10765 if (!Hparam.ybinsize) Hparam.ybinsize = 1;
10768
10769 // if log scale in Y, replace ymin,max by the log
10770 if (Hoption.Logy) {
10771 if (Hparam.ylowedge <=0 ) {
10774 }
10775 if (Hparam.ymin <=0 || Hparam.ymax <=0) {
10776 Error(where, "cannot set Y axis to log scale");
10777 return 0;
10778 }
10780 if (Hparam.yfirst < first) Hparam.yfirst = first;
10782 if (Hparam.ylast > last) Hparam.ylast = last;
10785 }
10786
10787
10788 // ----------------- Compute Z axis parameters
10789 Double_t bigp = TMath::Power(10,32);
10790 zmax = -bigp;
10791 zmin = bigp;
10792 Double_t c1, e1;
10793 Double_t allchan = 0;
10794 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
10795 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10796 c1 = fH->GetBinContent(i,j);
10797 zmax = TMath::Max(zmax,c1);
10798 if (Hoption.Error) {
10799 e1 = fH->GetBinError(i,j);
10800 zmax = TMath::Max(zmax,c1+e1);
10801 }
10802 zmin = TMath::Min(zmin,c1);
10803 allchan += c1;
10804 }
10805 }
10806
10807 // Take into account maximum , minimum
10808
10809 if (maximum) zmax = fH->GetMaximumStored();
10810 if (minimum) zmin = fH->GetMinimumStored();
10811 if (Hoption.Logz && zmax < 0) {
10812 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10813 return 0;
10814 } else if (Hoption.Logz && zmin>=0 && zmax==0) { // empty histogram in log scale
10815 zmin = 0.01;
10816 zmax = 10.;
10817 }
10818 if (zmin >= zmax) {
10819 if (Hoption.Logz) {
10820 if (zmax > 0) zmin = 0.001*zmax;
10821 else {
10822 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10823 return 0;
10824 }
10825 }
10826 }
10827
10828 // take into account normalization factor
10829 Hparam.allchan = allchan;
10830 Double_t factor = allchan;
10831 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
10832 if (allchan) factor /= allchan;
10833 if (factor == 0) factor = 1;
10834 Hparam.factor = factor;
10835 zmax = factor*zmax;
10836 zmin = factor*zmin;
10837 c1 = zmax;
10838 if (TMath::Abs(zmin) > TMath::Abs(c1)) c1 = zmin;
10839
10840 // For log scales, histogram coordinates are log10(ymin) and
10841 // log10(ymax). Final adjustment (if not option "Same")
10842 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
10843 // Maximum and Minimum are not defined.
10844 if (Hoption.Logz) {
10845 if (zmin <= 0) {
10846 zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
10847 fH->SetMinimum(zmin);
10848 }
10849 zmin = TMath::Log10(zmin);
10850 if (!minimum) zmin += TMath::Log10(0.5);
10851 zmax = TMath::Log10(zmax);
10852 if (!maximum) zmax += TMath::Log10(2*(0.9/0.95));
10853 goto LZMIN;
10854 }
10855
10856 // final adjustment of YMAXI for linear scale (if not option "Same"):
10857 // decrease histogram height to MAX% of allowed height if HMAXIM
10858 // has not been called.
10859 // MAX% is the value in percent which has been set in HPLSET
10860 // (default is 90%).
10861 if (!maximum) {
10862 zmax += yMARGIN*(zmax-zmin);
10863 }
10864
10865 // final adjustment of ymin for linear scale.
10866 // if minimum is not set , then ymin is set to zero if >0
10867 // or to ymin - yMARGIN if <0.
10868 if (!minimum) {
10869 if (Hoption.MinimumZero) {
10870 if (zmin >= 0) zmin = 0;
10871 else zmin -= yMARGIN*(zmax-zmin);
10872 } else {
10873 Double_t dzmin = yMARGIN*(zmax-zmin);
10874 if (zmin >= 0 && (zmin-dzmin <= 0)) zmin = 0;
10875 else zmin -= dzmin;
10876 }
10877 }
10878
10879LZMIN:
10880 Hparam.zmin = zmin;
10881 Hparam.zmax = zmax;
10882
10883 // Set bar offset and width
10886
10887 return 1;
10888}
10889
10890////////////////////////////////////////////////////////////////////////////////
10891/// This function returns the best format to print the error value (e)
10892/// knowing the parameter value (v) and the format (f) used to print it.
10893
10895{
10896
10897 static TString ef;
10898 TString tf, tv;
10899
10900 // print v with the format f in tv.
10901 tf.Form("%s%s","%",f);
10902 tv.Form(tf.Data(),v);
10903
10904 // Analyse tv.
10905 int ie = tv.Index("e");
10906 int iE = tv.Index("E");
10907 int id = tv.Index(".");
10908
10909 // v has been printed with the exponent notation.
10910 // There is 2 cases, the exponent is positive or negative
10911 if (ie >= 0 || iE >= 0) {
10912 if (tv.Index("+") >= 0) {
10913 if (e < 1) {
10914 ef.Form("%s.1f","%");
10915 } else {
10916 if (ie >= 0) {
10917 ef.Form("%s.%de","%",ie-id-1);
10918 } else {
10919 ef.Form("%s.%dE","%",iE-id-1);
10920 }
10921 }
10922 } else {
10923 if (ie >= 0) {
10924 ef.Form("%s.%de","%",ie-id-1);
10925 } else {
10926 ef.Form("%s.%dE","%",iE-id-1);
10927 }
10928 }
10929
10930 // There is not '.' in tv. e will be printed with one decimal digit.
10931 } else if (id < 0) {
10932 ef.Form("%s.1f","%");
10933
10934 // There is a '.' in tv and no exponent notation. e's decimal part will
10935 // have the same number of digits as v's one.
10936 } else {
10937 ef.Form("%s.%df","%",tv.Length()-id-1);
10938 }
10939
10940 return ef.Data();
10941}
10942
10943////////////////////////////////////////////////////////////////////////////////
10944/// Set projection.
10945
10947{
10948 if (fShowProjection2) {
10949 auto name2 = TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2);
10950 auto c2 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name2.Data()));
10951 if (c2) c2->Close();
10952 fShowProjection2 = 0;
10953 }
10954 if (fShowProjection) {
10955 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10956 auto c1 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name1.Data()));
10957 if (c1) c1->Close();
10958 fShowProjection = 0;
10959 }
10960
10961 if (nbins <= 0) return;
10962
10963 TString opt = option;
10964 opt.ToLower();
10965 Int_t projection = 0;
10966 if (opt.Contains("x")) projection = 1;
10967 if (opt.Contains("y")) projection = 2;
10968 if (opt.Contains("z")) projection = 3;
10969 if (opt.Contains("xy")) projection = 4;
10970 if (opt.Contains("yx")) projection = 5;
10971 if (opt.Contains("xz")) projection = 6;
10972 if (opt.Contains("zx")) projection = 7;
10973 if (opt.Contains("yz")) projection = 8;
10974 if (opt.Contains("zy")) projection = 9;
10975 if (projection < 4) fShowOption = option+1;
10976 else fShowOption = option+2;
10978 fShowProjection2 = 0;
10979 gROOT->MakeDefCanvas();
10980 gPad->SetName(TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection).Data());
10981 gPad->SetGrid();
10982}
10983
10985{
10986 if (fShowProjection2) {
10987 auto name2 = TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2);
10988 auto c2 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name2.Data()));
10989 if (c2) c2->Close();
10990 fShowProjection2 = 0;
10991 }
10992 if (fShowProjection) {
10993 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10994 auto c1 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name1.Data()));
10995 if (c1) c1->Close();
10996 fShowProjection = 0;
10997 }
10998
10999 if ((nbinsX <= 0) || (nbinsY <= 0)) return;
11000
11001
11002 TString opt = option;
11003 opt.ToLower();
11004 Int_t projection = 0;
11005 if (opt.Contains("x")) projection = 1;
11006 if (opt.Contains("y")) projection = 2;
11007 if (opt.Contains("z")) projection = 3;
11008 if (opt.Contains("xy")) projection = 4;
11009 if (opt.Contains("yx")) projection = 5;
11010 if (opt.Contains("xz")) projection = 6;
11011 if (opt.Contains("zx")) projection = 7;
11012 if (opt.Contains("yz")) projection = 8;
11013 if (opt.Contains("zy")) projection = 9;
11014 if (projection < 4) fShowOption = option+1;
11015 else fShowOption = option+2;
11018 gROOT->MakeDefCanvas();
11019 gPad->SetName(TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection).Data());
11020 gPad->SetGrid();
11021 gROOT->MakeDefCanvas();
11022 gPad->SetName(TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2).Data());
11023 gPad->SetGrid();
11024}
11025
11026
11027////////////////////////////////////////////////////////////////////////////////
11028/// Show projection onto X.
11029
11031{
11032
11034 gPad->SetDoubleBuffer(0); // turn off double buffer mode
11035 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
11036
11037 // Erase old position and draw a line at current position
11038 static int pyold1 = 0;
11039 static int pyold2 = 0;
11040 float uxmin = gPad->GetUxmin();
11041 float uxmax = gPad->GetUxmax();
11042 int pxmin = gPad->XtoAbsPixel(uxmin);
11043 int pxmax = gPad->XtoAbsPixel(uxmax);
11044 Float_t upy = gPad->AbsPixeltoY(py);
11045 Float_t y = gPad->PadtoY(upy);
11046 Int_t biny1 = fH->GetYaxis()->FindBin(y);
11048 Int_t py1 = gPad->YtoAbsPixel(gPad->GetLogy() ? TMath::Log10(fH->GetYaxis()->GetBinLowEdge(biny1)) : fH->GetYaxis()->GetBinLowEdge(biny1));
11049 Int_t py2 = gPad->YtoAbsPixel(gPad->GetLogy() ? TMath::Log10(fH->GetYaxis()->GetBinUpEdge(biny2)) : fH->GetYaxis()->GetBinUpEdge(biny2));
11050
11052 gVirtualX->DrawBox(pxmin,py1,pxmax,py2,TVirtualX::kFilled);
11053 pyold1 = py1;
11054 pyold2 = py2;
11055
11056 // Create or set the new canvas proj x
11058 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
11059 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(name1.Data());
11060 if (c) {
11061 c->Clear();
11062 } else {
11063 fShowProjection = 0;
11064 fShowProjection2 = 0;
11065 pyold1 = 0;
11066 pyold2 = 0;
11067 return;
11068 }
11069 c->cd();
11070 c->SetLogy(ctxt.GetSaved()->GetLogz());
11071 c->SetLogx(ctxt.GetSaved()->GetLogx());
11072
11073 // Draw slice corresponding to mouse position
11074 TString prjName = TString::Format("slice_px_of_%s",fH->GetName());
11075 TH1D *hp = ((TH2*)fH)->ProjectionX(prjName, biny1, biny2);
11076 if (hp) {
11077 hp->SetFillColor(38);
11078 // apply a patch from Oliver Freyermuth to set the title in the projection
11079 // using the range of the projected Y values
11080 if (biny1 == biny2) {
11083 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11085 if (fH->GetYaxis()->GetLabels() != nullptr) {
11086 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf] %s", biny1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetYaxis()->GetBinLabel(biny1)));
11087 } else {
11088 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf]", biny1, valuePrecision, valueFrom, valuePrecision, valueTo));
11089 }
11090 } else {
11093 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11094 // biny1 is used here to get equal precision no matter how large the binrange is,
11095 // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
11097 if (fH->GetYaxis()->GetLabels() != nullptr) {
11098 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)));
11099 } else {
11100 hp->SetTitle(TString::Format("ProjectionX of biny=[%d,%d] [y=%.*lf..%.*lf]", biny1, biny2, valuePrecision, valueFrom, valuePrecision, valueTo));
11101 }
11102 }
11103 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11104 hp->SetYTitle(((TH2*)fH)->GetZaxis()->GetTitle() ? ((TH2*)fH)->GetZaxis()->GetTitle() : "Number of Entries");
11105 hp->Draw();
11106 c->Update();
11107 }
11108}
11109
11110////////////////////////////////////////////////////////////////////////////////
11111/// Show projection onto Y.
11112
11114{
11115
11117 if (fShowProjection2)
11119 gPad->SetDoubleBuffer(0); // turn off double buffer mode
11120 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
11121
11122 // Erase old position and draw a line at current position
11123 static int pxold1 = 0;
11124 static int pxold2 = 0;
11125 float uymin = gPad->GetUymin();
11126 float uymax = gPad->GetUymax();
11127 int pymin = gPad->YtoAbsPixel(uymin);
11128 int pymax = gPad->YtoAbsPixel(uymax);
11129 Float_t upx = gPad->AbsPixeltoX(px);
11130 Float_t x = gPad->PadtoX(upx);
11131 Int_t binx1 = fH->GetXaxis()->FindBin(x);
11133 Int_t px1 = gPad->XtoAbsPixel(gPad->GetLogx() ? TMath::Log10(fH->GetXaxis()->GetBinLowEdge(binx1)) : fH->GetXaxis()->GetBinLowEdge(binx1));
11134 Int_t px2 = gPad->XtoAbsPixel(gPad->GetLogx() ? TMath::Log10(fH->GetXaxis()->GetBinUpEdge(binx2)) : fH->GetXaxis()->GetBinUpEdge(binx2));
11135
11137 gVirtualX->DrawBox(px1,pymin,px2,pymax,TVirtualX::kFilled);
11138 pxold1 = px1;
11139 pxold2 = px2;
11140
11141 // Create or set the new canvas proj y
11143
11144 TString name2 = fShowProjection2 ? TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2)
11145 : TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
11146
11147 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(name2.Data());
11148 if (c) {
11149 c->Clear();
11150 } else {
11151 fShowProjection = 0;
11152 fShowProjection2 = 0;
11153 pxold1 = 0;
11154 pxold2 = 0;
11155 return;
11156 }
11157 c->cd();
11158 c->SetLogy(ctxt.GetSaved()->GetLogz());
11159 c->SetLogx(ctxt.GetSaved()->GetLogy());
11160
11161 // Draw slice corresponding to mouse position
11162 TString prjName = TString::Format("slice_py_of_%s",fH->GetName());
11163 TH1D *hp = ((TH2*)fH)->ProjectionY(prjName, binx1, binx2);
11164 if (hp) {
11165 hp->SetFillColor(38);
11166 // apply a patch from Oliver Freyermuth to set the title in the projection
11167 // using the range of the projected X values
11168 if (binx1 == binx2) {
11171 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11173 if (fH->GetXaxis()->GetLabels() != nullptr) {
11174 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf] [%s]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetXaxis()->GetBinLabel(binx1)));
11175 } else {
11176 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo));
11177 }
11178 } else {
11181 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11182 // binx1 is used here to get equal precision no matter how large the binrange is,
11183 // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
11185 if (fH->GetXaxis()->GetLabels() != nullptr) {
11186 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)));
11187 } else {
11188 hp->SetTitle(TString::Format("ProjectionY of binx=[%d,%d] [x=%.*lf..%.*lf]", binx1, binx2, valuePrecision, valueFrom, valuePrecision, valueTo));
11189 }
11190 }
11191 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11192 hp->SetYTitle(((TH2*)fH)->GetZaxis()->GetTitle() ? ((TH2*)fH)->GetZaxis()->GetTitle() : "Number of Entries");
11193 hp->Draw(fShowProjection2 ? "hbar" : "");
11194 c->Update();
11195 }
11196}
11197
11198////////////////////////////////////////////////////////////////////////////////
11199/// Show projection (specified by `fShowProjection`) of a `TH3`.
11200/// The drawing option for the projection is in `fShowOption`.
11201///
11202/// First implementation; R.Brun
11203///
11204/// Full implementation: Tim Tran (timtran@jlab.org) April 2006
11205
11207{
11208
11209 Int_t nbins=(Int_t)fShowProjection/100; //decode nbins
11210 if (fH->GetDimension() < 3) {
11211 if (fShowProjection2 % 100 == 1) {
11212 ShowProjectionY(px, py);
11213 }
11214 if (fShowProjection % 100 == 1) {
11215 ShowProjectionX(px, py);
11216 return;
11217 }
11218 if (fShowProjection % 100 == 2) {
11219 ShowProjectionY(px, py);
11220 return;
11221 }
11222 }
11223
11224 gPad->SetDoubleBuffer(0); // turn off double buffer mode
11225 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
11226
11227 // Erase old position and draw a line at current position
11228 TView *view = gPad->GetView();
11229 if (!view) return;
11230 TH3 *h3 = (TH3*)fH;
11231 TAxis *xaxis = h3->GetXaxis();
11232 TAxis *yaxis = h3->GetYaxis();
11233 TAxis *zaxis = h3->GetZaxis();
11234 Double_t u[3],xx[3];
11235
11236 static TPoint line1[2];//store end points of a line, initialised 0 by default
11237 static TPoint line2[2];// second line when slice thickness > 1 bin thickness
11238 static TPoint line3[2];
11239 static TPoint line4[2];
11240 static TPoint endface1[5];
11241 static TPoint endface2[5];
11242 static TPoint rect1[5];//store vertices of the polyline (rectangle), initialsed 0 by default
11243 static TPoint rect2[5];// second rectangle when slice thickness > 1 bin thickness
11244
11245 Double_t uxmin = gPad->GetUxmin();
11246 Double_t uxmax = gPad->GetUxmax();
11247 Double_t uymin = gPad->GetUymin();
11248 Double_t uymax = gPad->GetUymax();
11249
11250 int pxmin = gPad->XtoAbsPixel(uxmin);
11251 int pxmax = gPad->XtoAbsPixel(uxmax);
11252 if (pxmin==pxmax) return;
11253 int pymin = gPad->YtoAbsPixel(uymin);
11254 int pymax = gPad->YtoAbsPixel(uymax);
11255 if (pymin==pymax) return;
11258 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(TString::Format("c_%zx_projection_%d",
11259 (size_t)fH, fShowProjection).Data());
11260 if (!c) {
11261 fShowProjection = 0;
11262 return;
11263 }
11264
11266
11267 switch ((Int_t)fShowProjection%100) {
11268 case 1:
11269 // "x"
11270 {
11271 Int_t firstY = yaxis->GetFirst();
11272 Int_t lastY = yaxis->GetLast();
11274 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11275 yaxis->SetRange(biny,biny2);
11276 Int_t firstZ = zaxis->GetFirst();
11277 Int_t lastZ = zaxis->GetLast();
11279 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11280 zaxis->SetRange(binz,binz2);
11281 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11282 if (nbins>1 && line1[0].GetX()) {
11283 gVirtualX->DrawPolyLine(2,line2);
11284 gVirtualX->DrawPolyLine(2,line3);
11285 gVirtualX->DrawPolyLine(2,line4);
11286 gVirtualX->DrawPolyLine(5,endface1);
11287 gVirtualX->DrawPolyLine(5,endface2);
11288 }
11289 xx[0] = xaxis->GetXmin();
11290 xx[2] = zaxis->GetBinCenter(binz);
11291 xx[1] = yaxis->GetBinCenter(biny);
11292 view->WCtoNDC(xx,u);
11293 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11294 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11295 xx[0] = xaxis->GetXmax();
11296 view->WCtoNDC(xx,u);
11297 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11298 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11299 gVirtualX->DrawPolyLine(2,line1);
11300 if (nbins>1) {
11301 xx[0] = xaxis->GetXmin();
11302 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11303 xx[1] = yaxis->GetBinCenter(biny);
11304 view->WCtoNDC(xx,u);
11305 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11306 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11307 xx[0] = xaxis->GetXmax();
11308 view->WCtoNDC(xx,u);
11309 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11310 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11311
11312 xx[0] = xaxis->GetXmin();
11313 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11314 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11315 view->WCtoNDC(xx,u);
11316 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11317 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11318 xx[0] = xaxis->GetXmax();
11319 view->WCtoNDC(xx,u);
11320 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11321 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11322
11323 xx[0] = xaxis->GetXmin();
11324 xx[2] = zaxis->GetBinCenter(binz);
11325 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11326 view->WCtoNDC(xx,u);
11327 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11328 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11329 xx[0] = xaxis->GetXmax();
11330 view->WCtoNDC(xx,u);
11331 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11332 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11333
11334 endface1[0].SetX(line1[0].GetX());
11335 endface1[0].SetY(line1[0].GetY());
11336 endface1[1].SetX(line2[0].GetX());
11337 endface1[1].SetY(line2[0].GetY());
11338 endface1[2].SetX(line3[0].GetX());
11339 endface1[2].SetY(line3[0].GetY());
11340 endface1[3].SetX(line4[0].GetX());
11341 endface1[3].SetY(line4[0].GetY());
11342 endface1[4].SetX(line1[0].GetX());
11343 endface1[4].SetY(line1[0].GetY());
11344
11345 endface2[0].SetX(line1[1].GetX());
11346 endface2[0].SetY(line1[1].GetY());
11347 endface2[1].SetX(line2[1].GetX());
11348 endface2[1].SetY(line2[1].GetY());
11349 endface2[2].SetX(line3[1].GetX());
11350 endface2[2].SetY(line3[1].GetY());
11351 endface2[3].SetX(line4[1].GetX());
11352 endface2[3].SetY(line4[1].GetY());
11353 endface2[4].SetX(line1[1].GetX());
11354 endface2[4].SetY(line1[1].GetY());
11355
11356 gVirtualX->DrawPolyLine(2,line2);
11357 gVirtualX->DrawPolyLine(2,line3);
11358 gVirtualX->DrawPolyLine(2,line4);
11359 gVirtualX->DrawPolyLine(5,endface1);
11360 gVirtualX->DrawPolyLine(5,endface2);
11361 }
11362 c->Clear();
11363 c->cd();
11364 TH1 *hp = h3->Project3D("x");
11365 yaxis->SetRange(firstY,lastY);
11366 zaxis->SetRange(firstZ,lastZ);
11367 if (hp) {
11368 hp->SetFillColor(38);
11369 if (nbins == 1)
11370 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny),
11371 binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
11372 else {
11373 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),
11374 binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
11375 }
11376 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11377 hp->SetYTitle("Number of Entries");
11378 hp->Draw(fShowOption.Data());
11379 }
11380 }
11381 break;
11382
11383 case 2:
11384 // "y"
11385 {
11386 Int_t firstX = xaxis->GetFirst();
11387 Int_t lastX = xaxis->GetLast();
11389 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11390 xaxis->SetRange(binx,binx2);
11391 Int_t firstZ = zaxis->GetFirst();
11392 Int_t lastZ = zaxis->GetLast();
11394 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11395 zaxis->SetRange(binz,binz2);
11396 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11397 if (nbins>1 && line1[0].GetX()) {
11398 gVirtualX->DrawPolyLine(2,line2);
11399 gVirtualX->DrawPolyLine(2,line3);
11400 gVirtualX->DrawPolyLine(2,line4);
11401 gVirtualX->DrawPolyLine(5,endface1);
11402 gVirtualX->DrawPolyLine(5,endface2);
11403 }
11404 xx[0]=xaxis->GetBinCenter(binx);
11405 xx[2] = zaxis->GetBinCenter(binz);
11406 xx[1] = yaxis->GetXmin();
11407 view->WCtoNDC(xx,u);
11408 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11409 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11410 xx[1] = yaxis->GetXmax();
11411 view->WCtoNDC(xx,u);
11412 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11413 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11414 gVirtualX->DrawPolyLine(2,line1);
11415 if (nbins>1) {
11416 xx[1] = yaxis->GetXmin();
11417 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11418 xx[0] = xaxis->GetBinCenter(binx);
11419 view->WCtoNDC(xx,u);
11420 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11421 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11422 xx[1] = yaxis->GetXmax();
11423 view->WCtoNDC(xx,u);
11424 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11425 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11426
11427 xx[1] = yaxis->GetXmin();
11428 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11429 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11430 view->WCtoNDC(xx,u);
11431 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11432 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11433 xx[1] = yaxis->GetXmax();
11434 view->WCtoNDC(xx,u);
11435 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11436 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11437
11438 xx[1] = yaxis->GetXmin();
11439 xx[2] = zaxis->GetBinCenter(binz);
11440 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11441 view->WCtoNDC(xx,u);
11442 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11443 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11444 xx[1] = yaxis->GetXmax();
11445 view->WCtoNDC(xx,u);
11446 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11447 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11448
11449 endface1[0].SetX(line1[0].GetX());
11450 endface1[0].SetY(line1[0].GetY());
11451 endface1[1].SetX(line2[0].GetX());
11452 endface1[1].SetY(line2[0].GetY());
11453 endface1[2].SetX(line3[0].GetX());
11454 endface1[2].SetY(line3[0].GetY());
11455 endface1[3].SetX(line4[0].GetX());
11456 endface1[3].SetY(line4[0].GetY());
11457 endface1[4].SetX(line1[0].GetX());
11458 endface1[4].SetY(line1[0].GetY());
11459
11460 endface2[0].SetX(line1[1].GetX());
11461 endface2[0].SetY(line1[1].GetY());
11462 endface2[1].SetX(line2[1].GetX());
11463 endface2[1].SetY(line2[1].GetY());
11464 endface2[2].SetX(line3[1].GetX());
11465 endface2[2].SetY(line3[1].GetY());
11466 endface2[3].SetX(line4[1].GetX());
11467 endface2[3].SetY(line4[1].GetY());
11468 endface2[4].SetX(line1[1].GetX());
11469 endface2[4].SetY(line1[1].GetY());
11470
11471 gVirtualX->DrawPolyLine(2,line2);
11472 gVirtualX->DrawPolyLine(2,line3);
11473 gVirtualX->DrawPolyLine(2,line4);
11474 gVirtualX->DrawPolyLine(5,endface1);
11475 gVirtualX->DrawPolyLine(5,endface2);
11476 }
11477 c->Clear();
11478 c->cd();
11479 TH1 *hp = h3->Project3D("y");
11480 xaxis->SetRange(firstX,lastX);
11481 zaxis->SetRange(firstZ,lastZ);
11482 if (hp) {
11483 hp->SetFillColor(38);
11484 if (nbins == 1)
11485 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
11486 binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
11487 else
11488 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),
11489 binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
11490 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11491 hp->SetYTitle("Number of Entries");
11492 hp->Draw(fShowOption.Data());
11493 }
11494 }
11495 break;
11496
11497 case 3:
11498 // "z"
11499 {
11500 Int_t firstX = xaxis->GetFirst();
11501 Int_t lastX = xaxis->GetLast();
11503 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11504 xaxis->SetRange(binx,binx2);
11505 Int_t firstY = yaxis->GetFirst();
11506 Int_t lastY = yaxis->GetLast();
11508 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11509 yaxis->SetRange(biny,biny2);
11510 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11511 if (nbins>1 && line1[0].GetX()) {
11512 gVirtualX->DrawPolyLine(2,line2);
11513 gVirtualX->DrawPolyLine(2,line3);
11514 gVirtualX->DrawPolyLine(2,line4);
11515 gVirtualX->DrawPolyLine(5,endface1);
11516 gVirtualX->DrawPolyLine(5,endface2);
11517 }
11518 xx[0] = xaxis->GetBinCenter(binx);
11519 xx[1] = yaxis->GetBinCenter(biny);
11520 xx[2] = zaxis->GetXmin();
11521 view->WCtoNDC(xx,u);
11522 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11523 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11524 xx[2] = zaxis->GetXmax();
11525 view->WCtoNDC(xx,u);
11526 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11527 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11528 gVirtualX->DrawPolyLine(2,line1);
11529 if (nbins>1) {
11530 xx[2] = zaxis->GetXmin();
11531 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11532 xx[0] = xaxis->GetBinCenter(binx);
11533 view->WCtoNDC(xx,u);
11534 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11535 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11536 xx[2] = zaxis->GetXmax();
11537 view->WCtoNDC(xx,u);
11538 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11539 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11540
11541 xx[2] = zaxis->GetXmin();
11542 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11543 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11544 view->WCtoNDC(xx,u);
11545 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11546 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11547 xx[2] = zaxis->GetXmax();
11548 view->WCtoNDC(xx,u);
11549 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11550 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11551
11552 xx[2] = zaxis->GetXmin();
11553 xx[1] = yaxis->GetBinCenter(biny);
11554 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11555 view->WCtoNDC(xx,u);
11556 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11557 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11558 xx[2] = zaxis->GetXmax();
11559 view->WCtoNDC(xx,u);
11560 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11561 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11562
11563 endface1[0].SetX(line1[0].GetX());
11564 endface1[0].SetY(line1[0].GetY());
11565 endface1[1].SetX(line2[0].GetX());
11566 endface1[1].SetY(line2[0].GetY());
11567 endface1[2].SetX(line3[0].GetX());
11568 endface1[2].SetY(line3[0].GetY());
11569 endface1[3].SetX(line4[0].GetX());
11570 endface1[3].SetY(line4[0].GetY());
11571 endface1[4].SetX(line1[0].GetX());
11572 endface1[4].SetY(line1[0].GetY());
11573
11574 endface2[0].SetX(line1[1].GetX());
11575 endface2[0].SetY(line1[1].GetY());
11576 endface2[1].SetX(line2[1].GetX());
11577 endface2[1].SetY(line2[1].GetY());
11578 endface2[2].SetX(line3[1].GetX());
11579 endface2[2].SetY(line3[1].GetY());
11580 endface2[3].SetX(line4[1].GetX());
11581 endface2[3].SetY(line4[1].GetY());
11582 endface2[4].SetX(line1[1].GetX());
11583 endface2[4].SetY(line1[1].GetY());
11584
11585 gVirtualX->DrawPolyLine(2,line2);
11586 gVirtualX->DrawPolyLine(2,line3);
11587 gVirtualX->DrawPolyLine(2,line4);
11588 gVirtualX->DrawPolyLine(5,endface1);
11589 gVirtualX->DrawPolyLine(5,endface2);
11590 }
11591 c->Clear();
11592 c->cd();
11593 TH1 *hp = h3->Project3D("z");
11594 xaxis->SetRange(firstX,lastX);
11595 yaxis->SetRange(firstY,lastY);
11596 if (hp) {
11597 hp->SetFillColor(38);
11598 if (nbins == 1)
11599 hp->SetTitle(TString::Format("ProjectionZ of binx=%d [x=%.1f..%.1f] biny=%d [y=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
11600 biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny)));
11601 else
11602 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),
11603 biny, biny2, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny2) ) );
11604 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11605 hp->SetYTitle("Number of Entries");
11606 hp->Draw(fShowOption.Data());
11607 }
11608 }
11609 break;
11610
11611 case 4:
11612 // "xy"
11613 {
11614 Int_t first = zaxis->GetFirst();
11615 Int_t last = zaxis->GetLast();
11616 Int_t binz = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11617 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11618 zaxis->SetRange(binz,binz2);
11619 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11620 if (nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11621 xx[0] = xaxis->GetXmin();
11622 xx[1] = yaxis->GetXmax();
11623 xx[2] = zaxis->GetBinCenter(binz);
11624 view->WCtoNDC(xx,u);
11625 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11626 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11627 rect1[4].SetX(rect1[0].GetX());
11628 rect1[4].SetY(rect1[0].GetY());
11629 xx[0] = xaxis->GetXmax();
11630 view->WCtoNDC(xx,u);
11631 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11632 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11633 xx[1] = yaxis->GetXmin();
11634 view->WCtoNDC(xx,u);
11635 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11636 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11637 xx[0] = xaxis->GetXmin();
11638 view->WCtoNDC(xx,u);
11639 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11640 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11641 gVirtualX->DrawPolyLine(5,rect1);
11642 if (nbins>1) {
11643 xx[0] = xaxis->GetXmin();
11644 xx[1] = yaxis->GetXmax();
11645 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11646 view->WCtoNDC(xx,u);
11647 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11648 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11649 rect2[4].SetX(rect2[0].GetX());
11650 rect2[4].SetY(rect2[0].GetY());
11651 xx[0] = xaxis->GetXmax();
11652 view->WCtoNDC(xx,u);
11653 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11654 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11655 xx[1] = yaxis->GetXmin();
11656 view->WCtoNDC(xx,u);
11657 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11658 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11659 xx[0] = xaxis->GetXmin();
11660 view->WCtoNDC(xx,u);
11661 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11662 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11663 gVirtualX->DrawPolyLine(5,rect2);
11664 }
11665
11666 c->Clear();
11667 c->cd();
11668 TH2 *hp = (TH2*)h3->Project3D("xy");
11669 zaxis->SetRange(first,last);
11670 if (hp) {
11671 hp->SetFillColor(38);
11672 if (nbins==1)hp->SetTitle(TString::Format("ProjectionXY of binz=%d [z=%.1f..%.f]", binz,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz)));
11673 else hp->SetTitle(TString::Format("ProjectionXY, binz=[%d,%d] [z=%.1f..%.1f]", binz,binz2,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz2)));
11674 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11675 hp->SetYTitle(fH->GetXaxis()->GetTitle());
11676 hp->SetZTitle("Number of Entries");
11677 hp->Draw(fShowOption.Data());
11678 }
11679 }
11680 break;
11681
11682 case 5:
11683 // "yx"
11684 {
11685 Int_t first = zaxis->GetFirst();
11686 Int_t last = zaxis->GetLast();
11687 Int_t binz = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11688 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11689 zaxis->SetRange(binz,binz2);
11690 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11691 if (nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11692 xx[0] = xaxis->GetXmin();
11693 xx[1] = yaxis->GetXmax();
11694 xx[2] = zaxis->GetBinCenter(binz);
11695 view->WCtoNDC(xx,u);
11696 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11697 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11698 rect1[4].SetX(rect1[0].GetX());
11699 rect1[4].SetY(rect1[0].GetY());
11700 xx[0] = xaxis->GetXmax();
11701 view->WCtoNDC(xx,u);
11702 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11703 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11704 xx[1] = yaxis->GetXmin();
11705 view->WCtoNDC(xx,u);
11706 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11707 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11708 xx[0] = xaxis->GetXmin();
11709 view->WCtoNDC(xx,u);
11710 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11711 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11712 gVirtualX->DrawPolyLine(5,rect1);
11713 if (nbins>1) {
11714 xx[0] = xaxis->GetXmin();
11715 xx[1] = yaxis->GetXmax();
11716 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11717 view->WCtoNDC(xx,u);
11718 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11719 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11720 rect2[4].SetX(rect2[0].GetX());
11721 rect2[4].SetY(rect2[0].GetY());
11722 xx[0] = xaxis->GetXmax();
11723 view->WCtoNDC(xx,u);
11724 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11725 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11726 xx[1] = yaxis->GetXmin();
11727 view->WCtoNDC(xx,u);
11728 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11729 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11730 xx[0] = xaxis->GetXmin();
11731 view->WCtoNDC(xx,u);
11732 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11733 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11734 gVirtualX->DrawPolyLine(5,rect2);
11735 }
11736 c->Clear();
11737 c->cd();
11738 TH2 *hp = (TH2*)h3->Project3D("yx");
11739 zaxis->SetRange(first,last);
11740 if (hp) {
11741 hp->SetFillColor(38);
11742 if (nbins==1)hp->SetTitle(TString::Format("ProjectionYX of binz=%d [z=%.1f..%.f]", binz,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz)));
11743 else hp->SetTitle(TString::Format("ProjectionYX, binz=[%d,%d] [z=%.1f..%.1f]", binz,binz2,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz2)));
11744 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11745 hp->SetYTitle(fH->GetYaxis()->GetTitle());
11746 hp->SetZTitle("Number of Entries");
11747 hp->Draw(fShowOption.Data());
11748 }
11749 }
11750 break;
11751
11752 case 6:
11753 // "xz"
11754 {
11755 Int_t first = yaxis->GetFirst();
11756 Int_t last = yaxis->GetLast();
11757 Int_t biny = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11758 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11759 yaxis->SetRange(biny,biny2);
11760 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11761 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11762 xx[0] = xaxis->GetXmin();
11763 xx[2] = zaxis->GetXmax();
11764 xx[1] = yaxis->GetBinCenter(biny);
11765 view->WCtoNDC(xx,u);
11766 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11767 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11768 rect1[4].SetX(rect1[0].GetX());
11769 rect1[4].SetY(rect1[0].GetY());
11770 xx[0] = xaxis->GetXmax();
11771 view->WCtoNDC(xx,u);
11772 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11773 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11774 xx[2] = zaxis->GetXmin();
11775 view->WCtoNDC(xx,u);
11776 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11777 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11778 xx[0] = xaxis->GetXmin();
11779 view->WCtoNDC(xx,u);
11780 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11781 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11782 gVirtualX->DrawPolyLine(5,rect1);
11783 if (nbins>1) {
11784 xx[0] = xaxis->GetXmin();
11785 xx[2] = zaxis->GetXmax();
11786 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11787 view->WCtoNDC(xx,u);
11788 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11789 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11790 rect2[4].SetX(rect2[0].GetX());
11791 rect2[4].SetY(rect2[0].GetY());
11792 xx[0] = xaxis->GetXmax();
11793 view->WCtoNDC(xx,u);
11794 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11795 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11796 xx[2] = zaxis->GetXmin();
11797 view->WCtoNDC(xx,u);
11798 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11799 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11800 xx[0] = xaxis->GetXmin();
11801 view->WCtoNDC(xx,u);
11802 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11803 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11804 gVirtualX->DrawPolyLine(5,rect2);
11805 }
11806 c->Clear();
11807 c->cd();
11808 TH2 *hp = (TH2*)h3->Project3D("xz");
11809 yaxis->SetRange(first,last);
11810 if (hp) {
11811 hp->SetFillColor(38);
11812 if (nbins==1)hp->SetTitle(TString::Format("ProjectionXZ of biny=%d [y=%.1f..%.f]", biny,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny)));
11813 else hp->SetTitle(TString::Format("ProjectionXZ, biny=[%d,%d] [y=%.1f..%.1f]", biny,biny2,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny2)));
11814 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11815 hp->SetYTitle(fH->GetXaxis()->GetTitle());
11816 hp->SetZTitle("Number of Entries");
11817 hp->Draw(fShowOption.Data());
11818 }
11819 }
11820 break;
11821
11822 case 7:
11823 // "zx"
11824 {
11825 Int_t first = yaxis->GetFirst();
11826 Int_t last = yaxis->GetLast();
11827 Int_t biny = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11828 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11829 yaxis->SetRange(biny,biny2);
11830 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11831 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11832 xx[0] = xaxis->GetXmin();
11833 xx[2] = zaxis->GetXmax();
11834 xx[1] = yaxis->GetBinCenter(biny);
11835 view->WCtoNDC(xx,u);
11836 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11837 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11838 rect1[4].SetX(rect1[0].GetX());
11839 rect1[4].SetY(rect1[0].GetY());
11840 xx[0] = xaxis->GetXmax();
11841 view->WCtoNDC(xx,u);
11842 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11843 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11844 xx[2] = zaxis->GetXmin();
11845 view->WCtoNDC(xx,u);
11846 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11847 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11848 xx[0] = xaxis->GetXmin();
11849 view->WCtoNDC(xx,u);
11850 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11851 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11852 gVirtualX->DrawPolyLine(5,rect1);
11853 if (nbins>1) {
11854 xx[0] = xaxis->GetXmin();
11855 xx[2] = zaxis->GetXmax();
11856 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11857 view->WCtoNDC(xx,u);
11858 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11859 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11860 rect2[4].SetX(rect2[0].GetX());
11861 rect2[4].SetY(rect2[0].GetY());
11862 xx[0] = xaxis->GetXmax();
11863 view->WCtoNDC(xx,u);
11864 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11865 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11866 xx[2] = zaxis->GetXmin();
11867 view->WCtoNDC(xx,u);
11868 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11869 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11870 xx[0] = xaxis->GetXmin();
11871 view->WCtoNDC(xx,u);
11872 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11873 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11874 gVirtualX->DrawPolyLine(5,rect2);
11875 }
11876 c->Clear();
11877 c->cd();
11878 TH2 *hp = (TH2*)h3->Project3D("zx");
11879 yaxis->SetRange(first,last);
11880 if (hp) {
11881 hp->SetFillColor(38);
11882 if (nbins==1)hp->SetTitle(TString::Format("ProjectionZX of biny=%d [y=%.1f..%.f]", biny,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny)));
11883 else hp->SetTitle(TString::Format("ProjectionZX, biny=[%d,%d] [y=%.1f..%.1f]", biny,biny2,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny2)));
11884 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11885 hp->SetYTitle(fH->GetZaxis()->GetTitle());
11886 hp->SetZTitle("Number of Entries");
11887 hp->Draw(fShowOption.Data());
11888 }
11889 }
11890 break;
11891
11892 case 8:
11893 // "yz"
11894 {
11895 Int_t first = xaxis->GetFirst();
11896 Int_t last = xaxis->GetLast();
11897 Int_t binx = first + Int_t((last-first)*(px-pxmin)/(pxmax-pxmin));
11898 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11899 xaxis->SetRange(binx,binx2);
11900 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11901 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11902 xx[2] = zaxis->GetXmin();
11903 xx[1] = yaxis->GetXmax();
11904 xx[0] = xaxis->GetBinCenter(binx);
11905 view->WCtoNDC(xx,u);
11906 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11907 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11908 rect1[4].SetX(rect1[0].GetX());
11909 rect1[4].SetY(rect1[0].GetY());
11910 xx[2] = zaxis->GetXmax();
11911 view->WCtoNDC(xx,u);
11912 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11913 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11914 xx[1] = yaxis->GetXmin();
11915 view->WCtoNDC(xx,u);
11916 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11917 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11918 xx[2] = zaxis->GetXmin();
11919 view->WCtoNDC(xx,u);
11920 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11921 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11922 gVirtualX->DrawPolyLine(5,rect1);
11923 if (nbins>1) {
11924 xx[2] = zaxis->GetXmin();
11925 xx[1] = yaxis->GetXmax();
11926 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11927 view->WCtoNDC(xx,u);
11928 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11929 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11930 rect2[4].SetX(rect2[0].GetX());
11931 rect2[4].SetY(rect2[0].GetY());
11932 xx[2] = zaxis->GetXmax();
11933 view->WCtoNDC(xx,u);
11934 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11935 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11936 xx[1] = yaxis->GetXmin();
11937 view->WCtoNDC(xx,u);
11938 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11939 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11940 xx[2] = zaxis->GetXmin();
11941 view->WCtoNDC(xx,u);
11942 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11943 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11944 gVirtualX->DrawPolyLine(5,rect2);
11945 }
11946 c->Clear();
11947 c->cd();
11948 TH2 *hp = (TH2*)h3->Project3D("yz");
11949 xaxis->SetRange(first,last);
11950 if (hp) {
11951 hp->SetFillColor(38);
11952 if (nbins==1)hp->SetTitle(TString::Format("ProjectionYZ of binx=%d [x=%.1f..%.f]", binx,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx)));
11953 else hp->SetTitle(TString::Format("ProjectionYZ, binx=[%d,%d] [x=%.1f..%.1f]", binx,binx2,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx2)));
11954 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11955 hp->SetYTitle(fH->GetYaxis()->GetTitle());
11956 hp->SetZTitle("Number of Entries");
11957 hp->Draw(fShowOption.Data());
11958 }
11959 }
11960 break;
11961
11962 case 9:
11963 // "zy"
11964 {
11965 Int_t first = xaxis->GetFirst();
11966 Int_t last = xaxis->GetLast();
11967 Int_t binx = first + Int_t((last-first)*(px-pxmin)/(pxmax-pxmin));
11968 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11969 xaxis->SetRange(binx,binx2);
11970 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11971 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11972 xx[2] = zaxis->GetXmin();
11973 xx[1] = yaxis->GetXmax();
11974 xx[0] = xaxis->GetBinCenter(binx);
11975 view->WCtoNDC(xx,u);
11976 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11977 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11978 rect1[4].SetX(rect1[0].GetX());
11979 rect1[4].SetY(rect1[0].GetY());
11980 xx[2] = zaxis->GetXmax();
11981 view->WCtoNDC(xx,u);
11982 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11983 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11984 xx[1] = yaxis->GetXmin();
11985 view->WCtoNDC(xx,u);
11986 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11987 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11988 xx[2] = zaxis->GetXmin();
11989 view->WCtoNDC(xx,u);
11990 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11991 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11992 gVirtualX->DrawPolyLine(5,rect1);
11993 if (nbins>1) {
11994 xx[2] = zaxis->GetXmin();
11995 xx[1] = yaxis->GetXmax();
11996 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11997 view->WCtoNDC(xx,u);
11998 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11999 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
12000 rect2[4].SetX(rect2[0].GetX());
12001 rect2[4].SetY(rect2[0].GetY());
12002 xx[2] = zaxis->GetXmax();
12003 view->WCtoNDC(xx,u);
12004 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
12005 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
12006 xx[1] = yaxis->GetXmin();
12007 view->WCtoNDC(xx,u);
12008 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
12009 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
12010 xx[2] = zaxis->GetXmin();
12011 view->WCtoNDC(xx,u);
12012 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
12013 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
12014 gVirtualX->DrawPolyLine(5,rect2);
12015 }
12016 c->Clear();
12017 c->cd();
12018 TH2 *hp = (TH2*)h3->Project3D("zy");
12019 xaxis->SetRange(first,last);
12020 if (hp) {
12021 hp->SetFillColor(38);
12022 if (nbins==1)hp->SetTitle(TString::Format("ProjectionZY of binx=%d [x=%.1f..%.f]", binx,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx)));
12023 else hp->SetTitle(TString::Format("ProjectionZY, binx=[%d,%d] [x=%.1f..%.1f]", binx,binx2,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx2)));
12024 hp->SetXTitle(fH->GetYaxis()->GetTitle());
12025 hp->SetYTitle(fH->GetZaxis()->GetTitle());
12026 hp->SetZTitle("Number of Entries");
12027 hp->Draw(fShowOption.Data());
12028 }
12029 }
12030 break;
12031 }
12032 c->Update();
12033}
@ kMouseMotion
Definition Buttons.h:23
@ kWheelUp
Definition Buttons.h:18
@ kButton1Motion
Definition Buttons.h:20
@ kButton1Up
Definition Buttons.h:19
@ kWheelDown
Definition Buttons.h:18
@ kButton1Down
Definition Buttons.h:17
@ kButton1Locate
Definition Buttons.h:22
@ kArrowVer
Definition GuiTypes.h:375
@ kPointer
Definition GuiTypes.h:376
#define d(i)
Definition RSha256.hxx:102
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
#define c(i)
Definition RSha256.hxx:101
#define g(i)
Definition RSha256.hxx:105
#define a(i)
Definition RSha256.hxx:99
#define h(i)
Definition RSha256.hxx:106
#define e(i)
Definition RSha256.hxx:103
cudaEvent_t event
short Style_t
Style number (short)
Definition RtypesCore.h:97
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:60
short Color_t
Color number (short)
Definition RtypesCore.h:100
unsigned int UInt_t
Unsigned integer 4 bytes (unsigned int)
Definition RtypesCore.h:61
short Width_t
Line width (short)
Definition RtypesCore.h:99
float Float_t
Float 4 bytes (float)
Definition RtypesCore.h:72
short Short_t
Signed Short integer 2 bytes (short)
Definition RtypesCore.h:54
constexpr Bool_t kFALSE
Definition RtypesCore.h:109
double Double_t
Double 8 bytes.
Definition RtypesCore.h:74
constexpr Bool_t kTRUE
Definition RtypesCore.h:108
const char Option_t
Option string (const char)
Definition RtypesCore.h:81
#define BIT(n)
Definition Rtypes.h:90
@ kBlack
Definition Rtypes.h:65
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
R__EXTERN TEnv * gEnv
Definition TEnv.h:126
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t option
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void pixel
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t wmin
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t np
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize id
Option_t Option_t TPoint TPoint const char 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
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
#define gVirtualX
Definition TVirtualX.h:379
Draw all kinds of Arrows.
Definition TArrow.h:29
virtual Int_t GetNdivisions() const
Definition TAttAxis.h:37
virtual Float_t GetLabelOffset() const
Definition TAttAxis.h:41
virtual Float_t GetLabelSize() const
Definition TAttAxis.h:42
virtual Float_t GetTickLength() const
Definition TAttAxis.h:46
virtual Float_t GetTitleOffset() const
Definition TAttAxis.h:44
virtual Color_t GetFillColor() const
Return the fill area color.
Definition TAttFill.h:32
virtual Style_t GetFillStyle() const
Return the fill area style.
Definition TAttFill.h:33
virtual void SetFillColor(Color_t fcolor)
Set the fill area color.
Definition TAttFill.h:40
virtual void SetFillStyle(Style_t fstyle)
Set the fill area style.
Definition TAttFill.h:42
virtual Color_t GetLineColor() const
Return the line color.
Definition TAttLine.h:36
virtual void SetLineStyle(Style_t lstyle)
Set the line style.
Definition TAttLine.h:46
virtual Width_t GetLineWidth() const
Return the line width.
Definition TAttLine.h:38
virtual void SetLineWidth(Width_t lwidth)
Set the line width.
Definition TAttLine.h:47
virtual void SetLineColor(Color_t lcolor)
Set the line color.
Definition TAttLine.h:44
virtual Style_t GetLineStyle() const
Return the line style.
Definition TAttLine.h:37
virtual Style_t GetMarkerStyle() const
Return the marker style.
Definition TAttMarker.h:35
virtual Color_t GetMarkerColor() const
Return the marker color.
Definition TAttMarker.h:34
virtual Size_t GetMarkerSize() const
Return the marker size.
Definition TAttMarker.h:36
virtual void SetMarkerStyle(Style_t mstyle=1)
Set the marker style.
virtual void SetMarkerSize(Size_t msize=1)
Set the marker size.
virtual void SetMarkerColor(Color_t mcolor=1)
Set the marker color.
static Style_t GetMarkerStyleBase(Style_t style)
Internal helper function that returns the corresponding marker style with line width 1 for the given ...
virtual void SetTextAlign(Short_t align=11)
Set the text alignment.
Definition TAttText.h:48
virtual Font_t GetTextFont() const
Return the text font.
Definition TAttText.h:38
virtual void SetTextAngle(Float_t tangle=0)
Set the text angle.
Definition TAttText.h:49
virtual void SetTextColor(Color_t tcolor=1)
Set the text color.
Definition TAttText.h:50
virtual void SetTextFont(Font_t tfont=62)
Set the text font.
Definition TAttText.h:52
virtual void SetTextSize(Float_t tsize=1)
Set the text size.
Definition TAttText.h:53
Class to manage histogram axis.
Definition TAxis.h:32
virtual Bool_t GetTimeDisplay() const
Definition TAxis.h:133
Bool_t IsAlphanumeric() const
Definition TAxis.h:90
const char * GetTitle() const override
Returns title of object.
Definition TAxis.h:137
virtual Double_t GetBinCenter(Int_t bin) const
Return center of bin.
Definition TAxis.cxx:482
Bool_t CanExtend() const
Definition TAxis.h:88
const TArrayD * GetXbins() const
Definition TAxis.h:138
Double_t GetXmax() const
Definition TAxis.h:142
@ kAxisRange
Definition TAxis.h:66
const char * GetBinLabel(Int_t bin) const
Return label for bin.
Definition TAxis.cxx:444
virtual Int_t FindBin(Double_t x)
Find bin number corresponding to abscissa x.
Definition TAxis.cxx:293
virtual Double_t GetBinLowEdge(Int_t bin) const
Return low edge of bin.
Definition TAxis.cxx:522
virtual Int_t FindFixBin(Double_t x) const
Find bin number corresponding to abscissa x
Definition TAxis.cxx:422
const char * ChooseTimeFormat(Double_t axislength=0)
Choose a reasonable time format from the coordinates in the active pad and the number of divisions in...
Definition TAxis.cxx:127
Int_t GetLast() const
Return last bin on the axis i.e.
Definition TAxis.cxx:473
virtual const char * GetTimeFormatOnly() const
Return only the time format from the string fTimeFormat.
Definition TAxis.cxx:604
Double_t GetXmin() const
Definition TAxis.h:141
Int_t GetNbins() const
Definition TAxis.h:127
virtual void SetRangeUser(Double_t ufirst, Double_t ulast)
Set the viewing range for the axis from ufirst to ulast (in user coordinates, that is,...
Definition TAxis.cxx:1090
virtual const char * GetTimeFormat() const
Definition TAxis.h:134
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width.
Definition TAxis.cxx:546
virtual Double_t GetBinUpEdge(Int_t bin) const
Return up edge of bin.
Definition TAxis.cxx:532
Int_t GetFirst() const
Return first bin on the axis i.e.
Definition TAxis.cxx:462
THashList * GetLabels() const
Definition TAxis.h:123
Create a Box.
Definition TBox.h:22
The candle plot painter class.
Definition TCandle.h:27
CandleOption
Definition TCandle.h:30
static Bool_t SupportAlpha()
Static function returning "true" if transparency is supported.
Definition TCanvas.cxx:2490
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition TClass.cxx:2999
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
The color creation and management class.
Definition TColor.h:22
static void RGBtoHLS(Float_t r, Float_t g, Float_t b, Float_t &h, Float_t &l, Float_t &s)
Definition TColor.h:83
static Int_t GetColor(const char *hexcolor)
Static method returning color number for color specified by hex color string of form: "#rrggbb",...
Definition TColor.cxx:1939
static Int_t GetColorBright(Int_t color)
Static function: Returns the bright color number corresponding to n If the TColor object does not exi...
Definition TColor.cxx:2108
static Int_t GetColorDark(Int_t color)
Static function: Returns the dark color number corresponding to n If the TColor object does not exist...
Definition TColor.cxx:2151
static void HLStoRGB(Float_t h, Float_t l, Float_t s, Float_t &r, Float_t &g, Float_t &b)
Definition TColor.h:78
To draw a Crown.
Definition TCrown.h:19
Graphical cut class.
Definition TCutG.h:20
static TClass * Class()
TDirectory::TContext keeps track and restore the current directory.
Definition TDirectory.h:89
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition TEnv.cxx:511
1-Dim function class
Definition TF1.h:182
virtual Double_t GetXmax() const
Definition TF1.h:525
virtual Int_t GetNDF() const
Return the number of degrees of freedom in the fit the fNDF parameter has been previously computed du...
Definition TF1.cxx:1940
virtual void GetParLimits(Int_t ipar, Double_t &parmin, Double_t &parmax) const
Return limits for parameter ipar.
Definition TF1.cxx:1991
virtual Double_t GetParError(Int_t ipar) const
Return value of parameter number ipar.
Definition TF1.cxx:1981
static TClass * Class()
Double_t GetChisquare() const
Return the Chisquare after fitting. See ROOT::Fit::FitResult::Chi2()
Definition TF1.h:409
virtual void SetMaximum(Double_t maximum=-1111)
Set the maximum value along Y for this function In case the function is already drawn,...
Definition TF1.cxx:3450
virtual Double_t GetMaximumStored() const
Definition TF1.h:438
virtual Int_t GetNpar() const
Definition TF1.h:446
virtual Int_t GetNumberFreeParameters() const
Return the number of free parameters.
Definition TF1.cxx:1951
@ kNotDraw
Definition TF1.h:297
virtual void SetMinimum(Double_t minimum=-1111)
Set the minimum value along Y for this function In case the function is already drawn,...
Definition TF1.cxx:3463
virtual const char * GetParName(Int_t ipar) const
Definition TF1.h:494
virtual Double_t Eval(Double_t x, Double_t y=0, Double_t z=0, Double_t t=0) const
Evaluate this function.
Definition TF1.cxx:1447
virtual Double_t GetXmin() const
Definition TF1.h:521
virtual Double_t GetParameter(Int_t ipar) const
Definition TF1.h:477
A 2-Dim function with parameters.
Definition TF2.h:29
void Paint(Option_t *option="") override
Paint this 2-D function with its current attributes.
Definition TF2.cxx:806
void SetRange(Double_t xmin, Double_t xmax) override
Initialize the upper and lower bounds to draw the function.
Definition TF2.h:133
static TClass * Class()
TF3 defines a 3D Function with Parameters.
Definition TF3.h:28
The axis painter class.
Definition TGaxis.h:26
void SetTimeFormat(const char *tformat)
Change the format used for time plotting.
Definition TGaxis.cxx:2937
virtual void PaintAxis(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax, Double_t &wmin, Double_t &wmax, Int_t &ndiv, Option_t *chopt="", Double_t gridlength=0, Bool_t drawGridOnly=kFALSE)
Control function to draw an axis.
Definition TGaxis.cxx:1006
void SetTitleOffset(Float_t titleoffset=1)
Definition TGaxis.h:130
virtual void SetTitle(const char *title="")
Change the title of the axis.
Definition TGaxis.cxx:2910
void SetLabelOffset(Float_t labeloffset)
Definition TGaxis.h:108
virtual void ImportAxisAttributes(TAxis *axis)
Internal method to import TAxis attributes to this TGaxis.
Definition TGaxis.cxx:953
void SetTickSize(Float_t ticksize)
Definition TGaxis.h:124
void SetLabelSize(Float_t labelsize)
Definition TGaxis.h:109
void SetOption(Option_t *option="")
To set axis options.
Definition TGaxis.cxx:2902
Graphics object made of three arrays X, Y and Z with the same number of points each.
Definition TGraph2D.h:41
static TClass * Class()
TGraphDelaunay2D generates a Delaunay triangulation of a TGraph2D.
TGraphDelaunay generates a Delaunay triangulation of a TGraph2D.
A TGraph is an object made of two arrays X and Y with npoints each.
Definition TGraph.h:41
static TClass * Class()
@ kClipFrame
Clip to the frame boundary.
Definition TGraph.h:75
void PaintGraph(Int_t npoints, const Double_t *x, const Double_t *y, Option_t *chopt)
Draw the (x,y) as a graph.
Definition TGraph.cxx:2015
void PaintGrapHist(Int_t npoints, const Double_t *x, const Double_t *y, Option_t *chopt)
Draw the (x,y) as a histogram.
Definition TGraph.cxx:2024
1-D histogram with a double per channel (see TH1 documentation)
Definition TH1.h:926
1-D histogram with a float per channel (see TH1 documentation)
Definition TH1.h:878
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:109
TAxis * GetZaxis()
Definition TH1.h:573
virtual EBinErrorOpt GetBinErrorOption() const
Definition TH1.h:517
virtual Float_t GetBarWidth() const
Definition TH1.h:501
virtual Double_t GetMinimumStored() const
Definition TH1.h:537
virtual Float_t GetBarOffset() const
Definition TH1.h:500
static TClass * Class()
virtual Double_t GetStdDev(Int_t axis=1) const
Returns the Standard Deviation (Sigma).
Definition TH1.cxx:7816
virtual Int_t GetNbinsY() const
Definition TH1.h:542
virtual Double_t GetBinError(Int_t bin) const
Return value of error associated to bin number bin.
Definition TH1.cxx:9293
virtual Int_t GetNbinsZ() const
Definition TH1.h:543
virtual Double_t GetNormFactor() const
Definition TH1.h:545
virtual Double_t GetMean(Int_t axis=1) const
For axis = 1,2 or 3 returns the mean value of the histogram along X,Y or Z axis.
Definition TH1.cxx:7744
virtual Double_t GetSkewness(Int_t axis=1) const
Definition TH1.cxx:7880
virtual Double_t GetContourLevelPad(Int_t level) const
Return the value of contour number "level" in Pad coordinates.
Definition TH1.cxx:8669
virtual Int_t GetDimension() const
Definition TH1.h:527
@ kNoTitle
Don't draw the histogram title.
Definition TH1.h:408
@ kUserContour
User specified contour levels.
Definition TH1.h:404
@ kNoStats
Don't draw stats box.
Definition TH1.h:403
TAxis * GetXaxis()
Definition TH1.h:571
virtual Double_t GetSumOfWeights() const
Return the sum of weights across all bins excluding under/overflows.
Definition TH1.h:559
virtual Int_t GetBin(Int_t binx, Int_t biny=0, Int_t binz=0) const
Return Global bin number corresponding to binx,y,z.
Definition TH1.cxx:5137
virtual Double_t GetMaximum(Double_t maxval=FLT_MAX) const
Return maximum value smaller than maxval of bins in the range, unless the value has been overridden b...
Definition TH1.cxx:8778
virtual Int_t GetNbinsX() const
Definition TH1.h:541
virtual void SetMaximum(Double_t maximum=-1111)
Definition TH1.h:652
TAxis * GetYaxis()
Definition TH1.h:572
virtual Double_t GetBinErrorLow(Int_t bin) const
Return lower error associated to bin number bin.
Definition TH1.cxx:9309
virtual void SetMinimum(Double_t minimum=-1111)
Definition TH1.h:653
virtual Double_t Integral(Option_t *option="") const
Return integral of bin contents.
Definition TH1.cxx:8170
virtual void SetBinContent(Int_t bin, Double_t content)
Set bin content see convention for numbering bins in TH1::GetBin In case the bin number is greater th...
Definition TH1.cxx:9452
virtual Double_t GetBinLowEdge(Int_t bin) const
Return bin lower edge for 1D histogram.
Definition TH1.cxx:9382
virtual Double_t GetEntries() const
Return the current number of entries.
Definition TH1.cxx:4574
TList * GetListOfFunctions() const
Definition TH1.h:488
virtual Double_t GetMeanError(Int_t axis=1) const
Return standard error of mean of this histogram along the X axis.
Definition TH1.cxx:7784
virtual Double_t GetMaximumStored() const
Definition TH1.h:533
virtual void GetMinimumAndMaximum(Double_t &min, Double_t &max) const
Retrieve the minimum and maximum values in the histogram.
Definition TH1.cxx:8964
virtual Int_t GetMaximumBin() const
Return location of bin with maximum value in the range.
Definition TH1.cxx:8810
@ kNormal
Errors with Normal (Wald) approximation: errorUp=errorLow= sqrt(N)
Definition TH1.h:115
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition TH1.cxx:5239
virtual Int_t GetContour(Double_t *levels=nullptr)
Return contour values into array levels if pointer levels is non zero.
Definition TH1.cxx:8640
const Double_t * GetBuffer() const
Definition TH1.h:483
virtual Bool_t IsHighlight() const
Definition TH1.h:585
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width for 1D histogram.
Definition TH1.cxx:9393
virtual void SetContour(Int_t nlevels, const Double_t *levels=nullptr)
Set the number and values of contour levels.
Definition TH1.cxx:8716
virtual Double_t GetBinErrorUp(Int_t bin) const
Return upper error associated to bin number bin.
Definition TH1.cxx:9340
virtual Int_t GetSumw2N() const
Definition TH1.h:562
virtual Double_t GetStdDevError(Int_t axis=1) const
Return error of standard deviation estimation for Normal distribution.
Definition TH1.cxx:7864
virtual Double_t GetMinimum(Double_t minval=-FLT_MAX) const
Return minimum value larger than minval of bins in the range, unless the value has been overridden by...
Definition TH1.cxx:8868
virtual void LabelsDeflate(Option_t *axis="X")
Reduce the number of bins for the axis passed in the option to the number of bins having a label.
Definition TH1.cxx:5423
virtual Int_t BufferEmpty(Int_t action=0)
Fill histogram with all entries in the buffer.
Definition TH1.cxx:1445
virtual Double_t GetKurtosis(Int_t axis=1) const
Definition TH1.cxx:7953
2-D histogram with a double per channel (see TH1 documentation)
Definition TH2.h:400
2-D histogram with a float per channel (see TH1 documentation)
Definition TH2.h:345
Helper class to represent a bin in the TH2Poly histogram.
Definition TH2Poly.h:25
2D Histogram with Polygonal Bins
Definition TH2Poly.h:66
static TClass * Class()
Service class for 2-D histogram classes.
Definition TH2.h:30
TH1D * ProjectionY(const char *name="_py", Int_t firstxbin=0, Int_t lastxbin=-1, Option_t *option="") const
Project a 2-D histogram into a 1-D histogram along Y (integration along X).
Definition TH2.cxx:2444
TH1D * ProjectionX(const char *name="_px", Int_t firstybin=0, Int_t lastybin=-1, Option_t *option="") const
Project a 2-D histogram into a 1-D histogram along X (integration along Y).
Definition TH2.cxx:2401
Double_t GetBinContent(Int_t binx, Int_t biny) const override
Definition TH2.h:97
static TClass * Class()
Double_t Integral(Option_t *option="") const override
Return integral of bin contents.
Definition TH2.cxx:1293
The 3-D histogram classes derived from the 1-D histogram classes.
Definition TH3.h:45
static TClass * Class()
The Histogram stack class.
Definition THStack.h:40
static TClass * Class()
The histogram painter class.
static Int_t ProjectSinusoidal2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function code for sinusoidal projection from Ernst-Jan Buis Source https://en....
void Paint(Option_t *option="") override
Control routine to paint any kind of histograms
TAxis * fYaxis
Pointer to Y axis.
std::unique_ptr< TPainter3dAlgorithms > fLego
Pointer to a TPainter3dAlgorithms object.
std::vector< Double_t > fXbuf
X buffer coordinates.
Int_t fXHighlightBin
X highlight bin.
TF3 * fCurrentF3
Current TF3 function.
virtual void PaintErrors(Option_t *option)
Draw 1D histograms error bars.
~THistPainter() override
destructor.
Int_t fShowProjection2
True if a second projection must be drawn (when calling SetShowProjectionXY on a TH2)
virtual void PaintTF3()
Control function to draw a 3D implicit functions.
virtual Int_t TableInit()
Initialize various options to draw 2D histograms.
virtual void PaintTH2PolyScatterPlot(Option_t *option)
Control function to draw a TH2Poly as a scatter plot.
static Int_t ProjectMollweide2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
static Int_t ProjectAitoff2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
virtual void PaintText(Option_t *option)
Control function to draw a 1D/2D histograms with the bin values.
Int_t DistancetoPrimitive(Int_t px, Int_t py) override
Compute the distance from the point px,py to a line.
virtual void PaintAxis(Bool_t drawGridOnly=kFALSE)
Draw axis (2D case) of an histogram.
virtual void PaintColorLevelsFast(Option_t *option)
[Rendering scheme for the COL2 and COLZ2 options] (HP14)
virtual Int_t PaintInit()
Compute histogram parameters used by the drawing routines.
virtual void Paint2DErrors(Option_t *option)
Draw 2D histograms errors.
Int_t fYHighlightBin
Y highlight bin.
virtual void PaintCandlePlot(Option_t *option)
Control function to draw a 2D histogram as a candle (box) plot or violin plot
virtual void PaintScatterPlot(Option_t *option)
Control function to draw a 2D histogram as a scatter plot.
void SetShowProjectionXY(const char *option, Int_t nbinsY, Int_t nbinsX) override
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 fShowProjection
True if a projection must be drawn.
virtual void PaintLegoAxis(TGaxis *axis, Double_t ang)
Draw the axis for legos and surface plots.
virtual void PaintTriangles(Option_t *option)
Control function to draw a table using Delaunay triangles.
virtual void HighlightBin(Int_t px, Int_t py)
Check on highlight bin.
virtual void PaintH3Box(Int_t iopt)
Control function to draw a 3D histogram with boxes.
Int_t MakeCuts(char *cutsopt) override
Decode string choptin and fill Graphical cuts structure.
TList * fFunctions
Pointer to histogram list of functions.
void DrawPanel() override
Display a panel with all histogram drawing options.
std::unique_ptr< TPie > fPie
Pointer to a TPie in case of option PIE.
static void PaintSpecialObjects(const TObject *obj, Option_t *option)
Static function to paint special objects like vectors and matrices.
virtual void PaintTitle()
new TGaxis/////////////////// Draw the histogram title
virtual void PaintTH2PolyColorLevels(Option_t *option)
Control function to draw a TH2Poly as a color plot.
virtual std::vector< THistRenderingRegion > ComputeRenderingRegions(TAxis *pAxis, Int_t nPixels, bool isLog)
Returns the rendering regions for an axis to use in the COL2 option.
virtual void ShowProjectionX(Int_t px, Int_t py)
Show projection onto X.
virtual void PaintPalette()
Paint the color palette on the right side of the pad.
TAxis * fXaxis
Pointer to X axis.
virtual void PaintStat2(Int_t dostat, TF1 *fit)
Draw the statistics box for 2D histograms.
virtual void PaintArrows(Option_t *option)
Control function to draw a table as an arrow plot
virtual void RecalculateRange()
Recompute the histogram range following graphics operations.
void PaintStat(Int_t dostat, TF1 *fit) override
Draw the statistics box for 1D and profile histograms.
static Int_t ProjectParabolic2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function code for parabolic projection from Ernst-Jan Buis.
std::unique_ptr< TGraph2DPainter > fGraph2DPainter
Pointer to a TGraph2DPainter object.
virtual void PaintBarH(Option_t *option)
Draw a bar char in a rotated pad (X vertical, Y horizontal)
virtual void PaintStat3(Int_t dostat, TF1 *fit)
Draw the statistics box for 3D histograms.
virtual void PaintSurface(Option_t *option)
Control function to draw a 2D histogram as a surface plot.
TList * fStack
Pointer to stack of histograms (if any)
THistPainter()
Default constructor.
TH1 * fH
Pointer to histogram to paint.
virtual void PaintTH2PolyText(Option_t *option)
Control function to draw a TH2Poly as a text plot.
virtual void ShowProjection3(Int_t px, Int_t py)
Show projection (specified by fShowProjection) of a TH3.
TAxis * fZaxis
Pointer to Z axis.
void SetHistogram(TH1 *h) override
Set current histogram to h
virtual void PaintFunction(Option_t *option)
[Paint functions associated to an histogram.](HP28")
virtual void PaintBar(Option_t *option)
Draw a bar-chart in a normal pad.
static Int_t ProjectMercator2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
virtual void PaintBoxes(Option_t *option)
Control function to draw a 2D histogram as a box plot
virtual Int_t MakeChopt(Option_t *option)
Decode string choptin and fill Hoption structure.
char * GetObjectInfo(Int_t px, Int_t py) const override
Display the histogram info (bin number, contents, integral up to bin corresponding to cursor position...
TList * GetContourList(Double_t contour) const override
Get a contour (as a list of TGraphs) using the Delaunay triangulation.
void ProcessMessage(const char *mess, const TObject *obj) override
Process message mess.
void SetShowProjection(const char *option, Int_t nbins) override
Set projection.
virtual void ShowProjectionY(Int_t px, Int_t py)
Show projection onto Y.
static const char * GetBestFormat(Double_t v, Double_t e, const char *f)
This function returns the best format to print the error value (e) knowing the parameter value (v) an...
virtual void PaintContour(Option_t *option)
Control function to draw a 2D histogram as a contour plot.
TCutG * fCuts[kMaxCuts]
Pointers to graphical cuts.
virtual void PaintTable(Option_t *option)
Control function to draw 2D/3D histograms (tables).
void ExecuteEvent(Int_t event, Int_t px, Int_t py) override
Execute the actions corresponding to event.
virtual Int_t PaintInitH()
Compute histogram parameters used by the drawing routines for a rotated pad.
virtual void PaintFrame()
Calculate range and clear pad (canvas).
Int_t fCutsOpt[kMaxCuts]
Sign of each cut.
virtual void PaintH3Iso()
Control function to draw a 3D histogram with Iso Surfaces.
std::vector< Double_t > fYbuf
Y buffer coordinates.
virtual void PaintH3BoxRaster()
Control function to draw a 3D histogram with boxes.
virtual void PaintHist(Option_t *option)
Control routine to draw 1D histograms
void SetHighlight() override
Set highlight (enable/disable) mode for fH.
virtual void DefineColorLevels(Int_t ndivz)
Define the color levels used to paint legos, surfaces etc..
TString fObjectInfo
virtual void PaintColorLevels(Option_t *option)
Control function to draw a 2D histogram as a color plot.
Bool_t IsInside(Int_t x, Int_t y) override
Return kTRUE if the cell ix, iy is inside one of the graphical cuts.
A class to define a conversion from pixel values to pixel color.
Definition TAttImage.h:33
static TImagePalette * CreateCOLPalette(Int_t nContours)
Factory method to creates an image palette for histogram plotting.
An abstract interface to image processing library.
Definition TImage.h:29
static TImage * Create()
Create an image.
Definition TImage.cxx:34
void Reset()
To draw Mathematical Formula.
Definition TLatex.h:20
A doubly linked list.
Definition TList.h:38
TObject * FindObject(const char *name) const override
Find an object in this list using its name.
Definition TList.cxx:708
void Add(TObject *obj) override
Definition TList.h:81
TObject * Remove(TObject *obj) override
Remove object from the list.
Definition TList.cxx:952
TObject * First() const override
Return the first object in the list. Returns 0 when list is empty.
Definition TList.cxx:789
virtual TObjLink * FirstLink() const
Definition TList.h:107
TObject * At(Int_t idx) const override
Returns the object at position idx. Returns 0 if idx is out of range.
Definition TList.cxx:487
void AddFirst(TObject *obj) override
Add object at the beginning of the list.
Definition TList.cxx:97
TMatrixTBase.
static TClass * Class()
A TMultiGraph is a collection of TGraph (or derived) objects.
Definition TMultiGraph.h:34
TList * GetListOfGraphs() const
Definition TMultiGraph.h:70
static TClass * Class()
virtual Int_t IsInside(Double_t x, Double_t y) const
Return 1 if the point (x,y) is inside one of the graphs 0 otherwise.
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:50
An array of TObjects.
Definition TObjArray.h:31
Mother of all ROOT objects.
Definition TObject.h:42
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:461
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:204
virtual Option_t * GetDrawOption() const
Get option used by the graphics system to draw this object.
Definition TObject.cxx:444
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1082
virtual TObject * FindObject(const char *name) const
Must be redefined in derived classes.
Definition TObject.cxx:424
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:886
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:548
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1096
virtual const char * GetTitle() const
Returns title of object.
Definition TObject.cxx:506
void ResetBit(UInt_t f)
Definition TObject.h:203
@ kCannotPick
if object in a pad cannot be picked
Definition TObject.h:76
@ kCanDelete
if object in a list can be deleted
Definition TObject.h:71
@ kMustCleanup
if object destructor must call RecursiveRemove()
Definition TObject.h:73
void DrawFaceMove3(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 3rd variant for "MOVING SCREEN" algorithm (draw level lines only)
void DrawLevelLines(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw level lines without hidden line removal.
void SurfaceFunction(Int_t ia, Int_t ib, Double_t *f, Double_t *t)
Service function for Surfaces.
void DrawFaceMode1(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *t)
Draw face - 1st variant (2 colors: 1st for external surface, 2nd for internal)
void GouraudFunction(Int_t ia, Int_t ib, Double_t *f, Double_t *t)
Find part of surface with luminosity in the corners.
void DrawFaceMove1(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 1st variant for "MOVING SCREEN" algorithm (draw face with level lines)
void DrawFaceRaster2(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 2nd variant for "RASTER SCREEN" algorithm (draw face for stacked lego plot)
void LegoFunction(Int_t ia, Int_t ib, Int_t &nv, Double_t *ab, Double_t *vv, Double_t *t)
Service function for Legos.
void DrawFaceMove2(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 2nd variant for "MOVING SCREEN" algorithm (draw face for stacked lego plot)
void DrawFaceRaster1(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 1st variant for "RASTER SCREEN" algorithm (draw face with level lines)
void DrawFaceMode3(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *t)
Draw face - 3rd option (draw face for stacked lego plot)
void DrawFaceMode2(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *t)
Draw face - 2nd option (fill in correspondence with function levels)
The palette painting class.
The histogram statistics painter class.
Definition TPaveStats.h:18
Int_t GetOptStat() const
Return the stat option.
virtual void SetStatFormat(const char *format="6.4g")
Change (i.e. set) the format for printing statistics.
void SetOptStat(Int_t stat=1)
Set the stat option.
virtual const char * GetFitFormat() const
Definition TPaveStats.h:35
virtual void SetFitFormat(const char *format="5.4g")
Change (i.e. set) the format for printing fit parameters in statistics box.
Int_t GetOptFit() const
Return the fit option.
void SetParent(TObject *obj) override
Definition TPaveStats.h:53
void SetOptFit(Int_t fit=1)
Set the fit option.
virtual const char * GetStatFormat() const
Definition TPaveStats.h:36
void Paint(Option_t *option="") override
Paint the pave stat.
static TClass * Class()
A Pave (see TPave) with text, lines or/and boxes inside.
Definition TPaveText.h:21
virtual TText * AddText(Double_t x1, Double_t y1, const char *label)
Add a new Text line to this pavetext at given coordinates.
static TClass * Class()
void Clear(Option_t *option="") override
Clear all lines in this pavetext.
virtual TText * GetLine(Int_t number) const
Get Pointer to line number in this pavetext.
const char * GetName() const override
Returns name of object.
Definition TPave.h:58
virtual void SetName(const char *name="")
Definition TPave.h:81
virtual void SetBorderSize(Int_t bordersize=4)
Sets the border size of the TPave box and shadow.
Definition TPave.h:79
Option_t * GetOption() const override
Definition TPave.h:59
Double_t GetX1NDC() const
Definition TPave.h:61
virtual void SetX2NDC(Double_t x2)
Definition TPave.h:85
void SetX(SCoord_t x)
Definition TPoint.h:48
void SetY(SCoord_t y)
Definition TPoint.h:49
Profile2D histograms are used to display the mean value of Z and its error for each cell in X,...
Definition TProfile2D.h:27
static TClass * Class()
Profile Histogram.
Definition TProfile.h:32
static TClass * Class()
Random number generator class based on the maximally equidistributed combined Tausworthe generator by...
Definition TRandom2.h:27
Sequenceable collection abstract base class.
Basic string class.
Definition TString.h:137
void ToLower()
Change string to lower-case.
Definition TString.cxx:1190
const char * Data() const
Definition TString.h:385
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:1872
Base class for several text objects.
Definition TText.h:22
TVectorT.
Definition TVectorT.h:29
static TClass * Class()
See TView3D.
Definition TView.h:25
virtual Double_t GetPsi()=0
virtual Double_t * GetRmax()=0
virtual void SetAxisNDC(const Double_t *x1, const Double_t *x2, const Double_t *y1, const Double_t *y2, const Double_t *z1, const Double_t *z2)=0
virtual Double_t * GetRmin()=0
virtual void WCtoNDC(const Float_t *pw, Float_t *pn)=0
virtual void SetOutlineToCube()=0
virtual Int_t GetDistancetoAxis(Int_t axis, Int_t px, Int_t py, Double_t &ratio)=0
virtual Double_t * GetTnorm()=0
virtual void ExecuteRotateView(Int_t event, Int_t px, Int_t py)=0
virtual TSeqCollection * GetOutline()=0
virtual void PadRange(Int_t rback)=0
virtual void SetRange(const Double_t *min, const Double_t *max)=0
virtual void FindNormal(Double_t x, Double_t y, Double_t z, Double_t &zn)=0
virtual void AxisVertex(Double_t ang, Double_t *av, Int_t &ix1, Int_t &ix2, Int_t &iy1, Int_t &iy2, Int_t &iz1, Int_t &iz2)=0
virtual void SetView(Double_t longitude, Double_t latitude, Double_t psi, Int_t &irep)=0
Abstract base class used by ROOT graphics editor.
static TVirtualPadEditor * GetPadEditor(Bool_t load=kTRUE)
Returns the pad editor dialog. Static method.
small helper class to store/restore gPad context in TPad methods
Definition TVirtualPad.h:61
TVirtualPad is an abstract base class for the Pad and Canvas classes.
Definition TVirtualPad.h:51
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