Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
THistPainter.cxx
Go to the documentation of this file.
1// @(#)root/histpainter:$Id$
2// Author: Rene Brun, Olivier Couet
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12#include <cstdlib>
13#include <cstring>
14#include <cstdio>
15#include <cctype>
16#include <iostream>
17
18#include "TROOT.h"
19#include "TSystem.h"
20#include "THistPainter.h"
21#include "TH2.h"
22#include "TH2Poly.h"
23#include "TH3.h"
24#include "TProfile.h"
25#include "TProfile2D.h"
26#include "THStack.h"
27#include "TF2.h"
28#include "TF3.h"
29#include "TCutG.h"
30#include "TMatrixDBase.h"
31#include "TMatrixFBase.h"
32#include "TVectorD.h"
33#include "TVectorF.h"
34#include "TCanvas.h"
35#include "TPad.h"
36#include "TPaveStats.h"
37#include "TFrame.h"
38#include "TLatex.h"
39#include "TPolyLine.h"
40#include "TPoints.h"
41#include "TStyle.h"
42#include "TGraph.h"
43#include "TMultiGraph.h"
44#include "TPie.h"
45#include "TGaxis.h"
46#include "TColor.h"
48#include "TGraph2D.h"
49#include "TGraph2DPainter.h"
50#include "TGraphDelaunay2D.h"
51#include "TView.h"
52#include "TMath.h"
53#include "TRandom2.h"
54#include "TObjArray.h"
55#include "Hoption.h"
56#include "Hparam.h"
57#include "TPluginManager.h"
58#include "TPaletteAxis.h"
59#include "TCrown.h"
60#include "TArrow.h"
61#include "TVirtualPadEditor.h"
62#include "TVirtualX.h"
63#include "TEnv.h"
64#include "TPoint.h"
65#include "TImage.h"
66#include "TCandle.h"
67#include "strlcpy.h"
68
69/*! \class THistPainter
70 \ingroup Histpainter
71 \brief The histogram painter class. Implements all histograms' drawing's options.
72
73- [Introduction](\ref HP00)
74- [Histograms' plotting options](\ref HP01)
75 - [Options supported for 1D and 2D histograms](\ref HP01a)
76 - [Options supported for 1D histograms](\ref HP01b)
77 - [Options supported for 2D histograms](\ref HP01c)
78 - [Options supported for 3D histograms](\ref HP01d)
79 - [Options supported for histograms' stacks (THStack)](\ref HP01e)
80- [Setting the Style](\ref HP02)
81- [Setting line, fill, marker, and text attributes](\ref HP03)
82- [Setting Tick marks on the histogram axis](\ref HP04)
83- [Giving titles to the X, Y and Z axis](\ref HP05)
84- [The option "SAME"](\ref HP060)
85 - [Limitations](\ref HP060a)
86- [Colors automatically picked in palette](\ref HP061)
87- [Superimposing two histograms with different scales in the same pad](\ref HP06)
88- [Statistics Display](\ref HP07)
89- [Fit Statistics](\ref HP08)
90- [The error bars options](\ref HP09)
91- [The bar chart option](\ref HP100)
92- [The "BAR" and "HBAR" options](\ref HP10)
93- [The SCATter plot option (legacy draw option)](\ref HP11)
94- [The ARRow option](\ref HP12)
95- [The BOX option](\ref HP13)
96- [The COLor option (default for 2D and 3D histograms)](\ref HP14)
97- [The CANDLE and VIOLIN options](\ref HP140)
98 - [The CANDLE option](\ref HP140a)
99 - [The VIOLIN option](\ref HP140b)
100- [The TEXT and TEXTnn Option](\ref HP15)
101- [The CONTour options](\ref HP16)
102 - [The LIST option](\ref HP16a)
103 - [The AITOFF, MERCATOR, SINUSOIDAL and PARABOLIC options](\ref HP16b)
104- [The LEGO options](\ref HP17)
105- [The "SURFace" options](\ref HP18)
106- [Cylindrical, Polar, Spherical and PseudoRapidity/Phi options](\ref HP19)
107- [Base line for bar-charts and lego plots](\ref HP20)
108- [TH2Poly Drawing](\ref HP20a)
109- [The SPEC option](\ref HP21)
110- [Option "Z" : Adding the color palette on the right side of the pad](\ref HP22)
111- [Setting the color palette](\ref HP23)
112- [Drawing a sub-range of a 2-D histogram; the [cutg] option](\ref HP24)
113- [Drawing options for 3D histograms](\ref HP25)
114- [Drawing option for histograms' stacks](\ref HP26)
115- [Drawing of 3D implicit functions](\ref HP27)
116- [Associated functions drawing](\ref HP28)
117- [Drawing using OpenGL](\ref HP29)
118 - [General information: plot types and supported options](\ref HP29a)
119 - [TH3 as color boxes](\ref HP290)
120 - [TH3 as boxes (spheres)](\ref HP29b)
121 - [TH3 as iso-surface(s)](\ref HP29c)
122 - [TF3 (implicit function)](\ref HP29d)
123 - [Parametric surfaces](\ref HP29e)
124 - [Interaction with the plots](\ref HP29f)
125 - [Selectable parts](\ref HP29g)
126 - [Rotation and zooming](\ref HP29h)
127 - [Panning](\ref HP29i)
128 - [Box cut](\ref HP29j)
129 - [Plot specific interactions (dynamic slicing etc.)](\ref HP29k)
130 - [Surface with option "GLSURF"](\ref HP29l)
131 - [TF3](\ref HP29m)
132 - [Box](\ref HP29n)
133 - [Iso](\ref HP29o)
134 - [Parametric plot](\ref HP29p)
135- [Highlight mode for histogram](\ref HP30)
136 - [Highlight mode and user function](\ref HP30a)
137
138
139\anchor HP00
140## Introduction
141
142
143Histograms are drawn via the `THistPainter` class. Each histogram has a
144pointer to its own painter (to be usable in a multithreaded program). When the
145canvas has to be redrawn, the `Paint` function of each objects in the
146pad is called. In case of histograms, `TH1::Paint` invokes directly
147`THistPainter::Paint`.
148
149To draw a histogram `h` it is enough to do:
150
151 h->Draw();
152
153`h` can be of any kind: 1D, 2D or 3D. To choose how the histogram will
154be drawn, the `Draw()` method can be invoked with an option. For instance
155to draw a 2D histogram as a lego plot it is enough to do:
156
157 h->Draw("lego");
158
159`THistPainter` offers many options to paint 1D, 2D and 3D histograms.
160
161When the `Draw()` method of a histogram is called for the first time
162(`TH1::Draw`), it creates a `THistPainter` object and saves a
163pointer to this "painter" as a data member of the histogram. The
164`THistPainter` class specializes in the drawing of histograms. It is
165separated from the histogram so that one can have histograms without the
166graphics overhead, for example in a batch program. Each histogram having its own
167painter (rather than a central singleton painter painting all histograms), allows
168two histograms to be drawn in two threads without overwriting the painter's
169values.
170
171When a displayed histogram is filled again, there is no need to call the
172`Draw()` method again; the image will be refreshed the next time the
173pad will be updated.
174
175A pad is updated after one of these three actions:
176
1771. a carriage control on the ROOT command line,
1782. a click inside the pad,
1793. a call to `TPad::Update`.
180
181
182By default a call to `TH1::Draw()` clears the pad of all objects
183before drawing the new image of the histogram. One can use the `SAME`
184option to leave the previous display intact and superimpose the new histogram.
185The same histogram can be drawn with different graphics options in different
186pads.
187
188When a displayed histogram is deleted, its image is automatically removed
189from the pad.
190
191To create a copy of the histogram when drawing it, one can use
192`TH1::DrawClone()`. This will clone the histogram and allow to change
193and delete the original one without affecting the clone.
194
195
196\anchor HP01
197### Histograms' plotting options
198
199
200Most options can be concatenated with or without spaces or commas, for example:
201
202 h->Draw("E1 SAME");
203
204The options are not case sensitive:
205
206 h->Draw("e1 same");
207
208
209The default drawing option can be set with `TH1::SetOption` and retrieve
210using `TH1::GetOption`:
211
212 root [0] h->Draw(); // Draw "h" using the standard histogram representation.
213 root [1] h->Draw("E"); // Draw "h" using error bars
214 root [3] h->SetOption("E"); // Change the default drawing option for "h"
215 root [4] h->Draw(); // Draw "h" using error bars
216 root [5] h->GetOption(); // Retrieve the default drawing option for "h"
217 (const Option_t* 0xa3ff948)"E"
218
219
220\anchor HP01a
221#### Options supported for 1D and 2D histograms
222
223| Option | Description |
224|----------|-------------------------------------------------------------------|
225| "E" | Draw error bars. |
226| "AXIS" | Draw only axis. |
227| "AXIG" | Draw only grid (if the grid is requested). |
228| \anchor OPTHIST "HIST" | When an histogram has errors it is visualized by default with error bars. To visualize it
229without errors use the option "HIST" together with the required option (eg "hist same c"). The "HIST" option can also
230be used to plot only the histogram and not the associated function(s). | | "FUNC" | When an histogram has a fitted
231function, this option allows to draw the fit result only. | | "SAME" | Superimpose on previous picture in the same
232pad. | | "SAMES" | Same as "SAME" and draw the statistics box| | "PFC" | Palette Fill Color: histogram's fill color
233is taken in the current palette. | | "PLC" | Palette Line Color: histogram's line color is taken in the current
234palette. | | "PMC" | Palette Marker Color: histogram's marker color is taken in the current palette. | | "LEGO" |
235Draw a lego plot with hidden line removal. | | "LEGO1" | Draw a lego plot with hidden surface removal. | | "LEGO2" |
236Draw a lego plot using colors to show the cell contents When the option "0" is used with any LEGO option, the empty bins
237are not drawn.| | "LEGO3" | Draw a lego plot with hidden surface removal, like LEGO1 but the border lines of each
238lego-bar are not drawn.| | "LEGO4" | Draw a lego plot with hidden surface removal, like LEGO1 but without the shadow
239effect on each lego-bar.| | "TEXT" | Draw bin contents as text (format set via `gStyle->SetPaintTextFormat`).| |
240"TEXTnn" | Draw bin contents as text at angle nn (0 < nn <= 90). | | "X+" | The X-axis is drawn on the top side of
241the plot. | | "Y+" | The Y-axis is drawn on the right side of the plot. | | "MIN0" | Set minimum value for the Y
242axis to 0, equivalent to gStyle->SetHistMinimumZero(). |
243
244\anchor HP01b
245#### Options supported for 1D histograms
246
247| Option | Description |
248|----------|-------------------------------------------------------------------|
249| " " | Default. |
250| "AH" | Draw histogram without axis. "A" can be combined with any drawing option. For instance, "AC" draws the
251histogram as a smooth Curve without axis.| | "][" | When this option is selected the first and last vertical lines
252of the histogram are not drawn.| | "B" | Bar chart option.| | "BAR" | Like option "B", but bars can be drawn
253with a 3D effect.| | "HBAR" | Like option "BAR", but bars are drawn horizontally.| | "C" | Draw a smooth Curve
254through the histogram bins.| | "E0" | Draw error bars. Markers are drawn for bins with 0 contents. Combined with E1
255or E2 it avoids error bars clipping| | "E1" | Draw error bars with perpendicular lines at the edges.| | "E2" |
256Draw error bars with rectangles.| | "E3" | Draw a fill area through the end points of the vertical error bars.| |
257"E4" | Draw a smoothed filled area through the end points of the error bars.| | "E5" | Like E3 but ignore the
258bins with 0 contents.| | "E6" | Like E4 but ignore the bins with 0 contents.| | "X0" | When used with one of the
259"E" option, it suppress the error bar along X as `gStyle->SetErrorX(0)` would do.| | "L" | Draw a line through the
260bin contents.| | "P" | Draw current marker at each bin except empty bins.| | "P*" | Draw a star marker at each
261bin except empty bins.| | "P0" | Draw current marker at each bin including empty bins.| | "PIE" | Draw histogram
262as a Pie Chart.| | "*H" | Draw histogram with a * at each bin.| | "LF2" | Draw histogram like with option "L" but
263with a fill area. Note that "L" draws also a fill area if the hist fill color is set but the fill area corresponds to
264the histogram contour.|
265
266
267\anchor HP01c
268#### Options supported for 2D histograms
269
270| Option | Description |
271|--------------|------------------------------------------------------------------|
272| " " | Default (color plot).|
273| "ARR" | Arrow mode. Shows gradient between adjacent cells.|
274| "BOX" | A box is drawn for each cell with surface proportional to the content's absolute value. A negative
275content is marked with a X. | | "BOX1" | A button is drawn for each cell with surface proportional to content's
276absolute value. A sunken button is drawn for negative values a raised one for positive.| | "COL" | A box is drawn
277for each cell with a color scale varying with contents. All the none empty bins are painted. Empty bins are not painted
278unless some bins have a negative content because in that case the null bins might be not empty. `TProfile2D` histograms
279are handled differently because, for this type of 2D histograms, it is possible to know if an empty bin has been filled
280or not. So even if all the bins' contents are positive some empty bins might be painted. And vice versa, if some bins
281have a negative content some empty bins might be not painted (default).| | "COLZ" | Same as "COL". In addition the
282color palette is also drawn.| | "COL2" | Alternative rendering algorithm to "COL". Can significantly improve
283rendering performance for large, non-sparse 2-D histograms.| | "COLZ2" | Same as "COL2". In addition the color
284palette is also drawn.| | "Z CJUST" | In combination with colored options "COL","CONT0" etc: Justify labels in the
285color palette at color boundaries. For more details see `TPaletteAxis`| | "CANDLE" | Draw a candle plot along X
286axis.| | "CANDLEX" | Same as "CANDLE".| | "CANDLEY" | Draw a candle plot along Y axis.| | "CANDLEXn" | Draw a
287candle plot along X axis. Different candle-styles with n from 1 to 6.| | "CANDLEYn" | Draw a candle plot along Y axis.
288Different candle-styles with n from 1 to 6.| | "VIOLIN" | Draw a violin plot along X axis.| | "VIOLINX" | Same as
289"VIOLIN".| | "VIOLINY" | Draw a violin plot along Y axis.| | "VIOLINXn" | Draw a violin plot along X axis.
290Different violin-styles with n being 1 or 2.| | "VIOLINYn" | Draw a violin plot along Y axis. Different violin-styles
291with n being 1 or 2.| | "CONT" | Draw a contour plot (same as CONT0).| | "CONT0" | Draw a contour plot using
292surface colors to distinguish contours.| | "CONT1" | Draw a contour plot using line styles to distinguish
293contours.| | "CONT2" | Draw a contour plot using the same line style for all contours.| | "CONT3" | Draw a
294contour plot using fill area colors.| | "CONT4" | Draw a contour plot using surface colors (SURF option at theta =
2950).| | "LIST" | Generate a list of TGraph objects for each contour.| | "SAME0" | Same as "SAME" but do not
296use the z-axis range of the first plot. | | "SAMES0" | Same as "SAMES" but do not use the z-axis range of the first
297plot. | | "CYL" | Use Cylindrical coordinates. The X coordinate is mapped on the angle and the Y coordinate on
298the cylinder length.| | "POL" | Use Polar coordinates. The X coordinate is mapped on the angle and the Y
299coordinate on the radius.| | "SPH" | Use Spherical coordinates. The X coordinate is mapped on the latitude and
300the Y coordinate on the longitude.| | "PSR" | Use PseudoRapidity/Phi coordinates. The X coordinate is mapped on
301Phi.| | "SURF" | Draw a surface plot with hidden line removal.| | "SURF1" | Draw a surface plot with hidden
302surface removal.| | "SURF2" | Draw a surface plot using colors to show the cell contents.| | "SURF3" | Same as
303SURF with in addition a contour view drawn on the top.| | "SURF4" | Draw a surface using Gouraud shading.| |
304"SURF5" | Same as SURF3 but only the colored contour is drawn. Used with option CYL, SPH or PSR it allows to draw
305colored contours on a sphere, a cylinder or a in pseudo rapidity space. In cartesian or polar coordinates, option SURF3
306is used.| | "AITOFF" | Draw a contour via an AITOFF projection.| | "MERCATOR" | Draw a contour via an Mercator
307projection.| | "SINUSOIDAL" | Draw a contour via an Sinusoidal projection.| | "PARABOLIC" | Draw a contour via an
308Parabolic projection.| | "MOLLWEIDE" | Draw a contour via an Mollweide projection.| | "LEGO9" | Draw the 3D axis
309only. Mainly needed for internal use | | "FB" | With LEGO or SURFACE, suppress the Front-Box.| | "BB" |
310With LEGO or SURFACE, suppress the Back-Box.| | "A" | With LEGO or SURFACE, suppress the axis.| | "SCAT" | Draw
311a scatter-plot (legacy draw option).| | "[cutg]" | Draw only the sub-range selected by the TCutG named "cutg".|
312
313
314\anchor HP01d
315#### Options supported for 3D histograms
316
317| Option | Description |
318|----------|-------------------------------------------------------------------|
319| " " | Default (color plot).|
320| "ISO" | Draw a Gouraud shaded 3d iso surface through a 3d histogram. It paints one surface at the value computed as
321follow: `SumOfWeights/(NbinsX*NbinsY*NbinsZ)`.| | "BOX" | Draw a for each cell with volume proportional to the
322content's absolute value. An hidden line removal algorithm is used| | "BOX1" | Same as BOX but an hidden surface
323removal algorithm is used| | "BOX2" | The boxes' colors are picked in the current palette according to the bins'
324contents| | "BOX2Z" | Same as "BOX2". In addition the color palette is also drawn.| | "BOX3" | Same as BOX1, but the
325border lines of each lego-bar are not drawn.| | "LEGO" | Same as `BOX`.|
326
327
328\anchor HP01e
329#### Options supported for histograms' stacks (`THStack`)
330
331| Option | Description |
332|------------|-----------------------------------------------------------------|
333| " " | Default, the histograms are drawn on top of each other (as lego plots for 2D histograms).|
334| "NOSTACK" | Histograms in the stack are all paint in the same pad as if the option `SAME` had been specified.|
335| "NOSTACKB" | Histograms are drawn next to each other as bar charts.|
336| "PADS" | The current pad/canvas is subdivided into a number of pads equal to the number of histograms in the stack
337and each histogram is paint into a separate pad.| | "PFC" | Palette Fill Color: stack's fill color is taken in the
338current palette. | | "PLC" | Palette Line Color: stack's line color is taken in the current palette. | | "PMC" |
339Palette Marker Color: stack's marker color is taken in the current palette. |
340
341
342
343\anchor HP02
344### Setting the Style
345
346
347Histograms use the current style (`gStyle`). When one changes the current
348style and would like to propagate the changes to the histogram,
349`TH1::UseCurrentStyle` should be called. Call `UseCurrentStyle` on
350each histogram is needed.
351
352To force all the histogram to use the current style use:
353
354 gROOT->ForceStyle();
355
356All the histograms read after this call will use the current style.
357
358
359\anchor HP03
360### Setting line, fill, marker, and text attributes
361
362
363The histogram classes inherit from the attribute classes:
364`TAttLine`, `TAttFill` and `TAttMarker`.
365See the description of these classes for the list of options.
366
367
368\anchor HP04
369### Setting Tick marks on the histogram axis
370
371
372The `TPad::SetTicks` method specifies the type of tick marks on the axis.
373If ` tx = gPad->GetTickx()` and `ty = gPad->GetTicky()` then:
374
375 tx = 1; tick marks on top side are drawn (inside)
376 tx = 2; tick marks and labels on top side are drawn
377 ty = 1; tick marks on right side are drawn (inside)
378 ty = 2; tick marks and labels on right side are drawn
379
380By default only the left Y axis and X bottom axis are drawn
381(`tx = ty = 0`)
382
383`TPad::SetTicks(tx,ty)` allows to set these options.
384See also The `TAxis` functions to set specific axis attributes.
385
386In case multiple color filled histograms are drawn on the same pad, the fill
387area may hide the axis tick marks. One can force a redraw of the axis over all
388the histograms by calling:
389
390 gPad->RedrawAxis();
391
392
393\anchor HP05
394### Giving titles to the X, Y and Z axis
395
396
397 h->GetXaxis()->SetTitle("X axis title");
398 h->GetYaxis()->SetTitle("Y axis title");
399
400The histogram title and the axis titles can be any `TLatex` string.
401The titles are part of the persistent histogram.
402
403
404\anchor HP060
405### The option "SAME"
406
407
408By default, when an histogram is drawn, the current pad is cleared before
409drawing. In order to keep the previous drawing and draw on top of it the
410option `SAME` should be use. The histogram drawn with the option
411`SAME` uses the coordinates system available in the current pad.
412
413This option can be used alone or combined with any valid drawing option but
414some combinations must be use with care.
415
416\anchor HP060a
417#### Limitations
418
419- It does not work when combined with the `LEGO` and `SURF` options unless the
420 histogram plotted with the option `SAME` has exactly the same
421 ranges on the X, Y and Z axis as the currently drawn histogram. To superimpose
422 lego plots [histograms' stacks](\ref HP26) should be used.
423
424
425\anchor HP061
426### Colors automatically picked in palette
427
428\since **ROOT version 6.09/01**
429
430When several histograms are painted in the same canvas thanks to the option "SAME"
431or via a `THStack` it might be useful to have an easy and automatic way to choose
432their color. The simplest way is to pick colors in the current active color
433palette. Palette coloring for histogram is activated thanks to the options `PFC`
434(Palette Fill Color), `PLC` (Palette Line Color) and `PMC` (Palette Marker Color).
435When one of these options is given to `TH1::Draw` the histogram get its color
436from the current color palette defined by `gStyle->SetPalette(...)`. The color
437is determined according to the number of objects having palette coloring in
438the current pad.
439
440Begin_Macro(source)
441../../../tutorials/hist/histpalettecolor.C
442End_Macro
443
444Begin_Macro(source)
445../../../tutorials/hist/thstackpalettecolor.C
446End_Macro
447
448Begin_Macro(source)
449../../../tutorials/hist/thstack2palettecolor.C
450End_Macro
451
452\anchor HP06
453### Superimposing two histograms with different scales in the same pad
454
455
456The following example creates two histograms, the second histogram is the bins
457integral of the first one. It shows a procedure to draw the two histograms in
458the same pad and it draws the scale of the second histogram using a new vertical
459axis on the right side. See also the tutorial `transpad.C` for a variant
460of this example.
461
462Begin_Macro(source)
463{
464 auto c1 = new TCanvas("c1","c1",600,400);
465 // create/fill draw h1
466 gStyle->SetOptStat(kFALSE);
467 auto h1 = new TH1F("h1","Superimposing two histograms with different scales",100,-3,3);
468 Int_t i;
469 for (i=0;i<10000;i++) h1->Fill(gRandom->Gaus(0,1));
470 h1->Draw();
471 c1->Update();
472
473 // create hint1 filled with the bins integral of h1
474 auto hint1 = new TH1F("hint1","h1 bins integral",100,-3,3);
475 float sum = 0.f;
476 for (i=1;i<=100;i++) {
477 sum += h1->GetBinContent(i);
478 hint1->SetBinContent(i,sum);
479 }
480
481 // scale hint1 to the pad coordinates
482 float rightmax = 1.1*hint1->GetMaximum();
483 float scale = gPad->GetUymax()/rightmax;
484 hint1->SetLineColor(kRed);
485 hint1->Scale(scale);
486 hint1->Draw("same");
487
488 // draw an axis on the right side
489 auto axis = new TGaxis(gPad->GetUxmax(),gPad->GetUymin(),
490 gPad->GetUxmax(), gPad->GetUymax(),0,rightmax,510,"+L");
491 axis->SetLineColor(kRed);
492 axis->SetTextColor(kRed);
493 axis->Draw();
494}
495End_Macro
496
497
498\anchor HP07
499### Statistics Display
500
501
502The type of information shown in the histogram statistics box can be selected
503with:
504
505 gStyle->SetOptStat(mode);
506
507The `mode` has up to nine digits that can be set to on (1 or 2), off (0).
508
509 mode = ksiourmen (default = 000001111)
510 k = 1; kurtosis printed
511 k = 2; kurtosis and kurtosis error printed
512 s = 1; skewness printed
513 s = 2; skewness and skewness error printed
514 i = 1; integral of bins printed
515 i = 2; integral of bins with option "width" printed
516 o = 1; number of overflows printed
517 u = 1; number of underflows printed
518 r = 1; standard deviation printed
519 r = 2; standard deviation and standard deviation error printed
520 m = 1; mean value printed
521 m = 2; mean and mean error values printed
522 e = 1; number of entries printed
523 n = 1; name of histogram is printed
524
525For example:
526
527 gStyle->SetOptStat(11);
528
529displays only the name of histogram and the number of entries, whereas:
530
531 gStyle->SetOptStat(1101);
532
533displays the name of histogram, mean value and standard deviation.
534
535<b>WARNING 1:</b> never do:
536
537 gStyle->SetOptStat(0001111);
538
539but instead do:
540
541 gStyle->SetOptStat(1111);
542
543because `0001111` will be taken as an octal number!
544
545<b>WARNING 2:</b> for backward compatibility with older versions
546
547 gStyle->SetOptStat(1);
548
549is taken as:
550
551 gStyle->SetOptStat(1111)
552
553To print only the name of the histogram do:
554
555 gStyle->SetOptStat(1000000001);
556
557<b>NOTE</b> that in case of 2D histograms, when selecting only underflow
558(10000) or overflow (100000), the statistics box will show all combinations
559of underflow/overflows and not just one single number.
560
561The parameter mode can be any combination of the letters `kKsSiIourRmMen`
562
563 k : kurtosis printed
564 K : kurtosis and kurtosis error printed
565 s : skewness printed
566 S : skewness and skewness error printed
567 i : integral of bins printed
568 I : integral of bins with option "width" printed
569 o : number of overflows printed
570 u : number of underflows printed
571 r : standard deviation printed
572 R : standard deviation and standard deviation error printed
573 m : mean value printed
574 M : mean value mean error values printed
575 e : number of entries printed
576 n : name of histogram is printed
577
578For example, to print only name of histogram and number of entries do:
579
580 gStyle->SetOptStat("ne");
581
582To print only the name of the histogram do:
583
584 gStyle->SetOptStat("n");
585
586The default value is:
587
588 gStyle->SetOptStat("nemr");
589
590When a histogram is painted, a `TPaveStats` object is created and added
591to the list of functions of the histogram. If a `TPaveStats` object
592already exists in the histogram list of functions, the existing object is just
593updated with the current histogram parameters.
594
595Once a histogram is painted, the statistics box can be accessed using
596`h->FindObject("stats")`. In the command line it is enough to do:
597
598 Root > h->Draw()
599 Root > TPaveStats *st = (TPaveStats*)h->FindObject("stats")
600
601because after `h->Draw()` the histogram is automatically painted. But
602in a script file the painting should be forced using `gPad->Update()`
603in order to make sure the statistics box is created:
604
605 h->Draw();
606 gPad->Update();
607 TPaveStats *st = (TPaveStats*)h->FindObject("stats");
608
609Without `gPad->Update()` the line `h->FindObject("stats")` returns a null pointer.
610
611When a histogram is drawn with the option `SAME`, the statistics box
612is not drawn. To force the statistics box drawing with the option
613`SAME`, the option `SAMES` must be used.
614If the new statistics box hides the previous statistics box, one can change
615its position with these lines (`h` being the pointer to the histogram):
616
617 Root > TPaveStats *st = (TPaveStats*)h->FindObject("stats")
618 Root > st->SetX1NDC(newx1); //new x start position
619 Root > st->SetX2NDC(newx2); //new x end position
620
621To change the type of information for an histogram with an existing
622`TPaveStats` one should do:
623
624 st->SetOptStat(mode);
625
626Where `mode` has the same meaning than when calling `gStyle->SetOptStat(mode)`
627(see above).
628
629One can delete the statistics box for a histogram `TH1* h` with:
630
631 h->SetStats(0)
632
633and activate it again with:
634
635 h->SetStats(1).
636
637Labels used in the statistics box ("Mean", "Std Dev", ...) can be changed from
638`$ROOTSYS/etc/system.rootrc` or `.rootrc` (look for the string `Hist.Stats.`).
639
640
641\anchor HP08
642### Fit Statistics
643
644
645The type of information about fit parameters printed in the histogram statistics
646box can be selected via the parameter mode. The parameter mode can be
647`= pcev` (default `= 0111`)
648
649 p = 1; print Probability
650 c = 1; print Chisquare/Number of degrees of freedom
651 e = 1; print errors (if e=1, v must be 1)
652 v = 1; print name/values of parameters
653
654Example:
655
656 gStyle->SetOptFit(1011);
657
658print fit probability, parameter names/values and errors.
659
6601. When `v = 1` is specified, only the non-fixed parameters are shown.
6612. When `v = 2` all parameters are shown.
662
663Note: `gStyle->SetOptFit(1)` means "default value", so it is equivalent
664to `gStyle->SetOptFit(111)`
665
666
667\anchor HP09
668### The error bars options
669
670
671| Option | Description |
672|----------|-------------------------------------------------------------------|
673| "E" | Default. Shows only the error bars, not a marker.|
674| "E1" | Small lines are drawn at the end of the error bars.|
675| "E2" | Error rectangles are drawn.|
676| "E3" | A filled area is drawn through the end points of the vertical error bars.|
677| "E4" | A smoothed filled area is drawn through the end points of the vertical error bars.|
678| "E0" | Draw error bars. Markers are drawn for bins with 0 contents. Combined with E1 or E2 it avoids error bars
679clipping| | "E5" | Like E3 but ignore the bins with 0 contents.| | "E6" | Like E4 but ignore the bins with 0
680contents.| | "X0" | When used with one of the "E" option, it suppress the error bar along X as
681`gStyle->SetErrorX(0)` would do.|
682
683Begin_Macro(source)
684{
685 auto c1 = new TCanvas("c1","c1",600,400);
686 auto he = new TH1F("he","Distribution drawn with error bars (option E1) ",100,-3,3);
687 for (int i=0; i<10000; i++) he->Fill(gRandom->Gaus(0,1));
688 gStyle->SetEndErrorSize(3);
689 gStyle->SetErrorX(1.);
690 he->SetMarkerStyle(20);
691 he->Draw("E1");
692}
693End_Macro
694
695The options "E3" and "E4" draw an error band through the end points of the
696vertical error bars. With "E4" the error band is smoothed. Because of the
697smoothing algorithm used some artefacts may appear at the end of the band
698like in the following example. In such cases "E3" should be used instead
699of "E4".
700
701Begin_Macro(source)
702{
703 auto ce4 = new TCanvas("ce4","ce4",600,400);
704 ce4->Divide(2,1);
705 auto he4 = new TH1F("he4","Distribution drawn with option E4",100,-3,3);
706 Int_t i;
707 for (i=0;i<10000;i++) he4->Fill(gRandom->Gaus(0,1));
708 he4->SetFillColor(kRed);
709 he4->GetXaxis()->SetRange(40,48);
710 ce4->cd(1);
711 he4->Draw("E4");
712 ce4->cd(2);
713 auto he3 = (TH1F*)he4->DrawClone("E3");
714 he3->SetTitle("Distribution drawn option E3");
715}
716End_Macro
717
7182D histograms can be drawn with error bars as shown is the following example:
719
720Begin_Macro(source)
721{
722 auto c2e = new TCanvas("c2e","c2e",600,400);
723 auto h2e = new TH2F("h2e","TH2 drawn with option E",40,-4,4,40,-20,20);
724 float px, py;
725 for (Int_t i = 0; i < 25000; i++) {
726 gRandom->Rannor(px,py);
727 h2e->Fill(px,5*py);
728 }
729 h2e->Draw("E");
730}
731End_Macro
732
733
734\anchor HP100
735### The bar chart option
736
737
738The option "B" allows to draw simple vertical bar charts.
739The bar width is controlled with `TH1::SetBarWidth()`,
740and the bar offset within the bin, with `TH1::SetBarOffset()`.
741These two settings are useful to draw several histograms on the
742same plot as shown in the following example:
743
744Begin_Macro(source)
745{
746 int i;
747 const Int_t nx = 8;
748 string os_X[nx] = {"8","32","128","512","2048","8192","32768","131072"};
749 float d_35_0[nx] = {0.75, -3.30, -0.92, 0.10, 0.08, -1.69, -1.29, -2.37};
750 float d_35_1[nx] = {1.01, -3.02, -0.65, 0.37, 0.34, -1.42, -1.02, -2.10};
751
752 auto cb = new TCanvas("cb","cb",600,400);
753 cb->SetGrid();
754
755 gStyle->SetHistMinimumZero();
756
757 auto h1b = new TH1F("h1b","Option B example",nx,0,nx);
758 h1b->SetFillColor(4);
759 h1b->SetBarWidth(0.4);
760 h1b->SetBarOffset(0.1);
761 h1b->SetStats(0);
762 h1b->SetMinimum(-5);
763 h1b->SetMaximum(5);
764
765 for (i=1; i<=nx; i++) {
766 h1b->SetBinContent(i, d_35_0[i-1]);
767 h1b->GetXaxis()->SetBinLabel(i,os_X[i-1].c_str());
768 }
769
770 h1b->Draw("b");
771
772 auto h2b = new TH1F("h2b","h2b",nx,0,nx);
773 h2b->SetFillColor(38);
774 h2b->SetBarWidth(0.4);
775 h2b->SetBarOffset(0.5);
776 h2b->SetStats(0);
777 for (i=1;i<=nx;i++) h2b->SetBinContent(i, d_35_1[i-1]);
778
779 h2b->Draw("b same");
780}
781End_Macro
782
783
784\anchor HP10
785### The "BAR" and "HBAR" options
786
787
788When the option `bar` or `hbar` is specified, a bar chart is drawn. A vertical
789bar-chart is drawn with the options `bar`, `bar0`, `bar1`, `bar2`, `bar3`, `bar4`.
790An horizontal bar-chart is drawn with the options `hbar`, `hbar0`, `hbar1`,
791`hbar2`, `hbar3`, `hbar4` (hbars.C).
792
793- The bar is filled with the histogram fill color.
794- The left side of the bar is drawn with a light fill color.
795- The right side of the bar is drawn with a dark fill color.
796- The percentage of the bar drawn with either the light or dark color is:
797 - 0% for option "(h)bar" or "(h)bar0"
798 - 10% for option "(h)bar1"
799 - 20% for option "(h)bar2"
800 - 30% for option "(h)bar3"
801 - 40% for option "(h)bar4"
802
803When an histogram has errors the option ["HIST"](\ref OPTHIST) together with the `(h)bar` option.
804
805Begin_Macro(source)
806../../../tutorials/hist/hbars.C
807End_Macro
808
809To control the bar width (default is the bin width) `TH1::SetBarWidth()`
810should be used.
811
812To control the bar offset (default is 0) `TH1::SetBarOffset()` should
813be used.
814
815These two parameters are useful when several histograms are plotted using
816the option `SAME`. They allow to plot the histograms next to each other.
817
818
819\anchor HP11
820### The SCATter plot option (legacy draw option)
821
822\attention
823Use of option `SCAT` has been deprecated. It was the default drawing option for 2D and
8243D histograms. The new default option is `COL` (heat-map).
825
826
827For each cell (i,j) a number of points proportional to the cell content is
828drawn. A maximum of `kNMAX` points per cell is drawn. If the maximum is above
829`kNMAX` contents are normalized to `kNMAX` (`kNMAX=2000`).
830If option is of the form `scat=ff`, (eg `scat=1.8`,
831`scat=1e-3`), then `ff` is used as a scale factor to compute the
832number of dots. `scat=1` is the default.
833
834By default the scatter plot is painted with a "dot marker" which not scalable
835(see the `TAttMarker` documentation). To change the marker size, a scalable marker
836type should be used. For instance a circle (marker style 20).
837
838Begin_Macro(source)
839{
840 auto c1 = new TCanvas("c1","c1",600,400);
841 auto hscat = new TH2F("hscat","Option SCATter example (default for 2D histograms) ",40,-4,4,40,-20,20);
842 float px, py;
843 for (Int_t i = 0; i < 25000; i++) {
844 gRandom->Rannor(px,py);
845 hscat->Fill(px,5*py);
846 hscat->Fill(3+0.5*px,2*py-10.);
847 }
848 hscat->Draw("scat=0.5"); // This a legacy draw option. Please consider using TScatter
849}
850End_Macro
851
852
853\anchor HP12
854### The ARRow option
855
856
857Shows gradient between adjacent cells. For each cell (i,j) an arrow is drawn
858The orientation of the arrow follows the cell gradient.
859
860Begin_Macro(source)
861{
862 auto c1 = new TCanvas("c1","c1",600,400);
863 auto harr = new TH2F("harr","Option ARRow example",20,-4,4,20,-20,20);
864 harr->SetLineColor(kRed);
865 float px, py;
866 for (Int_t i = 0; i < 25000; i++) {
867 gRandom->Rannor(px,py);
868 harr->Fill(px,5*py);
869 harr->Fill(3+0.5*px,2*py-10.,0.1);
870 }
871 harr->Draw("ARR");
872}
873End_Macro
874
875\since **ROOT version 6.17/01**
876
877The option `ARR` can be combined with the option `COL` or `COLZ`.
878
879Begin_Macro(source)
880{
881 auto c1 = new TCanvas("c1","c1",600,400);
882 auto harr = new TH2F("harr","Option ARR + COLZ example",20,-4,4,20,-20,20);
883 harr->SetStats(0);
884 float px, py;
885 for (Int_t i = 0; i < 25000; i++) {
886 gRandom->Rannor(px,py);
887 harr->Fill(px,5*py);
888 harr->Fill(3+0.5*px,2*py-10.,0.1);
889 }
890 harr->Draw("ARR COLZ");
891}
892End_Macro
893
894
895\anchor HP13
896### The BOX option
897
898
899For each cell (i,j) a box is drawn. The size (surface) of the box is
900proportional to the absolute value of the cell content.
901The cells with a negative content are drawn with a `X` on top of the box.
902
903Begin_Macro(source)
904{
905 auto c1 = new TCanvas("c1","c1",600,400);
906 auto hbox = new TH2F("hbox","Option BOX example",3,0,3,3,0,3);
907 hbox->SetFillColor(42);
908 hbox->Fill(0.5, 0.5, 1.);
909 hbox->Fill(0.5, 1.5, 4.);
910 hbox->Fill(0.5, 2.5, 3.);
911 hbox->Fill(1.5, 0.5, 2.);
912 hbox->Fill(1.5, 1.5, 12.);
913 hbox->Fill(1.5, 2.5, -6.);
914 hbox->Fill(2.5, 0.5, -4.);
915 hbox->Fill(2.5, 1.5, 6.);
916 hbox->Fill(2.5, 2.5, 0.5);
917 hbox->Draw("BOX");
918}
919End_Macro
920
921With option `BOX1` a button is drawn for each cell with surface
922proportional to content's absolute value. A sunken button is drawn for
923negative values a raised one for positive.
924
925Begin_Macro(source)
926{
927 auto c1 = new TCanvas("c1","c1",600,400);
928 auto hbox1 = new TH2F("hbox1","Option BOX1 example",3,0,3,3,0,3);
929 hbox1->SetFillColor(42);
930 hbox1->Fill(0.5, 0.5, 1.);
931 hbox1->Fill(0.5, 1.5, 4.);
932 hbox1->Fill(0.5, 2.5, 3.);
933 hbox1->Fill(1.5, 0.5, 2.);
934 hbox1->Fill(1.5, 1.5, 12.);
935 hbox1->Fill(1.5, 2.5, -6.);
936 hbox1->Fill(2.5, 0.5, -4.);
937 hbox1->Fill(2.5, 1.5, 6.);
938 hbox1->Fill(2.5, 2.5, 0.5);
939 hbox1->Draw("BOX1");
940}
941End_Macro
942
943When the option `SAME` (or "SAMES") is used with the option `BOX`,
944the boxes' sizes are computed taking the previous plots into account. The range
945along the Z axis is imposed by the first plot (the one without option
946`SAME`); therefore the order in which the plots are done is relevant.
947
948Begin_Macro(source)
949{
950 auto c1 = new TCanvas("c1","c1",600,400);
951 auto hb1 = new TH2F("hb1","Example of BOX plots with option SAME ",40,-3,3,40,-3,3);
952 auto hb2 = new TH2F("hb2","hb2",40,-3,3,40,-3,3);
953 auto hb3 = new TH2F("hb3","hb3",40,-3,3,40,-3,3);
954 auto hb4 = new TH2F("hb4","hb4",40,-3,3,40,-3,3);
955 for (Int_t i=0;i<1000;i++) {
956 double x,y;
957 gRandom->Rannor(x,y);
958 if (x>0 && y>0) hb1->Fill(x,y,4);
959 if (x<0 && y<0) hb2->Fill(x,y,3);
960 if (x>0 && y<0) hb3->Fill(x,y,2);
961 if (x<0 && y>0) hb4->Fill(x,y,1);
962 }
963 hb1->SetFillColor(1);
964 hb2->SetFillColor(2);
965 hb3->SetFillColor(3);
966 hb4->SetFillColor(4);
967 hb1->Draw("box");
968 hb2->Draw("box same");
969 hb3->Draw("box same");
970 hb4->Draw("box same");
971}
972End_Macro
973
974\since **ROOT version 6.17/01:**
975
976Sometimes the change of the range of the Z axis is unwanted, in which case, one
977can use `SAME0` (or `SAMES0`) option to opt out of this change.
978
979Begin_Macro(source)
980{
981 auto h2 = new TH2F("h2"," ",10,0,10,10,20,30);
982 auto hf = (TH2F*)h2->Clone("hf");
983 h2->SetBit(TH1::kNoStats);
984 hf->SetBit(TH1::kNoStats);
985 h2->Fill(5,22);
986 h2->Fill(5,23);
987 h2->Fill(6,22);
988 h2->Fill(6,23);
989 hf->Fill(6,23);
990 hf->Fill(6,23);
991 hf->Fill(6,23);
992 hf->Fill(6,23);
993 hf->Fill(5,23);
994
995 auto hf_copy1 = hf->Clone("hf_copy1");
996 TLatex lt;
997
998 auto cx = new TCanvas(); cx->Divide(2,1);
999
1000 cx->cd(1);
1001 h2->Draw("box");
1002 hf->Draw("text colz same");
1003 lt.DrawLatexNDC(0.3,0.5,"SAME");
1004
1005 cx->cd(2);
1006 h2->Draw("box");
1007 hf_copy1->Draw("text colz same0");
1008 lt.DrawLatexNDC(0.3,0.5,"SAME0");
1009}
1010End_Macro
1011
1012
1013\anchor HP14
1014### The COLor option (default for 2D histograms)
1015
1016The magnitude of individual cell (i,j) is represented as a color picked in the current color palette.
1017This data visualization technique is often called a heat map (or heat-map).
1018
1019The color table used is defined in the current style.
1020
1021If the histogram's minimum and maximum are the same (flat histogram), the
1022mapping on colors is not possible, therefore nothing is painted. To paint a
1023flat histogram it is enough to set the histogram minimum
1024(`TH1::SetMinimum()`) different from the bins' content.
1025
1026The default number of color levels used to paint the cells is 20.
1027It can be changed with `TH1::SetContour()` or
1028`TStyle::SetNumberContours()`. The higher this number is, the smoother
1029is the color change between cells.
1030
1031The color palette in TStyle can be modified via `gStyle->SetPalette()`.
1032
1033All the non-empty bins are painted. Empty bins are not painted unless
1034some bins have a negative content because in that case the null bins
1035might be not empty.
1036
1037`TProfile2D` histograms are handled differently because, for this type of 2D
1038histograms, it is possible to know if an empty bin has been filled or not. So even
1039if all the bins' contents are positive some empty bins might be painted. And vice versa,
1040if some bins have a negative content some empty bins might be not painted.
1041
1042Combined with the option `COL`, the option `Z` allows to
1043display the color palette defined by `gStyle->SetPalette()`.
1044
1045In the following example, the histogram has only positive bins; the empty
1046bins (containing 0) are not drawn.
1047
1048Begin_Macro(source)
1049{
1050 auto c1 = new TCanvas("c1","c1",600,400);
1051 auto hcol1 = new TH2F("hcol1","Option COLor example ",40,-4,4,40,-20,20);
1052 float px, py;
1053 for (Int_t i = 0; i < 25000; i++) {
1054 gRandom->Rannor(px,py);
1055 hcol1->Fill(px,5*py);
1056 }
1057 hcol1->Draw("COLZ");
1058}
1059End_Macro
1060
1061In the first plot of following example, the histogram has some negative bins;
1062the empty bins (containing 0) are drawn. In some cases one wants to not draw
1063empty bins (containing 0) of histograms having a negative minimum. The option
1064`1`, used to produce the second plot in the following picture, allows to do that.
1065
1066Begin_Macro(source)
1067{
1068 auto c1 = new TCanvas("c1","c1",600,600);
1069 c1->Divide(1,2);
1070 auto hcol23 = new TH2F("hcol23","Option COLZ example ",40,-4,4,40,-20,20);
1071 auto hcol24 = new TH2F("hcol24","Option COLZ1 example ",40,-4,4,40,-20,20);
1072 float px, py;
1073 for (Int_t i = 0; i < 25000; i++) {
1074 gRandom->Rannor(px,py);
1075 hcol23->Fill(px,5*py);
1076 hcol24->Fill(px,5*py);
1077 }
1078 hcol23->Fill(0.,0.,-200.);
1079 hcol24->Fill(0.,0.,-200.);
1080 c1->cd(1); hcol23->Draw("COLZ");
1081 c1->cd(2); hcol24->Draw("COLZ1");
1082}
1083End_Macro
1084
1085When the maximum of the histogram is set to a smaller value than the real maximum,
1086 the bins having a content between the new maximum and the real maximum are
1087painted with the color corresponding to the new maximum.
1088
1089When the minimum of the histogram is set to a greater value than the real minimum,
1090 the bins having a value between the real minimum and the new minimum are not drawn
1091 unless the option `0` is set.
1092
1093The following example illustrates the option `0` combined with the option `COL`.
1094
1095Begin_Macro(source)
1096{
1097 auto c1 = new TCanvas("c1","c1",600,600);
1098 c1->Divide(1,2);
1099 auto hcol21 = new TH2F("hcol21","Option COLZ",40,-4,4,40,-20,20);
1100 auto hcol22 = new TH2F("hcol22","Option COLZ0",40,-4,4,40,-20,20);
1101 float px, py;
1102 for (Int_t i = 0; i < 25000; i++) {
1103 gRandom->Rannor(px,py);
1104 hcol21->Fill(px,5*py);
1105 hcol22->Fill(px,5*py);
1106 }
1107 hcol21->SetBit(TH1::kNoStats);
1108 hcol22->SetBit(TH1::kNoStats);
1109 c1->cd(1); hcol21->Draw("COLZ");
1110 c1->cd(2); hcol22->Draw("COLZ0");
1111 hcol22->SetMaximum(100);
1112 hcol22->SetMinimum(40);
1113}
1114End_Macro
1115
1116\since **ROOT version 6.09/01:**
1117
1118When the option SAME (or "SAMES") is used with the option COL, the boxes' color
1119are computed taking the previous plots into account. The range along the Z axis
1120is imposed by the first plot (the one without option SAME); therefore the order
1121in which the plots are done is relevant. Same as [in the `BOX` option](\ref HP13), one can use
1122`SAME0` (or `SAMES0`) to opt out of this imposition.
1123
1124Begin_Macro(source)
1125{
1126 auto c = new TCanvas("c","Example of col plots with option SAME",200,10,700,500);
1127 auto h1 = new TH2F("h1","h1",40,-3,3,40,-3,3);
1128 auto h2 = new TH2F("h2","h2",40,-3,3,40,-3,3);
1129 auto h3 = new TH2F("h3","h3",40,-3,3,40,-3,3);
1130 auto h4 = new TH2F("h4","h4",40,-3,3,40,-3,3);
1131 h1->SetBit(TH1::kNoStats);
1132 for (Int_t i=0;i<5000;i++) {
1133 double x,y;
1134 gRandom->Rannor(x,y);
1135 if(x>0 && y>0) h1->Fill(x,y,4);
1136 if(x<0 && y<0) h2->Fill(x,y,3);
1137 if(x>0 && y<0) h3->Fill(x,y,2);
1138 if(x<0 && y>0) h4->Fill(x,y,1);
1139 }
1140 h1->Draw("colz");
1141 h2->Draw("col same");
1142 h3->Draw("col same");
1143 h4->Draw("col same");
1144}
1145End_Macro
1146
1147The option `COL` can be combined with the option `POL`:
1148
1149Begin_Macro(source)
1150{
1151 auto c1 = new TCanvas("c1","c1",600,400);
1152 auto hcol1 = new TH2F("hcol1","Option COLor combined with POL",40,-4,4,40,-4,4);
1153 float px, py;
1154 for (Int_t i = 0; i < 25000; i++) {
1155 gRandom->Rannor(px,py);
1156 hcol1->Fill(px,py);
1157 }
1158 hcol1->Draw("COLZPOL");
1159}
1160End_Macro
1161
1162\since **ROOT version 6.07/03:**
1163
1164A second rendering technique is also available with the COL2 and COLZ2 options.
1165
1166These options provide potential performance improvements compared to the standard
1167COL option. The performance comparison of the COL2 to the COL option depends on
1168the histogram and the size of the rendering region in the current pad. In general,
1169a small (approx. less than 100 bins per axis), sparsely populated TH2 will render
1170faster with the COL option.
1171
1172However, for larger histograms (approx. more than 100 bins per axis)
1173that are not sparse, the COL2 option will provide up to 20 times performance improvements.
1174For example, a 1000x1000 bin TH2 that is not sparse will render an order of magnitude
1175faster with the COL2 option.
1176
1177The COL2 option will also scale its performance based on the size of the
1178pixmap the histogram image is being rendered into. It also is much better optimized for
1179sessions where the user is forwarding X11 windows through an `ssh` connection.
1180
1181For the most part, the COL2 and COLZ2 options are a drop in replacement to the COL
1182and COLZ options. There is one major difference and that concerns the treatment of
1183bins with zero content. The COL2 and COLZ2 options color these bins the color of zero.
1184
1185COL2 option renders the histogram as a bitmap. Therefore it cannot be saved in vector
1186graphics file format like PostScript or PDF (an empty image will be generated). It can
1187be saved only in bitmap files like PNG format for instance.
1188
1189
1190\anchor HP140
1191### The CANDLE and VIOLIN options
1192
1193The mechanism behind Candle plots and Violin plots is very similar. Because of this they are
1194implemented in the same class TCandle. The keywords CANDLE or VIOLIN will initiate the drawing of
1195the corresponding plots. Followed by the keyword the user can select a plot direction (X or V for
1196vertical projections, or Y or H for horizontal projections) and/or predefined definitions
1197(1-6 for candles, 1-2 for violins). The order doesn't matter. Default is X and 1.
1198
1199Instead of using the predefined representations, the candle and violin parameters can be
1200changed individually. In that case the option have the following form:
1201
1202 CANDLEX(<option-string>)
1203 CANDLEY(<option-string>)
1204 VIOLINX(<option-string>)
1205 VIOLINY(<option-string>).
1206
1207All zeros at the beginning of `option-string` can be omitted.
1208
1209`option-string` consists eight values, defined as follow:
1210
1211 "CANDLEX(zhpawMmb)"
1212
1213Where:
1214
1215 - `b = 0`; no box drawn
1216 - `b = 1`; the box is drawn. As the candle-plot is also called a box-plot it
1217 makes sense in the very most cases to always draw the box
1218 - `b = 2`; draw a filled box with border
1219
1220 - `m = 0`; no median drawn
1221 - `m = 1`; median is drawn as a line
1222 - `m = 2`; median is drawn with errors (notches)
1223 - `m = 3`; median is drawn as a circle
1224
1225 - `M = 0`; no mean drawn
1226 - `M = 1`; mean is drawn as a dashed line
1227 - `M = 3`; mean is drawn as a circle
1228
1229 - `w = 0`; no whisker drawn
1230 - `w = 1`; whisker is drawn to end of distribution.
1231 - `w = 2`; whisker is drawn to max 1.5*iqr
1232
1233 - `a = 0`; no anchor drawn
1234 - `a = 1`; the anchors are drawn
1235
1236 - `p = 0`; no points drawn
1237 - `p = 1`; only outliers are drawn
1238 - `p = 2`; all datapoints are drawn
1239 - `p = 3`: all datapoints are drawn scattered
1240
1241 - `h = 0`; no histogram is drawn
1242 - `h = 1`; histogram at the left or bottom side is drawn
1243 - `h = 2`; histogram at the right or top side is drawn
1244 - `h = 3`; histogram at left and right or top and bottom (violin-style) is drawn
1245
1246 - `z = 0`; no zero indicator line is drawn
1247 - `z = 1`; zero indicator line is drawn.
1248
1249As one can see all individual options for both candle and violin plots can be accessed by this
1250mechanism. In deed the keywords CANDLE(<option-string>) and VIOLIN(<option-string>) have the same
1251meaning. So you can parametrise an option-string for a candle plot and use the keywords VIOLIN and
1252vice versa, if you wish.
1253
1254Using a logarithmic x- or y-axis is possible for candle and violin charts.
1255
1256\since **ROOT version 6.11/01**
1257
1258a logarithmic z-axis is possible, too but will only affect violin charts of course.
1259
1260\anchor HP140a
1261#### The CANDLE option
1262
1263<a href="http://en.wikipedia.org/wiki/Box_plot">A Candle plot</a> (also known as
1264a "box plot" or "whisker plot") was invented in 1977 by John Tukey. It is a convenient
1265way to describe graphically a data distribution (D) with only five numbers:
1266
1267 1. The minimum value of the distribution D (bottom or left whisker).
1268 2. The lower quartile (Q1): 25% of the data points in D are less than Q1 (bottom of the box).
1269 3. The median (M): 50% of the data points in D are less than M.
1270 4. The upper quartile (Q3): 75% of the data points in D are less than Q3 (top of the box).
1271 5. The maximum value of the distribution D (top or right whisker).
1272
1273In this implementation a TH2 is considered as a collection of TH1 along
1274X (option `CANDLE` or `CANDLEX`) or Y (option `CANDLEY`).
1275Each TH1 is represented as one candle.
1276
1277Begin_Macro(source)
1278../../../tutorials/hist/candleplotwhiskers.C
1279End_Macro
1280
1281The candle reduces the information coming from a whole distribution into few values.
1282Independently from the number of entries or the significance of the underlying distribution
1283a candle will always look like a candle. So candle plots should be used carefully in
1284particular with unknown distributions. The definition of a candle is based on
1285__unbinned data__. Here, candles are created from binned data. Because of this, the
1286deviation is connected to the bin width used. The calculation of the quantiles
1287normally done on unbinned data also. Because data are binned, this will
1288only work the best possible way within the resolution of one bin
1289
1290Because of all these facts one should take care that:
1291
1292 - there are enough points per candle
1293 - the bin width is small enough (more bins will increase the maximum
1294 available resolution of the quantiles although there will be some
1295 bins with no entries)
1296 - never make a candle-plot if the underlying distribution is double-distributed
1297 - only create candles of distributions that are more-or-less gaussian (the
1298 MPV should be not too far away from the mean).
1299
1300#### What a candle is made of
1301
1302\since **ROOT version 6.07/05**
1303
1304##### The box
1305The box displays the position of the inter-quantile-range of the underlying
1306distribution. The box contains 25% of the distribution below the median
1307and 25% of the distribution above the median. If the underlying distribution is large
1308enough and gaussian shaped the end-points of the box represent \f$ 0.6745\times\sigma \f$
1309(Where \f$ \sigma \f$ is the standard deviation of the gaussian). The width and
1310the position of the box can be modified by SetBarWidth() and SetBarOffset().
1311The +-25% quantiles are calculated by the GetQuantiles() methods.
1312
1313\since **ROOT version 6.11/01**
1314
1315Using the static function TCandle::SetBoxRange(double) the box definition will be
1316overwritten. E.g. using a box range of 0.68 will redefine the area of the lower box edge
1317to the upper box edge in order to cover 68% of the distribution illustrated by that candle.
1318The static function will affect all candle-charts in the running program.
1319Default is 0.5.
1320
1321Using the static function TCandle::SetScaledCandle(bool) the width of the box (and the
1322whole candle) can be influenced. Deactivated, the width is constant (to be set by
1323SetBarWidth() ). Activated, the width of the boxes will be scaled to each other based on the
1324amount of data in the corresponding candle, the maximum width can be influenced by
1325SetBarWidth(). The static function will affect all candle-charts in the running program.
1326Default is false. Scaling between multiple candle-charts (using "same" or THStack) is not
1327supported, yet
1328
1329##### The Median
1330For a sorted list of numbers, the median is the value in the middle of the list.
1331E.g. if a sorted list is made of five numbers "1,2,3,6,7" 3 will be the median
1332because it is in the middle of the list. If the number of entries is even the
1333average of the two values in the middle will be used. As histograms are binned
1334data, the situation is a bit more complex. The following example shows this:
1335
1336~~~ {.cpp}
1337void quantiles() {
1338 auto h = new TH1I("h","h",10,0,10);
1339 //h->Fill(3);
1340 //h->Fill(3);
1341 h->Fill(4);
1342 h->Draw();
1343 double p = 0.;
1344 double q = 0.;
1345 h->GetQuantiles(1,&q,&p);
1346
1347 cout << "Median is: " << q << std::endl;
1348}
1349~~~
1350
1351Here the bin-width is 1.0. If the two Fill(3) are commented out, as there are currently,
1352the example will return a calculated median of 4.5, because that's the bin center
1353of the bin in which the value 4.0 has been dropped. If the two Fill(3) are not
1354commented out, it will return 3.75, because the algorithm tries to evenly distribute
1355the individual values of a bin with bin content > 0. It means the sorted list
1356would be "3.25, 3.75, 4.5".
1357
1358The consequence is a median of 3.75. This shows how important it is to use a
1359small enough bin-width when using candle-plots on binned data.
1360If the distribution is large enough and gaussian shaped the median will be exactly
1361equal to the mean.
1362The median can be shown as a line or as a circle or not shown at all.
1363
1364In order to show the significance of the median notched candle plots apply a "notch" or
1365narrowing of the box around the median. The significance is defined by
1366\f$ 1.57\times\frac{iqr}{N} \f$ and will be represented as the size of the notch
1367(where iqr is the size of the box and N is the number of entries of the whole
1368distribution). Candle plots like these are usually called "notched candle plots".
1369
1370In case the significance of the median is greater that the size of the box, the
1371box will have an unnatural shape. Usually it means the chart has not enough data,
1372or that representing this uncertainty is not useful
1373
1374##### The Mean
1375The mean can be drawn as a dashed line or as a circle or not drawn at all.
1376The mean is the arithmetic average of the values in the distribution.
1377It is calculated using GetMean(). Because histograms are
1378binned data, the mean value can differ from a calculation on the raw-data.
1379If the distribution is large enough and gaussian shaped the mean will be
1380exactly the median.
1381
1382##### The Whiskers
1383The whiskers represent the part of the distribution not covered by the box.
1384The upper 25% and the lower 25% of the distribution are located within the whiskers.
1385Two representations are available.
1386
1387 - A simple one (using w=1) defining the lower whisker from the lowest data value
1388 to the bottom of the box, and the upper whisker from the top of the box to the
1389 highest data value. In this representation the whisker-lines are dashed.
1390 - A more complex one having a further restriction. The whiskers are still connected
1391 to the box but their length cannot exceed \f$ 1.5\times iqr \f$. So it might
1392 be that the outermost part of the underlying distribution will not be covered
1393 by the whiskers. Usually these missing parts will be represented by the outliers
1394 (see points). Of course the upper and the lower whisker may differ in length.
1395 In this representation the whiskers are drawn as solid lines.
1396
1397\since **ROOT version 6.11/01**
1398
1399Using the static function TCandle::SetWhiskerRange(double) the whisker definition w=1
1400will be overwritten. E.g. using a whisker-range of 0.95 and w=1 will redefine the area of
1401the lower whisker to the upper whisker in order to cover 95% of the distribution inside
1402that candle. The static function will affect all candle-charts in the running program.
1403Default is 1.
1404
1405If the distribution is large enough and gaussian shaped, the maximum length of
1406the whisker will be located at \f$ \pm 2.698 \sigma \f$ (when using the
14071.5*iqr-definition (w=2), where \f$ \sigma \f$ is the standard deviation
1408(see picture above). In that case 99.3% of the total distribution will be covered
1409by the box and the whiskers, whereas 0.7% are represented by the outliers.
1410
1411##### The Anchors
1412The anchors have no special meaning in terms of statistical calculation. They mark
1413the end of the whiskers and they have the width of the box. Both representation
1414with and without anchors are common.
1415
1416##### The Points
1417Depending on the configuration the points can have different meanings:
1418 - If p=1 the points represent the outliers. If they are shown, it means
1419 some parts of the underlying distribution are not covered by the whiskers.
1420 This can only occur when the whiskers are set to option w=2. Here the whiskers
1421 can have a maximum length of \f$ 1.5 \times iqr \f$. So any points outside the
1422 whiskers will be drawn as outliers. The outliers will be represented by crosses.
1423 - If p=2 all points in the distribution will be painted as crosses. This is
1424 useful for small datasets only (up to 10 or 20 points per candle).
1425 The outliers are shown along the candle. Because the underlying distribution
1426 is binned, is frequently occurs that a bin contains more than one value.
1427 Because of this the points will be randomly scattered within their bin along
1428 the candle axis. If the bin content for a bin is exactly 1 (usually
1429 this happens for the outliers) if will be drawn in the middle of the bin along
1430 the candle axis. As the maximum number of points per candle is limited by kNMax/2
1431 on very large datasets scaling will be performed automatically. In that case one
1432 would loose all outliers because they have usually a bin content of 1 (and a
1433 bin content between 0 and 1 after the scaling). Because of this all bin contents
1434 between 0 and 1 - after the scaling - will be forced to be 1.
1435 - As the drawing of all values on large datasets can lead to big amounts of crosses,
1436 one can show all values as a scatter plot instead by choosing p=3. The points will be
1437 drawn as dots and will be scattered within the width of the candle. The color
1438 of the points will be the color of the candle-chart.
1439
1440##### Other Options
1441Is is possible to combine all options of candle and violin plots with each other. E.g. a box-plot
1442with a histogram.
1443
1444#### How to use the candle-plots drawing option
1445
1446There are six predefined candle-plot representations:
1447
1448 - "CANDLEX1": Standard candle (whiskers cover the whole distribution)
1449 - "CANDLEX2": Standard candle with better whisker definition + outliers.
1450 It is a good compromise
1451 - "CANDLEX3": Like candle2 but with a mean as a circle.
1452 It is easier to distinguish mean and median
1453 - "CANDLEX4": Like candle3 but showing the uncertainty of the median as well
1454 (notched candle plots).
1455 For bigger datasets per candle
1456 - "CANDLEX5": Like candle2 but showing all data points.
1457 For very small datasets
1458 - "CANDLEX6": Like candle2 but showing all datapoints scattered.
1459 For huge datasets
1460
1461
1462The following picture shows how the six predefined representations look.
1463
1464Begin_Macro
1465{
1466 auto c1 = new TCanvas("c1","c1",700,800);
1467 c1->Divide(2,3);
1468 gStyle->SetOptStat(kFALSE);
1469
1470 auto hcandle = new TH2F("hcandle"," ",10,-4,4,40,-20,20);
1471 float px, py;
1472 for (Int_t i = 0; i < 15000; i++) {
1473 gRandom->Rannor(px,py);
1474 hcandle->Fill(px,5*py);
1475 }
1476 hcandle->SetMarkerSize(0.5);
1477
1478 TH2F *h2;
1479 for (Int_t i=1; i<7; i++) {
1480 c1->cd(i);
1481 h2 = (TH2F*)hcandle->DrawClone(Form("CANDLE%d",i));
1482 h2->SetTitle(Form("CANDLE%d",i));
1483 }
1484}
1485End_Macro
1486
1487
1488#### Example 1
1489Box and improved whisker, no mean, no median, no anchor no outliers
1490
1491 h1->Draw("CANDLEX(2001)");
1492
1493#### Example 2
1494A Candle-definition like "CANDLEX2" (New standard candle with better whisker definition + outliers)
1495
1496 h1->Draw("CANDLEX(112111)");
1497
1498#### Example 3
1499The following example shows how several candle plots can be super-imposed using
1500the option SAME. Note that the bar-width and bar-offset are active on candle plots.
1501Also the color, the line width, the size of the points and so on can be changed by the
1502standard attribute setting methods such as SetLineColor() SetLineWidth().
1503
1504Begin_Macro(source)
1505../../../tutorials/hist/candleplot.C
1506End_Macro
1507
1508\anchor HP140b
1509#### The VIOLIN option
1510
1511<a href="http://en.wikipedia.org/wiki/Violin_plot">A violin plot</a> is a candle plot
1512that also encodes the pdf information at each point.
1513
1514
1515Quartiles and mean are also represented at each point, with a marker
1516and two lines.
1517
1518In this implementation a TH2 is considered as a collection of TH1 along
1519X (option `VIOLIN` or `VIOLINX`) or Y (option `VIOLINY`).
1520
1521#### What a violin is made of
1522
1523\since **ROOT version 6.09/02**
1524
1525##### The histogram
1526The histogram is typically drawn to both directions with respect to the middle-line of the
1527corresponding bin. This can be achieved by using h=3. It is possible to draw a histogram only to
1528one side (h=1, or h=2).
1529The maximum number of bins in the histogram is limited to 500, if the number of bins in the used
1530histogram is higher it will be rebinned automatically. The maximum height of the histogram can
1531be modified by using SetBarWidth() and the position can be changed with SetBarOffset().
1532A solid fill style is recommended.
1533
1534\since **ROOT version 6.11/01**
1535
1536Using the static function TCandle::SetScaledViolin(bool) the height of the histogram or the
1537violin can be influenced. Activated, the height of the bins of the individual violins will be
1538scaled with respect to each other, the maximum height can be influenced by SetBarWidth().
1539Deactivated, the height of the bin with the maximum content of each individual violin is
1540set to a constant value using SetBarWidth(). The static function will affect all violin-charts
1541in the running program. Default is true. Scaling between multiple violin-charts
1542(using "same" or THStack) is not supported, yet.
1543
1544##### The zero indicator line
1545Typical for violin charts is a line in the background over the whole histogram indicating
1546the bins with zero entries. The zero indicator line can be activated with z=1. The line color
1547will always be the same as the fill-color of the histogram.
1548
1549##### The Mean
1550The Mean is illustrated with the same mechanism as used for candle plots. Usually a circle is used.
1551
1552##### Whiskers
1553The whiskers are illustrated by the same mechanism as used for candle plots. There is only one
1554difference. When using the simple whisker definition (w=1) and the zero indicator line (z=1), then
1555the whiskers will be forced to be solid (usually hashed)
1556
1557##### Points
1558The points are illustrated by the same mechanism as used for candle plots. E.g. VIOLIN2 uses
1559better whisker definition (w=2) and outliers (p=1).
1560
1561##### Other options
1562It is possible to combine all options of candle or violin plots with each other. E.g. a violin plot
1563including a box-plot.
1564
1565#### How to use the violin-plots drawing option
1566
1567There are two predefined violin-plot representations:
1568 - "VIOLINX1": Standard violin (histogram, mean, whisker over full distribution,
1569 zero indicator line)
1570 - "VIOLINX2": Line VIOLINX1 both with better whisker definition + outliers.
1571
1572A solid fill style is recommended for this plot (as opposed to a hollow or
1573hashed style).
1574
1575Begin_Macro(source)
1576{
1577 auto c1 = new TCanvas("c1","c1",600,400);
1578 Int_t nx(6), ny(40);
1579 double xmin(0.0), xmax(+6.0), ymin(0.0), ymax(+4.0);
1580 auto hviolin = new TH2F("hviolin", "Option VIOLIN example", nx, xmin, xmax, ny, ymin, ymax);
1581 TF1 f1("f1", "gaus", +0,0 +4.0);
1582 double x,y;
1583 for (Int_t iBin=1; iBin<hviolin->GetNbinsX(); ++iBin) {
1584 double xc = hviolin->GetXaxis()->GetBinCenter(iBin);
1585 f1.SetParameters(1, 2.0+TMath::Sin(1.0+xc), 0.2+0.1*(xc-xmin)/xmax);
1586 for(Int_t i=0; i<10000; ++i){
1587 x = xc;
1588 y = f1.GetRandom();
1589 hviolin->Fill(x, y);
1590 }
1591 }
1592 hviolin->SetFillColor(kGray);
1593 hviolin->SetMarkerStyle(20);
1594 hviolin->SetMarkerSize(0.5);
1595 hviolin->Draw("VIOLIN");
1596 c1->Update();
1597}
1598End_Macro
1599
1600The next example illustrates a time development of a certain value:
1601
1602Begin_Macro(source)
1603../../../tutorials/hist/candledecay.C
1604End_Macro
1605
1606
1607\anchor HP15
1608### The TEXT and TEXTnn Option
1609
1610
1611For each bin the content is printed. The text attributes are:
1612
1613- text font = current TStyle font (`gStyle->SetTextFont()`).
1614- text size = 0.02*padheight*markersize (if `h` is the histogram drawn
1615 with the option `TEXT` the marker size can be changed with
1616 `h->SetMarkerSize(markersize)`).
1617- text color = marker color.
1618
1619By default the format `g` is used. This format can be redefined
1620by calling `gStyle->SetPaintTextFormat()`.
1621
1622It is also possible to use `TEXTnn` in order to draw the text with
1623the angle `nn` (`0 < nn <= 90`).
1624
1625For 2D histograms the text is plotted in the center of each non empty cells.
1626It is possible to plot empty cells by calling `gStyle->SetHistMinimumZero()`
1627or providing MIN0 draw option. For 1D histogram the text is plotted at a y
1628position equal to the bin content.
1629
1630For 2D histograms when the option "E" (errors) is combined with the option
1631text ("TEXTE"), the error for each bin is also printed.
1632
1633Begin_Macro(source)
1634{
1635 auto c01 = new TCanvas("c01","c01",700,400);
1636 c01->Divide(2,1);
1637 auto htext1 = new TH1F("htext1","Option TEXT on 1D histograms ",10,-4,4);
1638 auto htext2 = new TH2F("htext2","Option TEXT on 2D histograms ",10,-4,4,10,-20,20);
1639 float px, py;
1640 for (Int_t i = 0; i < 25000; i++) {
1641 gRandom->Rannor(px,py);
1642 htext1->Fill(px,0.1);
1643 htext2->Fill(px,5*py,0.1);
1644 }
1645 gStyle->SetPaintTextFormat("4.1f m");
1646 htext2->SetMarkerSize(1.8);
1647 c01->cd(1);
1648 htext2->Draw("TEXT45");
1649 c01->cd(2);
1650 htext1->Draw();
1651 htext1->Draw("HIST TEXT0 SAME");
1652}
1653End_Macro
1654
1655\since **ROOT version 6.07/07:**
1656
1657In case several histograms are drawn on top ot each other (using option `SAME`),
1658the text can be shifted using `SetBarOffset()`. It specifies an offset for the
1659text position in each cell, in percentage of the bin width.
1660
1661Begin_Macro(source)
1662{
1663 auto c03 = new TCanvas("c03","c03",700,400);
1664 gStyle->SetOptStat(0);
1665 auto htext3 = new TH2F("htext3","Several 2D histograms drawn with option TEXT",10,-4,4,10,-20,20);
1666 auto htext4 = new TH2F("htext4","htext4",10,-4,4,10,-20,20);
1667 auto htext5 = new TH2F("htext5","htext5",10,-4,4,10,-20,20);
1668 float px, py;
1669 for (Int_t i = 0; i < 25000; i++) {
1670 gRandom->Rannor(px,py);
1671 htext3->Fill(4*px,20*py,0.1);
1672 htext4->Fill(4*px,20*py,0.5);
1673 htext5->Fill(4*px,20*py,1.0);
1674 }
1675 htext4->SetMarkerSize(1.8);
1676 htext5->SetMarkerSize(1.8);
1677 htext5->SetMarkerColor(kRed);
1678 htext4->SetBarOffset(0.2);
1679 htext4->Draw("COL TEXT SAME");
1680 htext5->SetBarOffset(-0.2);
1681 htext5->Draw("TEXT SAME");
1682}
1683End_Macro
1684
1685In the case of profile histograms it is possible to print the number
1686of entries instead of the bin content. It is enough to combine the
1687option "E" (for entries) with the option "TEXT".
1688
1689Begin_Macro(source)
1690{
1691 auto c02 = new TCanvas("c02","c02",700,400);
1692 c02->Divide(2,1);
1693 gStyle->SetPaintTextFormat("g");
1694
1695 auto profile = new TProfile("profile","profile",10,0,10);
1696 profile->SetMarkerSize(2.2);
1697 profile->Fill(0.5,1);
1698 profile->Fill(1.5,2);
1699 profile->Fill(2.5,3);
1700 profile->Fill(3.5,4);
1701 profile->Fill(4.5,5);
1702 profile->Fill(5.5,5);
1703 profile->Fill(6.5,4);
1704 profile->Fill(7.5,3);
1705 profile->Fill(8.5,2);
1706 profile->Fill(9.5,1);
1707 c02->cd(1); profile->Draw("HIST TEXT0");
1708 c02->cd(2); profile->Draw("HIST TEXT0E");
1709}
1710End_Macro
1711
1712\anchor HP16
1713### The CONTour options
1714
1715
1716The following contour options are supported:
1717
1718| Option | Description |
1719|----------|-----------------------------------------------------------------------------|
1720| "CONT" | Draw a contour plot (same as CONT0). |
1721| "CONT0" | Draw a contour plot using surface colors to distinguish contours. |
1722| "CONT1" | Draw a contour plot using the line colors to distinguish contours. |
1723| "CONT2" | Draw a contour plot using the line styles (1 to 5) to distinguish contours. |
1724| "CONT3" | Draw a contour plot using the same line style for all contours. |
1725| "CONT4" | Draw a contour plot using surface colors (`SURF` option at theta = 0). |
1726
1727
1728The following example shows a 2D histogram plotted with the option
1729`CONTZ`. The option `CONT` draws a contour plot using surface
1730colors to distinguish contours. Combined with the option `CONT` (or
1731`CONT0`), the option `Z` allows to display the color palette
1732defined by `gStyle->SetPalette()`.
1733
1734Begin_Macro(source)
1735{
1736 auto c1 = new TCanvas("c1","c1",600,400);
1737 auto hcontz = new TH2F("hcontz","Option CONTZ example ",40,-4,4,40,-20,20);
1738 float px, py;
1739 for (Int_t i = 0; i < 25000; i++) {
1740 gRandom->Rannor(px,py);
1741 hcontz->Fill(px-1,5*py);
1742 hcontz->Fill(2+0.5*px,2*py-10.,0.1);
1743 }
1744 hcontz->Draw("CONTZ");
1745}
1746End_Macro
1747
1748The following example shows a 2D histogram plotted with the option
1749`CONT1Z`. The option `CONT1` draws a contour plot using the
1750line colors to distinguish contours. Combined with the option `CONT1`,
1751the option `Z` allows to display the color palette defined by
1752`gStyle->SetPalette()`.
1753
1754Begin_Macro(source)
1755{
1756 auto c1 = new TCanvas("c1","c1",600,400);
1757 auto hcont1 = new TH2F("hcont1","Option CONT1Z example ",40,-4,4,40,-20,20);
1758 float px, py;
1759 for (Int_t i = 0; i < 25000; i++) {
1760 gRandom->Rannor(px,py);
1761 hcont1->Fill(px-1,5*py);
1762 hcont1->Fill(2+0.5*px,2*py-10.,0.1);
1763 }
1764 hcont1->Draw("CONT1Z");
1765}
1766End_Macro
1767
1768The following example shows a 2D histogram plotted with the option
1769`CONT2`. The option `CONT2` draws a contour plot using the
1770line styles (1 to 5) to distinguish contours.
1771
1772Begin_Macro(source)
1773{
1774 auto c1 = new TCanvas("c1","c1",600,400);
1775 auto hcont2 = new TH2F("hcont2","Option CONT2 example ",40,-4,4,40,-20,20);
1776 float px, py;
1777 for (Int_t i = 0; i < 25000; i++) {
1778 gRandom->Rannor(px,py);
1779 hcont2->Fill(px-1,5*py);
1780 hcont2->Fill(2+0.5*px,2*py-10.,0.1);
1781 }
1782 hcont2->Draw("CONT2");
1783}
1784End_Macro
1785
1786The following example shows a 2D histogram plotted with the option
1787`CONT3`. The option `CONT3` draws contour plot using the same line style for
1788all contours.
1789
1790Begin_Macro(source)
1791{
1792 auto c1 = new TCanvas("c1","c1",600,400);
1793 auto hcont3 = new TH2F("hcont3","Option CONT3 example ",40,-4,4,40,-20,20);
1794 float px, py;
1795 for (Int_t i = 0; i < 25000; i++) {
1796 gRandom->Rannor(px,py);
1797 hcont3->Fill(px-1,5*py);
1798 hcont3->Fill(2+0.5*px,2*py-10.,0.1);
1799 }
1800 hcont3->SetLineStyle(kDotted);
1801 hcont3->Draw("CONT3");
1802}
1803End_Macro
1804
1805The following example shows a 2D histogram plotted with the option
1806`CONT4`. The option `CONT4` draws a contour plot using surface
1807colors to distinguish contours (`SURF` option at theta = 0). Combined
1808with the option `CONT` (or `CONT0`), the option `Z`
1809allows to display the color palette defined by `gStyle->SetPalette()`.
1810
1811Begin_Macro(source)
1812{
1813 auto c1 = new TCanvas("c1","c1",600,400);
1814 auto hcont4 = new TH2F("hcont4","Option CONT4Z example ",40,-4,4,40,-20,20);
1815 float px, py;
1816 for (Int_t i = 0; i < 25000; i++) {
1817 gRandom->Rannor(px,py);
1818 hcont4->Fill(px-1,5*py);
1819 hcont4->Fill(2+0.5*px,2*py-10.,0.1);
1820 }
1821 hcont4->Draw("CONT4Z");
1822}
1823End_Macro
1824
1825The default number of contour levels is 20 equidistant levels and can be changed
1826with `TH1::SetContour()` or `TStyle::SetNumberContours()`.
1827
1828\anchor HP16a
1829#### The LIST option
1830
1831When option `LIST` is specified together with option
1832`CONT`, the points used to draw the contours are saved in
1833`TGraph` objects:
1834
1835 h->Draw("CONT LIST");
1836 gPad->Update();
1837
1838The contour are saved in `TGraph` objects once the pad is painted.
1839Therefore to use this functionality in a macro, `gPad->Update()`
1840should be performed after the histogram drawing. Once the list is
1841built, the contours are accessible in the following way:
1842
1843 TObjArray *contours = (TObjArray*)gROOT->GetListOfSpecials()->FindObject("contours");
1844 Int_t ncontours = contours->GetSize();
1845 TList *list = (TList*)contours->At(i);
1846
1847Where `i` is a contour number, and list contains a list of
1848`TGraph` objects.
1849For one given contour, more than one disjoint polyline may be generated.
1850The number of TGraphs per contour is given by:
1851
1852 list->GetSize();
1853
1854To access the first graph in the list one should do:
1855
1856 TGraph *gr1 = (TGraph*)list->First();
1857
1858
1859The following example (ContourList.C) shows how to use this functionality.
1860
1861Begin_Macro(source)
1862../../../tutorials/hist/ContourList.C
1863End_Macro
1864
1865\anchor HP16b
1866#### The AITOFF, MERCATOR, SINUSOIDAL and PARABOLIC options
1867
1868The following options select the `CONT4` option and are useful for
1869sky maps or exposure maps (earth.C).
1870
1871| Option | Description |
1872|--------------|---------------------------------------------------------------|
1873| "AITOFF" | Draw a contour via an AITOFF projection.|
1874| "MERCATOR" | Draw a contour via an Mercator projection.|
1875| "SINUSOIDAL" | Draw a contour via an Sinusoidal projection.|
1876| "PARABOLIC" | Draw a contour via an Parabolic projection.|
1877
1878Begin_Macro(source)
1879../../../tutorials/visualisation/graphics/earth.C
1880End_Macro
1881
1882
1883\anchor HP17
1884### The LEGO options
1885
1886
1887In a lego plot the cell contents are drawn as 3-d boxes. The height of each box
1888is proportional to the cell content. The lego aspect is control with the
1889following options:
1890
1891| Option | Description |
1892|----------|-------------------------------------------------------------------|
1893| "LEGO" | Draw a lego plot using the hidden lines removal technique.|
1894| "LEGO1" | Draw a lego plot using the hidden surface removal technique.|
1895| "LEGO2" | Draw a lego plot using colors to show the cell contents.|
1896| "LEGO3" | Draw a lego plot with hidden surface removal, like LEGO1 but the border lines of each lego-bar are not
1897drawn.| | "LEGO4" | Draw a lego plot with hidden surface removal, like LEGO1 but without the shadow effect on each
1898lego-bar.| | "0" | When used with any LEGO option, the empty bins are not drawn.|
1899
1900
1901See the limitations with [the option "SAME"](\ref HP060a).
1902
1903Line attributes can be used in lego plots to change the edges' style.
1904
1905The following example shows a 2D histogram plotted with the option
1906`LEGO`. The option `LEGO` draws a lego plot using the hidden
1907lines removal technique.
1908
1909Begin_Macro(source)
1910{
1911 auto c2 = new TCanvas("c2","c2",600,400);
1912 auto hlego = new TH2F("hlego","Option LEGO example ",40,-4,4,40,-20,20);
1913 float px, py;
1914 for (Int_t i = 0; i < 25000; i++) {
1915 gRandom->Rannor(px,py);
1916 hlego->Fill(px-1,5*py);
1917 hlego->Fill(2+0.5*px,2*py-10.,0.1);
1918 }
1919 hlego->Draw("LEGO");
1920}
1921End_Macro
1922
1923The following example shows a 2D histogram plotted with the option
1924`LEGO1`. The option `LEGO1` draws a lego plot using the
1925hidden surface removal technique. Combined with any `LEGOn` option, the
1926option `0` allows to not drawn the empty bins.
1927
1928Begin_Macro(source)
1929{
1930 auto c2 = new TCanvas("c2","c2",600,400);
1931 auto hlego1 = new TH2F("hlego1","Option LEGO1 example (with option 0) ",40,-4,4,40,-20,20);
1932 float px, py;
1933 for (Int_t i = 0; i < 25000; i++) {
1934 gRandom->Rannor(px,py);
1935 hlego1->Fill(px-1,5*py);
1936 hlego1->Fill(2+0.5*px,2*py-10.,0.1);
1937 }
1938 hlego1->SetFillColor(kYellow);
1939 hlego1->Draw("LEGO1 0");
1940}
1941End_Macro
1942
1943The following example shows a 2D histogram plotted with the option
1944`LEGO3`. Like the option `LEGO1`, the option `LEGO3`
1945draws a lego plot using the hidden surface removal technique but doesn't draw
1946the border lines of each individual lego-bar. This is very useful for histograms
1947having many bins. With such histograms the option `LEGO1` gives a black
1948image because of the border lines. This option also works with stacked legos.
1949
1950Begin_Macro(source)
1951{
1952 auto c2 = new TCanvas("c2","c2",600,400);
1953 auto hlego3 = new TH2F("hlego3","Option LEGO3 example",40,-4,4,40,-20,20);
1954 float px, py;
1955 for (Int_t i = 0; i < 25000; i++) {
1956 gRandom->Rannor(px,py);
1957 hlego3->Fill(px-1,5*py);
1958 hlego3->Fill(2+0.5*px,2*py-10.,0.1);
1959 }
1960 hlego3->SetFillColor(kRed);
1961 hlego3->Draw("LEGO3");
1962}
1963End_Macro
1964
1965The following example shows a 2D histogram plotted with the option
1966`LEGO2`. The option `LEGO2` draws a lego plot using colors to
1967show the cell contents. Combined with the option `LEGO2`, the option
1968`Z` allows to display the color palette defined by
1969`gStyle->SetPalette()`.
1970
1971Begin_Macro(source)
1972{
1973 auto c2 = new TCanvas("c2","c2",600,400);
1974 auto hlego2 = new TH2F("hlego2","Option LEGO2Z example ",40,-4,4,40,-20,20);
1975 float px, py;
1976 for (Int_t i = 0; i < 25000; i++) {
1977 gRandom->Rannor(px,py);
1978 hlego2->Fill(px-1,5*py);
1979 hlego2->Fill(2+0.5*px,2*py-10.,0.1);
1980 }
1981 hlego2->Draw("LEGO2Z");
1982}
1983End_Macro
1984
1985
1986
1987\anchor HP18
1988### The "SURFace" options
1989
1990
1991In a surface plot, cell contents are represented as a mesh.
1992The height of the mesh is proportional to the cell content.
1993
1994| Option | Description |
1995|----------|-------------------------------------------------------------------|
1996| "SURF" | Draw a surface plot using the hidden line removal technique.|
1997| "SURF1" | Draw a surface plot using the hidden surface removal technique.|
1998| "SURF2" | Draw a surface plot using colors to show the cell contents.|
1999| "SURF3" | Same as `SURF` with an additional filled contour plot on top.|
2000| "SURF4" | Draw a surface using the Gouraud shading technique.|
2001| "SURF5" | Used with one of the options CYL, PSR and CYL this option allows to draw a filled contour plot.|
2002| "SURF6" | This option should not be used directly. It is used internally when the CONT is used with option the option
2003SAME on a 3D plot.| | "SURF7" | Same as `SURF2` with an additional line contour plot on top.|
2004
2005
2006
2007See the limitations with [the option "SAME"](\ref HP060a).
2008
2009The following example shows a 2D histogram plotted with the option
2010`SURF`. The option `SURF` draws a lego plot using the hidden
2011lines removal technique.
2012
2013Begin_Macro(source)
2014{
2015 auto c2 = new TCanvas("c2","c2",600,400);
2016 auto hsurf = new TH2F("hsurf","Option SURF example ",30,-4,4,30,-20,20);
2017 float px, py;
2018 for (Int_t i = 0; i < 25000; i++) {
2019 gRandom->Rannor(px,py);
2020 hsurf->Fill(px-1,5*py);
2021 hsurf->Fill(2+0.5*px,2*py-10.,0.1);
2022 }
2023 hsurf->Draw("SURF");
2024}
2025End_Macro
2026
2027The following example shows a 2D histogram plotted with the option
2028`SURF1`. The option `SURF1` draws a surface plot using the
2029hidden surface removal technique. Combined with the option `SURF1`,
2030the option `Z` allows to display the color palette defined by
2031`gStyle->SetPalette()`.
2032
2033Begin_Macro(source)
2034{
2035 auto c2 = new TCanvas("c2","c2",600,400);
2036 auto hsurf1 = new TH2F("hsurf1","Option SURF1 example ",30,-4,4,30,-20,20);
2037 float px, py;
2038 for (Int_t i = 0; i < 25000; i++) {
2039 gRandom->Rannor(px,py);
2040 hsurf1->Fill(px-1,5*py);
2041 hsurf1->Fill(2+0.5*px,2*py-10.,0.1);
2042 }
2043 hsurf1->Draw("SURF1");
2044}
2045End_Macro
2046
2047The following example shows a 2D histogram plotted with the option
2048`SURF2`. The option `SURF2` draws a surface plot using colors
2049to show the cell contents. Combined with the option `SURF2`, the option
2050`Z` allows to display the color palette defined by
2051`gStyle->SetPalette()`.
2052
2053Begin_Macro(source)
2054{
2055 auto c2 = new TCanvas("c2","c2",600,400);
2056 auto hsurf2 = new TH2F("hsurf2","Option SURF2 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 hsurf2->Fill(px-1,5*py);
2061 hsurf2->Fill(2+0.5*px,2*py-10.,0.1);
2062 }
2063 hsurf2->Draw("SURF2");
2064}
2065End_Macro
2066
2067The following example shows a 2D histogram plotted with the option
2068`SURF3`. The option `SURF3` draws a surface plot using the
2069hidden line removal technique with, in addition, a filled contour view drawn on the
2070top. Combined with the option `SURF3`, the option `Z` allows
2071to display the color palette defined by `gStyle->SetPalette()`.
2072
2073Begin_Macro(source)
2074{
2075 auto c2 = new TCanvas("c2","c2",600,400);
2076 auto hsurf3 = new TH2F("hsurf3","Option SURF3 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 hsurf3->Fill(px-1,5*py);
2081 hsurf3->Fill(2+0.5*px,2*py-10.,0.1);
2082 }
2083 hsurf3->Draw("SURF3");
2084}
2085End_Macro
2086
2087The following example shows a 2D histogram plotted with the option
2088`SURF4`. The option `SURF4` draws a surface using the Gouraud
2089shading technique.
2090
2091Begin_Macro(source)
2092{
2093 auto c2 = new TCanvas("c2","c2",600,400);
2094 auto hsurf4 = new TH2F("hsurf4","Option SURF4 example ",30,-4,4,30,-20,20);
2095 float px, py;
2096 for (Int_t i = 0; i < 25000; i++) {
2097 gRandom->Rannor(px,py);
2098 hsurf4->Fill(px-1,5*py);
2099 hsurf4->Fill(2+0.5*px,2*py-10.,0.1);
2100 }
2101 hsurf4->SetFillColor(kOrange);
2102 hsurf4->Draw("SURF4");
2103}
2104End_Macro
2105
2106The following example shows a 2D histogram plotted with the option
2107`SURF5 CYL`. Combined with the option `SURF5`, the option
2108`Z` allows to display the color palette defined by `gStyle->SetPalette()`.
2109
2110Begin_Macro(source)
2111{
2112 auto c2 = new TCanvas("c2","c2",600,400);
2113 auto hsurf5 = new TH2F("hsurf4","Option SURF5 example ",30,-4,4,30,-20,20);
2114 float px, py;
2115 for (Int_t i = 0; i < 25000; i++) {
2116 gRandom->Rannor(px,py);
2117 hsurf5->Fill(px-1,5*py);
2118 hsurf5->Fill(2+0.5*px,2*py-10.,0.1);
2119 }
2120 hsurf5->Draw("SURF5 CYL");
2121}
2122End_Macro
2123
2124The following example shows a 2D histogram plotted with the option
2125`SURF7`. The option `SURF7` draws a surface plot using the
2126hidden surfaces removal technique with, in addition, a line contour view drawn on the
2127top. Combined with the option `SURF7`, the option `Z` allows
2128to display the color palette defined by `gStyle->SetPalette()`.
2129
2130Begin_Macro(source)
2131{
2132 auto c2 = new TCanvas("c2","c2",600,400);
2133 auto hsurf7 = new TH2F("hsurf3","Option SURF7 example ",30,-4,4,30,-20,20);
2134 float px, py;
2135 for (Int_t i = 0; i < 25000; i++) {
2136 gRandom->Rannor(px,py);
2137 hsurf7->Fill(px-1,5*py);
2138 hsurf7->Fill(2+0.5*px,2*py-10.,0.1);
2139 }
2140 hsurf7->Draw("SURF7");
2141}
2142End_Macro
2143
2144As shown in the following example, when a contour plot is painted on top of a
2145surface plot using the option `SAME`, the contours appear in 3D on the
2146surface.
2147
2148Begin_Macro(source)
2149{
2150 auto c20=new TCanvas("c20","c20",600,400);
2151 int NBins = 50;
2152 double d = 2;
2153 auto hsc = new TH2F("hsc", "Surface and contour with option SAME ", NBins, -d, d, NBins, -d, d);
2154 for (int bx = 1; bx <= NBins; ++bx) {
2155 for (int by = 1; by <= NBins; ++by) {
2156 double x = hsc->GetXaxis()->GetBinCenter(bx);
2157 double y = hsc->GetYaxis()->GetBinCenter(by);
2158 hsc->SetBinContent(bx, by, exp(-x*x)*exp(-y*y));
2159 }
2160 }
2161 hsc->Draw("surf2");
2162 hsc->Draw("CONT1 SAME");
2163}
2164End_Macro
2165
2166
2167\anchor HP19
2168### Cylindrical, Polar, Spherical and PseudoRapidity/Phi options
2169
2170
2171Legos and surfaces plots are represented by default in Cartesian coordinates.
2172Combined with any `LEGOn` or `SURFn` options the following
2173options allow to draw a lego or a surface in other coordinates systems.
2174
2175| Option | Description |
2176|----------|-------------------------------------------------------------------|
2177| "CYL" | Use Cylindrical coordinates. The X coordinate is mapped on the angle and the Y coordinate on the cylinder
2178length.| | "POL" | Use Polar coordinates. The X coordinate is mapped on the angle and the Y coordinate on the
2179radius.| | "SPH" | Use Spherical coordinates. The X coordinate is mapped on the latitude and the Y coordinate on the
2180longitude.| | "PSR" | Use PseudoRapidity/Phi coordinates. The X coordinate is mapped on Phi.|
2181
2182
2183
2184<b>WARNING:</b> Axis are not drawn with these options.
2185
2186The following example shows the same histogram as a lego plot is the four
2187different coordinates systems.
2188
2189Begin_Macro(source)
2190{
2191 auto c3 = new TCanvas("c3","c3",600,400);
2192 c3->Divide(2,2);
2193 auto hlcc = new TH2F("hlcc","Cylindrical coordinates",20,-4,4,20,-20,20);
2194 float px, py;
2195 for (Int_t i = 0; i < 25000; i++) {
2196 gRandom->Rannor(px,py);
2197 hlcc->Fill(px-1,5*py);
2198 hlcc->Fill(2+0.5*px,2*py-10.,0.1);
2199 }
2200 hlcc->SetFillColor(kYellow);
2201 c3->cd(1); hlcc->Draw("LEGO1 CYL");
2202 c3->cd(2); auto hlpc = (TH2F*) hlcc->DrawClone("LEGO1 POL");
2203 hlpc->SetTitle("Polar coordinates");
2204 c3->cd(3); auto hlsc = (TH2F*) hlcc->DrawClone("LEGO1 SPH");
2205 hlsc->SetTitle("Spherical coordinates");
2206 c3->cd(4); auto hlprpc = (TH2F*) hlcc->DrawClone("LEGO1 PSR");
2207 hlprpc->SetTitle("PseudoRapidity/Phi coordinates");
2208}
2209End_Macro
2210
2211The following example shows the same histogram as a surface plot is the four different coordinates systems.
2212
2213Begin_Macro(source)
2214{
2215 auto c4 = new TCanvas("c4","c4",600,400);
2216 c4->Divide(2,2);
2217 auto hscc = new TH2F("hscc","Cylindrical coordinates",20,-4,4,20,-20,20);
2218 float px, py;
2219 for (Int_t i = 0; i < 25000; i++) {
2220 gRandom->Rannor(px,py);
2221 hscc->Fill(px-1,5*py);
2222 hscc->Fill(2+0.5*px,2*py-10.,0.1);
2223 }
2224 c4->cd(1); hscc->Draw("SURF1 CYL");
2225 c4->cd(2); auto hspc = (TH2F*) hscc->DrawClone("SURF1 POL");
2226 hspc->SetTitle("Polar coordinates");
2227 c4->cd(3); auto hssc = (TH2F*) hscc->DrawClone("SURF1 SPH");
2228 hssc->SetTitle("Spherical coordinates");
2229 c4->cd(4); auto hsprpc = (TH2F*) hscc->DrawClone("SURF1 PSR");
2230 hsprpc->SetTitle("PseudoRapidity/Phi coordinates");
2231}
2232End_Macro
2233
2234
2235\anchor HP20
2236### Base line for bar-charts and lego plots
2237
2238
2239By default the base line used to draw the boxes for bar-charts and lego plots is
2240the histogram minimum. It is possible to force this base line to be 0, using MIN0 draw
2241option or with the command:
2242
2243 gStyle->SetHistMinimumZero();
2244
2245Begin_Macro(source)
2246{
2247 auto c5 = new TCanvas("c5","c5",700,400);
2248 c5->Divide(2,1);
2249 auto hz1 = new TH1F("hz1","Bar-chart drawn from 0",20,-3,3);
2250 auto hz2 = new TH2F("hz2","Lego plot drawn from 0",20,-3,3,20,-3,3);
2251 Int_t i;
2252 double x,y;
2253 hz1->SetFillColor(kBlue);
2254 hz2->SetFillColor(kBlue);
2255 for (i=0;i<10000;i++) {
2256 x = gRandom->Gaus(0,1);
2257 y = gRandom->Gaus(0,1);
2258 if (x>0) {
2259 hz1->Fill(x,1);
2260 hz2->Fill(x,y,1);
2261 } else {
2262 hz1->Fill(x,-1);
2263 hz2->Fill(x,y,-2);
2264 }
2265 }
2266 c5->cd(1); hz1->Draw("bar2 min0");
2267 c5->cd(2); hz2->Draw("lego1 min0");
2268}
2269End_Macro
2270
2271This option also works for horizontal plots. The example given in the section
2272["The bar chart option"](\ref HP100) appears as follow:
2273
2274Begin_Macro(source)
2275{
2276 int i;
2277 const Int_t nx = 8;
2278 string os_X[nx] = {"8","32","128","512","2048","8192","32768","131072"};
2279 float d_35_0[nx] = {0.75, -3.30, -0.92, 0.10, 0.08, -1.69, -1.29, -2.37};
2280 float d_35_1[nx] = {1.01, -3.02, -0.65, 0.37, 0.34, -1.42, -1.02, -2.10};
2281
2282 auto cbh = new TCanvas("cbh","cbh",400,600);
2283 cbh->SetGrid();
2284
2285 auto h1bh = new TH1F("h1bh","Option HBAR centered on 0",nx,0,nx);
2286 h1bh->SetFillColor(4);
2287 h1bh->SetBarWidth(0.4);
2288 h1bh->SetBarOffset(0.1);
2289 h1bh->SetStats(0);
2290 h1bh->SetMinimum(-5);
2291 h1bh->SetMaximum(5);
2292
2293 for (i=1; i<=nx; i++) {
2294 h1bh->Fill(os_X[i-1].c_str(), d_35_0[i-1]);
2295 h1bh->GetXaxis()->SetBinLabel(i,os_X[i-1].c_str());
2296 }
2297
2298 h1bh->Draw("hbar min0");
2299
2300 auto h2bh = new TH1F("h2bh","h2bh",nx,0,nx);
2301 h2bh->SetFillColor(38);
2302 h2bh->SetBarWidth(0.4);
2303 h2bh->SetBarOffset(0.5);
2304 h2bh->SetStats(0);
2305 for (i=1;i<=nx;i++) h2bh->Fill(os_X[i-1].c_str(), d_35_1[i-1]);
2306
2307 h2bh->Draw("hbar min0 same");
2308}
2309End_Macro
2310
2311
2312\anchor HP20a
2313### TH2Poly Drawing
2314
2315
2316The following options are supported:
2317
2318| Option | Description |
2319|----------|-------------------------------------------------------------------|
2320| "SCAT" | Draw a scatter plot (legacy draw option).|
2321| "COL" | Draw a color plot. All the bins are painted even the empty bins (default).|
2322| "COLZ" | Same as "COL". In addition the color palette is also drawn.|
2323| "0" | When used with any COL options, the empty bins are not drawn.|
2324| "TEXT" | Draw bin contents as text (format set via `gStyle->SetPaintTextFormat`).|
2325| "TEXTN" | Draw bin names as text.|
2326| "TEXTnn" | Draw bin contents as text at angle nn (0 < nn <= 90).|
2327| "L" | Draw the bins boundaries as lines. The lines attributes are the TGraphs ones.|
2328| "P" | Draw the bins boundaries as markers. The markers attributes are the TGraphs ones.|
2329| "F" | Draw the bins boundaries as filled polygons. The filled polygons attributes are the TGraphs ones.|
2330
2331
2332
2333`TH2Poly` can be drawn as a color plot (option COL). `TH2Poly` bins can have any
2334shapes. The bins are defined as graphs. The following macro is a very simple
2335example showing how to book a TH2Poly and draw it.
2336
2337Begin_Macro(source)
2338{
2339 auto ch2p1 = new TCanvas("ch2p1","ch2p1",600,400);
2340 auto h2p = new TH2Poly();
2341 h2p->SetName("h2poly_name");
2342 h2p->SetTitle("h2poly_title");
2343 double px1[] = {0, 5, 6};
2344 double py1[] = {0, 0, 5};
2345 double px2[] = {0, -1, -1, 0};
2346 double py2[] = {0, 0, -1, 3};
2347 double px3[] = {4, 3, 0, 1, 2.4};
2348 double py3[] = {4, 3.7, 1, 3.7, 2.5};
2349 h2p->AddBin(3, px1, py1);
2350 h2p->AddBin(4, px2, py2);
2351 h2p->AddBin(5, px3, py3);
2352 h2p->Fill(0.1, 0.01, 3);
2353 h2p->Fill(-0.5, -0.5, 7);
2354 h2p->Fill(-0.7, -0.5, 1);
2355 h2p->Fill(1, 3, 1.5);
2356 double fx[] = {0.1, -0.5, -0.7, 1};
2357 double fy[] = {0.01, -0.5, -0.5, 3};
2358 double fw[] = {3, 1, 1, 1.5};
2359 h2p->FillN(4, fx, fy, fw);
2360 h2p->Draw("col");
2361}
2362End_Macro
2363
2364Rectangular bins are a frequent case. The special version of
2365the `AddBin` method allows to define them more easily like
2366shown in the following example (th2polyBoxes.C).
2367
2368Begin_Macro(source)
2369../../../tutorials/hist/th2polyBoxes.C
2370End_Macro
2371
2372One `TH2Poly` bin can be a list of polygons. Such bins are defined
2373by calling `AddBin` with a `TMultiGraph`. The following example
2374shows a such case:
2375
2376Begin_Macro(source)
2377{
2378 auto ch2p2 = new TCanvas("ch2p2","ch2p2",600,400);
2379
2380 Int_t i, bin;
2381 const Int_t nx = 48;
2382 const char *states [nx] = {
2383 "alabama", "arizona", "arkansas", "california",
2384 "colorado", "connecticut", "delaware", "florida",
2385 "georgia", "idaho", "illinois", "indiana",
2386 "iowa", "kansas", "kentucky", "louisiana",
2387 "maine", "maryland", "massachusetts", "michigan",
2388 "minnesota", "mississippi", "missouri", "montana",
2389 "nebraska", "nevada", "new_hampshire", "new_jersey",
2390 "new_mexico", "new_york", "north_carolina", "north_dakota",
2391 "ohio", "oklahoma", "oregon", "pennsylvania",
2392 "rhode_island", "south_carolina", "south_dakota", "tennessee",
2393 "texas", "utah", "vermont", "virginia",
2394 "washington", "west_virginia", "wisconsin", "wyoming"
2395 };
2396 Double_t pop[nx] = {
2397 4708708, 6595778, 2889450, 36961664, 5024748, 3518288, 885122, 18537969,
2398 9829211, 1545801, 12910409, 6423113, 3007856, 2818747, 4314113, 4492076,
2399 1318301, 5699478, 6593587, 9969727, 5266214, 2951996, 5987580, 974989,
2400 1796619, 2643085, 1324575, 8707739, 2009671, 19541453, 9380884, 646844,
2401 11542645, 3687050, 3825657, 12604767, 1053209, 4561242, 812383, 6296254,
2402 24782302, 2784572, 621760, 7882590, 6664195, 1819777, 5654774, 544270
2403 };
2404
2405 Double_t lon1 = -130;
2406 Double_t lon2 = -65;
2407 Double_t lat1 = 24;
2408 Double_t lat2 = 50;
2409 auto p = new TH2Poly("USA","USA Population",lon1,lon2,lat1,lat2);
2410
2411 TFile::SetCacheFileDir(".");
2412 auto f = TFile::Open("http://root.cern/files/usa.root", "CACHEREAD");
2413
2414 TMultiGraph *mg;
2415 TKey *key;
2416 TIter nextkey(gDirectory->GetListOfKeys());
2417 while ((key = (TKey*)nextkey())) {
2418 TObject *obj = key->ReadObj();
2419 if (obj->InheritsFrom("TMultiGraph")) {
2420 mg = (TMultiGraph*)obj;
2421 bin = p->AddBin(mg);
2422 }
2423 }
2424
2425 for (i=0; i<nx; i++) p->Fill(states[i], pop[i]);
2426
2427 gStyle->SetOptStat(11);
2428 p->Draw("COLZ L");
2429}
2430End_Macro
2431
2432`TH2Poly` histograms can also be plotted using the GL interface using
2433the option "GLLEGO".
2434
2435\since **ROOT version 6.09/01**
2436
2437In some cases it can be useful to not draw the empty bins. the option "0"
2438combined with the option "COL" et COLZ allows to do that.
2439
2440Begin_Macro(source)
2441{
2442 auto chc = new TCanvas("chc","chc",600,400);
2443
2444 auto hc = new TH2Poly();
2445 hc->Honeycomb(0,0,.1,25,25);
2446 hc->SetName("hc");
2447 hc->SetTitle("Option COLZ 0");
2448 TRandom ran;
2449 for (int i = 0; i<300; i++) hc->Fill(ran.Gaus(2.,1), ran.Gaus(2.,1));
2450 hc->Draw("colz 0");
2451}
2452End_Macro
2453
2454\anchor HP21
2455### The SPEC option
2456
2457
2458This option allows to use the `TSpectrum2Painter` tools. See the full
2459documentation in `TSpectrum2Painter::PaintSpectrum`.
2460
2461
2462\anchor HP22
2463### Option "Z" : Adding the color palette on the right side of the pad
2464
2465
2466When this option is specified, a color palette with an axis indicating the value
2467of the corresponding color is drawn on the right side of the picture. In case,
2468not enough space is left, one can increase the size of the right margin by
2469calling `TPad::SetRightMargin()`. The attributes used to display the
2470palette axis values are taken from the Z axis of the object. For example, to
2471set the labels size on the palette axis do:
2472
2473 hist->GetZaxis()->SetLabelSize().
2474
2475<b>WARNING:</b> The palette axis is always drawn vertically.
2476
2477
2478\anchor HP23
2479### Setting the color palette
2480
2481
2482To change the color palette `TStyle::SetPalette` should be used, eg:
2483
2484 gStyle->SetPalette(ncolors,colors);
2485
2486For example the option `COL` draws a 2D histogram with cells
2487represented by a box filled with a color index which is a function
2488of the cell content.
2489If the cell content is N, the color index used will be the color number
2490in `colors[N]`, etc. If the maximum cell content is greater than
2491`ncolors`, all cell contents are scaled to `ncolors`.
2492
2493If ` ncolors <= 0`, a default palette (see below) of 50 colors is
2494defined. This palette is recommended for pads, labels ...
2495
2496`if ncolors == 1 && colors == 0`, then a Pretty Palette with a
2497Spectrum Violet->Red is created with 50 colors. That's the default rain bow
2498palette.
2499
2500Other pre-defined palettes with 255 colors are available when `colors == 0`.
2501The following value of `ncolors` give access to:
2502
2503
2504 if ncolors = 51 and colors=0, a Deep Sea palette is used.
2505 if ncolors = 52 and colors=0, a Grey Scale palette is used.
2506 if ncolors = 53 and colors=0, a Dark Body Radiator palette is used.
2507 if ncolors = 54 and colors=0, a two-color hue palette palette is used.(dark blue through neutral gray to bright
2508yellow) if ncolors = 55 and colors=0, a Rain Bow palette is used. if ncolors = 56 and colors=0, an inverted Dark Body
2509Radiator palette is used.
2510
2511
2512If `ncolors > 0 && colors == 0`, the default palette is used with a maximum of ncolors.
2513
2514The default palette defines:
2515
2516- index 0 to 9 : shades of grey
2517- index 10 to 19 : shades of brown
2518- index 20 to 29 : shades of blue
2519- index 30 to 39 : shades of red
2520- index 40 to 49 : basic colors
2521
2522The color numbers specified in the palette can be viewed by selecting
2523the item `colors` in the `VIEW` menu of the canvas tool bar.
2524The red, green, and blue components of a color can be changed thanks to
2525`TColor::SetRGB()`.
2526
2527\since **ROOT version 6.19/01**
2528
2529As default labels and ticks are drawn by `TGAxis` at equidistant (lin or log)
2530points as controlled by SetNdivisions.
2531If option "CJUST" is given labels and ticks are justified at the
2532color boundaries defined by the contour levels.
2533For more details see `TPaletteAxis`
2534
2535\anchor HP24
2536### Drawing a sub-range of a 2D histogram; the [cutg] option
2537
2538
2539Using a `TCutG` object, it is possible to draw a sub-range of a 2D
2540histogram. One must create a graphical cut (mouse or C++) and specify the name
2541of the cut between `[]` in the `Draw()` option.
2542For example (fit2a.C), with a `TCutG` named `cutg`, one can call:
2543
2544 myhist->Draw("surf1 [cutg]");
2545
2546To invert the cut, it is enough to put a `-` in front of its name:
2547
2548 myhist->Draw("surf1 [-cutg]");
2549
2550It is possible to apply several cuts (`,` means logical AND):
2551
2552 myhist->Draw("surf1 [cutg1,cutg2]");
2553
2554Begin_Macro(source)
2555../../../tutorials/fit/fit2a.C
2556End_Macro
2557
2558\anchor HP25
2559### Drawing options for 3D histograms
2560
2561
2562| Option | Description |
2563|----------|-------------------------------------------------------------------|
2564| "SCAT" | Draw a scatter plot (legacy draw option).|
2565| "ISO" | Draw a Gouraud shaded 3d iso surface through a 3d histogram. It paints one surface at the value computed as
2566follow: `SumOfWeights/(NbinsX*NbinsY*NbinsZ)`| | "BOX" | Draw a for each cell with volume proportional to the
2567content's absolute value. An hidden line removal algorithm is used| | "BOX1" | Same as BOX but an hidden surface
2568removal algorithm is used| | "BOX2" | Same as "COL". The boxes' colors are picked in the current palette according to
2569the bins' contents (default)| | "BOX2Z" | Same as "BOX2". In addition the color palette is also drawn.| | "BOX3" |
2570Same as BOX1, but the border lines of each lego-bar are not drawn.|
2571
2572Note that instead of `BOX` one can also use `LEGO`.
2573
2574By default, 3D histograms are drawn as a colored box plots.
2575
2576The following example shows a 3D histogram plotted as a scatter plot.
2577
2578Begin_Macro(source)
2579{
2580 auto c06 = new TCanvas("c06","c06",600,400);
2581 gStyle->SetOptStat(kFALSE);
2582 auto h3scat = new TH3F("h3scat","Option SCAT",15,-2,2,15,-2,2,15,0,4);
2583 double x, y, z;
2584 for (Int_t i=0;i<10000;i++) {
2585 gRandom->Rannor(x, y);
2586 z = x*x + y*y;
2587 h3scat->Fill(x,y,z);
2588 }
2589 h3scat->Draw("SCAT"); // This a legacy draw option
2590}
2591End_Macro
2592
2593The following example shows a 3D histogram plotted with the option `BOX`.
2594
2595Begin_Macro(source)
2596{
2597 auto c16 = new TCanvas("c16","c16",600,400);
2598 gStyle->SetOptStat(kFALSE);
2599 auto h3box = new TH3F("h3box","Option BOX",15,-2,2,15,-2,2,15,0,4);
2600 double x, y, z;
2601 for (Int_t i=0;i<10000;i++) {
2602 gRandom->Rannor(x, y);
2603 z = x*x + y*y;
2604 h3box->Fill(x,y,z);
2605 }
2606 h3box->Draw("BOX");
2607}
2608End_Macro
2609
2610The following example shows a 3D histogram plotted with the option `BOX1`.
2611
2612Begin_Macro(source)
2613{
2614 auto c36 = new TCanvas("c36","c36",600,400);
2615 gStyle->SetOptStat(kFALSE);
2616 auto h3box = new TH3F("h3box","Option BOX1",10,-2.,2.,10,-2.,2.,10,-0.5,2.);
2617 double x, y, z;
2618 for (Int_t i=0;i<10000;i++) {
2619 gRandom->Rannor(x, y);
2620 z = abs(sin(x)/x + cos(y)*y);
2621 h3box->Fill(x,y,z);
2622 }
2623 h3box->SetFillColor(9);
2624 h3box->Draw("BOX1");
2625}
2626End_Macro
2627
2628The following example shows a 3D histogram plotted with the option `BOX2`.
2629
2630Begin_Macro(source)
2631{
2632 auto c56 = new TCanvas("c56","c56",600,400);
2633 gStyle->SetOptStat(kFALSE);
2634 auto h3box = new TH3F("h3box","Option BOX2 (default)",10,-2.,2.,10,-2.,2.,10,-0.5,2.);
2635 double x, y, z;
2636 for (Int_t i=0;i<10000;i++) {
2637 gRandom->Rannor(x, y);
2638 z = abs(sin(x)/x + cos(y)*y);
2639 h3box->Fill(x,y,z);
2640 }
2641 h3box->Draw("BOX2 Z");
2642}
2643End_Macro
2644
2645The following example shows a 3D histogram plotted with the option `BOX3`.
2646
2647Begin_Macro(source)
2648{
2649 auto c46 = new TCanvas("c46","c46",600,400);
2650 c46->SetFillColor(38);
2651 gStyle->SetOptStat(kFALSE);
2652 auto h3box = new TH3F("h3box","Option BOX3",15,-2,2,15,-2,2,15,0,4);
2653 double x, y, z;
2654 for (Int_t i=0;i<10000;i++) {
2655 gRandom->Rannor(x, y);
2656 z = x*x + y*y;
2657 h3box->Fill(x,y,z);
2658 }
2659 h3box->Draw("BOX3");
2660}
2661End_Macro
2662
2663For all the `BOX` options each bin is drawn as a 3D box with a volume proportional
2664to the absolute value of the bin content. The bins with a negative content are
2665drawn with a X on each face of the box as shown in the following example:
2666
2667Begin_Macro(source)
2668{
2669 auto c = new TCanvas("c","c",600,400);
2670 gStyle->SetOptStat(kFALSE);
2671 auto h3box = new TH3F("h3box","Option BOX1 with negative bins",3, 0., 4., 3, 0.,4., 3, 0., 4.);
2672 h3box->Fill(0., 2., 2., 10.);
2673 h3box->Fill(2., 2., 2., 5.);
2674 h3box->Fill(2., 2., .5, 2.);
2675 h3box->Fill(2., 2., 3., -1.);
2676 h3box->Fill(3., 2., 2., -10.);
2677 h3box->SetFillColor(8);
2678 h3box->Draw("box1");
2679}
2680End_Macro
2681
2682The following example shows a 3D histogram plotted with the option `ISO`.
2683
2684Begin_Macro(source)
2685{
2686 auto c26 = new TCanvas("c26","c26",600,400);
2687 gStyle->SetOptStat(kFALSE);
2688 auto h3iso = new TH3F("h3iso","Option ISO",15,-2,2,15,-2,2,15,0,4);
2689 double x, y, z;
2690 for (Int_t i=0;i<10000;i++) {
2691 gRandom->Rannor(x, y);
2692 z = x*x + y*y;
2693 h3iso->Fill(x,y,z);
2694 }
2695 h3iso->SetFillColor(kCyan);
2696 h3iso->Draw("ISO");
2697}
2698End_Macro
2699
2700
2701\anchor HP26
2702### Drawing option for histograms' stacks
2703
2704
2705Stacks of histograms are managed with the `THStack`. A `THStack`
2706is a collection of `TH1` (or derived) objects. For painting only the
2707`THStack` containing `TH1` only or
2708`THStack` containing `TH2` only will be considered.
2709
2710By default, histograms are shown stacked:
2711
27121. The first histogram is paint.
27132. The sum of the first and second, etc...
2714
2715If the option `NOSTACK` is specified, the histograms are all paint in
2716the same pad as if the option `SAME` had been specified. This allows to
2717compute X and Y scales common to all the histograms, like
2718`TMultiGraph` does for graphs.
2719
2720If the option `PADS` is specified, the current pad/canvas is
2721subdivided into a number of pads equal to the number of histograms and each
2722histogram is paint into a separate pad.
2723
2724The following example shows various types of stacks (hstack.C).
2725
2726Begin_Macro(source)
2727../../../tutorials/hist/hstack.C
2728End_Macro
2729
2730The option `nostackb` allows to draw the histograms next to each
2731other as bar charts:
2732
2733Begin_Macro(source)
2734{
2735 auto cst0 = new TCanvas("cst0","cst0",600,400);
2736 auto hs = new THStack("hs","Stacked 1D histograms: option #font[82]{\"nostackb\"}");
2737
2738 auto h1 = new TH1F("h1","h1",10,-4,4);
2739 h1->FillRandom("gaus",20000);
2740 h1->SetFillColor(kRed);
2741 hs->Add(h1);
2742
2743 auto h2 = new TH1F("h2","h2",10,-4,4);
2744 h2->FillRandom("gaus",15000);
2745 h2->SetFillColor(kBlue);
2746 hs->Add(h2);
2747
2748 auto h3 = new TH1F("h3","h3",10,-4,4);
2749 h3->FillRandom("gaus",10000);
2750 h3->SetFillColor(kGreen);
2751 hs->Add(h3);
2752
2753 hs->Draw("nostackb");
2754 hs->GetXaxis()->SetNdivisions(-10);
2755 cst0->SetGridx();
2756}
2757End_Macro
2758
2759If at least one of the histograms in the stack has errors, the whole stack is
2760visualized by default with error bars. To visualize it without errors the
2761option `HIST` should be used.
2762
2763Begin_Macro(source)
2764{
2765 auto cst1 = new TCanvas("cst1","cst1",700,400);
2766 cst1->Divide(2,1);
2767
2768 auto hst11 = new TH1F("hst11", "", 20, -10, 10);
2769 hst11->Sumw2();
2770 hst11->FillRandom("gaus", 1000);
2771 hst11->SetFillColor(kViolet);
2772 hst11->SetLineColor(kViolet);
2773
2774 auto hst12 = new TH1F("hst12", "", 20, -10, 10);
2775 hst12->FillRandom("gaus", 500);
2776 hst12->SetFillColor(kBlue);
2777 hst12->SetLineColor(kBlue);
2778
2779 THStack st1("st1", "st1");
2780 st1.Add(hst11);
2781 st1.Add(hst12);
2782
2783 cst1->cd(1); st1.Draw();
2784 cst1->cd(2); st1.Draw("hist");
2785}
2786End_Macro
2787
2788\anchor HP27
2789### Drawing of 3D implicit functions
2790
2791
27923D implicit functions (`TF3`) can be drawn as iso-surfaces.
2793The implicit function f(x,y,z) = 0 is drawn in cartesian coordinates.
2794In the following example the options "FB" and "BB" suppress the
2795"Front Box" and "Back Box" around the plot.
2796
2797Begin_Macro(source)
2798{
2799 auto c2 = new TCanvas("c2","c2",600,400);
2800 auto f3 = new TF3("f3","sin(x*x+y*y+z*z-36)",-2,2,-2,2,-2,2);
2801 f3->SetClippingBoxOn(0,0,0);
2802 f3->SetFillColor(30);
2803 f3->SetLineColor(15);
2804 f3->Draw("FBBB");
2805}
2806End_Macro
2807
2808
2809\anchor HP28
2810### Associated functions drawing
2811
2812
2813An associated function is created by `TH1::Fit`. More than on fitted
2814function can be associated with one histogram (see `TH1::Fit`).
2815
2816A `TF1` object `f1` can be added to the list of associated
2817functions of an histogram `h` without calling `TH1::Fit`
2818simply doing:
2819
2820 h->GetListOfFunctions()->Add(f1);
2821
2822or
2823
2824 h->GetListOfFunctions()->Add(f1,someoption);
2825
2826To retrieve a function by name from this list, do:
2827
2828 TF1 *f1 = (TF1*)h->GetListOfFunctions()->FindObject(name);
2829
2830or
2831
2832 TF1 *f1 = h->GetFunction(name);
2833
2834Associated functions are automatically painted when an histogram is drawn.
2835To avoid the painting of the associated functions the option `HIST`
2836should be added to the list of the options used to paint the histogram.
2837
2838
2839\anchor HP29
2840### Drawing using OpenGL
2841
2842
2843The class `TGLHistPainter` allows to paint data set using the OpenGL 3D
2844graphics library. The plotting options start with `GL` keyword.
2845In addition, in order to inform canvases that OpenGL should be used to render
28463D representations, the following option should be set:
2847
2848 gStyle->SetCanvasPreferGL(true);
2849
2850
2851\anchor HP29a
2852#### General information: plot types and supported options
2853
2854The following types of plots are provided:
2855
2856For lego plots the supported options are:
2857
2858| Option | Description |
2859|----------|-------------------------------------------------------------------|
2860| "GLLEGO" | Draw a lego plot. It works also for `TH2Poly`.|
2861| "GLLEGO2"| Bins with color levels.|
2862| "GLLEGO3"| Cylindrical bars.|
2863
2864
2865
2866Lego painter in cartesian supports logarithmic scales for X, Y, Z.
2867In polar only Z axis can be logarithmic, in cylindrical only Y.
2868
2869For surface plots (`TF2` and `TH2`) the supported options are:
2870
2871| Option | Description |
2872|-----------|------------------------------------------------------------------|
2873| "GLSURF" | Draw a surface.|
2874| "GLSURF1" | Surface with color levels|
2875| "GLSURF2" | The same as "GLSURF1" but without polygon outlines.|
2876| "GLSURF3" | Color level projection on top of plot (works only in cartesian coordinate system).|
2877| "GLSURF4" | Same as "GLSURF" but without polygon outlines.|
2878
2879
2880
2881The surface painting in cartesian coordinates supports logarithmic scales along
2882X, Y, Z axis. In polar coordinates only the Z axis can be logarithmic,
2883in cylindrical coordinates only the Y axis.
2884
2885Additional options to SURF and LEGO - Coordinate systems:
2886
2887| Option | Description |
2888|----------|-------------------------------------------------------------------|
2889| " " | Default, cartesian coordinates system.|
2890| "POL" | Polar coordinates system.|
2891| "CYL" | Cylindrical coordinates system.|
2892| "SPH" | Spherical coordinates system.|
2893
2894
2895
2896\anchor HP290
2897#### TH3 as color boxes
2898
2899The supported option is:
2900
2901| Option | Description |
2902|----------|-------------------------------------------------------------------|
2903| "GLCOL" | H3 is drawn using semi-transparent colored boxes. See `$ROOTSYS/tutorials/visualisation/gl/glvox1.C`.|
2904
2905
2906
2907\anchor HP29b
2908#### TH3 as boxes (spheres)
2909
2910The supported options are:
2911
2912| Option | Description |
2913|----------|-------------------------------------------------------------------|
2914| "GLBOX" | TH3 as a set of boxes, size of box is proportional to bin content.|
2915| "GLBOX1" | The same as "glbox", but spheres are drawn instead of boxes.|
2916
2917
2918
2919\anchor HP29c
2920#### TH3 as iso-surface(s)
2921
2922The supported option is:
2923
2924| Option | Description |
2925|----------|-------------------------------------------------------------------|
2926| "GLISO" | TH3 is drawn using iso-surfaces.|
2927
2928
2929
2930\anchor HP29d
2931#### TF3 (implicit function)
2932
2933The supported option is:
2934
2935| Option | Description |
2936|----------|-------------------------------------------------------------------|
2937| "GL" | Draw a TF3.|
2938
2939
2940
2941\anchor HP29e
2942#### Parametric surfaces
2943
2944`$ROOTSYS/tutorials/visualisation/gl/glparametric.C` shows how to create parametric
2945equations and visualize the surface.
2946
2947\anchor HP29f
2948#### Interaction with the plots
2949
2950All the interactions are implemented via standard methods
2951`DistancetoPrimitive()` and `ExecuteEvent()`. That's why all the
2952interactions with the OpenGL plots are possible only when the mouse cursor is
2953in the plot's area (the plot's area is the part of a the pad occupied by
2954gl-produced picture). If the mouse cursor is not above gl-picture, the standard
2955pad interaction is performed.
2956
2957\anchor HP29g
2958#### Selectable parts
2959
2960Different parts of the plot can be selected:
2961
2962- xoz, yoz, xoy back planes: When such a plane selected, it's highlighted in green
2963 if the dynamic slicing by this plane is supported, and it's highlighted in red,
2964 if the dynamic slicing is not supported.
2965- The plot itself:
2966 On surfaces, the selected surface is outlined in red. (TF3 and
2967 ISO are not outlined). On lego plots, the selected bin is
2968 highlighted. The bin number and content are displayed in pad's
2969 status bar. In box plots, the box or sphere is highlighted and
2970 the bin info is displayed in pad's status bar.
2971
2972
2973\anchor HP29h
2974#### Rotation and zooming
2975
2976
2977- Rotation:
2978 When the plot is selected, it can be rotated by pressing and
2979 holding the left mouse button and move the cursor.
2980- Zoom/Unzoom:
2981 Mouse wheel or 'j', 'J', 'k', 'K' keys.
2982
2983
2984\anchor HP29i
2985#### Panning
2986
2987The selected plot can be moved in a pad's area by pressing and
2988holding the left mouse button and the shift key.
2989
2990\anchor HP29j
2991#### Box cut
2992
2993Surface, iso, box, TF3 and parametric painters support box cut by
2994pressing the 'c' or 'C' key when the mouse cursor is in a plot's
2995area. That will display a transparent box, cutting away part of the
2996surface (or boxes) in order to show internal part of plot. This box
2997can be moved inside the plot's area (the full size of the box is
2998equal to the plot's surrounding box) by selecting one of the box
2999cut axes and pressing the left mouse button to move it.
3000
3001\anchor HP29k
3002#### Plot specific interactions (dynamic slicing etc.)
3003
3004Currently, all gl-plots support some form of slicing. When back plane
3005is selected (and if it's highlighted in green) you can press and hold
3006left mouse button and shift key and move this back plane inside
3007plot's area, creating the slice. During this "slicing" plot becomes
3008semi-transparent. To remove all slices (and projected curves for
3009surfaces) double click with left mouse button in a plot's area.
3010
3011\anchor HP29l
3012#### Surface with option "GLSURF"
3013
3014The surface profile is displayed on the slicing plane.
3015The profile projection is drawn on the back plane
3016by pressing `'p'` or `'P'` key.
3017
3018\anchor HP29m
3019#### TF3
3020
3021The contour plot is drawn on the slicing plane. For TF3 the color
3022scheme can be changed by pressing 's' or 'S'.
3023
3024\anchor HP29n
3025#### Box
3026
3027The contour plot corresponding to slice plane position is drawn in real time.
3028
3029\anchor HP29o
3030#### Iso
3031
3032Slicing is similar to "GLBOX" option.
3033
3034\anchor HP29p
3035#### Parametric plot
3036
3037No slicing. Additional keys: 's' or 'S' to change color scheme -
3038about 20 color schemes supported ('s' for "scheme"); 'l' or 'L' to
3039increase number of polygons ('l' for "level" of details), 'w' or 'W'
3040to show outlines ('w' for "wireframe").
3041
3042\anchor HP30
3043#### Highlight mode for histogram
3044
3045\since **ROOT version 6.15/01**
3046
3047\image html hlHisto3_top.gif "Highlight mode"
3048
3049Highlight mode is implemented for `TH1` (and for `TGraph`) class. When
3050highlight mode is on, mouse movement over the bin will be represented
3051graphically. Bin will be highlighted as "bin box" (presented by box
3052object). Moreover, any highlight (change of bin) emits signal
3053`TCanvas::Highlighted()` which allows the user to react and call their own
3054function. For a better understanding see also the tutorials
3055`$ROOTSYS/tutorials/hist/hlHisto*.C` files.
3056
3057Highlight mode is switched on/off by `TH1::SetHighlight()` function
3058or interactively from `TH1` context menu. `TH1::IsHighlight()` to verify
3059whether the highlight mode enabled or disabled, default it is disabled.
3060
3061~~~ {.cpp}
3062 root [0] .x $ROOTSYS/tutorials/hsimple.C
3063 root [1] hpx->SetHighlight(kTRUE) // or interactively from TH1 context menu
3064 root [2] hpx->IsHighlight()
3065 (bool) true
3066~~~
3067
3068\image html hlsimple_nofun.gif "Highlight mode for histogram"
3069
3070\anchor HP30a
3071#### Highlight mode and user function
3072
3073The user can use (connect) `TCanvas::Highlighted()` signal, which is always
3074emitted if there is a highlight bin and call user function via signal
3075and slot communication mechanism. `TCanvas::Highlighted()` is similar
3076`TCanvas::Picked()`
3077
3078- when selected object (histogram as a whole) is different from previous
3079then emit `Picked()` signal
3080- when selected (highlighted) bin from histogram is different from previous
3081then emit `Highlighted()` signal
3082
3083Any user function (or functions) has to be defined
3084`UserFunction(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)`.
3085In example (see below) has name `PrintInfo()`. All parameters of user
3086function are taken from
3087
3088 void TCanvas::Highlighted(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)
3089
3090- `pad` is pointer to pad with highlighted histogram
3091- `obj` is pointer to highlighted histogram
3092- `x` is highlighted x bin for 1D histogram
3093- `y` is highlighted y bin for 2D histogram (for 1D histogram not in use)
3094
3095Example how to create a connection from any `TCanvas` object to a user
3096`UserFunction()` slot (see also `TQObject::Connect()` for additional info)
3097
3098 TQObject::Connect("TCanvas", "Highlighted(TVirtualPad*,TObject*,Int_t,Int_t)",
3099 0, 0, "UserFunction(TVirtualPad*,TObject*,Int_t,Int_t)");
3100
3101or use non-static "simplified" function
3102`TCanvas::HighlightConnect(const char *slot)`
3103
3104 c1->HighlightConnect("UserFunction(TVirtualPad*,TObject*,Int_t,Int_t)");
3105
3106NOTE the signal and slot string must have a form
3107"(TVirtualPad*,TObject*,Int_t,Int_t)"
3108
3109 root [0] .x $ROOTSYS/tutorials/hsimple.C
3110 root [1] hpx->SetHighlight(kTRUE)
3111 root [2] .x hlprint.C
3112
3113file `hlprint.C`
3114~~~ {.cpp}
3115void PrintInfo(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)
3116{
3117 auto h = (TH1F *)obj;
3118 if (!h->IsHighlight()) // after highlight disabled
3119 h->SetTitle("highlight disable");
3120 else
3121 h->SetTitle(TString::Format("bin[%03d] (%5.2f) content %g", x,
3122 h->GetBinCenter(x), h->GetBinContent(x)));
3123 pad->Update();
3124}
3125
3126void hlprint()
3127{
3128 if (!gPad) return;
3129 gPad->GetCanvas()->HighlightConnect("PrintInfo(TVirtualPad*,TObject*,Int_t,Int_t)");
3130}
3131~~~
3132
3133\image html hlsimple.gif "Highlight mode and simple user function"
3134
3135For more complex demo please see for example `$ROOTSYS/tutorials/io/tree/tree200_temperature.C` file.
3136
3137*/
3138
3140
3143
3144const Int_t kNMAX = 2000;
3145
3146const Int_t kMAXCONTOUR = 104;
3148
3149static std::unique_ptr<TBox> gXHighlightBox, gYHighlightBox; // highlight X and Y box
3150
3172
3174
3175////////////////////////////////////////////////////////////////////////////////
3176/// Default constructor.
3177
3179{
3180 fH = nullptr;
3181 fXaxis = nullptr;
3182 fYaxis = nullptr;
3183 fZaxis = nullptr;
3184 fFunctions = nullptr;
3185 fNcuts = 0;
3186 fStack = nullptr;
3187 fShowProjection = 0;
3188 fShowProjection2 = 0;
3189 fShowOption = "";
3190 for (int i=0; i<kMaxCuts; i++) {
3191 fCuts[i] = nullptr;
3192 fCutsOpt[i] = 0;
3193 }
3194 fXHighlightBin = -1;
3195 fYHighlightBin = -1;
3196 fCurrentF3 = nullptr;
3197
3198 gStringEntries = gEnv->GetValue("Hist.Stats.Entries", "Entries");
3199 gStringMean = gEnv->GetValue("Hist.Stats.Mean", "Mean");
3200 gStringMeanX = gEnv->GetValue("Hist.Stats.MeanX", "Mean x");
3201 gStringMeanY = gEnv->GetValue("Hist.Stats.MeanY", "Mean y");
3202 gStringMeanZ = gEnv->GetValue("Hist.Stats.MeanZ", "Mean z");
3203 gStringStdDev = gEnv->GetValue("Hist.Stats.StdDev", "Std Dev");
3204 gStringStdDevX = gEnv->GetValue("Hist.Stats.StdDevX", "Std Dev x");
3205 gStringStdDevY = gEnv->GetValue("Hist.Stats.StdDevY", "Std Dev y");
3206 gStringStdDevZ = gEnv->GetValue("Hist.Stats.StdDevZ", "Std Dev z");
3207 gStringUnderflow = gEnv->GetValue("Hist.Stats.Underflow", "Underflow");
3208 gStringOverflow = gEnv->GetValue("Hist.Stats.Overflow", "Overflow");
3209 gStringIntegral = gEnv->GetValue("Hist.Stats.Integral", "Integral");
3210 gStringIntegralBinWidth = gEnv->GetValue("Hist.Stats.IntegralBinWidth", "Integral(w)");
3211 gStringSkewness = gEnv->GetValue("Hist.Stats.Skewness", "Skewness");
3212 gStringSkewnessX = gEnv->GetValue("Hist.Stats.SkewnessX", "Skewness x");
3213 gStringSkewnessY = gEnv->GetValue("Hist.Stats.SkewnessY", "Skewness y");
3214 gStringSkewnessZ = gEnv->GetValue("Hist.Stats.SkewnessZ", "Skewness z");
3215 gStringKurtosis = gEnv->GetValue("Hist.Stats.Kurtosis", "Kurtosis");
3216 gStringKurtosisX = gEnv->GetValue("Hist.Stats.KurtosisX", "Kurtosis x");
3217 gStringKurtosisY = gEnv->GetValue("Hist.Stats.KurtosisY", "Kurtosis y");
3218 gStringKurtosisZ = gEnv->GetValue("Hist.Stats.KurtosisZ", "Kurtosis z");
3219}
3220
3221////////////////////////////////////////////////////////////////////////////////
3222/// destructor.
3223
3225{
3226}
3227
3228////////////////////////////////////////////////////////////////////////////////
3229/// Compute the distance from the point px,py to a line.
3230///
3231/// Compute the closest distance of approach from point px,py to elements of
3232/// an histogram. The distance is computed in pixels units.
3233///
3234/// Algorithm: Currently, this simple model computes the distance from the mouse
3235/// to the histogram contour only.
3236
3238{
3239
3240 Double_t defaultLabelSize = 0.04; // See TAttAxis.h for source of this value
3241
3242 const Int_t big = 9999;
3243 const Int_t kMaxDiff = 7;
3244
3245 if (fPie)
3246 return fPie->DistancetoPrimitive(px, py);
3247
3248 Double_t x = gPad->AbsPixeltoX(px);
3249 Double_t x1 = gPad->AbsPixeltoX(px+1);
3250
3251 Int_t puxmin = gPad->XtoAbsPixel(gPad->GetUxmin());
3252 Int_t puymin = gPad->YtoAbsPixel(gPad->GetUymin());
3253 Int_t puxmax = gPad->XtoAbsPixel(gPad->GetUxmax());
3254 Int_t puymax = gPad->YtoAbsPixel(gPad->GetUymax());
3255 Int_t curdist = big;
3256 Int_t yxaxis, dyaxis,xyaxis, dxaxis;
3257 Bool_t dsame;
3258 TObject *PadPointer = gPad->GetPadPointer();
3259 if (!PadPointer) return 0;
3260 TString doption = PadPointer->GetDrawOption();
3261 Double_t factor = 1;
3262 if (fH->GetNormFactor() != 0) {
3263 factor = fH->GetNormFactor()/fH->GetSumOfWeights();
3264 }
3265 // return if point is not in the histogram area
3266
3267 // If a 3D view exists, check distance to axis
3268 TView *view = gPad->GetView();
3269 Int_t d1,d2,d3;
3270 if (view && Hoption.Contour != 14) {
3271 Double_t ratio;
3272 d3 = view->GetDistancetoAxis(3, px, py, ratio);
3273 if (d3 <= kMaxDiff) {gPad->SetSelected(fZaxis); return 0;}
3274 d1 = view->GetDistancetoAxis(1, px, py, ratio);
3275 if (d1 <= kMaxDiff) {gPad->SetSelected(fXaxis); return 0;}
3276 d2 = view->GetDistancetoAxis(2, px, py, ratio);
3277 if (d2 <= kMaxDiff) {gPad->SetSelected(fYaxis); return 0;}
3278 if ( px > puxmin && px < puxmax && py > puymax && py < puymin) curdist = 1;
3279 goto FUNCTIONS;
3280 }
3281 // check if point is close to an axis
3282 doption.ToLower();
3283 dsame = kFALSE;
3284 if (doption.Contains("same")) dsame = kTRUE;
3285
3286 dyaxis = Int_t(2*(puymin-puymax)*TMath::Max(Double_t(fYaxis->GetLabelSize()), defaultLabelSize));
3287 if (doption.Contains("y+")) {
3288 xyaxis = puxmax + Int_t((puxmax-puxmin)*fYaxis->GetLabelOffset());
3289 if (px <= xyaxis+dyaxis && px >= xyaxis && py >puymax && py < puymin) {
3290 if (!dsame) {
3291 if (gPad->IsVertical()) gPad->SetSelected(fYaxis);
3292 else gPad->SetSelected(fXaxis);
3293 return 0;
3294 }
3295 }
3296 } else {
3297 xyaxis = puxmin - Int_t((puxmax-puxmin)*fYaxis->GetLabelOffset());
3298 if (px >= xyaxis-dyaxis && px <= xyaxis && py >puymax && py < puymin) {
3299 if (!dsame) {
3300 if (gPad->IsVertical()) gPad->SetSelected(fYaxis);
3301 else gPad->SetSelected(fXaxis);
3302 return 0;
3303 }
3304 }
3305 }
3306
3307 dxaxis = Int_t((puymin-puymax)*TMath::Max(Double_t(fXaxis->GetLabelSize()), defaultLabelSize));
3308 if (doption.Contains("x+")) {
3309 yxaxis = puymax - Int_t((puymin-puymax)*fXaxis->GetLabelOffset());
3310 if (py >= yxaxis-dxaxis && py <= yxaxis && px <puxmax && px > puxmin) {
3311 if (!dsame) {
3312 if (gPad->IsVertical()) gPad->SetSelected(fXaxis);
3313 else gPad->SetSelected(fYaxis);
3314 return 0;
3315 }
3316 }
3317 } else {
3318 yxaxis = puymin + Int_t((puymin-puymax)*fXaxis->GetLabelOffset());
3319 if (yxaxis < puymin) yxaxis = puymin;
3320 if (py <= yxaxis+dxaxis && py >= yxaxis && px <puxmax && px > puxmin) {
3321 if (!dsame) {
3322 if (gPad->IsVertical()) gPad->SetSelected(fXaxis);
3323 else gPad->SetSelected(fYaxis);
3324 return 0;
3325 }
3326 }
3327 }
3328
3329 if (fH->IsHighlight()) { // only if highlight is enable
3330 if ((px > puxmin) && (py < puymin) && (px < puxmax) && (py > puymax))
3331 HighlightBin(px, py);
3332 }
3333
3334 // if object is 2D or 3D return this object
3335 if (fH->GetDimension() == 2) {
3336 if (fH->InheritsFrom(TH2Poly::Class())) {
3337 TH2Poly *th2 = (TH2Poly*)fH;
3339 gPad->GetRangeAxis(xmin, ymin, xmax, ymax);
3340 Double_t pxu = gPad->AbsPixeltoX(px);
3341 Double_t pyu = gPad->AbsPixeltoY(py);
3342 if ((pxu>xmax) || (pxu < xmin) || (pyu>ymax) || (pyu < ymin)) {
3343 curdist = big;
3344 goto FUNCTIONS;
3345 } else {
3346 Int_t bin = th2->FindBin(pxu, pyu);
3347 if (bin>0) curdist = 1;
3348 else curdist = big;
3349 goto FUNCTIONS;
3350 }
3351 }
3352 Int_t delta2 = 5; //Give a margin of delta2 pixels to be in the 2-d area
3353 if ( px > puxmin + delta2
3354 && px < puxmax - delta2
3355 && py > puymax + delta2
3356 && py < puymin - delta2) {curdist =1; goto FUNCTIONS;}
3357 }
3358
3359 // point is inside histogram area. Find channel number
3360 if (gPad->IsVertical()) {
3361 Int_t bin = fXaxis->FindFixBin(gPad->PadtoX(x));
3362 Int_t binsup = fXaxis->FindFixBin(gPad->PadtoX(x1));
3363 Double_t binval = factor*fH->GetBinContent(bin);
3364 Int_t pybin = gPad->YtoAbsPixel(gPad->YtoPad(binval));
3365 if (binval == 0 && pybin < puymin) pybin = 10000;
3366 // special case if more than one bin for the pixel
3367 if (binsup-bin>1) {
3368 Double_t binvalmin, binvalmax;
3369 binvalmin=binval;
3370 binvalmax=binval;
3371 for (Int_t ibin=bin+1; ibin<binsup; ibin++) {
3372 Double_t binvaltmp = factor*fH->GetBinContent(ibin);
3373 if (binvalmin>binvaltmp) binvalmin=binvaltmp;
3374 if (binvalmax<binvaltmp) binvalmax=binvaltmp;
3375 }
3376 Int_t pybinmin = gPad->YtoAbsPixel(gPad->YtoPad(binvalmax));
3377 Int_t pybinmax = gPad->YtoAbsPixel(gPad->YtoPad(binvalmin));
3378 if (py<pybinmax+kMaxDiff/2 && py>pybinmin-kMaxDiff/2) pybin = py;
3379 }
3380 if (bin != binsup) { // Mouse on bin border
3381 Double_t binsupval = factor*fH->GetBinContent(binsup);
3382 Int_t pybinsub = gPad->YtoAbsPixel(gPad->YtoPad(binsupval));
3383 if (py <= TMath::Max(pybinsub,pybin) && py >= TMath::Min(pybinsub,pybin) && pybin != 10000) return 0;
3384 }
3385 if (TMath::Abs(py - pybin) <= kMaxDiff) return TMath::Abs(py - pybin);
3386 } else {
3387 Double_t y = gPad->AbsPixeltoY(py);
3388 Double_t y1 = gPad->AbsPixeltoY(py+1);
3389 Int_t bin = fXaxis->FindFixBin(gPad->PadtoY(y));
3390 Int_t binsup = fXaxis->FindFixBin(gPad->PadtoY(y1));
3391 Double_t binval = factor*fH->GetBinContent(bin);
3392 Int_t pxbin = gPad->XtoAbsPixel(gPad->XtoPad(binval));
3393 if (binval == 0 && pxbin > puxmin) pxbin = 10000;
3394 // special case if more than one bin for the pixel
3395 if (binsup-bin>1) {
3396 Double_t binvalmin, binvalmax;
3397 binvalmin=binval;
3398 binvalmax=binval;
3399 for (Int_t ibin=bin+1; ibin<binsup; ibin++) {
3400 Double_t binvaltmp = factor*fH->GetBinContent(ibin);
3401 if (binvalmin>binvaltmp) binvalmin=binvaltmp;
3402 if (binvalmax<binvaltmp) binvalmax=binvaltmp;
3403 }
3404 Int_t pxbinmin = gPad->XtoAbsPixel(gPad->XtoPad(binvalmax));
3405 Int_t pxbinmax = gPad->XtoAbsPixel(gPad->XtoPad(binvalmin));
3406 if (px<pxbinmax+kMaxDiff/2 && px>pxbinmin-kMaxDiff/2) pxbin = px;
3407 }
3408 if (TMath::Abs(px - pxbin) <= kMaxDiff) return TMath::Abs(px - pxbin);
3409 }
3410 // Loop on the list of associated functions and user objects
3411FUNCTIONS:
3412 TObject *f;
3413 TIter next(fFunctions);
3414 while ((f = (TObject*) next())) {
3415 Int_t dist;
3416 if (f->InheritsFrom(TF1::Class())) dist = f->DistancetoPrimitive(-px,py);
3417 else dist = f->DistancetoPrimitive(px,py);
3418 if (dist < kMaxDiff) {gPad->SetSelected(f); return dist;}
3419 }
3420 return curdist;
3421}
3422
3423////////////////////////////////////////////////////////////////////////////////
3424/// Display a panel with all histogram drawing options.
3425
3427{
3428
3429 gCurrentHist = fH;
3430 if (!gPad) {
3431 Error("DrawPanel", "need to draw histogram first");
3432 return;
3433 }
3435 editor->Show();
3436 gROOT->ProcessLine(TString::Format("((TCanvas*)0x%zx)->Selected((TVirtualPad*)0x%zx,(TObject*)0x%zx,1)",
3437 (size_t)gPad->GetCanvas(), (size_t)gPad, (size_t)fH).Data());
3438}
3439
3440////////////////////////////////////////////////////////////////////////////////
3441/// Execute the actions corresponding to `event`.
3442///
3443/// This function is called when a histogram is clicked with the locator at
3444/// the pixel position px,py.
3445
3447{
3448
3449 if (!gPad) return;
3450
3451 static Int_t bin, px1, py1, px2, py2, pyold;
3452 static std::unique_ptr<TBox> zoombox;
3453 Double_t zbx1,zbx2,zby1,zby2;
3454
3455 Int_t bin1, bin2;
3456 Double_t xlow, xup, ylow, binval, x, baroffset, barwidth, binwidth;
3457 Bool_t opaque = gPad->OpaqueMoving();
3458
3459 if (!gPad->IsEditable()) return;
3460
3461 if (fPie) {
3462 fPie->ExecuteEvent(event, px, py);
3463 return;
3464 }
3465 // come here if we have a lego/surface in the pad
3466 TView *view = gPad->GetView();
3467
3468 if (!fShowProjection && view && !view->TestBit(kCannotRotate)) {
3469 view->ExecuteRotateView(event, px, py);
3470 return;
3471 }
3472
3473 TAxis *xaxis = fH->GetXaxis();
3474 TAxis *yaxis = fH->GetYaxis();
3475 Int_t dimension = fH->GetDimension();
3476
3477 // In case of option SAME the axis must be the ones of the first drawn histogram
3478 TString IsSame = fH->GetDrawOption();
3479 IsSame.ToLower();
3480 if (IsSame.Index("same")>=0) {
3481 TH1 *h1;
3482 TIter next(gPad->GetListOfPrimitives());
3483 while ((h1 = (TH1 *)next())) {
3484 if (!h1->InheritsFrom(TH1::Class())) continue;
3485 xaxis = h1->GetXaxis();
3486 yaxis = h1->GetYaxis();
3487 break;
3488 }
3489 }
3490
3491 Double_t factor = 1;
3492 if (fH->GetNormFactor() != 0) {
3493 factor = fH->GetNormFactor()/fH->GetSumOfWeights();
3494 }
3495
3496 switch (event) {
3497
3498 case kButton1Down:
3499
3500 if (!opaque) gVirtualX->SetLineColor(-1);
3501 fH->TAttLine::Modify();
3502
3503 if (opaque && dimension ==2) {
3504 zbx1 = gPad->AbsPixeltoX(px);
3505 zbx2 = gPad->AbsPixeltoX(px);
3506 zby1 = gPad->AbsPixeltoY(py);
3507 zby2 = gPad->AbsPixeltoY(py);
3508 px1 = px;
3509 py1 = py;
3510 if (gPad->GetLogx()) {
3511 zbx1 = TMath::Power(10,zbx1);
3512 zbx2 = TMath::Power(10,zbx2);
3513 }
3514 if (gPad->GetLogy()) {
3515 zby1 = TMath::Power(10,zby1);
3516 zby2 = TMath::Power(10,zby2);
3517 }
3518 if (zoombox) Error("ExecuteEvent", "Last zoom box was not deleted");
3519 zoombox = std::make_unique<TBox>(zbx1, zby1, zbx2, zby2);
3520 Int_t ci = TColor::GetColor("#7d7dff");
3521 TColor *zoomcolor = gROOT->GetColor(ci);
3522 if (!TCanvas::SupportAlpha() || !zoomcolor) zoombox->SetFillStyle(3002);
3523 else zoomcolor->SetAlpha(0.5);
3524 zoombox->SetFillColor(ci);
3525 zoombox->Draw();
3526 gPad->Modified();
3527 gPad->Update();
3528 }
3529 // No break !!!
3530
3531 case kMouseMotion:
3532
3533 if (fShowProjection) {ShowProjection3(px,py); break;}
3534
3535 gPad->SetCursor(kPointer);
3536 if (dimension ==1) {
3537 if (Hoption.Bar) {
3538 baroffset = fH->GetBarOffset();
3539 barwidth = fH->GetBarWidth();
3540 } else {
3541 baroffset = 0;
3542 barwidth = 1;
3543 }
3544 x = gPad->AbsPixeltoX(px);
3545 bin = fXaxis->FindFixBin(gPad->PadtoX(x));
3546 binwidth = fXaxis->GetBinWidth(bin);
3547 xlow = gPad->XtoPad(fXaxis->GetBinLowEdge(bin) + baroffset*binwidth);
3548 xup = gPad->XtoPad(xlow + barwidth*binwidth);
3549 ylow = gPad->GetUymin();
3550 px1 = gPad->XtoAbsPixel(xlow);
3551 px2 = gPad->XtoAbsPixel(xup);
3552 py1 = gPad->YtoAbsPixel(ylow);
3553 py2 = py;
3554 pyold = py;
3555 if (gROOT->GetEditHistograms()) gPad->SetCursor(kArrowVer);
3556 }
3557
3558 break;
3559
3560 case kButton1Motion:
3561
3562 if (dimension ==1) {
3563 if (gROOT->GetEditHistograms()) {
3564 if (!opaque) {
3565 gVirtualX->DrawBox(px1, py1, px2, py2,TVirtualX::kHollow); // Draw the old box
3566 py2 += py - pyold;
3567 gVirtualX->DrawBox(px1, py1, px2, py2,TVirtualX::kHollow); // Draw the new box
3568 pyold = py;
3569 } else {
3570 py2 += py - pyold;
3571 pyold = py;
3572 binval = gPad->PadtoY(gPad->AbsPixeltoY(py2))/factor;
3573 fH->SetBinContent(bin,binval);
3574 gPad->Modified(kTRUE);
3575 }
3576 }
3577 }
3578
3579 if (opaque && dimension ==2) {
3580 if (TMath::Abs(px1-px)>5 && TMath::Abs(py1-py)>5) {
3581 zbx2 = gPad->AbsPixeltoX(px);
3582 zby2 = gPad->AbsPixeltoY(py);
3583 if (gPad->GetLogx()) zbx2 = TMath::Power(10,zbx2);
3584 if (gPad->GetLogy()) zby2 = TMath::Power(10,zby2);
3585 if (zoombox) {
3586 zoombox->SetX2(zbx2);
3587 zoombox->SetY2(zby2);
3588 }
3589 gPad->Modified();
3590 gPad->Update();
3591 }
3592 }
3593
3594 break;
3595
3596 case kWheelUp:
3597
3598 if (dimension ==2) {
3599 bin1 = xaxis->GetFirst()+1;
3600 bin2 = xaxis->GetLast()-1;
3601 bin1 = TMath::Max(bin1, 1);
3602 bin2 = TMath::Min(bin2, xaxis->GetNbins());
3603 if (bin2>bin1) xaxis->SetRange(bin1,bin2);
3604 bin1 = yaxis->GetFirst()+1;
3605 bin2 = yaxis->GetLast()-1;
3606 bin1 = TMath::Max(bin1, 1);
3607 bin2 = TMath::Min(bin2, yaxis->GetNbins());
3608 if (bin2>bin1) yaxis->SetRange(bin1,bin2);
3609 }
3610 gPad->Modified();
3611 gPad->Update();
3612
3613 break;
3614
3615 case kWheelDown:
3616
3617 if (dimension == 2) {
3618 bin1 = xaxis->GetFirst()-1;
3619 bin2 = xaxis->GetLast()+1;
3620 bin1 = TMath::Max(bin1, 1);
3621 bin2 = TMath::Min(bin2, xaxis->GetNbins());
3622 if (bin2>bin1) xaxis->SetRange(bin1,bin2);
3623 bin1 = yaxis->GetFirst()-1;
3624 bin2 = yaxis->GetLast()+1;
3625 bin1 = TMath::Max(bin1, 1);
3626 bin2 = TMath::Min(bin2, yaxis->GetNbins());
3627 if (bin2>bin1) yaxis->SetRange(bin1,bin2);
3628 }
3629 gPad->Modified();
3630 gPad->Update();
3631
3632 break;
3633
3634 case kButton1Up:
3635 if (dimension ==1) {
3636 if (gROOT->GetEditHistograms()) {
3637 binval = gPad->PadtoY(gPad->AbsPixeltoY(py2))/factor;
3638 fH->SetBinContent(bin,binval);
3639 PaintInit(); // recalculate Hparam structure and recalculate range
3640 }
3641
3642 // might resize pad pixmap so should be called before any paint routine
3644 }
3645 if (opaque && dimension ==2) {
3646 if (zoombox) {
3647 Double_t x1 = TMath::Min(zoombox->GetX1(), zoombox->GetX2());
3648 Double_t x2 = TMath::Max(zoombox->GetX1(), zoombox->GetX2());
3649 Double_t y1 = TMath::Min(zoombox->GetY1(), zoombox->GetY2());
3650 Double_t y2 = TMath::Max(zoombox->GetY1(), zoombox->GetY2());
3651 x1 = TMath::Max(x1,xaxis->GetXmin());
3652 x2 = TMath::Min(x2,xaxis->GetXmax());
3653 y1 = TMath::Max(y1,yaxis->GetXmin());
3654 y2 = TMath::Min(y2,yaxis->GetXmax());
3655 if (x1<x2 && y1<y2) {
3656 xaxis->SetRangeUser(x1, x2);
3657 yaxis->SetRangeUser(y1, y2);
3658 }
3659 zoombox.reset();
3660 }
3661 }
3662 gPad->Modified(kTRUE);
3663 if (opaque) gVirtualX->SetLineColor(-1);
3664
3665 break;
3666
3667 case kButton1Locate:
3668
3669 ExecuteEvent(kButton1Down, px, py);
3670
3671 while (true) {
3672 px = py = 0;
3673 event = gVirtualX->RequestLocator(1, 1, px, py);
3674
3676
3677 if (event != -1) { // button is released
3678 ExecuteEvent(kButton1Up, px, py);
3679 return;
3680 }
3681 }
3682 }
3683}
3684
3685////////////////////////////////////////////////////////////////////////////////
3686/// Get a contour (as a list of TGraphs) using the Delaunay triangulation.
3687
3689{
3690 // Check if fH contains a TGraphDelaunay2D
3691 TList *hl = fH->GetListOfFunctions();
3692 TGraphDelaunay2D *dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
3693 // try with the old painter
3694 TGraphDelaunay *dtOld = nullptr;
3695 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
3696
3697 if (!dt && !dtOld) return nullptr;
3698
3699 gCurrentHist = fH;
3700
3701 if (!fGraph2DPainter)
3702 ((THistPainter*)this)->fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
3703
3704 return fGraph2DPainter->GetContourList(contour);
3705}
3706
3707////////////////////////////////////////////////////////////////////////////////
3708/// Display the histogram info (bin number, contents, integral up to bin
3709/// corresponding to cursor position px,py.
3710
3712{
3713
3714 if (!gPad) return (char*)"";
3715
3716 Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
3717 Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
3718 Double_t x1 = gPad->PadtoX(gPad->AbsPixeltoX(px+1));
3719 TString drawOption = fH->GetDrawOption();
3720 drawOption.ToLower();
3721 Double_t xmin, xmax, uxmin,uxmax;
3722 Double_t ymin, ymax, uymin,uymax;
3723 if (fH->GetDimension() == 2) {
3724 if (gPad->GetView() || drawOption.Index("cont") >= 0) {
3725 uxmin=gPad->GetUxmin();
3726 uxmax=gPad->GetUxmax();
3729 x = xmin +(xmax-xmin)*(x-uxmin)/(uxmax-uxmin);
3730 uymin=gPad->GetUymin();
3731 uymax=gPad->GetUymax();
3734 y = ymin +(ymax-ymin)*(y-uymin)/(uymax-uymin);
3735 }
3736 }
3737 Int_t binx,biny,binmin=0,binx1;
3738 if (gPad->IsVertical()) {
3739 binx = fXaxis->FindFixBin(x);
3740 if (drawOption.Index("same") >= 0) {
3741 TH1 *h1;
3742 TIter next(gPad->GetListOfPrimitives());
3743 while ((h1 = (TH1 *)next())) {
3744 if (!h1->InheritsFrom(TH1::Class())) continue;
3745 binmin = h1->GetXaxis()->GetFirst();
3746 break;
3747 }
3748 } else {
3749 binmin = fXaxis->GetFirst();
3750 }
3751 binx1 = fXaxis->FindFixBin(x1);
3752 // special case if more than 1 bin in x per pixel
3753 if (binx1-binx>1 && fH->GetDimension() == 1) {
3754 Double_t binval=fH->GetBinContent(binx);
3755 Int_t binnear=binx;
3756 for (Int_t ibin=binx+1; ibin<binx1; ibin++) {
3757 Double_t binvaltmp = fH->GetBinContent(ibin);
3758 if (TMath::Abs(y-binvaltmp) < TMath::Abs(y-binval)) {
3759 binval=binvaltmp;
3760 binnear=ibin;
3761 }
3762 }
3763 binx = binnear;
3764 }
3765 } else {
3766 x1 = gPad->PadtoY(gPad->AbsPixeltoY(py+1));
3767 binx = fXaxis->FindFixBin(y);
3768 if (drawOption.Index("same") >= 0) {
3769 TH1 *h1;
3770 TIter next(gPad->GetListOfPrimitives());
3771 while ((h1 = (TH1 *)next())) {
3772 if (!h1->InheritsFrom(TH1::Class())) continue;
3773 binmin = h1->GetXaxis()->GetFirst();
3774 break;
3775 }
3776 } else {
3777 binmin = fXaxis->GetFirst();
3778 }
3779 binx1 = fXaxis->FindFixBin(x1);
3780 // special case if more than 1 bin in x per pixel
3781 if (binx1-binx>1 && fH->GetDimension() == 1) {
3782 Double_t binval=fH->GetBinContent(binx);
3783 Int_t binnear=binx;
3784 for (Int_t ibin=binx+1; ibin<binx1; ibin++) {
3785 Double_t binvaltmp = fH->GetBinContent(ibin);
3786 if (TMath::Abs(x-binvaltmp) < TMath::Abs(x-binval)) {
3787 binval=binvaltmp;
3788 binnear=ibin;
3789 }
3790 }
3791 binx = binnear;
3792 }
3793 }
3794 if (fH->GetDimension() == 1) {
3796 TProfile *tp = (TProfile*)fH;
3797 fObjectInfo.Form("(x=%g, y=%g, binx=%d, binc=%g, bine=%g, binn=%d)",
3798 x, y, binx, fH->GetBinContent(binx), fH->GetBinError(binx),
3799 (Int_t) tp->GetBinEntries(binx));
3800 }
3801 else {
3802 Double_t integ = 0;
3803 for (Int_t bin=binmin;bin<=binx;bin++) {integ += fH->GetBinContent(bin);}
3804 fObjectInfo.Form("(x=%g, y=%g, binx=%d, binc=%g, Sum=%g)",
3805 x,y,binx,fH->GetBinContent(binx),integ);
3806 }
3807 } else if (fH->GetDimension() == 2) {
3808 if (fH->InheritsFrom(TH2Poly::Class())) {
3809 TH2Poly *th2 = (TH2Poly*)fH;
3810 biny = th2->FindBin(x,y);
3811 fObjectInfo.Form("%s (x=%g, y=%g, bin=%d, binc=%g)",
3812 th2->GetBinTitle(biny),x,y,biny,th2->GetBinContent(biny));
3813 }
3814 else if (fH->InheritsFrom(TProfile2D::Class())) {
3815 TProfile2D *tp = (TProfile2D*)fH;
3816 biny = fYaxis->FindFixBin(y);
3817 Int_t bin = fH->GetBin(binx,biny);
3818 fObjectInfo.Form("(x=%g, y=%g, binx=%d, biny=%d, binc=%g, bine=%g, binn=%d)",
3819 x, y, binx, biny, fH->GetBinContent(bin),
3820 fH->GetBinError(bin), (Int_t) tp->GetBinEntries(bin));
3821 } else {
3822 biny = fYaxis->FindFixBin(y);
3823 fObjectInfo.Form("(x=%g, y=%g, binx=%d, biny=%d, binc=%g bine=%g)",
3824 x,y,binx,biny,fH->GetBinContent(binx,biny),
3825 fH->GetBinError(binx,biny));
3826 }
3827 } else {
3828 // 3d case: retrieving the x,y,z bin is not yet implemented
3829 // print just the x,y info
3830 fObjectInfo.Form("(x=%g, y=%g)",x,y);
3831 }
3832
3833 return (char *)fObjectInfo.Data();
3834}
3835
3836////////////////////////////////////////////////////////////////////////////////
3837/// Set highlight (enable/disable) mode for fH
3838
3840{
3841 if (fH->IsHighlight()) return;
3842
3843 fXHighlightBin = -1;
3844 fYHighlightBin = -1;
3845 // delete previous highlight box
3846 if (gXHighlightBox) gXHighlightBox.reset();
3847 if (gYHighlightBox) gYHighlightBox.reset();
3848 // emit Highlighted() signal (user can check on disabled)
3849 if (gPad->GetCanvas()) gPad->GetCanvas()->Highlighted(gPad, fH, fXHighlightBin, fYHighlightBin);
3850}
3851
3852////////////////////////////////////////////////////////////////////////////////
3853/// Check on highlight bin
3854
3856{
3857 // call from DistancetoPrimitive (only if highlight is enable)
3858
3859 Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
3860 Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
3861 Int_t binx = fXaxis->FindFixBin(x);
3862 Int_t biny = fYaxis->FindFixBin(y);
3863 if (!gPad->IsVertical()) binx = fXaxis->FindFixBin(y);
3864
3865 Bool_t changedBin = kFALSE;
3866 if (binx != fXHighlightBin) {
3867 fXHighlightBin = binx;
3868 changedBin = kTRUE;
3869 } else if (fH->GetDimension() == 1) return;
3870 if (biny != fYHighlightBin) {
3871 fYHighlightBin = biny;
3872 changedBin = kTRUE;
3873 }
3874 if (!changedBin) return;
3875
3876 // Info("HighlightBin", "histo: %p '%s'\txbin: %d, ybin: %d",
3877 // (void *)fH, fH->GetName(), fXHighlightBin, fYHighlightBin);
3878
3879 // paint highlight bin as box (recursive calls PaintHighlightBin)
3880 gPad->Modified(kTRUE);
3881 gPad->Update();
3882
3883 // emit Highlighted() signal
3884 if (gPad->GetCanvas()) gPad->GetCanvas()->Highlighted(gPad, fH, fXHighlightBin, fYHighlightBin);
3885}
3886
3887////////////////////////////////////////////////////////////////////////////////
3888/// Paint highlight bin as TBox object
3889
3891{
3892 // call from PaintTitle
3893
3894 if (!fH->IsHighlight()) return;
3895
3896 Double_t uxmin = gPad->GetUxmin();
3897 Double_t uxmax = gPad->GetUxmax();
3898 Double_t uymin = gPad->GetUymin();
3899 Double_t uymax = gPad->GetUymax();
3900 if (gPad->GetLogx()) {
3901 uxmin = TMath::Power(10.0, uxmin);
3902 uxmax = TMath::Power(10.0, uxmax);
3903 }
3904 if (gPad->GetLogy()) {
3905 uymin = TMath::Power(10.0, uymin);
3906 uymax = TMath::Power(10.0, uymax);
3907 }
3908
3909 // testing specific possibility (after zoom, draw with "same", log, etc.)
3910 Double_t hcenter;
3911 if (gPad->IsVertical()) {
3913 if ((hcenter < uxmin) || (hcenter > uxmax)) return;
3914 } else {
3916 if ((hcenter < uymin) || (hcenter > uymax)) return;
3917 }
3918 if (fH->GetDimension() == 2) {
3920 if ((hcenter < uymin) || (hcenter > uymax)) return;
3921 }
3922
3923 // paint X highlight bin (for 1D or 2D)
3924 Double_t hbx1, hbx2, hby1, hby2;
3925 if (gPad->IsVertical()) {
3928 hby1 = uymin;
3929 hby2 = uymax;
3930 } else {
3931 hbx1 = uxmin;
3932 hbx2 = uxmax;
3935 }
3936
3937 if (!gXHighlightBox) {
3938 gXHighlightBox = std::make_unique<TBox>(hbx1, hby1, hbx2, hby2);
3939 gXHighlightBox->SetBit(kCannotPick);
3940 gXHighlightBox->SetFillColor(TColor::GetColor("#9797ff"));
3941 if (!TCanvas::SupportAlpha()) gXHighlightBox->SetFillStyle(3001);
3942 else gROOT->GetColor(gXHighlightBox->GetFillColor())->SetAlpha(0.5);
3943 }
3944 gXHighlightBox->SetX1(hbx1);
3945 gXHighlightBox->SetX2(hbx2);
3946 gXHighlightBox->SetY1(hby1);
3947 gXHighlightBox->SetY2(hby2);
3948 gXHighlightBox->Paint();
3949
3950 // Info("PaintHighlightBin", "histo: %p '%s'\txbin: %d, ybin: %d",
3951 // (void *)fH, fH->GetName(), fXHighlightBin, fYHighlightBin);
3952
3953 // paint Y highlight bin (only for 2D)
3954 if (fH->GetDimension() != 2) return;
3955 hbx1 = uxmin;
3956 hbx2 = uxmax;
3959
3960 if (!gYHighlightBox) {
3961 gYHighlightBox = std::make_unique<TBox>(hbx1, hby1, hbx2, hby2);
3962 gYHighlightBox->SetBit(kCannotPick);
3963 gYHighlightBox->SetFillColor(gXHighlightBox->GetFillColor());
3964 gYHighlightBox->SetFillStyle(gXHighlightBox->GetFillStyle());
3965 }
3966 gYHighlightBox->SetX1(hbx1);
3967 gYHighlightBox->SetX2(hbx2);
3968 gYHighlightBox->SetY1(hby1);
3969 gYHighlightBox->SetY2(hby2);
3970 gYHighlightBox->Paint();
3971}
3972
3973////////////////////////////////////////////////////////////////////////////////
3974/// Return `kTRUE` if the cell `ix`, `iy` is inside one of the graphical cuts.
3975
3977{
3978
3979 for (Int_t i=0;i<fNcuts;i++) {
3982 if (fCutsOpt[i] > 0) {
3983 if (!fCuts[i]->IsInside(x,y)) return kFALSE;
3984 } else {
3985 if (fCuts[i]->IsInside(x,y)) return kFALSE;
3986 }
3987 }
3988 return kTRUE;
3989}
3990
3991////////////////////////////////////////////////////////////////////////////////
3992/// Return `kTRUE` if the point `x`, `y` is inside one of the graphical cuts.
3993
3995{
3996
3997 for (Int_t i=0;i<fNcuts;i++) {
3998 if (fCutsOpt[i] > 0) {
3999 if (!fCuts[i]->IsInside(x,y)) return kFALSE;
4000 } else {
4001 if (fCuts[i]->IsInside(x,y)) return kFALSE;
4002 }
4003 }
4004 return kTRUE;
4005}
4006
4007////////////////////////////////////////////////////////////////////////////////
4008/// Decode string `choptin` and fill Hoption structure.
4009
4011{
4012
4013 char *l;
4014 char chopt[128];
4015 Int_t nch = strlen(choptin);
4016 strlcpy(chopt,choptin,128);
4017 Int_t hdim = fH->GetDimension();
4018 Bool_t explicitColor = kFALSE;
4019
4027 Hoption.Candle = 0;
4028
4029 // special 2D options
4030 Hoption.List = 0;
4031 Hoption.Zscale = 0;
4032 Hoption.FrontBox = 1;
4033 Hoption.BackBox = 1;
4035
4036 Hoption.Zero = 0;
4037
4039
4040 //check for graphical cuts
4041 MakeCuts(chopt);
4042
4043 for (Int_t i=0;i<nch;i++) chopt[i] = toupper(chopt[i]);
4044 if (hdim > 1) Hoption.Color = 1; // Default drawing option for 2D and 3D histograms
4045 if (!nch) Hoption.Hist = 1;
4046 if (fFunctions->First()) Hoption.Func = 1;
4047 if (fH->GetSumw2N() && hdim == 1) Hoption.Error = 2;
4048
4049 char *l1 = strstr(chopt,"PFC"); // Automatic Fill Color
4050 char *l2 = strstr(chopt,"PLC"); // Automatic Line Color
4051 char *l3 = strstr(chopt,"PMC"); // Automatic Marker Color
4052 if (l1 || l2 || l3) {
4053 Int_t i = gPad->NextPaletteColor();
4054 if (l1) {memcpy(l1," ",3); fH->SetFillColor(i);}
4055 if (l2) {memcpy(l2," ",3); fH->SetLineColor(i);}
4056 if (l3) {memcpy(l3," ",3); fH->SetMarkerColor(i);}
4057 Hoption.Hist = 1; // Make sure something is drawn in case there is no drawing option specified.
4058 }
4059
4060 l = strstr(chopt,"MIN0");
4061 if (l) {
4062 Hoption.MinimumZero = 1;
4063 memcpy(l," ",4);
4064 }
4065
4066 l = strstr(chopt,"SPEC");
4067 if (l) {
4068 Hoption.Color = 0;
4069 memcpy(l," ",4);
4070 Int_t bs=0;
4071 l = strstr(chopt,"BF(");
4072 if (l) {
4073 if (sscanf(&l[3],"%d",&bs) > 0) {
4074 Int_t i=0;
4075 while (l[i]!=')') {
4076 l[i] = ' ';
4077 i++;
4078 }
4079 l[i] = ' ';
4080 }
4081 }
4082 Hoption.Spec = TMath::Max(1600,bs);
4083 return 1;
4084 }
4085
4086 l = strstr(chopt,"GL");
4087 if (l) {
4088 memcpy(l," ",2);
4089 }
4090 l = strstr(chopt,"X+");
4091 if (l) {
4092 Hoption.AxisPos = 10;
4093 memcpy(l," ",2);
4094 }
4095 l = strstr(chopt,"Y+");
4096 if (l) {
4097 Hoption.AxisPos += 1;
4098 memcpy(l," ",2);
4099 }
4100 if ((Hoption.AxisPos == 10 || Hoption.AxisPos == 1) && (nch == 2)) Hoption.Hist = 1;
4101 if (Hoption.AxisPos == 11 && nch == 4) Hoption.Hist = 1;
4102
4103 l = strstr(chopt,"SAMES");
4104 if (l) {
4105 if (nch == 5) Hoption.Hist = 1;
4106 Hoption.Same = 2;
4107 memcpy(l," ",5);
4108 if (l[5] == '0') { Hoption.Same += 10; l[5] = ' '; }
4109 }
4110 l = strstr(chopt,"SAME");
4111 if (l) {
4112 if (nch == 4) Hoption.Hist = 1;
4113 Hoption.Same = 1;
4114 memcpy(l," ",4);
4115 if (l[4] == '0') { Hoption.Same += 10; l[4] = ' '; }
4116 }
4117
4118 l = strstr(chopt,"SCAT");
4119 if (l) {
4120 Warning("MakeChopt","option SCAT is deprecated.");
4121 Hoption.Scat = 1;
4122 memcpy(l," ",4);
4123 Hoption.Color = 0;
4124 }
4125
4126 l = strstr(chopt,"PIE");
4127 if (l) {
4128 Hoption.Pie = 1;
4129 memcpy(l," ",3);
4130 }
4131
4132
4133 l = strstr(chopt,"CANDLE");
4134 if (l) {
4135 TCandle candle;
4136 Hoption.Candle = candle.ParseOption(l);
4137 Hoption.Color = 0;
4138 }
4139
4140 l = strstr(chopt,"VIOLIN");
4141 if (l) {
4142 TCandle candle;
4143 Hoption.Candle = candle.ParseOption(l);
4144 Hoption.Color = 0;
4145 }
4146
4147 l = strstr(chopt,"LEGO");
4148 if (l) {
4149 Hoption.Color = 0;
4150 Hoption.Lego = 1; memcpy(l," ",4);
4151 if (l[4] == '1') { Hoption.Lego = 11; l[4] = ' '; }
4152 if (l[4] == '2') { Hoption.Lego = 12; l[4] = ' '; }
4153 if (l[4] == '3') { Hoption.Lego = 13; l[4] = ' '; }
4154 if (l[4] == '4') { Hoption.Lego = 14; l[4] = ' '; }
4155 if (l[4] == '9') { Hoption.Lego = 19; l[4] = ' '; }
4156 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4157 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4158 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4159 }
4160
4161 l = strstr(chopt,"SURF");
4162 if (l) {
4163 Hoption.Color = 0;
4164 Hoption.Surf = 1; memcpy(l," ",4);
4165 if (l[4] == '1') { Hoption.Surf = 11; l[4] = ' '; }
4166 if (l[4] == '2') { Hoption.Surf = 12; l[4] = ' '; }
4167 if (l[4] == '3') { Hoption.Surf = 13; l[4] = ' '; }
4168 if (l[4] == '4') { Hoption.Surf = 14; l[4] = ' '; }
4169 if (l[4] == '5') { Hoption.Surf = 15; l[4] = ' '; }
4170 if (l[4] == '6') { Hoption.Surf = 16; l[4] = ' '; }
4171 if (l[4] == '7') { Hoption.Surf = 17; l[4] = ' '; }
4172 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4173 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4174 }
4175
4176 l = strstr(chopt,"TF3");
4177 if (l) {
4178 memcpy(l," ",3);
4179 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4180 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4181 }
4182
4183 l = strstr(chopt,"ISO");
4184 if (l) {
4185 memcpy(l," ",3);
4186 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4187 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4188 Hoption.Color = 0;
4189 }
4190
4191 l = strstr(chopt,"LIST"); if (l) { Hoption.List = 1; memcpy(l," ",4);}
4192
4193 l = strstr(chopt,"CONT");
4194 if (l) {
4195 memcpy(l," ",4);
4196 if (hdim>1) {
4197 Hoption.Color = 0;
4198 Hoption.Contour = 1;
4199 if (l[4] == '1') { Hoption.Contour = 11; l[4] = ' '; }
4200 if (l[4] == '2') { Hoption.Contour = 12; l[4] = ' '; }
4201 if (l[4] == '3') { Hoption.Contour = 13; l[4] = ' '; }
4202 if (l[4] == '4') { Hoption.Contour = 14; l[4] = ' '; }
4203 if (l[4] == '5') { Hoption.Contour = 15; l[4] = ' '; }
4204 } else {
4205 Hoption.Hist = 1;
4206 }
4207 }
4208 l = strstr(chopt,"HBAR");
4209 if (l) {
4210 Hoption.Hist = 0;
4211 Hoption.Bar = 20; memcpy(l," ",4);
4212 if (l[4] == '1') { Hoption.Bar = 21; l[4] = ' '; }
4213 if (l[4] == '2') { Hoption.Bar = 22; l[4] = ' '; }
4214 if (l[4] == '3') { Hoption.Bar = 23; l[4] = ' '; }
4215 if (l[4] == '4') { Hoption.Bar = 24; l[4] = ' '; }
4216 }
4217 l = strstr(chopt,"BAR");
4218 if (l) {
4219 Hoption.Hist = 0;
4220 Hoption.Bar = 10; memcpy(l," ",3);
4221 if (l[3] == '1') { Hoption.Bar = 11; l[3] = ' '; }
4222 if (l[3] == '2') { Hoption.Bar = 12; l[3] = ' '; }
4223 if (l[3] == '3') { Hoption.Bar = 13; l[3] = ' '; }
4224 if (l[3] == '4') { Hoption.Bar = 14; l[3] = ' '; }
4225 }
4226
4227 l = strstr(chopt,"ARR" );
4228 if (l) {
4229 memcpy(l," ", 3);
4230 if (hdim>1) {
4231 Hoption.Arrow = 1;
4232 Hoption.Color = 0;
4233 l = strstr(chopt,"COL"); if (l) { Hoption.Arrow = 2; memcpy(l," ",3); }
4234 l = strstr(chopt,"Z"); if (l) { Hoption.Zscale = 1; memcpy(l," ",1); }
4235 } else {
4236 Hoption.Hist = 1;
4237 }
4238 }
4239 l = strstr(chopt,"BOX" );
4240 if (l) {
4241 memcpy(l," ", 3);
4242 if (hdim>1) {
4243 Hoption.Color = 0;
4244 Hoption.Box = 1;
4245 if (l[3] == '1') { Hoption.Box = 11; l[3] = ' '; }
4246 if (l[3] == '2') { Hoption.Box = 12; l[3] = ' '; }
4247 if (l[3] == '3') { Hoption.Box = 13; l[3] = ' '; }
4248 } else {
4249 Hoption.Hist = 1;
4250 }
4251 }
4252 l = strstr(chopt,"TEXT");
4253 if (l) {
4254 Int_t angle;
4255 if (sscanf(&l[4],"%d",&angle) > 0) {
4256 if (angle < 0) angle=0;
4257 if (angle > 90) angle=90;
4258 Hoption.Text = 1000+angle;
4259 } else {
4260 Hoption.Text = 1;
4261 }
4262 memcpy(l," ", 4);
4263 l = strstr(chopt,"N");
4264 if (l && fH->InheritsFrom(TH2Poly::Class())) Hoption.Text += 3000;
4265 Hoption.Color = 0;
4266 }
4267 l = strstr(chopt,"COLZ");
4268 if (l) {
4269 memcpy(l," ",4);
4270 if (hdim > 1) {
4271 explicitColor = kTRUE;
4272 Hoption.Color = 1;
4273 Hoption.Zscale = 1;
4274 if (l[4] == '2') { Hoption.Color = 3; l[4] = ' '; }
4275 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4276 l = strstr(chopt,"1"); if (l) { Hoption.Color = 2; memcpy(l," ",1); }
4277 } else {
4278 Hoption.Hist = 1;
4279 }
4280 }
4281 l = strstr(chopt,"COL" );
4282 if (l) {
4283 memcpy(l," ", 3);
4284 if (hdim > 1) {
4285 explicitColor = kTRUE;
4286 Hoption.Color = 1;
4287 if (l[3] == '2') { Hoption.Color = 3; l[3] = ' '; }
4288 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4289 l = strstr(chopt,"1"); if (l) { Hoption.Color = 2; memcpy(l," ",1); }
4290 } else {
4291 Hoption.Hist = 1;
4292 }
4293 }
4294 l = strstr(chopt,"FUNC"); if (l) { Hoption.Func = 2; memcpy(l," ",4); Hoption.Hist = 0; }
4295 l = strstr(chopt,"HIST"); if (l) { Hoption.Hist = 2; memcpy(l," ",4); Hoption.Func = 0; Hoption.Error = 0;}
4296 l = strstr(chopt,"AXIS"); if (l) { Hoption.Axis = 1; memcpy(l," ",4); }
4297 l = strstr(chopt,"AXIG"); if (l) { Hoption.Axis = 2; memcpy(l," ",4); }
4298 l = strstr(chopt,"SCAT"); if (l) { Hoption.Scat = 1; memcpy(l," ",4); }
4299 l = strstr(chopt,"POL"); if (l) { Hoption.System = kPOLAR; memcpy(l," ",3); }
4300 l = strstr(chopt,"CYL"); if (l) { Hoption.System = kCYLINDRICAL; memcpy(l," ",3); }
4301 l = strstr(chopt,"SPH"); if (l) { Hoption.System = kSPHERICAL; memcpy(l," ",3); }
4302 l = strstr(chopt,"PSR"); if (l) { Hoption.System = kRAPIDITY; memcpy(l," ",3); }
4303
4304 l = strstr(chopt,"TRI");
4305 if (l) {
4306 if (!explicitColor) Hoption.Color = 0;
4307 Hoption.Tri = 1; memcpy(l," ",3);
4308 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4309 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4310 l = strstr(chopt,"ERR"); if (l) memcpy(l," ",3);
4311 }
4312
4313 l = strstr(chopt,"AITOFF");
4314 if (l) {
4315 Hoption.Proj = 1; memcpy(l," ",6); //Aitoff projection
4316 }
4317 l = strstr(chopt,"MERCATOR");
4318 if (l) {
4319 Hoption.Proj = 2; memcpy(l," ",8); //Mercator projection
4320 }
4321 l = strstr(chopt,"SINUSOIDAL");
4322 if (l) {
4323 Hoption.Proj = 3; memcpy(l," ",10); //Sinusoidal projection
4324 }
4325 l = strstr(chopt,"PARABOLIC");
4326 if (l) {
4327 Hoption.Proj = 4; memcpy(l," ",9); //Parabolic projection
4328 }
4329 l = strstr(chopt,"MOLLWEIDE");
4330 if (l) {
4331 Hoption.Proj = 5; memcpy(l," ",9); //Mollweide projection
4332 }
4333 if (Hoption.Proj > 0) {
4334 if (!explicitColor) Hoption.Color = 0;
4335 Hoption.Contour = 14;
4336 }
4337
4338 if (strstr(chopt,"A")) Hoption.Axis = -1;
4339 if (strstr(chopt,"B")) Hoption.Bar = 1;
4340 if (strstr(chopt,"C") && !strstr(chopt,"CJUST")) { Hoption.Curve =1; Hoption.Hist = -1;}
4341 if (strstr(chopt,"F")) Hoption.Fill =1;
4342 if (strstr(chopt,"][")) {Hoption.Off =1; Hoption.Hist =1;}
4343 if (strstr(chopt,"F2")) Hoption.Fill =2;
4344 if (strstr(chopt,"L")) { Hoption.Line =1; Hoption.Hist = -1;}
4345 if (strstr(chopt,"P")) { Hoption.Mark =1; Hoption.Hist = -1;}
4346 if (strstr(chopt,"Z")) Hoption.Zscale =1;
4347 if (strstr(chopt,"*")) Hoption.Star =1;
4348 if (strstr(chopt,"H")) Hoption.Hist =2;
4349 if (strstr(chopt,"P0")) Hoption.Mark =10;
4350
4351 if (fH->InheritsFrom(TH2Poly::Class())) {
4352 if ((Hoption.Fill+Hoption.Line+Hoption.Mark != 0) && !explicitColor) Hoption.Color = 0;
4353 }
4354
4355 if (strstr(chopt,"E")) {
4356 if (hdim == 1) {
4357 Hoption.Error = 1;
4358 if (strstr(chopt,"E1")) Hoption.Error = 11;
4359 if (strstr(chopt,"E2")) Hoption.Error = 12;
4360 if (strstr(chopt,"E3")) Hoption.Error = 13;
4361 if (strstr(chopt,"E4")) Hoption.Error = 14;
4362 if (strstr(chopt,"E5")) Hoption.Error = 15;
4363 if (strstr(chopt,"E6")) Hoption.Error = 16;
4364 if (strstr(chopt,"E0")) Hoption.Error += 40;
4365 if (strstr(chopt,"X0")) {
4366 if (Hoption.Error == 1) Hoption.Error += 20;
4367 Hoption.Error += 10;
4368 }
4370 Hoption.Text += 2000;
4371 Hoption.Error = 0;
4372 }
4373 } else {
4374 if (Hoption.Error == 0) {
4375 Hoption.Error = 100;
4376 if (!explicitColor) Hoption.Color = 0;
4377 }
4378 if (Hoption.Text) {
4379 Hoption.Text += 2000;
4380 Hoption.Error = 0;
4381 }
4382 }
4383 }
4384
4385 if (Hoption.Surf == 15) {
4387 Hoption.Surf = 13;
4388 Warning("MakeChopt","option SURF5 is not supported in Cartesian and Polar modes");
4389 }
4390 }
4391
4392 // Copy options from current style
4393 Hoption.Logx = gPad->GetLogx();
4394 Hoption.Logy = gPad->GetLogy();
4395 Hoption.Logz = gPad->GetLogz();
4396
4397 // Check options incompatibilities
4398 if (Hoption.Bar == 1) Hoption.Hist = -1;
4399 return 1;
4400}
4401
4402////////////////////////////////////////////////////////////////////////////////
4403/// Decode string `choptin` and fill Graphical cuts structure.
4404
4406{
4407
4408 fNcuts = 0;
4409 char *left = (char*)strchr(choptin,'[');
4410 if (!left) return 0;
4411 char *right = (char*)strchr(choptin,']');
4412 if (!right) return 0;
4413 Int_t nch = right-left;
4414 if (nch < 2) return 0;
4415 char *cuts = left+1;
4416 *right = 0;
4417 char *comma, *minus;
4418 Int_t i;
4419 while (true) {
4420 comma = strchr(cuts,',');
4421 if (comma) *comma = 0;
4422 minus = strchr(cuts,'-');
4423 if (minus) cuts = minus+1;
4424 while (*cuts == ' ') cuts++;
4425 Int_t nc = strlen(cuts);
4426 while (cuts[nc-1] == ' ') {cuts[nc-1] = 0; nc--;}
4427 TIter next(gROOT->GetListOfSpecials());
4428 TCutG *cut=nullptr;
4429 TObject *obj;
4430 while ((obj = next())) {
4431 if (!obj->InheritsFrom(TCutG::Class())) continue;
4432 if (strcmp(obj->GetName(),cuts)) continue;
4433 cut = (TCutG*)obj;
4434 break;
4435 }
4436 if (cut) {
4437 fCuts[fNcuts] = cut;
4438 fCutsOpt[fNcuts] = 1;
4439 if (minus) fCutsOpt[fNcuts] = -1;
4440 fNcuts++;
4441 }
4442 if (!comma) break;
4443 cuts = comma+1;
4444 }
4445 for (i=0;i<=nch;i++) left[i] = ' ';
4446 return fNcuts;
4447}
4448
4449////////////////////////////////////////////////////////////////////////////////
4450/// [Control routine to paint any kind of histograms](\ref HP00)
4451
4453{
4454
4455 if (fH->GetBuffer()) fH->BufferEmpty(-1);
4456
4457 //For iOS: put the histogram on the top of stack of pickable objects.
4458 const TPickerStackGuard topPush(fH);
4459
4460 gPad->SetVertical(kTRUE);
4461
4462 TH1 *oldhist = gCurrentHist;
4463 gCurrentHist = fH;
4464 TH1 *hsave = fH;
4465 Double_t minsav = fH->GetMinimumStored();
4466
4467 if (!MakeChopt(option)) return; //check options and fill Hoption structure
4468
4469 // Paint using TSpectrum2Painter
4470 if (Hoption.Spec) {
4471 if (!TableInit()) return;
4472 if (!TClass::GetClass("TSpectrum2Painter")) gSystem->Load("libSpectrumPainter");
4473 gROOT->ProcessLineFast(TString::Format("TSpectrum2Painter::PaintSpectrum((TH2F*)0x%zx,\"%s\",%d)",
4474 (size_t)fH, option, Hoption.Spec).Data());
4475 return;
4476 }
4477
4478 // Deflate the labels in case of alphanumeric labels
4482
4483 if (Hoption.Pie) {
4484 if (fH->GetDimension() == 1) {
4485 if (!fPie)
4486 fPie = std::make_unique<TPie>(fH);
4487 fPie->Paint(option);
4488 } else {
4489 Error("Paint", "Option PIE is for 1D histograms only");
4490 }
4491 return;
4492 } else {
4493 fPie.reset();
4494 }
4495
4496 fXbuf.resize(kNMAX);
4497 fYbuf.resize(kNMAX);
4498 if (fH->GetDimension() > 2) {
4499 PaintH3(option);
4500 fH->SetMinimum(minsav);
4501 if (Hoption.Func) {
4502 Hoption_t hoptsave = Hoption;
4503 Hparam_t hparsave = Hparam;
4505 SetHistogram(hsave);
4506 Hoption = hoptsave;
4507 Hparam = hparsave;
4508 }
4509 gCurrentHist = oldhist;
4510 fXbuf.clear();
4511 fYbuf.clear();
4512 return;
4513 }
4514 TView *view = gPad->GetView();
4515 if (view) {
4516 if (!Hoption.Lego && !Hoption.Surf && !Hoption.Tri) {
4517 delete view;
4518 gPad->SetView(nullptr);
4519 }
4520 }
4521 if (fH->GetDimension() > 1 || Hoption.Lego || Hoption.Surf) {
4522 // In case of 1D histogram, Z axis becomes Y axis.
4523 Int_t logysav=0, logzsav=0;
4524 if (fH->GetDimension() == 1) {
4525 logysav = Hoption.Logy;
4526 logzsav = Hoption.Logz;
4527 Hoption.Logz = 0;
4528 if (Hoption.Logy) {
4529 Hoption.Logz = 1;
4530 Hoption.Logy = 0;
4531 }
4532 }
4534 if (Hoption.Func) {
4535 Hoption_t hoptsave = Hoption;
4536 Hparam_t hparsave = Hparam;
4538 SetHistogram(hsave);
4539 Hoption = hoptsave;
4540 Hparam = hparsave;
4541 }
4542 fH->SetMinimum(minsav);
4543 gCurrentHist = oldhist;
4544 fXbuf.clear();
4545 fYbuf.clear();
4546 if (fH->GetDimension() == 1) {
4547 Hoption.Logy = logysav;
4548 Hoption.Logz = logzsav;
4549 }
4550 return;
4551 }
4552
4553 if (Hoption.Bar >= 20) {
4555 fXbuf.clear();
4556 fYbuf.clear();
4557 return;
4558 }
4559
4560 gPad->RangeAxisChanged(); //emit RangeAxisChanged() signal to sync axes
4561 // fill Hparam structure with histo parameters
4562 if (!PaintInit()) {
4563 fXbuf.clear();
4564 fYbuf.clear();
4565 return;
4566 }
4567
4568 // Picture surround (if new page) and page number (if requested).
4569 // Histogram surround (if not option "Same").
4570 PaintFrame();
4571
4572 // Paint histogram axis only
4573 Bool_t gridx = gPad->GetGridx();
4574 Bool_t gridy = gPad->GetGridy();
4575 if (Hoption.Axis > 0) {
4576 if (Hoption.Axis > 1) PaintAxis(kTRUE); //axis with grid
4577 else {
4578 if (gridx) gPad->SetGridx(0);
4579 if (gridy) gPad->SetGridy(0);
4581 if (gridx) gPad->SetGridx(1);
4582 if (gridy) gPad->SetGridy(1);
4583 }
4584 if ((Hoption.Same%10) ==1) Hoption.Same += 1;
4585 goto paintstat;
4586 }
4587 if (gridx || gridy) PaintAxis(kTRUE); // Draw the grid only
4588
4589 // test for options BAR or HBAR
4590 if (Hoption.Bar >= 10) {
4592 }
4593
4594 // do not draw histogram if error bars required
4595 if (!Hoption.Error) {
4596 if (Hoption.Hist && Hoption.Bar<10) PaintHist(option);
4597 }
4598
4599 // test for error bars or option E
4600 if (Hoption.Error) {
4602 if (Hoption.Hist == 2) PaintHist(option);
4603 }
4604
4606
4607 // test for associated function
4608 if (Hoption.Func) {
4609 Hoption_t hoptsave = Hoption;
4610 Hparam_t hparsave = Hparam;
4612 SetHistogram(hsave);
4613 Hoption = hoptsave;
4614 Hparam = hparsave;
4615 }
4616
4617 if (gridx) gPad->SetGridx(0);
4618 if (gridy) gPad->SetGridy(0);
4620 if (gridx) gPad->SetGridx(1);
4621 if (gridy) gPad->SetGridy(1);
4622
4623 PaintTitle(); // Draw histogram title
4624
4625 // Draw box with histogram statistics and/or fit parameters
4626paintstat:
4627 if ((Hoption.Same%10) != 1 && !fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
4628 TIter next(fFunctions);
4629 TObject *obj = nullptr;
4630 while ((obj = next())) {
4631 if (obj->InheritsFrom(TF1::Class())) break;
4632 obj = nullptr;
4633 }
4634
4635 //Stat is painted twice (first, it will be in canvas' list of primitives),
4636 //second, it will be here, this is not required on iOS.
4637 //Condition is ALWAYS true on a platform different from iOS.
4638 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode())
4639 PaintStat(gStyle->GetOptStat(),(TF1*)obj);
4640 }
4641 fH->SetMinimum(minsav);
4642 gCurrentHist = oldhist;
4643 fXbuf.clear();
4644 fYbuf.clear();
4645}
4646
4647////////////////////////////////////////////////////////////////////////////////
4648/// [Control function to draw a table as an arrow plot](\ref HP12)
4649
4651{
4652 Double_t xk, xstep, yk, ystep;
4653 Double_t dx, dy, x1, x2, y1, y2, xc, yc, dxn, dyn;
4656 Double_t xrg = gPad->GetUxmin();
4657 Double_t yrg = gPad->GetUymin();
4658 Double_t xln = gPad->GetUxmax() - xrg;
4659 Double_t yln = gPad->GetUymax() - yrg;
4660 Double_t cx = (xln/Double_t(ncx))/2.;
4661 Double_t cy = (yln/Double_t(ncy))/2.;
4662 Double_t dn = 1.E-30;
4663
4664 auto arrow = new TArrow();
4665 arrow->SetAngle(30);
4666 arrow->SetFillStyle(1001);
4667 arrow->SetFillColor(fH->GetLineColor());
4668 arrow->SetLineColor(fH->GetLineColor());
4669 arrow->SetLineWidth(fH->GetLineWidth());
4670
4671 // Initialize the levels on the Z axis
4672 Int_t ncolors=0, ndivz=0;
4673 Double_t scale=0.;
4674 if (Hoption.Arrow>1) {
4675 ncolors = gStyle->GetNumberOfColors();
4676 Int_t ndiv = fH->GetContour();
4677 if (ndiv == 0 ) {
4678 ndiv = gStyle->GetNumberContours();
4679 fH->SetContour(ndiv);
4680 }
4681 ndivz = TMath::Abs(ndiv);
4682 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
4683 scale = ndivz/(fH->GetMaximum()-fH->GetMinimum());
4684 }
4685
4686 for (Int_t id=1;id<=2;id++) {
4687 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
4688 yk = fYaxis->GetBinLowEdge(j);
4689 ystep = fYaxis->GetBinWidth(j);
4690 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
4691 xk = fXaxis->GetBinLowEdge(i);
4692 xstep = fXaxis->GetBinWidth(i);
4693 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
4694 if (i == Hparam.xfirst) {
4695 dx = fH->GetBinContent(i+1, j) - fH->GetBinContent(i, j);
4696 } else if (i == Hparam.xlast) {
4697 dx = fH->GetBinContent(i, j) - fH->GetBinContent(i-1, j);
4698 } else {
4699 dx = 0.5*(fH->GetBinContent(i+1, j) - fH->GetBinContent(i-1, j));
4700 }
4701 if (j == Hparam.yfirst) {
4702 dy = fH->GetBinContent(i, j+1) - fH->GetBinContent(i, j);
4703 } else if (j == Hparam.ylast) {
4704 dy = fH->GetBinContent(i, j) - fH->GetBinContent(i, j-1);
4705 } else {
4706 dy = 0.5*(fH->GetBinContent(i, j+1) - fH->GetBinContent(i, j-1));
4707 }
4708 if (id == 1) {
4709 dn = TMath::Max(dn, TMath::Abs(dx));
4710 dn = TMath::Max(dn, TMath::Abs(dy));
4711 } else if (id == 2) {
4712 xc = xrg + xln*(Double_t(i - Hparam.xfirst+1)-0.5)/Double_t(ncx);
4713 dxn = cx*dx/dn;
4714 x1 = xc - dxn;
4715 x2 = xc + dxn;
4716 yc = yrg + yln*(Double_t(j - Hparam.yfirst+1)-0.5)/Double_t(ncy);
4717 dyn = cy*dy/dn;
4718 y1 = yc - dyn;
4719 y2 = yc + dyn;
4720 if (Hoption.Arrow>1) {
4721 int color = Int_t(0.01+(fH->GetBinContent(i, j)-fH->GetMinimum())*scale);
4722 Int_t theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
4723 if (theColor > ncolors-1) theColor = ncolors-1;
4724 arrow->SetFillColor(gStyle->GetColorPalette(theColor));
4725 arrow->SetLineColor(gStyle->GetColorPalette(theColor));
4726 }
4727 if (TMath::Abs(x2-x1) > 0. || TMath::Abs(y2-y1) > 0.) {
4728 arrow->PaintArrow(x1, y1, x2, y2, 0.015, "|>");
4729 } else {
4730 arrow->PaintArrow(x1, y1, x2, y2, 0.005, "|>");
4731 }
4732 }
4733 }
4734 }
4735 }
4736
4738}
4739
4740////////////////////////////////////////////////////////////////////////////////
4741/// Draw axis (2D case) of an histogram.
4742///
4743/// If `drawGridOnly` is `TRUE`, only the grid is painted (if needed). This allows
4744/// to draw the grid and the axis separately. In `THistPainter::Paint` this
4745/// feature is used to make sure that the grid is drawn in the background and
4746/// the axis tick marks in the foreground of the pad.
4747
4749{
4750
4751 //On iOS, grid should not be pickable and can not be highlighted.
4752 //Condition is never true on a platform different from iOS.
4753 if (drawGridOnly && (gPad->PadInHighlightMode() || gPad->PadInSelectionMode()))
4754 return;
4755
4756 if (Hoption.Axis == -1) return;
4757 if (Hoption.Same && Hoption.Axis <= 0) return;
4758
4759 // Repainting alphanumeric labels axis on a plot done with
4760 // the option HBAR (horizontal) needs some adjustments.
4761 TAxis *xaxis = nullptr;
4762 TAxis *yaxis = nullptr;
4763 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4764 if (fXaxis->GetLabels() || fYaxis->GetLabels()) { // One axis has alphanumeric labels
4765 TIter next(gPad->GetListOfPrimitives());
4766 TObject *obj;
4767 // Check if the first TH1 of THStack in the pad is drawn with the option HBAR
4768 while ((obj = next())) {
4769 if (!obj->InheritsFrom(TH1::Class()) &&
4770 !obj->InheritsFrom(THStack::Class())) continue;
4771 TString opt = obj->GetDrawOption();
4772 opt.ToLower();
4773 // if drawn with HBAR, the axis should be inverted and the pad set to horizontal
4774 if (strstr(opt,"hbar")) {
4775 gPad->SetVertical(kFALSE);
4776 xaxis = fXaxis;
4777 yaxis = fYaxis;
4778 if (!strcmp(xaxis->GetName(),"xaxis")) {
4779 fXaxis = yaxis;
4780 fYaxis = xaxis;
4781 }
4782 }
4783 break;
4784 }
4785 }
4786 }
4787
4788 static char chopt[10] = "";
4789 Double_t gridl = 0;
4790 Int_t ndiv, ndivx, ndivy, nx1, nx2, ndivsave;
4791 Int_t useHparam = 0;
4792 Double_t umin, umax, uminsave, umaxsave;
4793 Short_t xAxisPos = Hoption.AxisPos/10;
4794 Short_t yAxisPos = Hoption.AxisPos - 10*xAxisPos;
4795
4796 Double_t axmin = gPad->GetUxmin();
4797 Double_t axmax = gPad->GetUxmax();
4798 Double_t aymin = gPad->GetUymin();
4799 Double_t aymax = gPad->GetUymax();
4800 char *cw = nullptr;
4801 TGaxis axis;
4802
4803 // In case of option 'cont4' or in case of option 'same' over a 'cont4 plot'
4804 // Hparam must be use for the axis limits.
4805 if (Hoption.Contour == 14) useHparam = 1;
4806 if (Hoption.Same) {
4807 TObject *obj;
4808 TIter next(gPad->GetListOfPrimitives());
4809 while ((obj=next())) {
4810 if (strstr(obj->GetDrawOption(),"cont4")) {
4811 useHparam = 1;
4812 break;
4813 }
4814 }
4815 }
4816
4817 // Paint X axis
4818
4819 //To make X-axis selectable on iOS device.
4820 if (gPad->PadInSelectionMode())
4821 gPad->PushSelectableObject(fXaxis);
4822
4823 //This condition is ALWAYS true, unless it works on iOS (can be false on iOS).
4824 if (gPad->PadInSelectionMode() || !gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && gPad->GetSelected() == fXaxis)) {
4825 ndivx = fXaxis->GetNdivisions();
4826 if (ndivx > 1000) {
4827 nx2 = ndivx/100;
4828 nx1 = TMath::Max(1, ndivx%100);
4829 ndivx = 100*nx2 + Int_t(Float_t(nx1)*gPad->GetAbsWNDC());
4830 }
4831 axis.SetTextAngle(0);
4833
4834 chopt[0] = 0;
4835 strlcat(chopt, "SDH",10);
4836 if (ndivx < 0) strlcat(chopt, "N",10);
4837 if (gPad->GetGridx()) {
4838 gridl = (aymax-aymin)/(gPad->GetY2() - gPad->GetY1());
4839 strlcat(chopt, "W",10);
4840 }
4841
4842 // Define X-Axis limits
4843 if (Hoption.Logx) {
4844 strlcat(chopt, "G",10);
4845 ndiv = TMath::Abs(ndivx);
4846 if (useHparam) {
4847 umin = TMath::Power(10,Hparam.xmin);
4848 umax = TMath::Power(10,Hparam.xmax);
4849 } else {
4850 umin = TMath::Power(10,axmin);
4851 umax = TMath::Power(10,axmax);
4852 }
4853 } else {
4854 ndiv = TMath::Abs(ndivx);
4855 if (useHparam) {
4856 umin = Hparam.xmin;
4857 umax = Hparam.xmax;
4858 } else {
4859 umin = axmin;
4860 umax = axmax;
4861 }
4862 }
4863
4864 // Display axis as time
4865 if (fXaxis->GetTimeDisplay()) {
4866 strlcat(chopt,"t",10);
4867 if (strlen(fXaxis->GetTimeFormatOnly()) == 0) {
4869 }
4870 }
4871
4872 // The main X axis can be on the bottom or on the top of the pad
4873 Double_t xAxisYPos1, xAxisYPos2;
4874 if (xAxisPos == 1) {
4875 // Main X axis top
4876 xAxisYPos1 = aymax;
4877 xAxisYPos2 = aymin;
4878 } else {
4879 // Main X axis bottom
4880 xAxisYPos1 = aymin;
4881 xAxisYPos2 = aymax;
4882 }
4883
4884 // Paint the main X axis (always)
4885 uminsave = umin;
4886 umaxsave = umax;
4887 ndivsave = ndiv;
4888 axis.SetOption(chopt);
4889 if (xAxisPos) {
4890 strlcat(chopt, "-",10);
4891 gridl = -gridl;
4892 }
4893 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4894 axis.SetLabelSize(0.);
4895 axis.SetTitle("");
4896 }
4897 axis.PaintAxis(axmin, xAxisYPos1,
4898 axmax, xAxisYPos1,
4899 umin, umax, ndiv, chopt, gridl, drawGridOnly);
4900
4901 // Paint additional X axis (if needed)
4902 // On iOS, this additional X axis is neither pickable, nor highlighted.
4903 // Additional checks PadInSelectionMode etc. does not effect non-iOS platform.
4904 if (gPad->GetTickx() && !gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
4905 if (xAxisPos) {
4906 cw=strstr(chopt,"-");
4907 *cw='z';
4908 } else {
4909 strlcat(chopt, "-",10);
4910 }
4911 if (gPad->GetTickx() < 2) strlcat(chopt, "U",10);
4912 if ((cw=strstr(chopt,"W"))) *cw='z';
4913 axis.SetTitle("");
4914 axis.PaintAxis(axmin, xAxisYPos2,
4915 axmax, xAxisYPos2,
4916 uminsave, umaxsave, ndivsave, chopt, gridl, drawGridOnly);
4917 }
4918 }//End of "if pad in selection mode etc".
4919
4920 // Paint Y axis
4921 //On iOS, Y axis must pushed into the stack of selectable objects.
4922 if (gPad->PadInSelectionMode())
4923 gPad->PushSelectableObject(fYaxis);
4924
4925 //This conditions is ALWAYS true on a platform, different from iOS (on iOS can be true, can be false).
4926 if (gPad->PadInSelectionMode() || !gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && gPad->GetSelected() == fYaxis)) {
4927 ndivy = fYaxis->GetNdivisions();
4929
4930 chopt[0] = 0;
4931 strlcat(chopt, "SDH",10);
4932 if (ndivy < 0) strlcat(chopt, "N",10);
4933 if (gPad->GetGridy()) {
4934 gridl = (axmax-axmin)/(gPad->GetX2() - gPad->GetX1());
4935 strlcat(chopt, "W",10);
4936 }
4937
4938 // Define Y-Axis limits
4939 if (Hoption.Logy) {
4940 strlcat(chopt, "G",10);
4941 ndiv = TMath::Abs(ndivy);
4942 if (useHparam) {
4943 umin = TMath::Power(10,Hparam.ymin);
4944 umax = TMath::Power(10,Hparam.ymax);
4945 } else {
4946 umin = TMath::Power(10,aymin);
4947 umax = TMath::Power(10,aymax);
4948 }
4949 } else {
4950 ndiv = TMath::Abs(ndivy);
4951 if (useHparam) {
4952 umin = Hparam.ymin;
4953 umax = Hparam.ymax;
4954 } else {
4955 umin = aymin;
4956 umax = aymax;
4957 }
4958 }
4959
4960 // Display axis as time
4961 if (fYaxis->GetTimeDisplay()) {
4962 strlcat(chopt,"t",10);
4963 if (strlen(fYaxis->GetTimeFormatOnly()) == 0) {
4965 }
4966 }
4967
4968 // The main Y axis can be on the left or on the right of the pad
4969 Double_t yAxisXPos1, yAxisXPos2;
4970 if (yAxisPos == 1) {
4971 // Main Y axis left
4972 yAxisXPos1 = axmax;
4973 yAxisXPos2 = axmin;
4974 } else {
4975 // Main Y axis right
4976 yAxisXPos1 = axmin;
4977 yAxisXPos2 = axmax;
4978 }
4979
4980 // Paint the main Y axis (always)
4981 uminsave = umin;
4982 umaxsave = umax;
4983 ndivsave = ndiv;
4984 axis.SetOption(chopt);
4985 if (yAxisPos) {
4986 strlcat(chopt, "+L",10);
4987 gridl = -gridl;
4988 }
4989 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4990 axis.SetLabelSize(0.);
4991 axis.SetTitle("");
4992 }
4993 axis.PaintAxis(yAxisXPos1, aymin,
4994 yAxisXPos1, aymax,
4995 umin, umax, ndiv, chopt, gridl, drawGridOnly);
4996
4997 // Paint the additional Y axis (if needed)
4998 // Additional checks for pad mode are required on iOS: this "second" axis is
4999 // neither pickable, nor highlighted. Additional checks have no effect on non-iOS platform.
5000 if (gPad->GetTicky() && !gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
5001 if (gPad->GetTicky() < 2) {
5002 strlcat(chopt, "U",10);
5004 } else {
5005 strlcat(chopt, "+L",10);
5006 }
5007 if ((cw=strstr(chopt,"W"))) *cw='z';
5008 axis.SetTitle("");
5009 axis.PaintAxis(yAxisXPos2, aymin,
5010 yAxisXPos2, aymax,
5011 uminsave, umaxsave, ndivsave, chopt, gridl, drawGridOnly);
5012 }
5013 }//End of "if pad is in selection mode etc."
5014
5015 // Reset the axis if they have been inverted in case of option HBAR
5016 if (xaxis) {
5017 fXaxis = xaxis;
5018 fYaxis = yaxis;
5019 }
5020}
5021
5022////////////////////////////////////////////////////////////////////////////////
5023/// [Draw a bar-chart in a normal pad.](\ref HP10)
5024
5026{
5027
5028 Int_t bar = Hoption.Bar - 10;
5029 Double_t xmin,xmax,ymin,ymax,umin,umax,w,y;
5032 TBox box;
5033 Int_t hcolor = fH->GetFillColor();
5034 if (hcolor == gPad->GetFrameFillColor()) ++hcolor;
5035 Int_t hstyle = fH->GetFillStyle();
5036 box.SetFillColor(hcolor);
5037 box.SetFillStyle(hstyle);
5038 box.SetLineStyle(fH->GetLineStyle());
5039 box.SetLineColor(fH->GetLineColor());
5040 box.SetLineWidth(fH->GetLineWidth());
5041 for (Int_t bin=fXaxis->GetFirst();bin<=fXaxis->GetLast();bin++) {
5042 y = fH->GetBinContent(bin);
5043 xmin = gPad->XtoPad(fXaxis->GetBinLowEdge(bin));
5044 xmax = gPad->XtoPad(fXaxis->GetBinUpEdge(bin));
5045 ymin = gPad->GetUymin();
5046 ymax = gPad->YtoPad(y);
5047 if (ymax < gPad->GetUymin()) continue;
5048 if (ymax > gPad->GetUymax()) ymax = gPad->GetUymax();
5049 if (ymin < gPad->GetUymin()) ymin = gPad->GetUymin();
5050 if (Hoption.MinimumZero && ymin < 0)
5051 ymin=TMath::Min(0.,gPad->GetUymax());
5052 w = (xmax-xmin)*width;
5053 xmin += offset*(xmax-xmin);
5054 xmax = xmin + w;
5055 if (bar < 1) {
5056 box.PaintBox(xmin,ymin,xmax,ymax);
5057 } else {
5058 umin = xmin + bar*(xmax-xmin)/10.;
5059 umax = xmax - bar*(xmax-xmin)/10.;
5060 box.SetFillColor(TColor::GetColorBright(hcolor)); //bright
5061 box.PaintBox(xmin,ymin,umin,ymax);
5062 box.SetFillColor(hcolor);
5063 box.PaintBox(umin,ymin,umax,ymax);
5064 box.SetFillColor(TColor::GetColorDark(hcolor)); //dark
5065 box.PaintBox(umax,ymin,xmax,ymax);
5066 }
5067 }
5068}
5069
5070////////////////////////////////////////////////////////////////////////////////
5071/// [Draw a bar char in a rotated pad (X vertical, Y horizontal)](\ref HP10)
5072
5074{
5075
5076 gPad->SetVertical(kFALSE);
5077
5078 PaintInitH();
5079
5080 TAxis *xaxis = fXaxis;
5081 TAxis *yaxis = fYaxis;
5082 if (!strcmp(xaxis->GetName(),"xaxis")) {
5083 fXaxis = yaxis;
5084 fYaxis = xaxis;
5085 }
5086
5087 PaintFrame();
5089
5090 Int_t bar = Hoption.Bar - 20;
5091 Double_t xmin,xmax,ymin,ymax,umin,umax,w;
5094 TBox box;
5095 Int_t hcolor = fH->GetFillColor();
5096 if (hcolor == gPad->GetFrameFillColor()) ++hcolor;
5097 Int_t hstyle = fH->GetFillStyle();
5098 box.SetFillColor(hcolor);
5099 box.SetFillStyle(hstyle);
5100 box.SetLineStyle(fH->GetLineStyle());
5101 box.SetLineColor(fH->GetLineColor());
5102 box.SetLineWidth(fH->GetLineWidth());
5103 for (Int_t bin=fYaxis->GetFirst();bin<=fYaxis->GetLast();bin++) {
5104 ymin = gPad->YtoPad(fYaxis->GetBinLowEdge(bin));
5105 ymax = gPad->YtoPad(fYaxis->GetBinUpEdge(bin));
5106 xmin = gPad->GetUxmin();
5107 xmax = gPad->XtoPad(fH->GetBinContent(bin));
5108 if (xmax < gPad->GetUxmin()) continue;
5109 if (xmax > gPad->GetUxmax()) xmax = gPad->GetUxmax();
5110 if (xmin < gPad->GetUxmin()) xmin = gPad->GetUxmin();
5111 if (Hoption.MinimumZero && xmin < 0)
5112 xmin=TMath::Min(0.,gPad->GetUxmax());
5113 w = (ymax-ymin)*width;
5114 ymin += offset*(ymax-ymin);
5115 ymax = ymin + w;
5116 if (bar < 1) {
5117 box.PaintBox(xmin,ymin,xmax,ymax);
5118 } else {
5119 umin = ymin + bar*(ymax-ymin)/10.;
5120 umax = ymax - bar*(ymax-ymin)/10.;
5121 box.SetFillColor(TColor::GetColorDark(hcolor)); //dark
5122 box.PaintBox(xmin,ymin,xmax,umin);
5123 box.SetFillColor(hcolor);
5124 box.PaintBox(xmin,umin,xmax,umax);
5125 box.SetFillColor(TColor::GetColorBright(hcolor)); //bright
5126 box.PaintBox(xmin,umax,xmax,ymax);
5127 }
5128 }
5129
5130 PaintTitle();
5131
5132 // Draw box with histogram statistics and/or fit parameters
5133 if ((Hoption.Same%10) != 1 && !fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
5134 TIter next(fFunctions);
5135 TObject *obj = nullptr;
5136 while ((obj = next())) {
5137 if (obj->InheritsFrom(TF1::Class())) break;
5138 obj = nullptr;
5139 }
5140 PaintStat(gStyle->GetOptStat(),(TF1*)obj);
5141 }
5142
5143 fXaxis = xaxis;
5144 fYaxis = yaxis;
5145}
5146
5147////////////////////////////////////////////////////////////////////////////////
5148/// [Control function to draw a 2D histogram as a box plot](\ref HP13)
5149
5151{
5152
5153 Style_t fillsav = fH->GetFillStyle();
5154 Style_t colsav = fH->GetFillColor();
5155 if (fH->GetFillColor() == 0) fH->SetFillStyle(0);
5156 if (Hoption.Box == 11) fH->SetFillStyle(1001);
5157 fH->TAttLine::Modify();
5158 fH->TAttFill::Modify();
5159
5160 Double_t z, xk,xstep, yk, ystep, xcent, ycent, xlow, xup, ylow, yup;
5161 Double_t ux1 = gPad->PixeltoX(1);
5162 Double_t ux0 = gPad->PixeltoX(0);
5163 Double_t uy1 = gPad->PixeltoY(1);
5164 Double_t uy0 = gPad->PixeltoY(0);
5165 Double_t dxmin = 0.51*(gPad->PadtoX(ux1)-gPad->PadtoX(ux0));
5166 Double_t dymin = 0.51*(gPad->PadtoY(uy0)-gPad->PadtoY(uy1));
5167
5168 Double_t zmin = TMath::Max(fH->GetMinimum(),0.);
5171 Double_t zminlin = zmin, zmaxlin = zmax;
5172
5173 // In case of option SAME, zmin and zmax values are taken from the
5174 // first plotted 2D histogram.
5175 if (Hoption.Same > 0 && Hoption.Same < 10) {
5176 TH2 *h2;
5177 TIter next(gPad->GetListOfPrimitives());
5178 while ((h2 = (TH2 *)next())) {
5179 if (!h2->InheritsFrom(TH2::Class())) continue;
5180 zmin = TMath::Max(h2->GetMinimum(), 0.);
5181 zmax = TMath::Max(TMath::Abs(h2->GetMaximum()),
5182 TMath::Abs(h2->GetMinimum()));
5183 zminlin = zmin;
5184 zmaxlin = zmax;
5185 if (Hoption.Logz) {
5186 if (zmin <= 0) {
5187 zmin = TMath::Log10(zmax*0.001);
5188 } else {
5189 zmin = TMath::Log10(zmin);
5190 }
5191 zmax = TMath::Log10(zmax);
5192 }
5193 break;
5194 }
5195 } else {
5196 if (Hoption.Logz) {
5197 if (zmin > 0) {
5198 zmin = TMath::Log10(zmin);
5199 zmax = TMath::Log10(zmax);
5200 } else {
5201 return;
5202 }
5203 }
5204 }
5205
5206 Double_t zratio, dz = zmax - zmin;
5207 Bool_t kZminNeg = kFALSE;
5208 if (fH->GetMinimum()<0) kZminNeg = kTRUE;
5209 Bool_t kZNeg = kFALSE;
5210
5211 // Define the dark and light colors the "button style" boxes.
5212 Color_t color = fH->GetFillColor();
5213 Color_t light=0, dark=0;
5214 if (Hoption.Box == 11) {
5215 light = TColor::GetColorBright(color);
5216 dark = TColor::GetColorDark(color);
5217 }
5218
5219 // Loop over all the bins and draw the boxes
5220 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
5221 yk = fYaxis->GetBinLowEdge(j);
5222 ystep = fYaxis->GetBinWidth(j);
5223 ycent = 0.5*ystep;
5224 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
5225 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
5226 xk = fXaxis->GetBinLowEdge(i);
5227 xstep = fXaxis->GetBinWidth(i);
5228 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
5229 xcent = 0.5*xstep;
5230 z = Hparam.factor*fH->GetBinContent(bin);
5231 kZNeg = kFALSE;
5232
5233 if (TMath::Abs(z) < zminlin) continue; // Can be the case with ...
5234 if (TMath::Abs(z) > zmaxlin) z = zmaxlin; // ... option Same
5235 if (kZminNeg && z==0) continue; // Do not draw empty bins if case of histo with negative bins.
5236
5237 if (z < 0) {
5238 if (Hoption.Logz) continue;
5239 z = -z;
5240 kZNeg = kTRUE;
5241 }
5242 if (Hoption.Logz) {
5243 if (z != 0) z = TMath::Log10(z);
5244 else z = zmin;
5245 }
5246
5247 if (dz == 0) continue;
5248 zratio = TMath::Sqrt((z-zmin)/dz);
5249 if (zratio == 0) continue;
5250
5251 xup = xcent*zratio + xk + xcent;
5252 xlow = 2*(xk + xcent) - xup;
5253 if (xup-xlow < dxmin) xup = xlow+dxmin;
5254 if (Hoption.Logx) {
5255 if (xup > 0) xup = TMath::Log10(xup);
5256 else continue;
5257 if (xlow > 0) xlow = TMath::Log10(xlow);
5258 else continue;
5259 }
5260
5261 yup = ycent*zratio + yk + ycent;
5262 ylow = 2*(yk + ycent) - yup;
5263 if (yup-ylow < dymin) yup = ylow+dymin;
5264 if (Hoption.Logy) {
5265 if (yup > 0) yup = TMath::Log10(yup);
5266 else continue;
5267 if (ylow > 0) ylow = TMath::Log10(ylow);
5268 else continue;
5269 }
5270
5271 xlow = TMath::Max(xlow, gPad->GetUxmin());
5272 ylow = TMath::Max(ylow, gPad->GetUymin());
5273 xup = TMath::Min(xup , gPad->GetUxmax());
5274 yup = TMath::Min(yup , gPad->GetUymax());
5275
5276 if (xlow >= xup) continue;
5277 if (ylow >= yup) continue;
5278
5279 if (Hoption.Box == 1) {
5280 fH->SetFillColor(color);
5281 fH->TAttFill::Modify();
5282 gPad->PaintBox(xlow, ylow, xup, yup);
5283 if (kZNeg) {
5284 gPad->PaintLine(xlow, ylow, xup, yup);
5285 gPad->PaintLine(xlow, yup, xup, ylow);
5286 }
5287 } else if (Hoption.Box == 11) {
5288 // Draw the center of the box
5289 fH->SetFillColor(color);
5290 fH->TAttFill::Modify();
5291 gPad->PaintBox(xlow, ylow, xup, yup);
5292
5293 // Draw top&left part of the box
5294 Double_t x[7], y[7];
5295 Double_t bwidth = 0.1;
5296 x[0] = xlow; y[0] = ylow;
5297 x[1] = xlow + bwidth*(xup-xlow); y[1] = ylow + bwidth*(yup-ylow);
5298 x[2] = x[1]; y[2] = yup - bwidth*(yup-ylow);
5299 x[3] = xup - bwidth*(xup-xlow); y[3] = y[2];
5300 x[4] = xup; y[4] = yup;
5301 x[5] = xlow; y[5] = yup;
5302 x[6] = xlow; y[6] = ylow;
5303 if (kZNeg) fH->SetFillColor(dark);
5304 else fH->SetFillColor(light);
5305 fH->TAttFill::Modify();
5306 gPad->PaintFillArea(7, x, y);
5307
5308 // Draw bottom&right part of the box
5309 x[0] = xlow; y[0] = ylow;
5310 x[1] = xlow + bwidth*(xup-xlow); y[1] = ylow + bwidth*(yup-ylow);
5311 x[2] = xup - bwidth*(xup-xlow); y[2] = y[1];
5312 x[3] = x[2]; y[3] = yup - bwidth*(yup-ylow);
5313 x[4] = xup; y[4] = yup;
5314 x[5] = xup; y[5] = ylow;
5315 x[6] = xlow; y[6] = ylow;
5316 if (kZNeg) fH->SetFillColor(light);
5317 else fH->SetFillColor(dark);
5318 fH->TAttFill::Modify();
5319 gPad->PaintFillArea(7, x, y);
5320 }
5321 }
5322 }
5323
5325 fH->SetFillStyle(fillsav);
5326 fH->SetFillColor(colsav);
5327 fH->TAttFill::Modify();
5328}
5329
5330
5331
5332////////////////////////////////////////////////////////////////////////////////
5333/// [Control function to draw a 2D histogram as a candle (box) plot or violin plot](\ref HP14)
5334
5336{
5337 TH1D *hproj = nullptr;
5338 TH2D *h2 = (TH2D*)fH;
5339
5340 TCandle myCandle;
5342 myCandle.SetMarkerColor(fH->GetLineColor());
5343 myCandle.SetLineColor(fH->GetLineColor());
5344 myCandle.SetLineWidth(fH->GetLineWidth());
5345 myCandle.SetFillColor(fH->GetFillColor());
5346 myCandle.SetFillStyle(fH->GetFillStyle());
5347 myCandle.SetMarkerSize(fH->GetMarkerSize());
5348 myCandle.SetMarkerStyle(fH->GetMarkerStyle());
5350
5351 Bool_t swapXY = myCandle.IsHorizontal();
5352 const Double_t standardCandleWidth = 0.66;
5353 const Double_t standardHistoWidth = 0.8;
5354
5355 double allMaxContent = 0, allMaxIntegral = 0;
5356 if (myCandle.IsViolinScaled())
5357 allMaxContent = h2->GetBinContent(h2->GetMaximumBin());
5358
5359 if (!swapXY) { // Vertical candle
5360 //Determining the slice with the maximum integral - if necessary
5361 if (myCandle.IsCandleScaled())
5362 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast; i++) {
5363 hproj = h2->ProjectionY("_px", i, i);
5364 if (hproj->Integral() > allMaxIntegral) allMaxIntegral = hproj->Integral();
5365 }
5366 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast; i++) {
5367 Double_t binPosX = fXaxis->GetBinLowEdge(i);
5368 Double_t binWidth = fXaxis->GetBinWidth(i);
5369 hproj = h2->ProjectionY("_px", i, i);
5370 if (hproj->GetEntries() != 0) {
5371 Double_t candleWidth = fH->GetBarWidth();
5372 Double_t offset = fH->GetBarOffset()*binWidth;
5373 double myMaxContent = hproj->GetBinContent(hproj->GetMaximumBin());
5374 double myIntegral = hproj->Integral();
5375 Double_t histoWidth = candleWidth;
5376 if (candleWidth > 0.999 && candleWidth < 1.001) {
5377 candleWidth = standardCandleWidth;
5378 histoWidth = standardHistoWidth;
5379 }
5380 if (Hoption.Logz && myMaxContent > 0) {
5381 histoWidth *= myMaxContent/TMath::Log10(myMaxContent);
5382 if (myCandle.IsViolinScaled() && myMaxContent > 0 && allMaxContent > 0)
5383 histoWidth *= TMath::Log10(myMaxContent)/TMath::Log10(allMaxContent);
5384 } else if (myCandle.IsViolinScaled() && (allMaxContent > 0))
5385 histoWidth *= myMaxContent/allMaxContent;
5386 if (myCandle.IsCandleScaled() && (allMaxIntegral > 0))
5387 candleWidth *= myIntegral/allMaxIntegral;
5388
5389 myCandle.SetAxisPosition(binPosX+binWidth/2. + offset);
5390 myCandle.SetCandleWidth(candleWidth*binWidth);
5391 myCandle.SetHistoWidth(histoWidth*binWidth);
5392 myCandle.SetHistogram(hproj);
5393 myCandle.Paint();
5394 }
5395 }
5396 } else { // Horizontal candle
5397 //Determining the slice with the maximum integral - if necessary
5398 if (myCandle.IsCandleScaled())
5399 for (Int_t i=Hparam.yfirst; i<=Hparam.ylast; i++) {
5400 hproj = h2->ProjectionX("_py", i, i);
5401 if (hproj->Integral() > allMaxIntegral) allMaxIntegral = hproj->Integral();
5402 }
5403 for (Int_t i=Hparam.yfirst; i<=Hparam.ylast; i++) {
5404 Double_t binPosY = fYaxis->GetBinLowEdge(i);
5405 Double_t binWidth = fYaxis->GetBinWidth(i);
5406 hproj = h2->ProjectionX("_py", i, i);
5407 if (hproj->GetEntries() != 0) {
5408 Double_t candleWidth = fH->GetBarWidth();
5409 Double_t offset = fH->GetBarOffset()*binWidth;
5410 double myMaxContent = hproj->GetBinContent(hproj->GetMaximumBin());
5411 double myIntegral = hproj->Integral();
5412 Double_t histoWidth = candleWidth;
5413 if (candleWidth > 0.999 && candleWidth < 1.001) {
5414 candleWidth = standardCandleWidth;
5415 histoWidth = standardHistoWidth;
5416 }
5417 if (Hoption.Logz && myMaxContent > 0) {
5418 histoWidth *= myMaxContent/TMath::Log10(myMaxContent);
5419 if (myCandle.IsViolinScaled() && myMaxContent > 0 && allMaxContent > 0)
5420 histoWidth *= TMath::Log10(myMaxContent)/TMath::Log10(allMaxContent);
5421 } else if (myCandle.IsViolinScaled() && (allMaxContent > 0))
5422 histoWidth *= myMaxContent/allMaxContent;
5423 if (myCandle.IsCandleScaled() && (allMaxIntegral > 0))
5424 candleWidth *= myIntegral/allMaxIntegral;
5425
5426 myCandle.SetAxisPosition(binPosY+binWidth/2. + offset);
5427 myCandle.SetCandleWidth(candleWidth*binWidth);
5428 myCandle.SetHistoWidth(histoWidth*binWidth);
5429 myCandle.SetHistogram(hproj);
5430 myCandle.Paint();
5431 }
5432 }
5433 }
5434 delete hproj;
5435}
5436
5437
5438
5439////////////////////////////////////////////////////////////////////////////////
5440/// Returns the rendering regions for an axis to use in the COL2 option
5441///
5442/// The algorithm analyses the size of the axis compared to the size of
5443/// the rendering region. It figures out the boundaries to use for each color
5444/// of the rendering region. Only one axis is computed here.
5445///
5446/// This allows for a single computation of the boundaries before iterating
5447/// through all of the bins.
5448///
5449/// \param pAxis the axis to consider
5450/// \param nPixels the number of pixels to render axis into
5451/// \param isLog whether the axis is log scale
5452
5453std::vector<THistRenderingRegion>
5455{
5456 std::vector<THistRenderingRegion> regions;
5457
5458 enum STRATEGY { Bins, Pixels } strategy;
5459
5460 Int_t nBins = (pAxis->GetLast() - pAxis->GetFirst() + 1);
5461
5462 if (nBins >= nPixels) {
5463 // more bins than pixels... we should loop over pixels and sample
5464 strategy = Pixels;
5465 } else {
5466 // fewer bins than pixels... we should loop over bins
5467 strategy = Bins;
5468 }
5469
5470 if (isLog) {
5471
5472 Double_t xMin = pAxis->GetBinLowEdge(pAxis->GetFirst());
5473 Int_t binOffset=0;
5474 while (xMin <= 0 && ((pAxis->GetFirst()+binOffset) != pAxis->GetLast()) ) {
5475 binOffset++;
5476 xMin = pAxis->GetBinLowEdge(pAxis->GetFirst()+binOffset);
5477 }
5478 if (xMin <= 0) {
5479 // this should cause an error if we have
5480 return regions;
5481 }
5482 Double_t xMax = pAxis->GetBinUpEdge(pAxis->GetLast());
5483
5484 if (strategy == Bins) {
5485 // logarithmic plot. we find the pixel for the bin
5486 // pixel = eta * log10(V) - alpha
5487 // where eta = nPixels/(log10(Vmax)-log10(Vmin))
5488 // and alpha = nPixels*log10(Vmin)/(log10(Vmax)-log10(Vmin))
5489 // and V is axis value
5490 Double_t eta = (nPixels-1.0)/(TMath::Log10(xMax) - TMath::Log10(xMin));
5491 Double_t offset = -1.0 * eta * TMath::Log10(xMin);
5492
5493 for (Int_t bin=pAxis->GetFirst()+binOffset; bin<=pAxis->GetLast(); bin++) {
5494
5495 // linear plot. we simply need to find the appropriate bin
5496 // for the
5497 Double_t xLowValue = pAxis->GetBinLowEdge(bin);
5498 Double_t xUpValue = pAxis->GetBinUpEdge(bin);
5499 Int_t xPx0 = eta*TMath::Log10(xLowValue)+ offset;
5500 Int_t xPx1 = eta*TMath::Log10(xUpValue) + offset;
5501 THistRenderingRegion region = {std::make_pair(xPx0, xPx1),
5502 std::make_pair(bin, bin+1)};
5503 regions.push_back(region);
5504 }
5505
5506 } else {
5507
5508 // loop over pixels
5509
5510 Double_t beta = (TMath::Log10(xMax) - TMath::Log10(xMin))/(nPixels-1.0);
5511
5512 for (Int_t pixelIndex=0; pixelIndex<(nPixels-1); pixelIndex++) {
5513 // linear plot
5514 Int_t binLow = pAxis->FindBin(xMin*TMath::Power(10.0, beta*pixelIndex));
5515 Int_t binHigh = pAxis->FindBin(xMin*TMath::Power(10.0, beta*(pixelIndex+1)));
5516 THistRenderingRegion region = { std::make_pair(pixelIndex, pixelIndex+1),
5517 std::make_pair(binLow, binHigh)};
5518 regions.push_back(region);
5519 }
5520 }
5521 } else {
5522 // standard linear plot
5523
5524 if (strategy == Bins) {
5525 // loop over bins
5526 for (Int_t bin=pAxis->GetFirst(); bin<=pAxis->GetLast(); bin++) {
5527
5528 // linear plot. we simply need to find the appropriate bin
5529 // for the
5530 Int_t xPx0 = ((bin - pAxis->GetFirst()) * nPixels)/nBins;
5531 Int_t xPx1 = xPx0 + nPixels/nBins;
5532
5533 // make sure we don't compute beyond our bounds
5534 if (xPx1>= nPixels) xPx1 = nPixels-1;
5535
5536 THistRenderingRegion region = {std::make_pair(xPx0, xPx1),
5537 std::make_pair(bin, bin+1)};
5538 regions.push_back(region);
5539 }
5540 } else {
5541 // loop over pixels
5542 for (Int_t pixelIndex=0; pixelIndex<nPixels-1; pixelIndex++) {
5543 // linear plot
5544 Int_t binLow = (nBins*pixelIndex)/nPixels + pAxis->GetFirst();
5545 Int_t binHigh = binLow + nBins/nPixels;
5546 THistRenderingRegion region = { std::make_pair(pixelIndex, pixelIndex+1),
5547 std::make_pair(binLow, binHigh)};
5548 regions.push_back(region);
5549 }
5550 }
5551 }
5552
5553 return regions;
5554}
5555
5556////////////////////////////////////////////////////////////////////////////////
5557/// [Rendering scheme for the COL2 and COLZ2 options] (\ref HP14)
5558
5560{
5561
5562 if (Hoption.System != kCARTESIAN) {
5563 Error("THistPainter::PaintColorLevelsFast(Option_t*)",
5564 "Only cartesian coordinates supported by 'COL2' option. Using 'COL' option instead.");
5565 PaintColorLevels(nullptr);
5566 return;
5567 }
5568
5569 Double_t z;
5570
5571 // Use existing max or min values. If either is already set
5572 // the appropriate value to use.
5573 Double_t zmin = fH->GetMinimumStored();
5574 Double_t zmax = fH->GetMaximumStored();
5575 Double_t originalZMin = zmin;
5576 Double_t originalZMax = zmax;
5577 if ((zmin == -1111) && (zmax == -1111)) {
5578 fH->GetMinimumAndMaximum(zmin, zmax);
5579 fH->SetMinimum(zmin);
5580 fH->SetMaximum(zmax);
5581 } else if (zmin == -1111) {
5582 zmin = fH->GetMinimum();
5583 fH->SetMinimum(zmin);
5584 } else if (zmax == -1111) {
5585 zmax = fH->GetMaximum();
5586 fH->SetMaximum(zmax);
5587 }
5588
5589 Double_t dz = zmax - zmin;
5590 if (dz <= 0) { // Histogram filled with a constant value
5591 zmax += 0.1*TMath::Abs(zmax);
5592 zmin -= 0.1*TMath::Abs(zmin);
5593 dz = zmax - zmin;
5594 }
5595
5596 if (Hoption.Logz) {
5597 if (zmin > 0) {
5598 zmin = TMath::Log10(zmin);
5599 zmax = TMath::Log10(zmax);
5600 dz = zmax - zmin;
5601 } else {
5602 Error("THistPainter::PaintColorLevelsFast(Option_t*)",
5603 "Cannot plot logz because bin content is less than 0.");
5604 return;
5605 }
5606 }
5607
5608 // Initialize the levels on the Z axis
5609 Int_t ndiv = fH->GetContour();
5610 if (ndiv == 0 ) {
5611 ndiv = gStyle->GetNumberContours();
5612 fH->SetContour(ndiv);
5613 }
5614 std::vector<Double_t> colorBounds(ndiv);
5615 std::vector<Double_t> contours(ndiv, 0);
5616 if (!fH->TestBit(TH1::kUserContour)) {
5617 fH->SetContour(ndiv);
5618 } else {
5619 fH->GetContour(contours.data());
5620 }
5621
5622 Double_t step = 1.0/ndiv;
5623 for (Int_t i=0; i<ndiv; ++i) {
5624 colorBounds[i] = step*i;
5625 }
5626
5627 auto pFrame = gPad->GetFrame();
5628 Int_t px0 = gPad->XtoPixel(pFrame->GetX1());
5629 Int_t px1 = gPad->XtoPixel(pFrame->GetX2());
5630 Int_t py0 = gPad->YtoPixel(pFrame->GetY1());
5631 Int_t py1 = gPad->YtoPixel(pFrame->GetY2());
5632 Int_t nXPixels = px1-px0;
5633 Int_t nYPixels = py0-py1; // y=0 is at the top of the screen
5634
5635 std::vector<Double_t> buffer(nXPixels*nYPixels, 0);
5636
5637 auto xRegions = ComputeRenderingRegions(fXaxis, nXPixels, Hoption.Logx);
5638 auto yRegions = ComputeRenderingRegions(fYaxis, nYPixels, Hoption.Logy);
5639 if (xRegions.empty() || yRegions.empty()) {
5640 Error("THistPainter::PaintColorLevelFast(Option_t*)",
5641 "Encountered error while computing rendering regions.");
5642 return;
5643 }
5644
5645 Bool_t minExists = kFALSE;
5646 Bool_t maxExists = kFALSE;
5647 Double_t minValue = 1.;
5648 Double_t maxValue = 0.;
5649 for (auto& yRegion : yRegions) {
5650 for (auto& xRegion : xRegions ) {
5651
5652 const auto& xBinRange = xRegion.fBinRange;
5653 const auto& yBinRange = yRegion.fBinRange;
5654
5655 // sample the range
5656 z = fH->GetBinContent(xBinRange.second-1, yBinRange.second-1);
5657
5658 if (Hoption.Logz) {
5659 if (z > 0) z = TMath::Log10(z);
5660 else z = zmin;
5661 }
5662
5663 // obey the user's max and min values if they were set
5664 if (z > zmax) z = zmax;
5665 if (z < zmin) z = zmin;
5666
5668 // contours are absolute values
5669 auto index = TMath::BinarySearch(contours.size(), contours.data(), z);
5670 z = colorBounds[index];
5671 } else {
5672 Int_t index = 0;
5673 if (dz != 0) {
5674 index = 0.001 + ((z - zmin)/dz)*ndiv;
5675 }
5676
5677 if (index == static_cast<Int_t>(colorBounds.size())) {
5678 index--;
5679 }
5680
5681 // Do a little bookkeeping to use later for getting libAfterImage to produce
5682 // the correct colors
5683 if (index == 0) {
5684 minExists = kTRUE;
5685 } else if (index == static_cast<Int_t>(colorBounds.size()-1)) {
5686 maxExists = kTRUE;
5687 }
5688
5689 z = colorBounds[index];
5690
5691 if (z < minValue) {
5692 minValue = z;
5693 }
5694 if (z > maxValue) {
5695 maxValue = z;
5696 }
5697 }
5698
5699 // fill in the actual pixels
5700 const auto& xPixelRange = xRegion.fPixelRange;
5701 const auto& yPixelRange = yRegion.fPixelRange;
5702 for (Int_t xPx = xPixelRange.first; xPx <= xPixelRange.second; ++xPx) {
5703 for (Int_t yPx = yPixelRange.first; yPx <= yPixelRange.second; ++yPx) {
5704 Int_t pixel = yPx*nXPixels + xPx;
5705 buffer[pixel] = z;
5706 }
5707 }
5708 } // end px loop
5709 } // end py loop
5710
5711 // This is a bit of a hack to ensure that we span the entire color range and
5712 // don't screw up the colors for a sparse histogram. No one will notice that I set a
5713 // single pixel on the edge of the image to a different color. This is even more
5714 // true because the chosen pixels will be covered by the axis.
5715 if (minValue != maxValue) {
5716 if ( !minExists) {
5717 buffer.front() = 0;
5718 }
5719
5720 if ( !maxExists) {
5721 buffer[buffer.size()-nXPixels] = 0.95;
5722 }
5723 }
5724
5725 // Generate the TImage
5727 TImage* pImage = TImage::Create();
5729 pImage->SetImage(buffer.data(), nXPixels, nYPixels, pPalette);
5730 delete pPalette;
5731
5732 Window_t wid = static_cast<Window_t>(gVirtualX->GetWindowID(gPad->GetPixmapID()));
5733 pImage->PaintImage(wid, px0, py1, 0, 0, nXPixels, nYPixels);
5734 delete pImage;
5735
5737
5738 // Reset the maximum and minimum values to their original values
5739 // when this function was called. If we don't do this, an initial
5740 // value of -1111 will be replaced with the true max or min values.
5741 fH->SetMinimum(originalZMin);
5742 fH->SetMaximum(originalZMax);
5743}
5744
5745////////////////////////////////////////////////////////////////////////////////
5746/// [Control function to draw a 2D histogram as a color plot.](\ref HP14)
5747
5749{
5750 Double_t z, zc, xk, xstep, yk, ystep, xlow, xup, ylow, yup;
5751
5752 Double_t zmin = fH->GetMinimum();
5753 Double_t zmax = fH->GetMaximum();
5754
5755 Double_t dz = zmax - zmin;
5756 if (dz <= 0) { // Histogram filled with a constant value
5757 zmax += 0.1*TMath::Abs(zmax);
5758 zmin -= 0.1*TMath::Abs(zmin);
5759 dz = zmax - zmin;
5760 }
5761
5762 // In case of option SAME, zmin and zmax values are taken from the
5763 // first plotted 2D histogram.
5764 if (Hoption.Same > 0 && Hoption.Same < 10) {
5765 TH2 *h2;
5766 TIter next(gPad->GetListOfPrimitives());
5767 while ((h2 = (TH2 *)next())) {
5768 if (!h2->InheritsFrom(TH2::Class())) continue;
5769 zmin = h2->GetMinimum();
5770 zmax = h2->GetMaximum();
5771 fH->SetMinimum(zmin);
5772 fH->SetMaximum(zmax);
5773 if (Hoption.Logz) {
5774 if (zmin <= 0) {
5775 zmin = TMath::Log10(zmax*0.001);
5776 } else {
5777 zmin = TMath::Log10(zmin);
5778 }
5779 zmax = TMath::Log10(zmax);
5780 }
5781 dz = zmax - zmin;
5782 break;
5783 }
5784 } else {
5785 if (Hoption.Logz) {
5786 if (zmin > 0) {
5787 zmin = TMath::Log10(zmin);
5788 zmax = TMath::Log10(zmax);
5789 dz = zmax - zmin;
5790 } else {
5791 return;
5792 }
5793 }
5794 }
5795
5796 Style_t fillsav = fH->GetFillStyle();
5797 Style_t colsav = fH->GetFillColor();
5798 fH->SetFillStyle(1001);
5799 fH->TAttFill::Modify();
5800
5801 // Initialize the levels on the Z axis
5802 Int_t ncolors = gStyle->GetNumberOfColors();
5803 Int_t ndiv = fH->GetContour();
5804 if (ndiv == 0 ) {
5805 ndiv = gStyle->GetNumberContours();
5806 fH->SetContour(ndiv);
5807 }
5808 Int_t ndivz = TMath::Abs(ndiv);
5809 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
5810 Double_t scale = (dz ? ndivz / dz : 1.0);
5811
5812 Int_t color;
5813 TProfile2D* prof2d = dynamic_cast<TProfile2D*>(fH);
5814 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
5815 yk = fYaxis->GetBinLowEdge(j);
5816 ystep = fYaxis->GetBinWidth(j);
5817 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
5818 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
5819 xk = fXaxis->GetBinLowEdge(i);
5820 xstep = fXaxis->GetBinWidth(i);
5821 if (Hoption.System == kPOLAR && xk<0) xk= 2*TMath::Pi()+xk;
5822 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
5823 z = fH->GetBinContent(bin);
5824 // if fH is a profile histogram do not draw empty bins
5825 if (prof2d) {
5826 const Double_t binEntries = prof2d->GetBinEntries(bin);
5827 if (binEntries == 0)
5828 continue;
5829 } else {
5830 // don't draw the empty bins for non-profile histograms
5831 // with positive content
5832 if (z == 0) {
5833 if (zmin >= 0 || Hoption.Logz) continue;
5834 if (Hoption.Color == 2) continue;
5835 }
5836 }
5837
5838 if (Hoption.Logz) {
5839 if (z > 0) z = TMath::Log10(z);
5840 else z = zmin;
5841 }
5842 if (z < zmin && !Hoption.Zero) continue;
5843 xup = xk + xstep;
5844 xlow = xk;
5845 if (Hoption.Logx) {
5846 if (xup > 0) xup = TMath::Log10(xup);
5847 else continue;
5848 if (xlow > 0) xlow = TMath::Log10(xlow);
5849 else continue;
5850 }
5851 yup = yk + ystep;
5852 ylow = yk;
5853 if (Hoption.System != kPOLAR) {
5854 if (Hoption.Logy) {
5855 if (yup > 0) yup = TMath::Log10(yup);
5856 else continue;
5857 if (ylow > 0) ylow = TMath::Log10(ylow);
5858 else continue;
5859 }
5860 if (xup < gPad->GetUxmin()) continue;
5861 if (yup < gPad->GetUymin()) continue;
5862 if (xlow > gPad->GetUxmax()) continue;
5863 if (ylow > gPad->GetUymax()) continue;
5864 if (xlow < gPad->GetUxmin()) xlow = gPad->GetUxmin();
5865 if (ylow < gPad->GetUymin()) ylow = gPad->GetUymin();
5866 if (xup > gPad->GetUxmax()) xup = gPad->GetUxmax();
5867 if (yup > gPad->GetUymax()) yup = gPad->GetUymax();
5868 }
5869
5871 zc = fH->GetContourLevelPad(0);
5872 if (z < zc) continue;
5873 color = -1;
5874 for (Int_t k=0; k<ndiv; k++) {
5875 zc = fH->GetContourLevelPad(k);
5876 if (z < zc) {
5877 continue;
5878 } else {
5879 color++;
5880 }
5881 }
5882 } else {
5883 color = Int_t(0.01+(z-zmin)*scale);
5884 }
5885
5886 Int_t theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
5887 if (theColor > ncolors-1) theColor = ncolors-1;
5889 fH->TAttFill::Modify();
5890 if (Hoption.System != kPOLAR) {
5891 gPad->PaintBox(xlow, ylow, xup, yup);
5892 } else {
5893 TCrown crown(0,0,ylow,yup,xlow*TMath::RadToDeg(),xup*TMath::RadToDeg());
5894 crown.SetFillColor(gStyle->GetColorPalette(theColor));
5895 crown.SetLineColor(fH->GetLineColor());
5896 crown.SetLineWidth(fH->GetLineWidth());
5897 crown.SetLineStyle(fH->GetLineStyle());
5898 crown.Paint();
5899 }
5900 }
5901 }
5902
5904
5905 fH->SetFillStyle(fillsav);
5906 fH->SetFillColor(colsav);
5907 fH->TAttFill::Modify();
5908
5909}
5910
5911////////////////////////////////////////////////////////////////////////////////
5912/// [Control function to draw a 2D histogram as a contour plot.](\ref HP16)
5913
5915{
5916
5917 Int_t i, j, count, ncontour, icol, n, lj, m, ix, jx, ljfill;
5918 Int_t itars, mode, ir[4];
5919 Double_t xsave, ysave, thesave,phisave,x[4], y[4], zc[4];
5920
5921 if (Hoption.Contour == 14) {
5922 Hoption.Surf = 12;
5923 Hoption.Axis = 1;
5924 thesave = gPad->GetTheta();
5925 phisave = gPad->GetPhi();
5926 gPad->SetPhi(0.);
5927 gPad->SetTheta(90.);
5929 gPad->SetPhi(phisave);
5930 gPad->SetTheta(thesave);
5931 TView *view = gPad->GetView();
5932 if (view) view->SetBit(kCannotRotate); //tested in ExecuteEvent
5933 PaintAxis();
5934 return;
5935 }
5936
5937 if (Hoption.Same) {
5938 // If the contour is painted on a 3d plot, the contour lines are
5939 // paint in 3d too.
5940 TObject *obj;
5941 TIter next(gPad->GetListOfPrimitives());
5942 while ((obj=next())) {
5943 if (strstr(obj->GetDrawOption(),"surf") ||
5944 strstr(obj->GetDrawOption(),"lego") ||
5945 strstr(obj->GetDrawOption(),"tri")) {
5946 Hoption.Surf = 16;
5948 return;
5949 }
5950 }
5951 }
5952
5953 if (Hoption.Contour == 15) {
5954 TGraphDelaunay2D *dt = nullptr;
5955 TGraphDelaunay *dtOld = nullptr;
5956 TList *hl = fH->GetListOfFunctions();
5957 dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
5958 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
5959 if (!dt && !dtOld) return;
5960 if (!fGraph2DPainter)
5961 fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
5962 fGraph2DPainter->Paint(option);
5963 return;
5964 }
5965
5966 gPad->SetBit(TGraph::kClipFrame);
5967
5968 std::vector<Double_t> levels(2*kMAXCONTOUR);
5969 std::vector<Double_t> xarr(2*kMAXCONTOUR);
5970 std::vector<Double_t> yarr(2*kMAXCONTOUR);
5971 std::vector<Int_t> itarr(2*kMAXCONTOUR);
5972
5973 Int_t npmax = 0;
5974 for (i=0;i<2*kMAXCONTOUR;i++) itarr[i] = 0;
5975
5976 ncontour = fH->GetContour();
5977 if (ncontour == 0) {
5978 ncontour = gStyle->GetNumberContours();
5979 fH->SetContour(ncontour);
5980 }
5981 if (ncontour > kMAXCONTOUR) {
5982 Warning("PaintContour", "maximum number of contours is %d, asked for %d",
5983 kMAXCONTOUR, ncontour);
5984 ncontour = kMAXCONTOUR-1;
5985 }
5986 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ncontour);
5987
5988 for (i=0;i<ncontour;i++) levels[i] = fH->GetContourLevelPad(i);
5989 Int_t linesav = fH->GetLineStyle();
5990 Int_t colorsav = fH->GetLineColor();
5991 Int_t fillsav = fH->GetFillColor();
5992 if (Hoption.Contour == 13) {
5993 fH->TAttLine::Modify();
5994 }
5995
5996 std::vector<std::unique_ptr<TPolyLine>> polys;
5997 TObjArray *contours = nullptr;
5998 TList *list = nullptr;
5999 TGraph *graph = nullptr;
6000 std::vector<Int_t> np;
6001 if (Hoption.Contour == 1) {
6002 np.resize(ncontour);
6003 for (i=0;i<ncontour;i++)
6004 np[i] = 0;
6005 for (i=0;i<ncontour;i++)
6006 polys.emplace_back(std::make_unique<TPolyLine>(100));
6007 if (Hoption.List == 1) {
6008 contours = (TObjArray*)gROOT->GetListOfSpecials()->FindObject("contours");
6009 if (contours) {
6010 gROOT->GetListOfSpecials()->Remove(contours);
6011 count = contours->GetSize();
6012 for (i=0;i<count;i++) {
6013 list = (TList*)contours->At(i);
6014 if (list) list->Delete();
6015 }
6016 contours->Delete();
6017 delete contours;
6018 }
6019 contours = new TObjArray(ncontour);
6020 contours->SetName("contours");
6021 gROOT->GetListOfSpecials()->Add(contours);
6022 for (i=0;i<ncontour;i++) {
6023 list = new TList();
6024 contours->Add(list);
6025 }
6026 }
6027 }
6028 Int_t theColor;
6029 Int_t ncolors = gStyle->GetNumberOfColors();
6030 Int_t ndivz = TMath::Abs(ncontour);
6031
6032 Int_t k,ipoly;
6033 for (j=Hparam.yfirst; j<Hparam.ylast; j++) {
6034 y[0] = fYaxis->GetBinCenter(j);
6035 y[1] = y[0];
6036 y[2] = fYaxis->GetBinCenter(j+1);
6037 y[3] = y[2];
6038 for (i=Hparam.xfirst; i<Hparam.xlast; i++) {
6039 zc[0] = fH->GetBinContent(i, j);
6040 zc[1] = fH->GetBinContent(i+1, j);
6041 zc[2] = fH->GetBinContent(i+1, j+1);
6042 zc[3] = fH->GetBinContent(i, j+1);
6043 if (!IsInside(fXaxis->GetBinCenter(i),fYaxis->GetBinCenter(j))) continue;
6044 if (Hoption.Logz) {
6045 if (zc[0] > 0) zc[0] = TMath::Log10(zc[0]);
6046 else zc[0] = Hparam.zmin;
6047 if (zc[1] > 0) zc[1] = TMath::Log10(zc[1]);
6048 else zc[1] = Hparam.zmin;
6049 if (zc[2] > 0) zc[2] = TMath::Log10(zc[2]);
6050 else zc[2] = Hparam.zmin;
6051 if (zc[3] > 0) zc[3] = TMath::Log10(zc[3]);
6052 else zc[3] = Hparam.zmin;
6053 }
6054 for (k=0;k<4;k++) {
6055 ir[k] = TMath::BinarySearch(ncontour, levels.data(), zc[k]);
6056 }
6057 if (ir[0] != ir[1] || ir[1] != ir[2] || ir[2] != ir[3] || ir[3] != ir[0]) {
6058 x[0] = fXaxis->GetBinCenter(i);
6059 x[3] = x[0];
6060 x[1] = fXaxis->GetBinCenter(i+1);
6061 x[2] = x[1];
6062 if (zc[0] <= zc[1]) n = 0; else n = 1;
6063 if (zc[2] <= zc[3]) m = 2; else m = 3;
6064 if (zc[n] > zc[m]) n = m;
6065 n++;
6066 lj=1;
6067 for (ix=1;ix<=4;ix++) {
6068 m = n%4 + 1;
6069 ljfill = PaintContourLine(zc[n-1],ir[n-1],x[n-1],y[n-1],zc[m-1],
6070 ir[m-1],x[m-1],y[m-1], xarr.data()+lj-1,yarr.data()+lj-1,itarr.data()+lj-1, levels.data());
6071 lj += 2*ljfill;
6072 n = m;
6073 }
6074
6075 if (zc[0] <= zc[1]) n = 0; else n = 1;
6076 if (zc[2] <= zc[3]) m = 2; else m = 3;
6077 if (zc[n] > zc[m]) n = m;
6078 n++;
6079 lj=2;
6080 for (ix=1;ix<=4;ix++) {
6081 if (n == 1) m = 4;
6082 else m = n-1;
6083 ljfill = PaintContourLine(zc[n-1],ir[n-1],x[n-1],y[n-1],zc[m-1],
6084 ir[m-1],x[m-1],y[m-1],xarr.data()+lj-1,yarr.data()+lj-1,itarr.data()+lj-1, levels.data());
6085 lj += 2*ljfill;
6086 n = m;
6087 }
6088
6089 // Re-order endpoints
6090
6091 count = 0;
6092 for (ix=1; ix<=lj-5; ix +=2) {
6093 //count = 0;
6094 while (itarr[ix-1] != itarr[ix]) {
6095 xsave = xarr[ix];
6096 ysave = yarr[ix];
6097 itars = itarr[ix];
6098 for (jx=ix; jx<=lj-5; jx +=2) {
6099 xarr[jx] = xarr[jx+2];
6100 yarr[jx] = yarr[jx+2];
6101 itarr[jx] = itarr[jx+2];
6102 }
6103 xarr[lj-3] = xsave;
6104 yarr[lj-3] = ysave;
6105 itarr[lj-3] = itars;
6106 if (count > 100) break;
6107 count++;
6108 }
6109 }
6110
6111 if (count > 100) continue;
6112 for (ix=1; ix<=lj-2; ix +=2) {
6113 theColor = Int_t((itarr[ix-1]+0.99)*Float_t(ncolors)/Float_t(ndivz));
6114 icol = gStyle->GetColorPalette(theColor);
6115 if (Hoption.Contour == 11) {
6116 fH->SetLineColor(icol);
6117 }
6118 if (Hoption.Contour == 12) {
6119 mode = icol%5;
6120 if (mode == 0) mode = 5;
6122 }
6123 if (Hoption.Contour != 1) {
6124 fH->TAttLine::Modify();
6125 gPad->PaintPolyLine(2,xarr.data()+ix-1,yarr.data()+ix-1);
6126 continue;
6127 }
6128
6129 ipoly = itarr[ix-1];
6130 if (ipoly >=0 && ipoly <ncontour) {
6131 polys[ipoly]->SetPoint(np[ipoly] ,xarr[ix-1],yarr[ix-1]);
6132 polys[ipoly]->SetPoint(np[ipoly]+1,xarr[ix], yarr[ix]);
6133 np[ipoly] += 2;
6134 if (npmax < np[ipoly]) npmax = np[ipoly];
6135 }
6136 }
6137 } // end of if (ir[0]
6138 } //end of for (i
6139 } //end of for (j
6140
6142 std::vector<Double_t> xp, yp;
6143 Int_t nadd,iminus,iplus;
6144 Int_t istart;
6145 Int_t first = ncontour;
6146 std::vector<Int_t> polysort;
6147 Int_t contListNb;
6148 if (Hoption.Contour != 1) goto theEND;
6149
6150 //The 2 points line generated above are now sorted/merged to generate
6151 //a list of consecutive points.
6152 // If the option "List" has been specified, the list of points is saved
6153 // in the form of TGraph objects in the ROOT list of special objects.
6154 xmin = gPad->GetUxmin();
6155 ymin = gPad->GetUymin();
6156 xp.resize(2*npmax);
6157 yp.resize(2*npmax);
6158 polysort.resize(ncontour);
6159 //find first positive contour
6160 for (ipoly=0;ipoly<ncontour;ipoly++) {
6161 if (levels[ipoly] >= 0) {first = ipoly; break;}
6162 }
6163 //store negative contours from 0 to minimum, then all positive contours
6164 k = 0;
6165 for (ipoly=first-1;ipoly>=0;ipoly--) {polysort[k] = ipoly; k++;}
6166 for (ipoly=first;ipoly<ncontour;ipoly++) {polysort[k] = ipoly; k++;}
6167 // we can now draw sorted contours
6168 contListNb = 0;
6169 fH->SetFillStyle(1001);
6170 for (k=0;k<ncontour;k++) {
6171 ipoly = polysort[k];
6172 if (np[ipoly] == 0) continue;
6173 if (Hoption.List) list = (TList*)contours->At(contListNb);
6174 contListNb++;
6175 Double_t *xx = polys[ipoly]->GetX();
6176 Double_t *yy = polys[ipoly]->GetY();
6177 istart = 0;
6178 while (true) {
6179 iminus = npmax;
6180 iplus = iminus+1;
6181 xp[iminus]= xx[istart]; yp[iminus] = yy[istart];
6182 xp[iplus] = xx[istart+1]; yp[iplus] = yy[istart+1];
6183 xx[istart] = xmin; yy[istart] = ymin;
6184 xx[istart+1] = xmin; yy[istart+1] = ymin;
6185 while (true) {
6186 nadd = 0;
6187 for (i=2;i<np[ipoly];i+=2) {
6188 if ((iplus < 2*npmax-1) && (xx[i] == xp[iplus]) && (yy[i] == yp[iplus])) {
6189 iplus++;
6190 xp[iplus] = xx[i+1]; yp[iplus] = yy[i+1];
6191 xx[i] = xmin; yy[i] = ymin;
6192 xx[i+1] = xmin; yy[i+1] = ymin;
6193 nadd++;
6194 }
6195 if ((iminus > 0) && (xx[i+1] == xp[iminus]) && (yy[i+1] == yp[iminus])) {
6196 iminus--;
6197 xp[iminus] = xx[i]; yp[iminus] = yy[i];
6198 xx[i] = xmin; yy[i] = ymin;
6199 xx[i+1] = xmin; yy[i+1] = ymin;
6200 nadd++;
6201 }
6202 }
6203 if (nadd == 0) break;
6204 }
6205 theColor = Int_t((ipoly+0.99)*Float_t(ncolors)/Float_t(ndivz));
6206 icol = gStyle->GetColorPalette(theColor);
6207 if (ndivz > 1) fH->SetFillColor(icol);
6208 fH->TAttFill::Modify();
6209 gPad->PaintFillArea(iplus-iminus+1,xp.data()+iminus,yp.data()+iminus);
6210 if (Hoption.List) {
6211 graph = new TGraph(iplus-iminus+1,xp.data()+iminus,yp.data()+iminus);
6212 graph->SetFillColor(icol);
6213 graph->SetLineWidth(fH->GetLineWidth());
6214 list->Add(graph);
6215 }
6216 //check if more points are left
6217 istart = 0;
6218 for (i=2;i<np[ipoly];i+=2) {
6219 if (xx[i] != xmin && yy[i] != ymin) {
6220 istart = i;
6221 break;
6222 }
6223 }
6224 if (istart == 0) break;
6225 }
6226 }
6227
6228theEND:
6229 gPad->ResetBit(TGraph::kClipFrame);
6231 fH->SetLineStyle(linesav);
6232 fH->SetLineColor(colorsav);
6233 fH->SetFillColor(fillsav);
6234}
6235
6236////////////////////////////////////////////////////////////////////////////////
6237/// Fill the matrix `xarr` and `yarr` for Contour Plot.
6238
6240 Double_t elev2, Int_t icont2, Double_t x2, Double_t y2,
6241 Double_t *xarr, Double_t *yarr, Int_t *itarr, Double_t *levels)
6242{
6243
6244 Bool_t vert;
6245 Double_t tlen, tdif, elev, diff, pdif, xlen;
6246 Int_t n, i, icount;
6247
6248 if (x1 == x2) {
6249 vert = kTRUE;
6250 tlen = y2 - y1;
6251 } else {
6252 vert = kFALSE;
6253 tlen = x2 - x1;
6254 }
6255
6256 n = icont1 +1;
6257 tdif = elev2 - elev1;
6258 i = 0;
6259 icount = 0;
6260 while (n <= icont2 && i <= kMAXCONTOUR/2 -3) {
6261 //elev = fH->GetContourLevel(n);
6262 elev = levels[n];
6263 diff = elev - elev1;
6264 pdif = diff/tdif;
6265 xlen = tlen*pdif;
6266 if (vert) {
6267 if (Hoption.Logx)
6268 xarr[i] = TMath::Log10(x1);
6269 else
6270 xarr[i] = x1;
6271 if (Hoption.Logy)
6272 yarr[i] = TMath::Log10(y1 + xlen);
6273 else
6274 yarr[i] = y1 + xlen;
6275 } else {
6276 if (Hoption.Logx)
6277 xarr[i] = TMath::Log10(x1 + xlen);
6278 else
6279 xarr[i] = x1 + xlen;
6280 if (Hoption.Logy)
6281 yarr[i] = TMath::Log10(y1);
6282 else
6283 yarr[i] = y1;
6284 }
6285 itarr[i] = n;
6286 icount++;
6287 i +=2;
6288 n++;
6289 }
6290 return icount;
6291}
6292
6293////////////////////////////////////////////////////////////////////////////////
6294/// [Draw 1D histograms error bars.](\ref HP09)
6295
6297{
6298
6299 // On iOS, we do not highlight histogram, if it's not picked at the moment
6300 // (but part of histogram (axis or pavestat) was picked, that's why this code
6301 // is called at all. This conditional statement never executes on non-iOS platform.
6302 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH) return;
6303
6304 const Int_t kBASEMARKER=8;
6305 Double_t xp, yp, ex1, ex2, ey1, ey2;
6306 Double_t delta;
6307 Double_t s2x, s2y, bxsize, bysize, symbolsize, xerror, sbasex, sbasey;
6308 Double_t xi1, xi2, xi3, xi4, yi1, yi2, yi3, yi4;
6310 Double_t logxmin = 0;
6311 Double_t logymin = 0;
6312 Double_t offset = 0.;
6313 Double_t width = 0.;
6314 Int_t i, k, npoints, first, last, fixbin;
6315 Int_t if1 = 0;
6316 Int_t if2 = 0;
6317 Int_t drawmarker, errormarker;
6318 Int_t option0, option1, option2, option3, option4, optionE, optionEX0, optionI0;
6319 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};
6320 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};
6321
6322 std::vector<Double_t> xline, yline;
6323 option0 = option1 = option2 = option3 = option4 = optionE = optionEX0 = optionI0 = 0;
6324 if (Hoption.Error >= 40) {Hoption.Error -=40; option0 = 1;}
6325 if (Int_t(Hoption.Error/10) == 2) {optionEX0 = 1; Hoption.Error -= 10;}
6326 if (Hoption.Error == 31) {optionEX0 = 1; Hoption.Error = 1;}
6327 if (Hoption.Error == 11) option1 = 1;
6328 if (Hoption.Error == 12) option2 = 1;
6329 if (Hoption.Error == 13) option3 = 1;
6330 if (Hoption.Error == 14) {option4 = 1; option3 = 1;}
6331 if (Hoption.Error == 15) {optionI0 = 1; option3 = 1;}
6332 if (Hoption.Error == 16) {optionI0 = 1; option4 = 1; option3 = 1;}
6333 if (option2+option3 == 0) optionE = 1;
6334 if (Hoption.Error == 0) optionE = 0;
6335 if (fXaxis->GetXbins()->fN) fixbin = 0;
6336 else fixbin = 1;
6337
6338 offset = fH->GetBarOffset();
6339 width = fH->GetBarWidth();
6340
6342 if (optionEX0) {
6343 xerror = 0;
6344 } else {
6345 xerror = gStyle->GetErrorX();
6346 }
6347 symbolsize = fH->GetMarkerSize();
6348 if (errormarker == 1) symbolsize = 0.01;
6349 sbasex = sbasey = symbolsize*kBASEMARKER;
6350 if (errormarker >= 20 && errormarker <= 49) {
6351 sbasex *= cxx[errormarker-20];
6352 sbasey *= cyy[errormarker-20];
6353 }
6354 // set the graphics attributes
6355
6356 fH->TAttLine::Modify();
6357 fH->TAttFill::Modify();
6358 fH->TAttMarker::Modify();
6359
6360 // set the first and last bin
6361
6362 Double_t factor = Hparam.factor;
6363 first = Hparam.xfirst;
6364 last = Hparam.xlast;
6365 npoints = last - first +1;
6366 xmin = gPad->GetUxmin();
6367 xmax = gPad->GetUxmax();
6368 ymin = gPad->GetUymin();
6369 ymax = gPad->GetUymax();
6370
6371
6372 if (option3) {
6373 xline.resize(2*npoints);
6374 yline.resize(2*npoints);
6375 if ((npoints > 0) && (xline.empty() || yline.empty())) {
6376 Error("PaintErrors", "too many points, out of memory");
6377 return;
6378 }
6379 if1 = 1;
6380 if2 = 2*npoints;
6381 }
6382
6383 // compute the offset of the error bars due to the symbol size
6384 s2x = gPad->PixeltoX(Int_t(0.5*sbasex)) - gPad->PixeltoX(0);
6385 s2y =-gPad->PixeltoY(Int_t(0.5*sbasey)) + gPad->PixeltoY(0);
6386
6387 // compute size of the lines at the end of the error bars
6388 Int_t dxend = Int_t(gStyle->GetEndErrorSize());
6389 bxsize = gPad->PixeltoX(dxend) - gPad->PixeltoX(0);
6390 bysize =-gPad->PixeltoY(dxend) + gPad->PixeltoY(0);
6391
6392
6393 if (fixbin) {
6394 if (Hoption.Logx) xp = TMath::Power(10,Hparam.xmin) + 0.5*Hparam.xbinsize;
6395 else xp = Hparam.xmin + 0.5*Hparam.xbinsize;
6396 } else {
6397 delta = fH->GetBinWidth(first);
6398 xp = fH->GetBinLowEdge(first) + 0.5*delta;
6399 }
6400
6401 // if errormarker = 0 or symbolsize = 0. no symbol is drawn
6402 if (Hoption.Logx) logxmin = TMath::Power(10,Hparam.xmin);
6403 if (Hoption.Logy) logymin = TMath::Power(10,Hparam.ymin);
6404
6405 // ---------------------- Loop over the points---------------------
6406 for (k=first; k<=last; k++) {
6407
6408 // get the data
6409 // xp = X position of the current point
6410 // yp = Y position of the current point
6411 // ex1 = Low X error
6412 // ex2 = Up X error
6413 // ey1 = Low Y error
6414 // ey2 = Up Y error
6415 // (xi,yi) = Error bars coordinates
6416
6417 // apply offset on errors for bar histograms
6418 Double_t xminTmp = gPad->XtoPad(fXaxis->GetBinLowEdge(k));
6419 Double_t xmaxTmp = gPad->XtoPad(fXaxis->GetBinUpEdge(k));
6420 if (Hoption.Logx) {
6421 xminTmp = TMath::Power(10, xminTmp);
6422 xmaxTmp = TMath::Power(10, xmaxTmp);
6423 }
6424 Double_t w = (xmaxTmp-xminTmp)*width;
6425 xminTmp += offset*(xmaxTmp-xminTmp);
6426 xmaxTmp = xminTmp + w;
6427 xp = (xminTmp+xmaxTmp)/2.;
6428
6429 if (Hoption.Logx) {
6430 if (xp <= 0) goto L30;
6431 if (xp < logxmin) goto L30;
6432 if (xp > TMath::Power(10,xmax)) break;
6433 } else {
6434 if (xp < xmin) goto L30;
6435 if (xp > xmax) break;
6436 }
6437 yp = factor*fH->GetBinContent(k);
6438 if (optionI0 && yp==0) goto L30;
6439 if (fixbin) {
6440 ex1 = xerror*Hparam.xbinsize;
6441 } else {
6442 delta = fH->GetBinWidth(k);
6443 ex1 = xerror*delta;
6444 }
6445 if (fH->GetBinErrorOption() == TH1::kNormal) {
6446 ey1 = factor*fH->GetBinError(k);
6447 ey2 = ey1;
6448 } else {
6449 ey1 = factor*fH->GetBinErrorLow(k);
6450 ey2 = factor*fH->GetBinErrorUp(k);
6451 }
6452 ex2 = ex1;
6453
6454 xi4 = xp;
6455 xi3 = xp;
6456 xi2 = xp + ex2;
6457 xi1 = xp - ex1;
6458
6459 yi1 = yp;
6460 yi2 = yp;
6461 yi3 = yp - ey1;
6462 yi4 = yp + ey2;
6463
6464 // take the LOG if necessary
6465 if (Hoption.Logx) {
6466 xi1 = TMath::Log10(TMath::Max(xi1,logxmin));
6467 xi2 = TMath::Log10(TMath::Max(xi2,logxmin));
6468 xi3 = TMath::Log10(TMath::Max(xi3,logxmin));
6469 xi4 = TMath::Log10(TMath::Max(xi4,logxmin));
6470 }
6471 if (Hoption.Logy) {
6472 yi1 = TMath::Log10(TMath::Max(yi1,logymin));
6473 yi2 = TMath::Log10(TMath::Max(yi2,logymin));
6474 yi3 = TMath::Log10(TMath::Max(yi3,logymin));
6475 yi4 = TMath::Log10(TMath::Max(yi4,logymin));
6476 }
6477
6478 // test if error bars are not outside the limits
6479 // otherwise they are truncated
6480
6481 xi1 = TMath::Max(xi1,xmin);
6482 xi2 = TMath::Min(xi2,xmax);
6483 yi3 = TMath::Max(yi3,ymin);
6484 yi4 = TMath::Min(yi4,ymax);
6485
6486 // test if the marker is on the frame limits. If "Yes", the
6487 // marker will not be drawn and the error bars will be readjusted.
6488
6489 drawmarker = kTRUE;
6490 if (!option0 && !option3) {
6491 if (Hoption.Logy && yp < logymin) goto L30;
6492 if (yi1 < ymin || yi1 > ymax) goto L30;
6493 if (Hoption.Error != 0 && yp == 0 && ey1 <= 0) drawmarker = kFALSE;
6494 }
6495 if (!symbolsize || !errormarker) drawmarker = kFALSE;
6496
6497 // draw the error rectangles
6498 if (option2) {
6499 if (yi3 >= ymax) goto L30;
6500 if (yi4 <= ymin) goto L30;
6501 gPad->PaintBox(xi1,yi3,xi2,yi4);
6502 }
6503
6504 // keep points for fill area drawing
6505 if (option3) {
6506 xline[if1-1] = xi3;
6507 xline[if2-1] = xi3;
6508 yline[if1-1] = yi4;
6509 yline[if2-1] = yi3;
6510 if1++;
6511 if2--;
6512 }
6513
6514 // draw the error bars
6515 if (Hoption.Logy && yp < logymin) drawmarker = kFALSE;
6516 if (optionE && drawmarker) {
6517 if ((yi3 < yi1 - s2y) && (yi3 < ymax)) gPad->PaintLine(xi3,yi3,xi4,TMath::Min(yi1 - s2y,ymax));
6518 if ((yi1 + s2y < yi4) && (yi4 > ymin)) gPad->PaintLine(xi3,TMath::Max(yi1 + s2y, ymin),xi4,yi4);
6519 // don't duplicate the horizontal line
6520 if (Hoption.Hist != 2) {
6521 if (yi1<ymax && yi1>ymin) {
6522 if (xi1 < xi3 - s2x) gPad->PaintLine(xi1,yi1,xi3 - s2x,yi2);
6523 if (xi3 + s2x < xi2) gPad->PaintLine(xi3 + s2x,yi1,xi2,yi2);
6524 }
6525 }
6526 }
6527 if (optionE && !drawmarker && (ey1 != 0 || ey2 !=0)) {
6528 if ((yi3 < yi1) && (yi3 < ymax)) gPad->PaintLine(xi3,yi3,xi4,TMath::Min(yi1,ymax));
6529 if ((yi1 < yi4) && (yi4 > ymin)) gPad->PaintLine(xi3,TMath::Max(yi1,ymin),xi4,yi4);
6530 // don't duplicate the horizontal line
6531 if (Hoption.Hist != 2) {
6532 if (yi1<ymax && yi1>ymin) {
6533 if (xi1 < xi3) gPad->PaintLine(xi1,yi1,xi3,yi2);
6534 if (xi3 < xi2) gPad->PaintLine(xi3,yi1,xi2,yi2);
6535 }
6536 }
6537 }
6538
6539 // draw line at the end of the error bars
6540
6541 if (option1 && drawmarker) {
6542
6543 if (yi3 < yi1-s2y && yi3 < ymax && yi3 > ymin) gPad->PaintLine(xi3 - bxsize, yi3 , xi3 + bxsize, yi3);
6544 if (yi4 > yi1+s2y && yi4 < ymax && yi4 > ymin) gPad->PaintLine(xi3 - bxsize, yi4 , xi3 + bxsize, yi4);
6545 if (yi1 <= ymax && yi1 >= ymin) {
6546 if (xi1 < xi3-s2x) gPad->PaintLine(xi1 , yi1 - bysize, xi1 , yi1 + bysize);
6547 if (xi2 > xi3+s2x) gPad->PaintLine(xi2 , yi1 - bysize, xi2 , yi1 + bysize);
6548 }
6549 }
6550
6551 // draw the marker
6552
6553 if (drawmarker) gPad->PaintPolyMarker(1, &xi3, &yi1);
6554
6555L30:
6556 if (fixbin) xp += Hparam.xbinsize;
6557 else {
6558 if (k < last) {
6559 delta = fH->GetBinWidth(k+1);
6560 xp = fH->GetBinLowEdge(k+1) + 0.5*delta;
6561 }
6562 }
6563 } //end of for loop
6564
6565 // draw the filled area
6566
6567 if (option3) {
6568 TGraph graph;
6569 graph.SetLineStyle(fH->GetLineStyle());
6570 graph.SetLineColor(fH->GetLineColor());
6571 graph.SetLineWidth(fH->GetLineWidth());
6572 graph.SetFillStyle(fH->GetFillStyle());
6573 graph.SetFillColor(fH->GetFillColor());
6574 Int_t logx = gPad->GetLogx();
6575 Int_t logy = gPad->GetLogy();
6576 gPad->SetLogx(0);
6577 gPad->SetLogy(0);
6578
6579 // In some cases the number of points in the fill area is smaller than
6580 // 2*npoints. In such cases the array xline and yline must be arranged
6581 // before being plotted. The next loop does that.
6582 if (if2 > npoints) {
6583 for (i=1; i<if1; i++) {
6584 xline[if1-2+i] = xline[if2-1+i];
6585 yline[if1-2+i] = yline[if2-1+i];
6586 }
6587 npoints = if1-1;
6588 }
6589 if (option4) graph.PaintGraph(2*npoints,xline.data(),yline.data(),"FC");
6590 else graph.PaintGraph(2*npoints,xline.data(),yline.data(),"F");
6591 gPad->SetLogx(logx);
6592 gPad->SetLogy(logy);
6593 }
6594}
6595
6596////////////////////////////////////////////////////////////////////////////////
6597/// Draw 2D histograms errors.
6598
6600{
6601
6602 fH->TAttMarker::Modify();
6603 fH->TAttLine::Modify();
6604
6605 // Define the 3D view
6606 fXbuf[0] = Hparam.xmin;
6607 fYbuf[0] = Hparam.xmax;
6608 fXbuf[1] = Hparam.ymin;
6609 fYbuf[1] = Hparam.ymax;
6610 fXbuf[2] = Hparam.zmin;
6611 fYbuf[2] = Hparam.zmax*(1. + gStyle->GetHistTopMargin());
6612 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
6613 TView *view = gPad ? gPad->GetView() : nullptr;
6614 if (!view) {
6615 Error("Paint2DErrors", "no TView in current pad");
6616 return;
6617 }
6618 Double_t thedeg = 90 - gPad->GetTheta();
6619 Double_t phideg = -90 - gPad->GetPhi();
6620 Double_t psideg = view->GetPsi();
6621 Int_t irep;
6622 view->SetView(phideg, thedeg, psideg, irep);
6623
6624 // Set color/style for back box
6625 fLego->SetFillStyle(gPad->GetFrameFillStyle());
6626 fLego->SetFillColor(gPad->GetFrameFillColor());
6627 fLego->TAttFill::Modify();
6628 Int_t backcolor = gPad->GetFrameFillColor();
6629 if (Hoption.System != kCARTESIAN) backcolor = 0;
6630 view->PadRange(backcolor);
6631 fLego->SetFillStyle(fH->GetFillStyle());
6632 fLego->SetFillColor(fH->GetFillColor());
6633 fLego->TAttFill::Modify();
6634
6635 // Paint the Back Box if needed
6636 if (Hoption.BackBox && !Hoption.Same && !Hoption.Lego && !Hoption.Surf) {
6637 fLego->InitMoveScreen(-1.1,1.1);
6638 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
6640 fLego->BackBox(90);
6641 }
6642
6643 // Paint the Errors
6644 Double_t x, ex, x1, x2;
6645 Double_t y, ey, y1, y2;
6646 Double_t z, ez1, ez2, z1, z2;
6647 Double_t temp1[3],temp2[3];
6648 Double_t xyerror;
6649 if (Hoption.Error == 110) {
6650 xyerror = 0;
6651 } else {
6652 xyerror = gStyle->GetErrorX();
6653 }
6654
6655 Double_t xk, xstep, yk, ystep;
6656 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
6657 y = fYaxis->GetBinCenter(j);
6658 ey = fYaxis->GetBinWidth(j)*xyerror;
6659 y1 = y-ey;
6660 y2 = y+ey;
6661 if (Hoption.Logy) {
6662 if (y > 0) y = TMath::Log10(y);
6663 else continue;
6664 if (y1 > 0) y1 = TMath::Log10(y1);
6665 else y1 = Hparam.ymin;
6666 if (y2 > 0) y2 = TMath::Log10(y2);
6667 else y2 = Hparam.ymin;
6668 }
6669 yk = fYaxis->GetBinLowEdge(j);
6670 ystep = fYaxis->GetBinWidth(j);
6671 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
6672 xk = fXaxis->GetBinLowEdge(i);
6673 xstep = fXaxis->GetBinWidth(i);
6674 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
6675 Int_t bin = fH->GetBin(i,j);
6676 x = fXaxis->GetBinCenter(i);
6677 ex = fXaxis->GetBinWidth(i)*xyerror;
6678 x1 = x-ex;
6679 x2 = x+ex;
6680 if (Hoption.Logx) {
6681 if (x > 0) x = TMath::Log10(x);
6682 else continue;
6683 if (x1 > 0) x1 = TMath::Log10(x1);
6684 else x1 = Hparam.xmin;
6685 if (x2 > 0) x2 = TMath::Log10(x2);
6686 else x2 = Hparam.xmin;
6687 }
6688 z = fH->GetBinContent(bin);
6689 if (fH->GetBinErrorOption() == TH1::kNormal) {
6690 ez1 = fH->GetBinError(bin);
6691 ez2 = ez1;
6692 }
6693 else {
6694 ez1 = fH->GetBinErrorLow(bin);
6695 ez2 = fH->GetBinErrorUp(bin);
6696 }
6697 z1 = z - ez1;
6698 z2 = z + ez2;
6699 if (Hoption.Logz) {
6700 if (z > 0) z = TMath::Log10(z);
6701 else z = Hparam.zmin;
6702 if (z1 > 0) z1 = TMath::Log10(z1);
6703 else z1 = Hparam.zmin;
6704 if (z2 > 0) z2 = TMath::Log10(z2);
6705 else z2 = Hparam.zmin;
6706
6707 }
6708 if (z <= Hparam.zmin) continue;
6709 if (z > Hparam.zmax) z = Hparam.zmax;
6710
6711 temp1[0] = x1;
6712 temp1[1] = y;
6713 temp1[2] = z;
6714 temp2[0] = x2;
6715 temp2[1] = y;
6716 temp2[2] = z;
6717 gPad->PaintLine3D(temp1, temp2);
6718 temp1[0] = x;
6719 temp1[1] = y1;
6720 temp1[2] = z;
6721 temp2[0] = x;
6722 temp2[1] = y2;
6723 temp2[2] = z;
6724 gPad->PaintLine3D(temp1, temp2);
6725 temp1[0] = x;
6726 temp1[1] = y;
6727 temp1[2] = z1;
6728 temp2[0] = x;
6729 temp2[1] = y;
6730 temp2[2] = z2;
6731 gPad->PaintLine3D(temp1, temp2);
6732 temp1[0] = x;
6733 temp1[1] = y;
6734 temp1[2] = z;
6735 view->WCtoNDC(temp1, &temp2[0]);
6736 gPad->PaintPolyMarker(1, &temp2[0], &temp2[1]);
6737 }
6738 }
6739
6740 // Paint the Front Box if needed
6741 if (Hoption.FrontBox) {
6742 fLego->InitMoveScreen(-1.1,1.1);
6744 fLego->FrontBox(90);
6745 }
6746
6747 // Paint the Axis if needed
6748 if (!Hoption.Axis && !Hoption.Same && !Hoption.Lego && !Hoption.Surf) {
6749 TGaxis axis;
6750 PaintLegoAxis(&axis, 90);
6751 }
6752
6753 fLego.reset();
6754}
6755
6756////////////////////////////////////////////////////////////////////////////////
6757/// Calculate range and clear pad (canvas).
6758
6760{
6761
6762 if (Hoption.Same) return;
6763
6765
6766 if (Hoption.Lego || Hoption.Surf || Hoption.Tri ||
6767 Hoption.Contour == 14 || Hoption.Error >= 100) {
6768 TObject *frame = gPad->FindObject("TFrame");
6769 if (frame) gPad->Remove(frame);
6770 return;
6771 }
6772
6773 //The next statement is always executed on non-iOS platform,
6774 //on iOS depends on pad mode.
6775 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode())
6776 gPad->PaintPadFrame(Hparam.xmin,Hparam.ymin,Hparam.xmax,Hparam.ymax);
6777}
6778
6779////////////////////////////////////////////////////////////////////////////////
6780/// [Paint functions associated to an histogram.](\ref HP28")
6781
6783{
6784 auto lnk = fFunctions->FirstLink();
6785
6786 while (lnk) {
6787 auto obj = lnk->GetObject();
6788 TVirtualPad::TContext ctxt(true);
6789 if (obj->InheritsFrom(TF2::Class())) {
6790 if (!obj->TestBit(TF2::kNotDraw)) {
6791 if (Hoption.Lego || Hoption.Surf || Hoption.Error >= 100) {
6792 TF2 *f2 = (TF2*)obj;
6793 f2->SetMinimum(fH->GetMinimum());
6794 f2->SetMaximum(fH->GetMaximum());
6795 f2->SetRange(fH->GetXaxis()->GetXmin(), fH->GetYaxis()->GetXmin(), fH->GetXaxis()->GetXmax(), fH->GetYaxis()->GetXmax() );
6796 f2->Paint("surf same");
6797 } else {
6798 obj->Paint("cont3 same");
6799 }
6800 }
6801 } else if (obj->InheritsFrom(TF1::Class())) {
6802 if (!obj->TestBit(TF1::kNotDraw)) obj->Paint("lsame");
6803 } else {
6804 //Let's make this 'function' selectable on iOS device (for example, it can be TPaveStat).
6805 gPad->PushSelectableObject(obj);
6806
6807 //The next statement is ALWAYS executed on non-iOS platform, on iOS it depends on pad's mode
6808 //and picked object.
6809 if (!gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && obj == gPad->GetSelected()))
6810 obj->Paint(lnk->GetOption());
6811 }
6812 lnk = lnk->Next();
6813 }
6814}
6815
6816////////////////////////////////////////////////////////////////////////////////
6817/// [Control routine to draw 1D histograms](\ref HP01b)
6818
6820{
6821
6822 //On iOS: do not highlight hist, if part of it was selected.
6823 //Never executes on non-iOS platform.
6824 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
6825 return;
6826
6827 static char chopth[17];
6828
6829 Int_t htype, oldhtype;
6830 Int_t i, j, first, last, nbins, fixbin;
6831 Double_t c1, yb;
6832 yb = 0;
6833
6834 strlcpy(chopth, " ",17);
6835
6838 Double_t baroffset = fH->GetBarOffset();
6839 Double_t barwidth = fH->GetBarWidth();
6840 Double_t baroffsetsave = gStyle->GetBarOffset();
6841 Double_t barwidthsave = gStyle->GetBarWidth();
6842 gStyle->SetBarOffset(baroffset);
6843 gStyle->SetBarWidth(barwidth);
6844
6845 // Create "LIFE" structure to keep current histogram status
6846
6847 first = Hparam.xfirst;
6848 last = Hparam.xlast;
6849 nbins = last - first + 1;
6850
6851 std::vector<Double_t> keepx, keepy;
6852 if (fXaxis->GetXbins()->fN) fixbin = 0;
6853 else fixbin = 1;
6854 if (fixbin) keepx.resize(2);
6855 else keepx.resize(nbins+1);
6856 keepy.resize(nbins);
6857 Double_t logymin = 0;
6858 if (Hoption.Logy) logymin = TMath::Power(10,ymin);
6859
6860 // Loop on histogram bins
6861
6862 for (j=first; j<=last;j++) {
6864 if (TMath::Abs(ymax-ymin) > 0) {
6865 if (Hoption.Logy) yb = TMath::Log10(TMath::Max(c1,.1*logymin));
6866 else yb = c1;
6867 }
6868 if (!Hoption.Line) {
6869 yb = TMath::Max(yb, ymin);
6870 yb = TMath::Min(yb, ymax);
6871 }
6872 keepy[j-first] = yb;
6873 }
6874
6875 // Draw histogram according to value of FillStyle and FillColor
6876
6877 if (fixbin) { keepx[0] = Hparam.xmin; keepx[1] = Hparam.xmax; }
6878 else {
6879 for (i=0; i<nbins; i++) keepx[i] = fXaxis->GetBinLowEdge(i+first);
6880 keepx[nbins] = fXaxis->GetBinUpEdge(nbins-1+first);
6881 }
6882
6883 // Prepare Fill area (systematic with option "Bar").
6884
6885 oldhtype = fH->GetFillStyle();
6886 htype = oldhtype;
6887 if (Hoption.Bar) {
6888 if (htype == 0 || htype == 1000) htype = 1001;
6889 }
6890
6891 Width_t lw = (Width_t)fH->GetLineWidth();
6892
6893 // Code option for GrapHist
6894
6895 if (Hoption.Line) chopth[0] = 'L';
6896 if (Hoption.Star) chopth[1] = '*';
6897 if (Hoption.Mark) chopth[2] = 'P';
6898 if (Hoption.Mark == 10) chopth[3] = '0';
6900 if (Hoption.Curve) chopth[3] = 'C';
6901 if (Hoption.Hist > 0) chopth[4] = 'H';
6902 else if (Hoption.Bar) chopth[5] = 'B';
6903 if (Hoption.Logy) chopth[6] = '1';
6904 if (fH->GetFillColor() && htype) {
6905 if (Hoption.Hist > 0 || Hoption.Curve || Hoption.Line) {
6906 chopth[7] = 'F';
6907 }
6908 }
6909 }
6910 if (!fixbin && strlen(chopth)) {
6911 chopth[8] = 'N';
6912 }
6913
6914 if (Hoption.Fill == 2) chopth[13] = '2';
6915
6916 // Option LOGX
6917
6918 if (Hoption.Logx) {
6919 chopth[9] = 'G';
6920 chopth[10] = 'X';
6921 if (fixbin) {
6922 keepx[0] = TMath::Power(10,keepx[0]);
6923 keepx[1] = TMath::Power(10,keepx[1]);
6924 }
6925 }
6926
6927 if (Hoption.Off) {
6928 chopth[11] = ']';
6929 chopth[12] = '[';
6930 }
6931
6932 // Draw the histogram
6933
6934 TGraph graph;
6935 graph.SetLineWidth(lw);
6936 graph.SetLineStyle(fH->GetLineStyle());
6937 graph.SetLineColor(fH->GetLineColor());
6938 graph.SetFillStyle(htype);
6939 graph.SetFillColor(fH->GetFillColor());
6940 graph.SetMarkerStyle(fH->GetMarkerStyle());
6941 graph.SetMarkerSize(fH->GetMarkerSize());
6942 graph.SetMarkerColor(fH->GetMarkerColor());
6943 if (!Hoption.Same) graph.ResetBit(TGraph::kClipFrame);
6944
6945 graph.PaintGrapHist(nbins, keepx.data(), keepy.data() ,chopth);
6946
6947 gStyle->SetBarOffset(baroffsetsave);
6948 gStyle->SetBarWidth(barwidthsave);
6949
6950 htype=oldhtype;
6951}
6952
6953////////////////////////////////////////////////////////////////////////////////
6954/// [Control function to draw a 3D histograms.](\ref HP01d)
6955
6957{
6958
6959 TString cmd;
6960 TString opt = option;
6961 opt.ToLower();
6962 Int_t irep;
6963 Float_t NEntries = fH->GetEntries();
6964
6965 if (fCurrentF3 || strstr(opt,"tf3")) {
6966 PaintTF3();
6967 return;
6968 }
6969
6970 if (NEntries > 0) {
6971 if (Hoption.Box || Hoption.Lego || Hoption.Color) {
6972 if (Hoption.Box == 11 || Hoption.Lego == 11) {
6973 PaintH3Box(1);
6974 } else if (Hoption.Box == 12 || Hoption.Lego == 12 || Hoption.Color == 1) {
6975 PaintH3Box(2);
6976 } else if (Hoption.Box == 13 || Hoption.Lego == 13) {
6977 PaintH3Box(3);
6978 } else {
6980 }
6981 return;
6982 }
6983
6984 if (strstr(opt,"iso")) {
6985 PaintH3Iso();
6986 return;
6987 }
6988 }
6989
6990 TView *view = gPad ? gPad->GetView() : nullptr;
6991 if (!view) return;
6992
6993 if (strstr(opt,"fb")) Hoption.FrontBox = 0;
6994 if (strstr(opt,"bb")) Hoption.BackBox = 0;
6995
6996 Double_t thedeg = 90 - gPad->GetTheta();
6997 Double_t phideg = -90 - gPad->GetPhi();
6998 Double_t psideg = view->GetPsi();
6999 view->SetView(phideg, thedeg, psideg, irep);
7000
7001 if(NEntries > 0) { // Paint as 3D scatter plot
7002 cmd.Form("TPolyMarker3D::PaintH3((TH1 *)0x%zx,\"%s\");",(size_t)fH,option);
7003 gROOT->ProcessLine(cmd.Data());
7004 } else {
7005 TAxis* xAxis = fH->GetXaxis();
7006 TAxis* yAxis = fH->GetYaxis();
7007 TAxis* zAxis = fH->GetZaxis();
7008 Double_t xmin = xAxis->GetXmin();
7009 Double_t xmax = xAxis->GetXmax();
7010 Double_t ymin = yAxis->GetXmin();
7011 Double_t ymax = yAxis->GetXmax();
7012 Double_t zmin = zAxis->GetXmin();
7013 Double_t zmax = zAxis->GetXmax();
7014 view->SetRange(xmin, ymin, zmin, xmax, ymax, zmax); // Set the axis limits (Xmin, Ymin, Zmin, Xmax, Ymax, Zmax)
7015 }
7016
7017 if (Hoption.Same) return;
7018
7019 // Draw axis
7020 view->SetOutlineToCube();
7021 TSeqCollection *ol = view->GetOutline();
7022 if (ol && Hoption.BackBox && Hoption.FrontBox) ol->Paint(option);
7024
7025 if (!Hoption.Axis && !Hoption.Same) {
7026 TGaxis axis;
7027 PaintLegoAxis(&axis, 90);
7028 }
7029
7030 // Draw palette. In case of 4D plot with TTree::Draw() the palette should
7031 // be painted with the option colz.
7032 if (fH->GetDrawOption() && strstr(opt,"colz")) {
7033 Int_t ndiv = fH->GetContour();
7034 if (ndiv == 0 ) {
7035 ndiv = gStyle->GetNumberContours();
7036 fH->SetContour(ndiv);
7037 }
7038 PaintPalette();
7039 }
7040
7041 // Draw title
7042 PaintTitle();
7043
7044 //Draw stats and fit results
7045 TF1 *fit = nullptr;
7046 TIter next(fFunctions);
7047 while (auto obj = next()) {
7048 if (obj->InheritsFrom(TF1::Class())) {
7049 fit = (TF1*)obj;
7050 break;
7051 }
7052 }
7053 if ((Hoption.Same%10) != 1) {
7054 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7056 }
7057 }
7058
7059}
7060
7061////////////////////////////////////////////////////////////////////////////////
7062/// Compute histogram parameters used by the drawing routines.
7063
7065{
7066
7067 if (fH->GetDimension() > 1 || Hoption.Lego || Hoption.Surf) return 1;
7068
7069 Int_t i;
7070 static const char *where = "PaintInit";
7071 Double_t yMARGIN = gStyle->GetHistTopMargin();
7072 Int_t maximum = 0;
7073 Int_t minimum = 0;
7074 if (fH->GetMaximumStored() != -1111) maximum = 1;
7075 if (fH->GetMinimumStored() != -1111) minimum = 1;
7076
7077 // Compute X axis parameters
7078
7079 Int_t last = fXaxis->GetLast();
7080 Int_t first = fXaxis->GetFirst();
7083 Hparam.xlast = last;
7084 Hparam.xfirst = first;
7087
7088 // if log scale in X, replace xmin,max by the log
7089 if (Hoption.Logx) {
7090 if (Hparam.xmax<=0) {
7091 Error(where, "cannot set X axis to log scale");
7092 return 0;
7093 }
7094 if (Hparam.xlowedge <=0 ) {
7095 if (Hoption.Same) {
7096 TH1* h1 = nullptr;
7097 TObject *obj;
7098 TIter next(gPad->GetListOfPrimitives());
7099 while ((obj = (TObject *)next())) {
7100 if (obj->InheritsFrom(TH1::Class())) { h1 = (TH1*)(obj) ; break; }
7101 if (obj->InheritsFrom(THStack::Class())) { h1 = ((THStack*)(obj))->GetHistogram() ; break; }
7102 if (obj->InheritsFrom(TGraph::Class())) { h1 = ((TGraph*)(obj))->GetHistogram() ; break; }
7103 if (obj->InheritsFrom(TMultiGraph::Class())) { h1 = ((TMultiGraph*)(obj))->GetHistogram(); break; }
7104 if (obj->InheritsFrom(TGraph2D::Class())) { h1 = ((TGraph2D*)(obj))->GetHistogram(); break; }
7105 if (obj->InheritsFrom(TF1::Class())) { h1 = ((TF1*)(obj))->GetHistogram(); break; }
7106 }
7107 if (h1) {
7109 } else {
7110 Error(where, "undefined user's coordinates. Cannot use option SAME");
7111 return 0;
7112 }
7113 } else {
7114 for (i=first; i<=last; i++) {
7115 Double_t binLow = fXaxis->GetBinLowEdge(i);
7116 if (binLow>0) {
7117 Hparam.xlowedge = binLow;
7118 break;
7119 }
7120 if (binLow == 0 && fH->GetBinContent(i) !=0) {
7121 Hparam.xlowedge = fXaxis->GetBinUpEdge(i)*0.001;
7122 break;
7123 }
7124 }
7125 if (Hparam.xlowedge<=0) {
7126 Error(where, "cannot set X axis to log scale");
7127 return 0;
7128 }
7129 }
7131 }
7136 if (Hparam.xlast > last) Hparam.xlast = last;
7137 if (Hparam.xfirst < first) Hparam.xfirst = first;
7138 }
7139
7140 // Compute Y axis parameters
7141 Double_t bigp = TMath::Power(10,32);
7142 Double_t ymax = -bigp;
7143 Double_t ymin = bigp;
7144 Double_t c1, e1;
7145 Double_t xv[1];
7146 Double_t fval;
7147 TObject *f;
7148 TF1 *f1;
7149 Double_t allchan = 0;
7150 Int_t nonNullErrors = 0;
7151 TIter next(fFunctions);
7152 for (i=first; i<=last;i++) {
7153 c1 = fH->GetBinContent(i);
7155 if (Hoption.Logy) {
7156 if (c1 > 0) ymin = TMath::Min(ymin,c1);
7157 } else {
7159 }
7160 if (Hoption.Error) {
7162 e1 = fH->GetBinError(i);
7163 else
7164 e1 = fH->GetBinErrorUp(i);
7165 if (e1 > 0) nonNullErrors++;
7166 ymax = TMath::Max(ymax,c1+e1);
7168 e1 = fH->GetBinErrorLow(i);
7169
7170 if (Hoption.Logy) {
7171 if (c1-e1>0.01*TMath::Abs(c1)) ymin = TMath::Min(ymin,c1-e1);
7172 } else {
7173 ymin = TMath::Min(ymin,c1-e1);
7174 }
7175 }
7176 if (Hoption.Func) {
7177 xv[0] = fXaxis->GetBinCenter(i);
7178 while ((f = (TObject*) next())) {
7179 if (f->IsA() == TF1::Class()) {
7180 f1 = (TF1*)f;
7181 if (xv[0] < f1->GetXmin() || xv[0] > f1->GetXmax()) continue;
7182 fval = f1->Eval(xv[0],0,0);
7183 if (f1->GetMaximumStored() != -1111) fval = TMath::Min(f1->GetMaximumStored(), fval);
7184 ymax = TMath::Max(ymax,fval);
7185 if (Hoption.Logy) {
7186 if (c1 > 0 && fval > 0.3*c1) ymin = TMath::Min(ymin,fval);
7187 }
7188 }
7189 }
7190 next.Reset();
7191 }
7192 allchan += c1;
7193 }
7194 if (!nonNullErrors) {
7195 if (Hoption.Error) {
7196 if (!Hoption.Mark && !Hoption.Line && !Hoption.Star && !Hoption.Curve) Hoption.Hist = 2;
7197 Hoption.Error=0;
7198 }
7199 }
7200
7201
7202 // Take into account maximum , minimum
7203
7204 if (Hoption.Logy && ymin <= 0) {
7205 if (ymax >= 1) ymin = TMath::Max(.005,ymax*1e-10);
7206 else ymin = 0.001*ymax;
7207 }
7208
7209 Double_t xm = ymin;
7210 if (maximum) ymax = fH->GetMaximumStored();
7211 if (minimum) xm = fH->GetMinimumStored();
7212 if (Hoption.Logy && xm < 0) {
7213 Error(where, "log scale requested with a negative argument (%f)", xm);
7214 return 0;
7215 } else if (Hoption.Logy && xm>=0 && ymax==0) { // empty histogram in log scale
7216 ymin = 0.01;
7217 ymax = 10.;
7218 } else {
7219 ymin = xm;
7220 }
7221
7222 if (ymin >= ymax) {
7223 if (Hoption.Logy) {
7224 if (ymax > 0) ymin = 0.001*ymax;
7225 else {
7226 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", ymax);
7227 return 0;
7228 }
7229 }
7230 else {
7231 if (ymin > 0) {
7232 ymin = 0;
7233 ymax *= 2;
7234 } else if (ymin < 0) {
7235 ymax = 0;
7236 ymin *= 2;
7237 } else {
7238 ymin = 0;
7239 ymax = 1;
7240 }
7241 }
7242 }
7243
7244 // In some cases, mainly because of precision issues, ymin and ymax could almost equal.
7245 if (TMath::AreEqualRel(ymin,ymax,1E-15)) {
7246 ymin = ymin*(1-1E-14);
7247 ymax = ymax*(1+1E-14);
7248 }
7249
7250 // take into account normalization factor
7251 Hparam.allchan = allchan;
7252 Double_t factor = allchan;
7253 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
7254 if (allchan) factor /= allchan;
7255 if (factor == 0) factor = 1;
7256 Hparam.factor = factor;
7257 ymax = factor*ymax;
7258 ymin = factor*ymin;
7259 //just in case the norm factor is negative
7260 // this may happen with a positive norm factor and a negative integral !
7261 if (ymax < ymin) {
7262 Double_t temp = ymax;
7263 ymax = ymin;
7264 ymin = temp;
7265 }
7266
7267 // For log scales, histogram coordinates are LOG10(ymin) and
7268 // LOG10(ymax). Final adjustment (if not option "Same"
7269 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
7270 // Maximum and Minimum are not defined.
7271 if (Hoption.Logy) {
7272 if (ymin <=0 || ymax <=0) {
7273 Error(where, "Cannot set Y axis to log scale");
7274 return 0;
7275 }
7277 if (!minimum) ymin += TMath::Log10(0.5);
7279 if (!maximum) ymax += TMath::Log10(2*(0.9/0.95));
7280 if (!Hoption.Same) {
7281 Hparam.ymin = ymin;
7282 Hparam.ymax = ymax;
7283 }
7284 return 1;
7285 }
7286
7287 // final adjustment of ymin for linear scale.
7288 // if minimum is not set , then ymin is set to zero if >0
7289 // or to ymin - margin if <0.
7290 if (!minimum) {
7291 if (Hoption.MinimumZero) {
7292 if (ymin >= 0) ymin = 0;
7293 else ymin -= yMARGIN*(ymax-ymin);
7294 } else {
7295 Double_t dymin = yMARGIN*(ymax-ymin);
7296 if (ymin >= 0 && (ymin-dymin <= 0)) ymin = 0;
7297 else ymin -= dymin;
7298 }
7299 }
7300
7301 // final adjustment of YMAXI for linear scale (if not option "Same"):
7302 // decrease histogram height to MAX% of allowed height if HMAXIM
7303 // has not been called.
7304 if (!maximum) {
7305 ymax += yMARGIN*(ymax-ymin);
7306 }
7307
7308 Hparam.ymin = ymin;
7309 Hparam.ymax = ymax;
7310 return 1;
7311}
7312
7313////////////////////////////////////////////////////////////////////////////////
7314/// Compute histogram parameters used by the drawing routines for a rotated pad.
7315
7317{
7318
7319 static const char *where = "PaintInitH";
7320 Double_t yMARGIN = gStyle->GetHistTopMargin();
7321 Int_t maximum = 0;
7322 Int_t minimum = 0;
7323 if (fH->GetMaximumStored() != -1111) maximum = 1;
7324 if (fH->GetMinimumStored() != -1111) minimum = 1;
7325
7326 // Compute X axis parameters
7327
7328 Int_t last = fXaxis->GetLast();
7329 Int_t first = fXaxis->GetFirst();
7332 Hparam.xlast = last;
7333 Hparam.xfirst = first;
7336
7337 // if log scale in Y, replace ymin,max by the log
7338 if (Hoption.Logy) {
7339 if (Hparam.xlowedge <=0 ) {
7342 }
7343 if (Hparam.ymin <=0 || Hparam.ymax <=0) {
7344 Error(where, "cannot set Y axis to log scale");
7345 return 0;
7346 }
7351 if (Hparam.xlast > last) Hparam.xlast = last;
7352 }
7353
7354 // Compute Y axis parameters
7355 Double_t bigp = TMath::Power(10,32);
7356 Double_t xmax = -bigp;
7357 Double_t xmin = bigp;
7358 Double_t c1, e1;
7359 Double_t xv[1];
7360 Double_t fval;
7361 Int_t i;
7362 TObject *f;
7363 TF1 *f1;
7364 Double_t allchan = 0;
7365 TIter next(fFunctions);
7366 for (i=first; i<=last;i++) {
7367 c1 = fH->GetBinContent(i);
7370 if (Hoption.Error) {
7371 e1 = fH->GetBinError(i);
7372 xmax = TMath::Max(xmax,c1+e1);
7373 xmin = TMath::Min(xmin,c1-e1);
7374 }
7375 if (Hoption.Func) {
7376 xv[0] = fXaxis->GetBinCenter(i);
7377 while ((f = (TObject*) next())) {
7378 if (f->IsA() == TF1::Class()) {
7379 f1 = (TF1*)f;
7380 if (xv[0] < f1->GetXmin() || xv[0] > f1->GetXmax()) continue;
7381 fval = f1->Eval(xv[0],0,0);
7382 xmax = TMath::Max(xmax,fval);
7383 if (Hoption.Logy) {
7384 if (fval > 0.3*c1) xmin = TMath::Min(xmin,fval);
7385 }
7386 }
7387 }
7388 next.Reset();
7389 }
7390 allchan += c1;
7391 }
7392
7393 // Take into account maximum , minimum
7394
7395 if (Hoption.Logx && xmin <= 0) {
7396 if (xmax >= 1) xmin = TMath::Max(.5,xmax*1e-10);
7397 else xmin = 0.001*xmax;
7398 }
7399 Double_t xm = xmin;
7400 if (maximum) xmax = fH->GetMaximumStored();
7401 if (minimum) xm = fH->GetMinimumStored();
7402 if (Hoption.Logx && xm <= 0) {
7403 Error(where, "log scale requested with zero or negative argument (%f)", xm);
7404 return 0;
7405 }
7406 else xmin = xm;
7407 if (xmin >= xmax) {
7408 if (Hoption.Logx) {
7409 if (xmax > 0) xmin = 0.001*xmax;
7410 else {
7411 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", xmax);
7412 return 0;
7413 }
7414 }
7415 else {
7416 if (xmin > 0) {
7417 xmin = 0;
7418 xmax *= 2;
7419 } else if (xmin < 0) {
7420 xmax = 0;
7421 xmin *= 2;
7422 } else {
7423 xmin = 0;
7424 xmax = 1;
7425 }
7426 }
7427 }
7428
7429 // take into account normalization factor
7430 Hparam.allchan = allchan;
7431 Double_t factor = allchan;
7432 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
7433 if (allchan) factor /= allchan;
7434 if (factor == 0) factor = 1;
7435 Hparam.factor = factor;
7436 xmax = factor*xmax;
7437 xmin = factor*xmin;
7438
7439 // For log scales, histogram coordinates are LOG10(ymin) and
7440 // LOG10(ymax). Final adjustment (if not option "Same"
7441 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
7442 // Maximum and Minimum are not defined.
7443 if (Hoption.Logx) {
7444 if (xmin <=0 || xmax <=0) {
7445 Error(where, "Cannot set Y axis to log scale");
7446 return 0;
7447 }
7449 if (!minimum) xmin += TMath::Log10(0.5);
7451 if (!maximum) xmax += TMath::Log10(2*(0.9/0.95));
7452 if (!Hoption.Same) {
7453 Hparam.xmin = xmin;
7454 Hparam.xmax = xmax;
7455 }
7456 return 1;
7457 }
7458
7459 // final adjustment of ymin for linear scale.
7460 // if minimum is not set , then ymin is set to zero if >0
7461 // or to ymin - margin if <0.
7462 if (!minimum) {
7463 if (xmin >= 0) xmin = 0;
7464 else xmin -= yMARGIN*(xmax-xmin);
7465 }
7466
7467 // final adjustment of YMAXI for linear scale (if not option "Same"):
7468 // decrease histogram height to MAX% of allowed height if HMAXIM
7469 // has not been called.
7470 if (!maximum) {
7471 xmax += yMARGIN*(xmax-xmin);
7472 }
7473 Hparam.xmin = xmin;
7474 Hparam.xmax = xmax;
7475 return 1;
7476}
7477
7478////////////////////////////////////////////////////////////////////////////////
7479/// [Control function to draw a 3D histogram with boxes.](\ref HP25)
7480
7482{
7483 // Predefined box structure
7484 Double_t wxyz[8][3] = { {-1,-1,-1}, {1,-1,-1}, {1,1,-1}, {-1,1,-1},
7485 {-1,-1, 1}, {1,-1, 1}, {1,1, 1}, {-1,1, 1} };
7486 Int_t iface[6][4] = { {0,3,2,1}, {4,5,6,7},
7487 {0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7} };
7488
7489 // Define dimensions of world space
7490 TAxis *xaxis = fH->GetXaxis();
7491 TAxis *yaxis = fH->GetYaxis();
7492 TAxis *zaxis = fH->GetZaxis();
7493
7494 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7495 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7496 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7497 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7498 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7499 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7500
7501 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7502
7503 // Set view
7504 TView *view = gPad ? gPad->GetView() : nullptr;
7505 if (!view) {
7506 Error("PaintH3", "no TView in current pad");
7507 return;
7508 }
7509 Double_t thedeg = 90 - gPad->GetTheta();
7510 Double_t phideg = -90 - gPad->GetPhi();
7511 Double_t psideg = view->GetPsi();
7512 Int_t irep;
7513 view->SetView(phideg, thedeg, psideg, irep);
7514
7515 Int_t backcolor = gPad->GetFrameFillColor();
7516 view->PadRange(backcolor);
7517
7518 // Draw back surfaces of frame box
7519 fLego->InitMoveScreen(-1.1,1.1);
7520 if (Hoption.BackBox) {
7521 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
7523 fLego->BackBox(90);
7524 }
7525
7527
7528 // Define order of drawing
7529 Double_t *tnorm = view->GetTnorm();
7530 if (!tnorm) return;
7531 Int_t incrx = (tnorm[ 8] < 0.) ? -1 : +1;
7532 Int_t incry = (tnorm[ 9] < 0.) ? -1 : +1;
7533 Int_t incrz = (tnorm[10] < 0.) ? -1 : +1;
7534 Int_t ix1 = (incrx == +1) ? xaxis->GetFirst() : xaxis->GetLast();
7535 Int_t iy1 = (incry == +1) ? yaxis->GetFirst() : yaxis->GetLast();
7536 Int_t iz1 = (incrz == +1) ? zaxis->GetFirst() : zaxis->GetLast();
7537 Int_t ix2 = (incrx == +1) ? xaxis->GetLast() : xaxis->GetFirst();
7538 Int_t iy2 = (incry == +1) ? yaxis->GetLast() : yaxis->GetFirst();
7539 Int_t iz2 = (incrz == +1) ? zaxis->GetLast() : zaxis->GetFirst();
7540
7541 // Set graphic attributes (colour, style, etc.)
7542 Style_t fillsav = fH->GetFillStyle();
7543 Style_t colsav = fH->GetFillColor();
7544 Style_t coldark = TColor::GetColorDark(colsav);
7545 Style_t colbright = TColor::GetColorBright(colsav);
7546
7547 fH->SetFillStyle(1001);
7548 fH->TAttFill::Modify();
7549 fH->TAttLine::Modify();
7550 Int_t ncolors = gStyle->GetNumberOfColors();
7551 Int_t theColor;
7552
7553 // Create bin boxes and draw
7557
7558 Double_t pmin[3], pmax[3], sxyz[8][3];
7559 for (Int_t ix = ix1; ix !=ix2+incrx; ix += incrx) {
7560 pmin[0] = xaxis->GetBinLowEdge(ix);
7561 pmax[0] = xaxis->GetBinUpEdge(ix);
7562 for (Int_t iy = iy1; iy != iy2+incry; iy += incry) {
7563 pmin[1] = yaxis->GetBinLowEdge(iy);
7564 pmax[1] = yaxis->GetBinUpEdge(iy);
7565 for (Int_t iz = iz1; iz != iz2+incrz; iz += incrz) {
7566 pmin[2] = zaxis->GetBinLowEdge(iz);
7567 pmax[2] = zaxis->GetBinUpEdge(iz);
7568 Double_t w = fH->GetBinContent(fH->GetBin(ix,iy,iz));
7569 Bool_t neg = kFALSE;
7570 Int_t n = 5;
7571 if (w<0) {
7572 w = -w;
7573 neg = kTRUE;
7574 }
7575 if (w < wmin) continue;
7576 if (w > wmax) w = wmax;
7577 Double_t scale = (TMath::Power((w-wmin)/(wmax-wmin),1./3.))/2.;
7578 if (scale == 0) continue;
7579 for (Int_t i=0; i<3; ++i) {
7580 Double_t c = (pmax[i] + pmin[i])*0.5;
7581 Double_t d = (pmax[i] - pmin[i])*scale;
7582 for (Int_t k=0; k<8; ++k) { // set bin box vertices
7583 sxyz[k][i] = wxyz[k][i]*d + c;
7584 }
7585 }
7586 for (Int_t k=0; k<8; ++k) { // transform to normalized space
7587 view->WCtoNDC(&sxyz[k][0],&sxyz[k][0]);
7588 }
7589 Double_t x[8], y[8]; // draw bin box faces
7590 for (Int_t k=0; k<6; ++k) {
7591 for (Int_t i=0; i<4; ++i) {
7592 Int_t iv = iface[k][i];
7593 x[i] = sxyz[iv][0];
7594 y[i] = sxyz[iv][1];
7595 }
7596 x[4] = x[0] ; y[4] = y[0];
7597 if (neg) {
7598 x[5] = x[2] ; y[5] = y[2];
7599 x[6] = x[3] ; y[6] = y[3];
7600 x[7] = x[1] ; y[7] = y[1];
7601 n = 8;
7602 } else {
7603 n = 5;
7604 }
7605 Double_t z = (x[2]-x[0])*(y[3]-y[1]) - (y[2]-y[0])*(x[3]-x[1]);
7606 if (z <= 0.) continue;
7607 if (iopt == 2) {
7608 theColor = ncolors*((w-wmin)/(wmax-wmin)) -1;
7610 } else {
7611 if (k == 3 || k == 5) {
7612 fH->SetFillColor(coldark);
7613 } else if (k == 0 || k == 1) {
7614 fH->SetFillColor(colbright);
7615 } else {
7616 fH->SetFillColor(colsav);
7617 }
7618 }
7619 fH->TAttFill::Modify();
7620 gPad->PaintFillArea(4, x, y);
7621 if (iopt != 3)gPad->PaintPolyLine(n, x, y);
7622 }
7623 }
7624 }
7625 }
7626
7627 // Draw front surfaces of frame box
7628 if (Hoption.FrontBox) fLego->FrontBox(90);
7629
7630 // Draw axis and title
7631 if (!Hoption.Axis && !Hoption.Same) {
7632 TGaxis axis;
7633 PaintLegoAxis(&axis, 90);
7634 }
7635 PaintTitle();
7636
7637 // Draw palette. if needed.
7638 if (Hoption.Zscale) {
7639 Int_t ndiv = fH->GetContour();
7640 if (ndiv == 0 ) {
7641 ndiv = gStyle->GetNumberContours();
7642 fH->SetContour(ndiv);
7643 }
7644 PaintPalette();
7645 }
7646
7647 //Draw stats and fit results
7648 TF1 *fit = nullptr;
7649 TIter next(fFunctions);
7650 while (auto obj = next()) {
7651 if (obj->InheritsFrom(TF1::Class())) {
7652 fit = (TF1*)obj;
7653 break;
7654 }
7655 }
7656 if ((Hoption.Same%10) != 1) {
7657 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7659 }
7660 }
7661
7662 fLego.reset();
7663
7664 fH->SetFillStyle(fillsav);
7665 fH->SetFillColor(colsav);
7666 fH->TAttFill::Modify();
7667}
7668
7669////////////////////////////////////////////////////////////////////////////////
7670/// [Control function to draw a 3D histogram with boxes.](\ref HP25)
7671
7673{
7674 // Predefined box structure
7675 Double_t wxyz[8][3] = {
7676 {-1,-1,-1}, {1,-1,-1}, {1,1,-1}, {-1,1,-1}, // bottom vertices
7677 {-1,-1, 1}, {1,-1, 1}, {1,1, 1}, {-1,1, 1} // top vertices
7678 };
7679 Int_t iface[6][4] = {
7680 {0,3,2,1}, {4,5,6,7}, // bottom and top faces
7681 {0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7} // side faces
7682 };
7683 Double_t normal[6][3] = {
7684 {0,0,-1}, {0,0,1}, // Z-, Z+
7685 {0,-1,0}, {1,0,0}, {0,1,0}, {-1,0,0} // Y-, X+, Y+, X-
7686 };
7687
7688 // Define dimensions of world space
7689 TAxis *xaxis = fH->GetXaxis();
7690 TAxis *yaxis = fH->GetYaxis();
7691 TAxis *zaxis = fH->GetZaxis();
7692
7693 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7694 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7695 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7696 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7697 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7698 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7699
7700 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7701
7702 // Set view
7703 TView *view = gPad ? gPad->GetView() : nullptr;
7704 if (!view) {
7705 Error("PaintH3", "no TView in current pad");
7706 return;
7707 }
7708 Double_t thedeg = 90 - gPad->GetTheta();
7709 Double_t phideg = -90 - gPad->GetPhi();
7710 Double_t psideg = view->GetPsi();
7711 Int_t irep;
7712 view->SetView(phideg, thedeg, psideg, irep);
7713
7714 Int_t backcolor = gPad->GetFrameFillColor();
7715 view->PadRange(backcolor);
7716
7717 // Draw front surfaces of frame box
7718 if (Hoption.FrontBox) {
7719 fLego->InitMoveScreen(-1.1,1.1);
7721 }
7722
7723 // Initialize hidden line removal algorithm "raster screen"
7724 fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
7725
7726 // Define order of drawing
7727 Double_t *tnorm = view->GetTnorm();
7728 if (!tnorm) return;
7729 Int_t incrx = (tnorm[ 8] < 0.) ? +1 : -1;
7730 Int_t incry = (tnorm[ 9] < 0.) ? +1 : -1;
7731 Int_t incrz = (tnorm[10] < 0.) ? +1 : -1;
7732 Int_t ix1 = (incrx == +1) ? xaxis->GetFirst() : xaxis->GetLast();
7733 Int_t iy1 = (incry == +1) ? yaxis->GetFirst() : yaxis->GetLast();
7734 Int_t iz1 = (incrz == +1) ? zaxis->GetFirst() : zaxis->GetLast();
7735 Int_t ix2 = (incrx == +1) ? xaxis->GetLast() : xaxis->GetFirst();
7736 Int_t iy2 = (incry == +1) ? yaxis->GetLast() : yaxis->GetFirst();
7737 Int_t iz2 = (incrz == +1) ? zaxis->GetLast() : zaxis->GetFirst();
7738
7739 // Set line attributes (colour, style, etc.)
7740 fH->TAttLine::Modify();
7741
7742 // Create bin boxes and draw
7743 const Int_t NTMAX = 100;
7744 Double_t tt[NTMAX][2];
7748 Double_t pmin[3], pmax[3], sxyz[8][3], pp[4][2];
7749 for (Int_t ix = ix1; ix !=ix2+incrx; ix += incrx) {
7750 pmin[0] = xaxis->GetBinLowEdge(ix);
7751 pmax[0] = xaxis->GetBinUpEdge(ix);
7752 for (Int_t iy = iy1; iy != iy2+incry; iy += incry) {
7753 pmin[1] = yaxis->GetBinLowEdge(iy);
7754 pmax[1] = yaxis->GetBinUpEdge(iy);
7755 for (Int_t iz = iz1; iz != iz2+incrz; iz += incrz) {
7756 pmin[2] = zaxis->GetBinLowEdge(iz);
7757 pmax[2] = zaxis->GetBinUpEdge(iz);
7758 Double_t w = fH->GetBinContent(fH->GetBin(ix,iy,iz));
7759 Bool_t neg = kFALSE;
7760 if (w<0) {
7761 w = -w;
7762 neg = kTRUE;
7763 }
7764 if (w < wmin) continue;
7765 if (w > wmax) w = wmax;
7766 Double_t scale = (TMath::Power((w-wmin)/(wmax-wmin),1./3.))/2.;
7767 if (scale == 0) continue;
7768 for (Int_t i=0; i<3; ++i) {
7769 Double_t c = (pmax[i] + pmin[i])*0.5;
7770 Double_t d = (pmax[i] - pmin[i])*scale;
7771 for (Int_t k=0; k<8; ++k) { // set bin box vertices
7772 sxyz[k][i] = wxyz[k][i]*d + c;
7773 }
7774 }
7775 for (Int_t k=0; k<8; ++k) { // transform to normalized space
7776 view->WCtoNDC(&sxyz[k][0],&sxyz[k][0]);
7777 }
7778 for (Int_t k=0; k<6; ++k) { // draw box faces
7779 Double_t zn;
7780 view->FindNormal(normal[k][0], normal[k][1], normal[k][2], zn);
7781 if (zn <= 0) continue;
7782 for (Int_t i=0; i<4; ++i) {
7783 Int_t ip = iface[k][i];
7784 pp[i][0] = sxyz[ip][0];
7785 pp[i][1] = sxyz[ip][1];
7786 }
7787 for (Int_t i=0; i<4; ++i) {
7788 Int_t i1 = i;
7789 Int_t i2 = (i == 3) ? 0 : i + 1;
7790 Int_t nt;
7791 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7792 Double_t xdel = pp[i2][0] - pp[i1][0];
7793 Double_t ydel = pp[i2][1] - pp[i1][1];
7794 Double_t x[2], y[2];
7795 for (Int_t it = 0; it < nt; ++it) {
7796 x[0] = pp[i1][0] + xdel*tt[it][0];
7797 y[0] = pp[i1][1] + ydel*tt[it][0];
7798 x[1] = pp[i1][0] + xdel*tt[it][1];
7799 y[1] = pp[i1][1] + ydel*tt[it][1];
7800 gPad->PaintPolyLine(2, x, y);
7801 }
7802 }
7803 if (neg) {
7804 Int_t i1 = 0;
7805 Int_t i2 = 2;
7806 Int_t nt;
7807 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7808 Double_t xdel = pp[i2][0] - pp[i1][0];
7809 Double_t ydel = pp[i2][1] - pp[i1][1];
7810 Double_t x[2], y[2];
7811 for (Int_t it = 0; it < nt; ++it) {
7812 x[0] = pp[i1][0] + xdel*tt[it][0];
7813 y[0] = pp[i1][1] + ydel*tt[it][0];
7814 x[1] = pp[i1][0] + xdel*tt[it][1];
7815 y[1] = pp[i1][1] + ydel*tt[it][1];
7816 gPad->PaintPolyLine(2, x, y);
7817 }
7818 i1 = 1;
7819 i2 = 3;
7820 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7821 xdel = pp[i2][0] - pp[i1][0];
7822 ydel = pp[i2][1] - pp[i1][1];
7823 for (Int_t it = 0; it < nt; ++it) {
7824 x[0] = pp[i1][0] + xdel*tt[it][0];
7825 y[0] = pp[i1][1] + ydel*tt[it][0];
7826 x[1] = pp[i1][0] + xdel*tt[it][1];
7827 y[1] = pp[i1][1] + ydel*tt[it][1];
7828 gPad->PaintPolyLine(2, x, y);
7829 }
7830 }
7831 fLego->FillPolygonBorder(4, &pp[0][0]); // update raster screen
7832 }
7833 }
7834 }
7835 }
7836
7837 // Draw frame box
7838 if (Hoption.BackBox) {
7839 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
7841 fLego->BackBox(90);
7842 }
7843
7844 if (Hoption.FrontBox) fLego->FrontBox(90);
7845
7846 // Draw axis and title
7847 if (!Hoption.Axis && !Hoption.Same) {
7848 TGaxis axis;
7849 PaintLegoAxis(&axis, 90);
7850 }
7851 PaintTitle();
7852
7853 //Draw stats and fit results
7854 TF1 *fit = nullptr;
7855 TIter next(fFunctions);
7856 while (auto obj = next()) {
7857 if (obj->InheritsFrom(TF1::Class())) {
7858 fit = (TF1*)obj;
7859 break;
7860 }
7861 }
7862 if ((Hoption.Same%10) != 1) {
7863 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7865 }
7866 }
7867
7868 fLego.reset();
7869}
7870
7871////////////////////////////////////////////////////////////////////////////////
7872/// [Control function to draw a 3D histogram with Iso Surfaces.](\ref HP25)
7873
7875{
7876
7877 const Double_t ydiff = 1;
7878 const Double_t yligh1 = 10;
7879 const Double_t qa = 0.15;
7880 const Double_t qd = 0.15;
7881 const Double_t qs = 0.8;
7882 Double_t fmin, fmax;
7883 Int_t i, irep;
7884 Int_t nbcol = 28;
7885 Int_t icol1 = 201;
7886 Int_t ic1 = icol1;
7887 Int_t ic2 = ic1+nbcol;
7888 Int_t ic3 = ic2+nbcol;
7889
7890 TAxis *xaxis = fH->GetXaxis();
7891 TAxis *yaxis = fH->GetYaxis();
7892 TAxis *zaxis = fH->GetZaxis();
7893
7894 Int_t nx = fH->GetNbinsX();
7895 Int_t ny = fH->GetNbinsY();
7896 Int_t nz = fH->GetNbinsZ();
7897
7898 std::vector<Double_t> x(nx);
7899 std::vector<Double_t> y(ny);
7900 std::vector<Double_t> z(nz);
7901
7902 for (i=0; i<nx; i++) x[i] = xaxis->GetBinCenter(i+1);
7903 for (i=0; i<ny; i++) y[i] = yaxis->GetBinCenter(i+1);
7904 for (i=0; i<nz; i++) z[i] = zaxis->GetBinCenter(i+1);
7905
7906 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7907 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7908 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7909 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7910 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7911 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7912
7913 Double_t s[3];
7914 s[0] = fH->GetSumOfWeights()/(fH->GetNbinsX()*fH->GetNbinsY()*fH->GetNbinsZ());
7915 s[1] = 0.5*s[0];
7916 s[2] = 1.5*s[0];
7917
7918 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7919
7920 TView *view = gPad ? gPad->GetView() : nullptr;
7921 if (!view) {
7922 Error("PaintH3Iso", "no TView in current pad");
7923 return;
7924 }
7925 Double_t thedeg = 90 - gPad->GetTheta();
7926 Double_t phideg = -90 - gPad->GetPhi();
7927 Double_t psideg = view->GetPsi();
7928 view->SetView(phideg, thedeg, psideg, irep);
7929
7930 Int_t backcolor = gPad->GetFrameFillColor();
7931 if (Hoption.System != kCARTESIAN) backcolor = 0;
7932 view->PadRange(backcolor);
7933
7934 Double_t dcol = 0.5/Double_t(nbcol);
7935 TColor *colref = gROOT->GetColor(fH->GetFillColor());
7936 if (!colref) {
7937 return;
7938 }
7939 Float_t r, g, b, hue, light, satur;
7940 colref->GetRGB(r,g,b);
7941 TColor::RGBtoHLS(r,g,b,hue,light,satur);
7942 TColor *acol;
7943 for (Int_t col=0;col<nbcol;col++) {
7944 acol = gROOT->GetColor(col+icol1);
7945 TColor::HLStoRGB(hue, .4+col*dcol, satur, r, g, b);
7946 if (acol) acol->SetRGB(r, g, b);
7947 }
7948
7949 fLego->InitMoveScreen(-1.1,1.1);
7950
7951 if (Hoption.BackBox) {
7952 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
7954 fLego->BackBox(90);
7955 }
7956
7957 fLego->LightSource(0, ydiff, 0, 0, 0, irep);
7958 fLego->LightSource(1, yligh1, 1, 1, 1, irep);
7959 fLego->SurfaceProperty(qa, qd, qs, 1, irep);
7960 fmin = ydiff*qa;
7961 fmax = ydiff*qa + (yligh1+0.1)*(qd+qs);
7962 fLego->SetIsoSurfaceParameters(fmin, fmax, nbcol, ic1, ic2, ic3);
7963
7964 fLego->IsoSurface(1, s, nx, ny, nz, x.data(), y.data(), z.data(), "BF");
7965
7966 if (Hoption.FrontBox) {
7967 fLego->InitMoveScreen(-1.1,1.1);
7969 fLego->FrontBox(90);
7970 }
7971 if (!Hoption.Axis && !Hoption.Same) {
7972 TGaxis axis;
7973 PaintLegoAxis(&axis, 90);
7974 }
7975
7976 PaintTitle();
7977
7978 //Draw stats and fit results
7979 TF1 *fit = nullptr;
7980 TIter next(fFunctions);
7981 while (auto obj = next()) {
7982 if (obj->InheritsFrom(TF1::Class())) {
7983 fit = (TF1*)obj;
7984 break;
7985 }
7986 }
7987 if ((Hoption.Same%10) != 1) {
7988 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7990 }
7991 }
7992
7993 fLego.reset();
7994}
7995
7996////////////////////////////////////////////////////////////////////////////////
7997/// [Control function to draw a 2D histogram as a lego plot.](\ref HP17)
7998
8000{
8001
8002 Int_t raster = 1;
8003 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
8004 Int_t nx = Hparam.xlast - Hparam.xfirst + 1;
8005 Int_t ny = Hparam.ylast - Hparam.yfirst + 1;
8006 Double_t zmin = Hparam.zmin;
8007 Double_t zmax = Hparam.zmax;
8008 Double_t xlab1 = Hparam.xmin;
8009 Double_t xlab2 = Hparam.xmax;
8010 Double_t ylab1 = Hparam.ymin;
8011 Double_t ylab2 = Hparam.ymax;
8012 Double_t dangle = 10*3.141592/180; //Delta angle for Rapidity option
8013 Double_t deltaz = TMath::Abs(zmin);
8014 if (deltaz == 0) deltaz = 1;
8015 if (zmin >= zmax) {
8016 zmin -= 0.5*deltaz;
8017 zmax += 0.5*deltaz;
8018 }
8019 Double_t z1c = zmin;
8020 Double_t z2c = zmin + (zmax-zmin)*(1+gStyle->GetHistTopMargin());
8021
8022 // Compute the lego limits and instantiate a lego object
8023 fXbuf[0] = -1;
8024 fYbuf[0] = 1;
8025 fXbuf[1] = -1;
8026 fYbuf[1] = 1;
8027 if (Hoption.System == kPOLAR) {
8028 fXbuf[2] = z1c;
8029 fYbuf[2] = z2c;
8030 } else if (Hoption.System == kCYLINDRICAL) {
8031 if (Hoption.Logy) {
8032 if (ylab1 > 0) fXbuf[2] = TMath::Log10(ylab1);
8033 else fXbuf[2] = 0;
8034 if (ylab2 > 0) fYbuf[2] = TMath::Log10(ylab2);
8035 else fYbuf[2] = 0;
8036 } else {
8037 fXbuf[2] = ylab1;
8038 fYbuf[2] = ylab2;
8039 }
8040 z1c = 0; z2c = 1;
8041 } else if (Hoption.System == kSPHERICAL) {
8042 fXbuf[2] = -1;
8043 fYbuf[2] = 1;
8044 z1c = 0; z2c = 1;
8045 } else if (Hoption.System == kRAPIDITY) {
8046 fXbuf[2] = -1/TMath::Tan(dangle);
8047 fYbuf[2] = 1/TMath::Tan(dangle);
8048 } else {
8049 fXbuf[0] = xlab1;
8050 fYbuf[0] = xlab2;
8051 fXbuf[1] = ylab1;
8052 fYbuf[1] = ylab2;
8053 fXbuf[2] = z1c;
8054 fYbuf[2] = z2c;
8055 raster = 0;
8056 }
8057
8058 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data(), Hoption.System);
8059
8060 Int_t nids = -1;
8061 TH1 * hid = nullptr;
8062 Color_t colormain = -1, colordark = -1;
8063 Bool_t drawShadowsInLego1 = kTRUE;
8064
8065 // LEGO3 is like LEGO1 except that the black lines around each lego are not drawn.
8066 if (Hoption.Lego == 13) {
8067 Hoption.Lego = 11;
8068 fLego->SetMesh(0);
8069 }
8070 // LEGO4 is like LEGO1 except no shadows are drawn.
8071 if (Hoption.Lego == 14) {
8072 Hoption.Lego = 11;
8073 drawShadowsInLego1 = kFALSE;
8074 }
8075
8076 // Initialize the levels on the Z axis
8077 Int_t ndiv = fH->GetContour();
8078 if (ndiv == 0 ) {
8079 ndiv = gStyle->GetNumberContours();
8080 fH->SetContour(ndiv);
8081 }
8082 Int_t ndivz = TMath::Abs(ndiv);
8083 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
8084
8085 // Initialize colors
8086 if (!fStack) {
8087 fLego->SetEdgeAtt(fH->GetLineColor(),fH->GetLineStyle(),fH->GetLineWidth(),0);
8088 } else {
8089 for (Int_t id=0;id<=fStack->GetSize();id++) {
8090 hid = (TH1*)fStack->At((id==0)?id:id-1);
8091 fLego->SetEdgeAtt(hid->GetLineColor(),hid->GetLineStyle(),hid->GetLineWidth(),id);
8092 }
8093 }
8094
8095 if (Hoption.Lego == 11) {
8096 nids = 1;
8097 if (fStack) nids = fStack->GetSize();
8098 hid = fH;
8099 for (Int_t id=0;id<=nids;id++) {
8100 if (id > 0 && fStack) hid = (TH1*)fStack->At(id-1);
8101 colormain = hid->GetFillColor();
8102 if (colormain == 1) colormain = 17; //avoid drawing with black
8103 if (drawShadowsInLego1) colordark = TColor::GetColorDark(colormain);
8104 else colordark = colormain;
8105 fLego->SetColorMain(colormain,id);
8106 fLego->SetColorDark(colordark,id);
8107 if (id <= 1) fLego->SetColorMain(colormain,-1); // Set Bottom color
8108 if (id == nids) fLego->SetColorMain(colormain,99); // Set Top color
8109 }
8110 }
8111
8112 // Now ready to draw the lego plot
8113 Int_t irep = 0;
8114
8115 TView *view = gPad ? gPad->GetView() : nullptr;
8116 if (!view) {
8117 Error("PaintLego", "no TView in current pad");
8118 return;
8119 }
8120
8121 Double_t thedeg = 90 - gPad->GetTheta();
8122 Double_t phideg = -90 - gPad->GetPhi();
8123 Double_t psideg = view->GetPsi();
8124 view->SetView(phideg, thedeg, psideg, irep);
8125
8126 fLego->SetLineColor(kBlack); // zgrid color for lego1 & lego2
8127 fLego->SetFillStyle(fH->GetFillStyle());
8128
8129 // Set color/style for back box
8130 fLego->SetFillStyle(gPad->GetFrameFillStyle());
8131 fLego->SetFillColor(gPad->GetFrameFillColor());
8132 fLego->TAttFill::Modify();
8133
8134 Int_t backcolor = gPad->GetFrameFillColor();
8135 if (Hoption.System != kCARTESIAN) backcolor = 0;
8136 view->PadRange(backcolor);
8137
8138 fLego->SetFillStyle(fH->GetFillStyle());
8139 fLego->SetFillColor(fH->GetFillColor());
8140 fLego->TAttFill::Modify();
8141
8142 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
8143
8144 if (raster) fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
8145 else fLego->InitMoveScreen(-1.1,1.1);
8146
8147 if (Hoption.Lego == 19) {
8149 if (Hoption.BackBox) fLego->BackBox(90);
8150 if (Hoption.FrontBox) fLego->FrontBox(90);
8151 if (!Hoption.Axis) { TGaxis axis; PaintLegoAxis(&axis, 90); }
8152 return;
8153 }
8154
8155 if (Hoption.Lego == 11 || Hoption.Lego == 12) {
8158 fLego->BackBox(90);
8159 }
8160 }
8161
8162 if (Hoption.Lego == 12) DefineColorLevels(ndivz);
8163
8164 fLego->SetLegoFunction(&TPainter3dAlgorithms::LegoFunction);
8166 if (Hoption.Lego == 11) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode3);
8167 if (Hoption.Lego == 12) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode2);
8168 if (Hoption.System == kPOLAR) {
8169 if (Hoption.Lego == 1) fLego->LegoPolar(1,nx,ny,"FB");
8170 if (Hoption.Lego == 11) fLego->LegoPolar(1,nx,ny,"BF");
8171 if (Hoption.Lego == 12) fLego->LegoPolar(1,nx,ny,"BF");
8172 } else if (Hoption.System == kCYLINDRICAL) {
8173 if (Hoption.Lego == 1) fLego->LegoCylindrical(1,nx,ny,"FB");
8174 if (Hoption.Lego == 11) fLego->LegoCylindrical(1,nx,ny,"BF");
8175 if (Hoption.Lego == 12) fLego->LegoCylindrical(1,nx,ny,"BF");
8176 } else if (Hoption.System == kSPHERICAL) {
8177 if (Hoption.Lego == 1) fLego->LegoSpherical(0,1,nx,ny,"FB");
8178 if (Hoption.Lego == 11) fLego->LegoSpherical(0,1,nx,ny,"BF");
8179 if (Hoption.Lego == 12) fLego->LegoSpherical(0,1,nx,ny,"BF");
8180 } else if (Hoption.System == kRAPIDITY) {
8181 if (Hoption.Lego == 1) fLego->LegoSpherical(1,1,nx,ny,"FB");
8182 if (Hoption.Lego == 11) fLego->LegoSpherical(1,1,nx,ny,"BF");
8183 if (Hoption.Lego == 12) fLego->LegoSpherical(1,1,nx,ny,"BF");
8184 } else {
8185 if (Hoption.Lego == 1) {
8187 fLego->LegoCartesian(90,nx,ny,"FB");}
8188 if (Hoption.Lego == 11) fLego->LegoCartesian(90,nx,ny,"BF");
8189 if (Hoption.Lego == 12) fLego->LegoCartesian(90,nx,ny,"BF");
8190 }
8191
8192 if (Hoption.Lego == 1 || Hoption.Lego == 11) {
8195 fLego->BackBox(90);
8196 }
8197 }
8198 if (Hoption.System == kCARTESIAN) {
8199 fLego->InitMoveScreen(-1.1,1.1);
8201 if (Hoption.FrontBox) fLego->FrontBox(90);
8202 }
8203 if (!Hoption.Axis && !Hoption.Same) {
8204 TGaxis axis;
8205 PaintLegoAxis(&axis, 90);
8206 }
8208 fLego.reset();
8209}
8210
8211////////////////////////////////////////////////////////////////////////////////
8212/// Draw the axis for legos and surface plots.
8213
8215{
8216
8217 static Double_t epsil = 0.001;
8218
8219 Double_t cosa, sina;
8220 Double_t bmin, bmax;
8221 Double_t r[24] /* was [3][8] */;
8222 Int_t ndivx, ndivy, ndivz, i;
8223 Double_t x1[3], x2[3], y1[3], y2[3], z1[3], z2[3], av[24] /* was [3][8] */;
8224 static char chopax[8], chopay[8], chopaz[8];
8225 Int_t ix1, ix2, iy1, iy2, iz1, iz2;
8226 Double_t rad;
8227
8228 TView *view = gPad ? gPad->GetView() : nullptr;
8229 if (!view) {
8230 Error("PaintLegoAxis", "no TView in current pad");
8231 return;
8232 }
8233
8234 // In polar coordinates, draw a short line going from the external circle
8235 // corresponding to r = 1 up to r = 1.1
8236 if (Hoption.System == kPOLAR) {
8237 r[0] = 1;
8238 r[1] = 0;
8239 r[2] = 0;
8240 view->WCtoNDC(r, x1);
8241 r[0] = 1.1;
8242 r[1] = 0;
8243 r[2] = 0;
8244 view->WCtoNDC(r, x2);
8245 gPad->PaintLine(x1[0],x1[1],x2[0],x2[1]);
8246 return;
8247 }
8248
8249 if (Hoption.System != kCARTESIAN) return;
8250
8251 rad = TMath::ATan(1.) * 4. /180.;
8252 cosa = TMath::Cos(ang*rad);
8253 sina = TMath::Sin(ang*rad);
8254
8255 view->AxisVertex(ang, av, ix1, ix2, iy1, iy2, iz1, iz2);
8256 for (i = 1; i <= 8; ++i) {
8257 r[i*3 - 3] = av[i*3 - 3] + av[i*3 - 2]*cosa;
8258 r[i*3 - 2] = av[i*3 - 2]*sina;
8259 r[i*3 - 1] = av[i*3 - 1];
8260 }
8261
8262 view->WCtoNDC(&r[ix1*3 - 3], x1);
8263 view->WCtoNDC(&r[ix2*3 - 3], x2);
8264 view->WCtoNDC(&r[iy1*3 - 3], y1);
8265 view->WCtoNDC(&r[iy2*3 - 3], y2);
8266 view->WCtoNDC(&r[iz1*3 - 3], z1);
8267 view->WCtoNDC(&r[iz2*3 - 3], z2);
8268
8269 view->SetAxisNDC(x1, x2, y1, y2, z1, z2);
8270
8271 Double_t *rmin = view->GetRmin();
8272 Double_t *rmax = view->GetRmax();
8273 if (!rmin || !rmax) return;
8274
8275 // Initialize the axis options
8276 if (x1[0] > x2[0]) strlcpy(chopax, "SDH=+",8);
8277 else strlcpy(chopax, "SDH=-",8);
8278 if (y1[0] > y2[0]) strlcpy(chopay, "SDH=+",8);
8279 else strlcpy(chopay, "SDH=-",8);
8280 if (z2[1] > z1[1]) strlcpy(chopaz, "SDH=+",8);
8281 else strlcpy(chopaz, "SDH=-",8);
8282
8283 // Option LOG is required ?
8284 if (Hoption.Logx) strlcat(chopax,"G",8);
8285 if (Hoption.Logy) strlcat(chopay,"G",8);
8286 if (Hoption.Logz) strlcat(chopaz,"G",8);
8287
8288 // Initialize the number of divisions. If the
8289 // number of divisions is negative, option 'N' is required.
8290 ndivx = fXaxis->GetNdivisions();
8291 ndivy = fYaxis->GetNdivisions();
8292 ndivz = fZaxis->GetNdivisions();
8293 if (ndivx < 0) {
8294 ndivx = TMath::Abs(ndivx);
8295 strlcat(chopax, "N",8);
8296 }
8297 if (ndivy < 0) {
8298 ndivy = TMath::Abs(ndivy);
8299 strlcat(chopay, "N",8);
8300 }
8301 if (ndivz < 0) {
8302 ndivz = TMath::Abs(ndivz);
8303 strlcat(chopaz, "N",8);
8304 }
8305
8306 // Set Axis attributes.
8307 // The variable SCALE rescales the VSIZ
8308 // in order to have the same label size for all angles.
8309
8310 axis->SetLineWidth(1);
8311
8312 // X axis drawing
8313 if (TMath::Abs(x1[0] - x2[0]) >= epsil || TMath::Abs(x1[1] - x2[1]) > epsil) {
8316 if (Hoption.Logx && !fH->InheritsFrom(TH3::Class())) {
8317 bmin = TMath::Power(10, rmin[0]);
8318 bmax = TMath::Power(10, rmax[0]);
8319 } else {
8320 bmin = rmin[0];
8321 bmax = rmax[0];
8322 }
8323 // Option time display is required ?
8324 if (fXaxis->GetTimeDisplay()) {
8325 strlcat(chopax,"t",8);
8326 if (strlen(fXaxis->GetTimeFormatOnly()) == 0) {
8327 axis->SetTimeFormat(fXaxis->ChooseTimeFormat(bmax-bmin));
8328 } else {
8330 }
8331 }
8332 axis->SetOption(chopax);
8333 axis->PaintAxis(x1[0], x1[1], x2[0], x2[1], bmin, bmax, ndivx, chopax);
8334 }
8335
8336 // Y axis drawing
8337 if (TMath::Abs(y1[0] - y2[0]) >= epsil || TMath::Abs(y1[1] - y2[1]) > epsil) {
8340 if (fYaxis->GetTitleOffset() == 0) axis->SetTitleOffset(1.5);
8341
8342 if (fH->GetDimension() < 2) {
8343 strlcpy(chopay, "V=+UN",8);
8344 ndivy = 0;
8345 }
8346 if (TMath::Abs(y1[0] - y2[0]) < epsil) {
8347 y2[0] = y1[0];
8348 }
8349 if (Hoption.Logy && !fH->InheritsFrom(TH3::Class())) {
8350 bmin = TMath::Power(10, rmin[1]);
8351 bmax = TMath::Power(10, rmax[1]);
8352 } else {
8353 bmin = rmin[1];
8354 bmax = rmax[1];
8355 }
8356 // Option time display is required ?
8357 if (fYaxis->GetTimeDisplay()) {
8358 strlcat(chopay,"t",8);
8359 if (strlen(fYaxis->GetTimeFormatOnly()) == 0) {
8360 axis->SetTimeFormat(fYaxis->ChooseTimeFormat(bmax-bmin));
8361 } else {
8363 }
8364 }
8365 axis->SetOption(chopay);
8366 axis->PaintAxis(y1[0], y1[1], y2[0], y2[1], bmin, bmax, ndivy, chopay);
8367 }
8368
8369 // Z axis drawing
8370 if (TMath::Abs(z1[0] - z2[0]) >= 100*epsil || TMath::Abs(z1[1] - z2[1]) > 100*epsil) {
8372 if (Hoption.Logz && !fH->InheritsFrom(TH3::Class())) {
8373 bmin = TMath::Power(10, rmin[2]);
8374 bmax = TMath::Power(10, rmax[2]);
8375 } else {
8376 bmin = rmin[2];
8377 bmax = rmax[2];
8378 }
8379 // Option time display is required ?
8380 if (fZaxis->GetTimeDisplay()) {
8381 strlcat(chopaz,"t",8);
8382 if (strlen(fZaxis->GetTimeFormatOnly()) == 0) {
8383 axis->SetTimeFormat(fZaxis->ChooseTimeFormat(bmax-bmin));
8384 } else {
8386 }
8387 }
8388 axis->SetOption(chopaz);
8389 TString ztit = fZaxis->GetTitle();
8390 if (ztit.Index(";")>0) {
8391 ztit.Remove(ztit.Index(";"),ztit.Length());
8392 axis->SetTitle(ztit.Data());
8393 }
8394 axis->PaintAxis(z1[0], z1[1], z2[0], z2[1], bmin, bmax, ndivz, chopaz);
8395 }
8396
8397 //fH->SetLineStyle(1); /// otherwise fEdgeStyle[i] gets overwritten!
8398}
8399
8400////////////////////////////////////////////////////////////////////////////////
8401/// [Paint the color palette on the right side of the pad.](\ref HP22)
8402
8404{
8405 TPaletteAxis *palette = (TPaletteAxis*)fFunctions->FindObject("palette");
8406 TView *view = gPad ? gPad->GetView() : nullptr;
8407 if (palette) {
8408 if (view) {
8409 if (!palette->TestBit(TPaletteAxis::kHasView)) {
8410 fFunctions->Remove(palette);
8411 delete palette; palette = nullptr;
8412 }
8413 } else {
8414 if (palette->TestBit(TPaletteAxis::kHasView)) {
8415 fFunctions->Remove(palette);
8416 delete palette; palette = nullptr;
8417 }
8418 }
8419 // make sure the histogram member of the palette is setup correctly. It may not be after a Clone()
8420 if (palette && !palette->GetHistogram()) palette->SetHistogram(fH);
8421 }
8422
8423 if (!palette) {
8424 Double_t xup = gPad->GetUxmax();
8425 Double_t x2 = gPad->PadtoX(gPad->GetX2());
8426 Double_t ymin = gPad->PadtoY(gPad->GetUymin());
8427 Double_t ymax = gPad->PadtoY(gPad->GetUymax());
8428 Double_t xr = 0.05*(gPad->GetX2() - gPad->GetX1());
8429 Double_t xmin = gPad->PadtoX(xup +0.1*xr);
8430 Double_t xmax = gPad->PadtoX(xup + xr);
8431 if (xmax > x2) xmax = gPad->PadtoX(gPad->GetX2()-0.01*xr);
8432 palette = new TPaletteAxis(xmin,ymin,xmax,ymax,fH);
8433 fFunctions->AddFirst(palette);
8434 palette->Paint();
8435 }
8436}
8437
8438////////////////////////////////////////////////////////////////////////////////
8439/// [Control function to draw a 2D histogram as a scatter plot.](\ref HP11)
8440
8442{
8443
8444 fH->TAttMarker::Modify();
8445
8446 Int_t k, marker;
8447 Double_t dz, z, xk,xstep, yk, ystep;
8448 Double_t scale = 1;
8449 Bool_t ltest = kFALSE;
8450 Double_t zmax = fH->GetMaximum();
8451 Double_t zmin = fH->GetMinimum();
8452 if (zmin == 0 && zmax == 0) return;
8453 if (zmin == zmax) {
8454 zmax += 0.1*TMath::Abs(zmax);
8455 zmin -= 0.1*TMath::Abs(zmin);
8456 }
8458 if (Hoption.Logz) {
8459 if (zmin > 0) zmin = TMath::Log10(zmin);
8460 else zmin = 0;
8461 if (zmax > 0) zmax = TMath::Log10(zmax);
8462 else zmax = 0;
8463 if (zmin == 0 && zmax == 0) return;
8464 dz = zmax - zmin;
8465 scale = 100/dz;
8466 if (ncells > 10000) scale /= 5;
8467 ltest = kTRUE;
8468 } else {
8469 dz = zmax - zmin;
8470 if (dz >= kNMAX || zmax < 1) {
8471 scale = (kNMAX-1)/dz;
8472 if (ncells > 10000) scale /= 5;
8473 ltest = kTRUE;
8474 }
8475 }
8476 if (fH->GetMinimumStored() == -1111) {
8477 Double_t yMARGIN = gStyle->GetHistTopMargin();
8478 if (Hoption.MinimumZero) {
8479 if (zmin >= 0) zmin = 0;
8480 else zmin -= yMARGIN*(zmax-zmin);
8481 } else {
8482 Double_t dzmin = yMARGIN*(zmax-zmin);
8483 if (zmin >= 0 && (zmin-dzmin <= 0)) zmin = 0;
8484 else zmin -= dzmin;
8485 }
8486 }
8487
8488 TString opt = option;
8489 opt.ToLower();
8490 if (opt.Contains("scat=")) {
8491 char optscat[100];
8492 strlcpy(optscat,opt.Data(),100);
8493 char *oscat = strstr(optscat,"scat=");
8494 char *blank = strstr(oscat," "); if (blank) *blank = 0;
8495 sscanf(oscat+5,"%lg",&scale);
8496 }
8497 // use an independent instance of a random generator
8498 // instead of gRandom to avoid conflicts and
8499 // to get same random numbers when drawing the same histogram
8500 TRandom2 random;
8501 marker=0;
8502 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
8503 yk = fYaxis->GetBinLowEdge(j);
8504 ystep = fYaxis->GetBinWidth(j);
8505 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
8506 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
8507 xk = fXaxis->GetBinLowEdge(i);
8508 xstep = fXaxis->GetBinWidth(i);
8509 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
8510 z = fH->GetBinContent(bin);
8511 if (z < zmin) z = zmin;
8512 if (z > zmax) z = zmax;
8513 if (Hoption.Logz) {
8514 if (z > 0) z = TMath::Log10(z) - zmin;
8515 } else {
8516 z -= zmin;
8517 }
8518 if (z <= 0) continue;
8519 k = Int_t(z*scale);
8520 if (ltest) k++;
8521 if (k > 0) {
8522 for (Int_t loop=0; loop<k; loop++) {
8523 if (k+marker >= kNMAX) {
8524 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
8525 marker=0;
8526 }
8527 fXbuf[marker] = (random.Rndm()*xstep) + xk;
8528 fYbuf[marker] = (random.Rndm()*ystep) + yk;
8529 if (Hoption.Logx) {
8530 if (fXbuf[marker] > 0) fXbuf[marker] = TMath::Log10(fXbuf[marker]);
8531 else break;
8532 }
8533 if (Hoption.Logy) {
8534 if (fYbuf[marker] > 0) fYbuf[marker] = TMath::Log10(fYbuf[marker]);
8535 else break;
8536 }
8537 if (fXbuf[marker] < gPad->GetUxmin()) break;
8538 if (fYbuf[marker] < gPad->GetUymin()) break;
8539 if (fXbuf[marker] > gPad->GetUxmax()) break;
8540 if (fYbuf[marker] > gPad->GetUymax()) break;
8541 marker++;
8542 }
8543 }
8544 }
8545 }
8546 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
8547
8549}
8550
8551////////////////////////////////////////////////////////////////////////////////
8552/// Static function to paint special objects like vectors and matrices.
8553/// This function is called via `gROOT->ProcessLine` to paint these objects
8554/// without having a direct dependency of the graphics or histogramming
8555/// system.
8556
8558{
8559
8560 if (!obj) return;
8563
8564 if (obj->InheritsFrom(TMatrixFBase::Class())) {
8565 // case TMatrixF
8566 TH2F *R__TMatrixFBase = new TH2F((TMatrixFBase &)*obj);
8567 R__TMatrixFBase->SetBit(kCanDelete);
8568 R__TMatrixFBase->Draw(option);
8569
8570 } else if (obj->InheritsFrom(TMatrixDBase::Class())) {
8571 // case TMatrixD
8572 TH2D *R__TMatrixDBase = new TH2D((TMatrixDBase &)*obj);
8573 R__TMatrixDBase->SetBit(kCanDelete);
8574 R__TMatrixDBase->Draw(option);
8575
8576 } else if (obj->InheritsFrom(TVectorF::Class())) {
8577 //case TVectorF
8578 TH1F *R__TVectorF = new TH1F((TVectorF &)*obj);
8579 R__TVectorF->SetBit(kCanDelete);
8580 R__TVectorF->Draw(option);
8581
8582 } else if (obj->InheritsFrom(TVectorD::Class())) {
8583 //case TVectorD
8584 TH1D *R__TVectorD = new TH1D((TVectorD &)*obj);
8585 R__TVectorD->SetBit(kCanDelete);
8586 R__TVectorD->Draw(option);
8587 }
8588
8589 TH1::AddDirectory(status);
8590}
8591
8592////////////////////////////////////////////////////////////////////////////////
8593/// [Draw the statistics box for 1D and profile histograms.](\ref HP07)
8594
8596{
8597 TString tt, tf;
8598 Int_t dofit;
8599 TPaveStats *stats = nullptr;
8600 TIter next(fFunctions);
8601 while (auto obj = next()) {
8602 if (obj->InheritsFrom(TPaveStats::Class())) {
8603 stats = (TPaveStats*)obj;
8604 break;
8605 }
8606 }
8607
8608 if (stats && dostat) {
8609 dofit = stats->GetOptFit();
8610 dostat = stats->GetOptStat();
8611 } else {
8612 dofit = gStyle->GetOptFit();
8613 }
8614 if (!dofit) fit = nullptr;
8615 if (dofit == 1) dofit = 111;
8616 if (dostat == 1) dostat = 1111;
8617 Int_t print_name = dostat%10;
8618 Int_t print_entries = (dostat/10)%10;
8619 Int_t print_mean = (dostat/100)%10;
8620 Int_t print_stddev = (dostat/1000)%10;
8621 Int_t print_under = (dostat/10000)%10;
8622 Int_t print_over = (dostat/100000)%10;
8623 Int_t print_integral= (dostat/1000000)%10;
8624 Int_t print_skew = (dostat/10000000)%10;
8625 Int_t print_kurt = (dostat/100000000)%10;
8626 Int_t nlines = print_name + print_entries + print_mean + print_stddev +
8627 print_under + print_over + print_integral +
8628 print_skew + print_kurt;
8629 Int_t print_fval = dofit%10;
8630 Int_t print_ferrors = (dofit/10)%10;
8631 Int_t print_fchi2 = (dofit/100)%10;
8632 Int_t print_fprob = (dofit/1000)%10;
8633 Int_t nlinesf = print_fval + print_fchi2 + print_fprob;
8634 if (fit) {
8635 if (print_fval < 2) nlinesf += fit->GetNumberFreeParameters();
8636 else nlinesf += fit->GetNpar();
8637 }
8638 if (fH->InheritsFrom(TProfile::Class())) nlinesf += print_mean + print_stddev;
8639
8640 // Pavetext with statistics
8641 Bool_t done = kFALSE;
8642 if (!dostat && !fit) {
8643 if (stats) { fFunctions->Remove(stats); delete stats;}
8644 return;
8645 }
8646 Double_t statw = gStyle->GetStatW();
8647 if (fit) statw = 1.8*gStyle->GetStatW();
8648 Double_t stath = (nlines+nlinesf)*gStyle->GetStatFontSize();
8649 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
8650 stath = 0.25*(nlines+nlinesf)*gStyle->GetStatH();
8651 }
8652 if (stats) {
8653 stats->Clear();
8654 done = kTRUE;
8655 } else {
8656 stats = new TPaveStats(
8657 gStyle->GetStatX()-statw,
8658 gStyle->GetStatY()-stath,
8659 gStyle->GetStatX(),
8660 gStyle->GetStatY(),"brNDC");
8661
8662 stats->SetParent(fH);
8663 stats->SetOptFit(dofit);
8664 stats->SetOptStat(dostat);
8665 stats->SetFillColor(gStyle->GetStatColor());
8666 stats->SetFillStyle(gStyle->GetStatStyle());
8668 stats->SetTextFont(gStyle->GetStatFont());
8669 if (gStyle->GetStatFont()%10 > 2)
8671 stats->SetFitFormat(gStyle->GetFitFormat());
8673 stats->SetName("stats");
8674
8676 stats->SetTextAlign(12);
8677 stats->SetBit(kCanDelete);
8678 stats->SetBit(kMustCleanup);
8679 }
8680 if (print_name) stats->AddText(fH->GetName());
8681 if (print_entries) {
8682 if (fH->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(fH->GetEntries()+0.5));
8683 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(fH->GetEntries()));
8684 stats->AddText(tt.Data());
8685 }
8686 if (print_mean) {
8687 if (print_mean == 1) {
8688 tf.Form("%s = %s%s",gStringMean.Data(),"%",stats->GetStatFormat());
8689 tt.Form(tf.Data(),fH->GetMean(1));
8690 } else {
8691 tf.Form("%s = %s%s #pm %s%s",gStringMean.Data(),"%",stats->GetStatFormat()
8692 ,"%",stats->GetStatFormat());
8693 tt.Form(tf.Data(),fH->GetMean(1),fH->GetMeanError(1));
8694 }
8695 stats->AddText(tt.Data());
8697 if (print_mean == 1) {
8698 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
8699 tt.Form(tf.Data(),fH->GetMean(2));
8700 } else {
8701 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
8702 ,"%",stats->GetStatFormat());
8703 tt.Form(tf.Data(),fH->GetMean(2),fH->GetMeanError(2));
8704 }
8705 stats->AddText(tt.Data());
8706 }
8707 }
8708 if (print_stddev) {
8709 if (print_stddev == 1) {
8710 tf.Form("%s = %s%s",gStringStdDev.Data(),"%",stats->GetStatFormat());
8711 tt.Form(tf.Data(),fH->GetStdDev(1));
8712 } else {
8713 tf.Form("%s = %s%s #pm %s%s",gStringStdDev.Data(),"%",stats->GetStatFormat()
8714 ,"%",stats->GetStatFormat());
8715 tt.Form(tf.Data(),fH->GetStdDev(1),fH->GetStdDevError(1));
8716 }
8717 stats->AddText(tt.Data());
8719 if (print_stddev == 1) {
8720 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
8721 tt.Form(tf.Data(),fH->GetStdDev(2));
8722 } else {
8723 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
8724 ,"%",stats->GetStatFormat());
8725 tt.Form(tf.Data(),fH->GetStdDev(2),fH->GetStdDevError(2));
8726 }
8727 stats->AddText(tt.Data());
8728 }
8729 }
8730 if (print_under) {
8731 tf.Form("%s = %s%s",gStringUnderflow.Data(),"%",stats->GetStatFormat());
8732 tt.Form(tf.Data(),fH->GetBinContent(0));
8733 stats->AddText(tt.Data());
8734 }
8735 if (print_over) {
8736 tf.Form("%s = %s%s",gStringOverflow.Data(),"%",stats->GetStatFormat());
8737 tt.Form(tf.Data(),fH->GetBinContent(fXaxis->GetNbins()+1));
8738 stats->AddText(tt.Data());
8739 }
8740 if (print_integral) {
8741 if (print_integral == 1) {
8742 tf.Form("%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
8743 tt.Form(tf.Data(),fH->Integral());
8744 } else {
8745 tf.Form("%s = %s%s",gStringIntegralBinWidth.Data(),"%",stats->GetStatFormat());
8746 tt.Form(tf.Data(),fH->Integral("width"));
8747 }
8748 stats->AddText(tt.Data());
8749 }
8750 if (print_skew) {
8751 if (print_skew == 1) {
8752 tf.Form("%s = %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat());
8753 tt.Form(tf.Data(),fH->GetSkewness(1));
8754 } else {
8755 tf.Form("%s = %s%s #pm %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat()
8756 ,"%",stats->GetStatFormat());
8757 tt.Form(tf.Data(),fH->GetSkewness(1),fH->GetSkewness(11));
8758 }
8759 stats->AddText(tt.Data());
8760 }
8761 if (print_kurt) {
8762 if (print_kurt == 1) {
8763 tf.Form("%s = %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat());
8764 tt.Form(tf.Data(),fH->GetKurtosis(1));
8765 } else {
8766 tf.Form("%s = %s%s #pm %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat()
8767 ,"%",stats->GetStatFormat());
8768 tt.Form(tf.Data(),fH->GetKurtosis(1),fH->GetKurtosis(11));
8769 }
8770 stats->AddText(tt.Data());
8771 }
8772
8773 // Draw Fit parameters
8774 if (fit) {
8775 Int_t ndf = fit->GetNDF();
8776 tf.Form("#chi^{2} / ndf = %s%s / %d","%",stats->GetFitFormat(),ndf);
8777 tt.Form(tf.Data(),fit->GetChisquare());
8778 if (print_fchi2) stats->AddText(tt.Data());
8779 if (print_fprob) {
8780 tf.Form("Prob = %s%s","%",stats->GetFitFormat());
8781 tt.Form(tf.Data(),TMath::Prob(fit->GetChisquare(),ndf));
8782 stats->AddText(tt.Data());
8783 }
8784 if (print_fval || print_ferrors) {
8785 Double_t parmin,parmax;
8786 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
8787 fit->GetParLimits(ipar,parmin,parmax);
8788 if (print_fval < 2 && parmin*parmax != 0 && parmin >= parmax) continue;
8789 if (print_ferrors) {
8790 tf.Form("%-8s = %s%s #pm %s ", fit->GetParName(ipar), "%",stats->GetFitFormat(),
8791 GetBestFormat(fit->GetParameter(ipar), fit->GetParError(ipar), stats->GetFitFormat()));
8792 tt.Form(tf.Data(),fit->GetParameter(ipar)
8793 ,fit->GetParError(ipar));
8794 } else {
8795 tf.Form("%-8s = %s%s ",fit->GetParName(ipar), "%",stats->GetFitFormat());
8796 tt.Form(tf.Data(),fit->GetParameter(ipar));
8797 }
8798 stats->AddText(tt.Data());
8799 }
8800 }
8801 }
8802
8803 if (!done) fFunctions->Add(stats);
8804 stats->Paint(stats->GetOption());
8805}
8806
8807////////////////////////////////////////////////////////////////////////////////
8808/// [Draw the statistics box for 2D histograms.](\ref HP07)
8809
8811{
8812
8813 if (fH->GetDimension() != 2) return;
8814 TH2 *h2 = (TH2*)fH;
8815
8816 TString tt, tf;
8817 Int_t dofit;
8818 TPaveStats *stats = nullptr;
8819 TIter next(fFunctions);
8820 while (auto obj = next()) {
8821 if (obj->InheritsFrom(TPaveStats::Class())) {
8822 stats = (TPaveStats*)obj;
8823 break;
8824 }
8825 }
8826 if (stats && dostat) {
8827 dofit = stats->GetOptFit();
8828 dostat = stats->GetOptStat();
8829 } else {
8830 dofit = gStyle->GetOptFit();
8831 }
8832 if (dostat == 1) dostat = 1111;
8833 Int_t print_name = dostat%10;
8834 Int_t print_entries = (dostat/10)%10;
8835 Int_t print_mean = (dostat/100)%10;
8836 Int_t print_stddev = (dostat/1000)%10;
8837 Int_t print_under = (dostat/10000)%10;
8838 Int_t print_over = (dostat/100000)%10;
8839 Int_t print_integral= (dostat/1000000)%10;
8840 Int_t print_skew = (dostat/10000000)%10;
8841 Int_t print_kurt = (dostat/100000000)%10;
8842 Int_t nlines = print_name + print_entries + 2*print_mean + 2*print_stddev + print_integral;
8843 if (print_under || print_over) nlines += 3;
8844
8845 // Pavetext with statistics
8846 if (!gStyle->GetOptFit()) fit = nullptr;
8847 Bool_t done = kFALSE;
8848 if (!dostat && !fit) {
8849 if (stats) { fFunctions->Remove(stats); delete stats;}
8850 return;
8851 }
8852 Double_t statw = gStyle->GetStatW();
8853 if (fit) statw = 1.8*gStyle->GetStatW();
8854 Double_t stath = nlines*gStyle->GetStatFontSize();
8855 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
8856 stath = 0.25*nlines*gStyle->GetStatH();
8857 }
8858 if (fit) stath += gStyle->GetStatH();
8859 if (stats) {
8860 stats->Clear();
8861 done = kTRUE;
8862 } else {
8863 stats = new TPaveStats(
8864 gStyle->GetStatX()-statw,
8865 gStyle->GetStatY()-stath,
8866 gStyle->GetStatX(),
8867 gStyle->GetStatY(),"brNDC");
8868
8869 stats->SetParent(fH);
8870 stats->SetOptFit(dofit);
8871 stats->SetOptStat(dostat);
8872 stats->SetFillColor(gStyle->GetStatColor());
8873 stats->SetFillStyle(gStyle->GetStatStyle());
8875 stats->SetName("stats");
8876
8878 stats->SetTextAlign(12);
8879 stats->SetTextFont(gStyle->GetStatFont());
8880 if (gStyle->GetStatFont()%10 > 2)
8882 stats->SetFitFormat(gStyle->GetFitFormat());
8884 stats->SetBit(kCanDelete);
8885 stats->SetBit(kMustCleanup);
8886 }
8887 if (print_name) stats->AddText(h2->GetName());
8888 if (print_entries) {
8889 if (h2->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(h2->GetEntries()+0.5));
8890 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(h2->GetEntries()));
8891 stats->AddText(tt.Data());
8892 }
8893 if (print_mean) {
8894 if (print_mean == 1) {
8895 tf.Form("%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
8896 tt.Form(tf.Data(),h2->GetMean(1));
8897 stats->AddText(tt.Data());
8898 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
8899 tt.Form(tf.Data(),h2->GetMean(2));
8900 stats->AddText(tt.Data());
8901 } else {
8902 tf.Form("%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
8903 ,"%",stats->GetStatFormat());
8904 tt.Form(tf.Data(),h2->GetMean(1),h2->GetMeanError(1));
8905 stats->AddText(tt.Data());
8906 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
8907 ,"%",stats->GetStatFormat());
8908 tt.Form(tf.Data(),h2->GetMean(2),h2->GetMeanError(2));
8909 stats->AddText(tt.Data());
8910 }
8911 }
8912 if (print_stddev) {
8913 if (print_stddev == 1) {
8914 tf.Form("%s = %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat());
8915 tt.Form(tf.Data(),h2->GetStdDev(1));
8916 stats->AddText(tt.Data());
8917 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
8918 tt.Form(tf.Data(),h2->GetStdDev(2));
8919 stats->AddText(tt.Data());
8920 } else {
8921 tf.Form("%s = %s%s #pm %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat()
8922 ,"%",stats->GetStatFormat());
8923 tt.Form(tf.Data(),h2->GetStdDev(1),h2->GetStdDevError(1));
8924 stats->AddText(tt.Data());
8925 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
8926 ,"%",stats->GetStatFormat());
8927 tt.Form(tf.Data(),h2->GetStdDev(2),h2->GetStdDevError(2));
8928 stats->AddText(tt.Data());
8929 }
8930 }
8931 if (print_integral) {
8932 tf.Form("%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
8933 tt.Form(tf.Data(),fH->Integral());
8934 stats->AddText(tt.Data());
8935 }
8936 if (print_skew) {
8937 if (print_skew == 1) {
8938 tf.Form("%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
8939 tt.Form(tf.Data(),h2->GetSkewness(1));
8940 stats->AddText(tt.Data());
8941 tf.Form("%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
8942 tt.Form(tf.Data(),h2->GetSkewness(2));
8943 stats->AddText(tt.Data());
8944 } else {
8945 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
8946 ,"%",stats->GetStatFormat());
8947 tt.Form(tf.Data(),h2->GetSkewness(1),h2->GetSkewness(11));
8948 stats->AddText(tt.Data());
8949 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
8950 ,"%",stats->GetStatFormat());
8951 tt.Form(tf.Data(),h2->GetSkewness(2),h2->GetSkewness(12));
8952 stats->AddText(tt.Data());
8953 }
8954 }
8955 if (print_kurt) {
8956 if (print_kurt == 1) {
8957 tf.Form("%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
8958 tt.Form(tf.Data(),h2->GetKurtosis(1));
8959 stats->AddText(tt.Data());
8960 tf.Form("%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
8961 tt.Form(tf.Data(),h2->GetKurtosis(2));
8962 stats->AddText(tt.Data());
8963 } else {
8964 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
8965 ,"%",stats->GetStatFormat());
8966 tt.Form(tf.Data(),h2->GetKurtosis(1),h2->GetKurtosis(11));
8967 stats->AddText(tt.Data());
8968 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
8969 ,"%",stats->GetStatFormat());
8970 tt.Form(tf.Data(),h2->GetKurtosis(2),h2->GetKurtosis(12));
8971 stats->AddText(tt.Data());
8972 }
8973 }
8974 if (print_under || print_over) {
8975 //get 3*3 under/overflows for 2d hist
8976 Double_t unov[9];
8977
8978 Int_t cellsX = h2->GetXaxis()->GetNbins() + 1;
8979 Int_t cellsY = h2->GetYaxis()->GetNbins() + 1;
8980 Int_t firstX = std::max(1, h2->GetXaxis()->GetFirst());
8981 Int_t firstY = std::max(1, h2->GetYaxis()->GetFirst());
8982 Int_t lastX = std::min(h2->GetXaxis()->GetLast(), h2->GetXaxis()->GetNbins());
8983 Int_t lastY = std::min(h2->GetYaxis()->GetLast(), h2->GetYaxis()->GetNbins());
8984
8985 unov[0] = h2->Integral( 0, firstX-1, lastY+1, cellsY );
8986 unov[1] = h2->Integral(firstX , lastX , lastY+1, cellsY );
8987 unov[2] = h2->Integral(lastX+1, cellsX , lastY+1, cellsY );
8988 unov[3] = h2->Integral( 0, firstX-1, firstY , lastY );
8989 unov[4] = h2->Integral(firstX , lastX , firstY , lastY );
8990 unov[5] = h2->Integral(lastX+1, cellsX , firstY , lastY );
8991 unov[6] = h2->Integral( 0, firstX-1, 0, firstY-1);
8992 unov[7] = h2->Integral(firstX, lastX, 0, firstY-1);
8993 unov[8] = h2->Integral(lastX+1, cellsX , 0, firstY-1);
8994
8995 tt.Form("%g|%g|%g\n", unov[0], unov[1], unov[2]);
8996 stats->AddText(tt.Data());
8997 tt.Form("%g|%g|%g\n", unov[3], unov[4], unov[5]);
8998 stats->AddText(tt.Data());
8999 tt.Form("%g|%g|%g\n", unov[6], unov[7], unov[8]);
9000 stats->AddText(tt.Data());
9001 }
9002
9003 // Draw Fit parameters
9004 if (fit) {
9005 Int_t ndf = fit->GetNDF();
9006 tt.Form("#chi^{2} / ndf = %6.4g / %d",fit->GetChisquare(),ndf);
9007 stats->AddText(tt.Data());
9008 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
9009 tt.Form("%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
9010 ,fit->GetParameter(ipar)
9011 ,fit->GetParError(ipar));
9012 stats->AddText(tt.Data());
9013 }
9014 }
9015
9016 if (!done) fFunctions->Add(stats);
9017 stats->Paint(stats->GetOption());
9018}
9019
9020////////////////////////////////////////////////////////////////////////////////
9021/// [Draw the statistics box for 3D histograms.](\ref HP07)
9022
9024{
9025
9026 if (fH->GetDimension() != 3) return;
9027 TH3 *h3 = (TH3*)fH;
9028
9029 TString tt, tf;
9030 Int_t dofit;
9031 TPaveStats *stats = nullptr;
9032 TIter next(fFunctions);
9033 while (auto obj = next()) {
9034 if (obj->InheritsFrom(TPaveStats::Class())) {
9035 stats = (TPaveStats*)obj;
9036 break;
9037 }
9038 }
9039 if (stats && dostat) {
9040 dofit = stats->GetOptFit();
9041 dostat = stats->GetOptStat();
9042 } else {
9043 dofit = gStyle->GetOptFit();
9044 }
9045 if (dostat == 1) dostat = 1111;
9046 Int_t print_name = dostat%10;
9047 Int_t print_entries = (dostat/10)%10;
9048 Int_t print_mean = (dostat/100)%10;
9049 Int_t print_stddev = (dostat/1000)%10;
9050 Int_t print_under = (dostat/10000)%10;
9051 Int_t print_over = (dostat/100000)%10;
9052 Int_t print_integral= (dostat/1000000)%10;
9053 Int_t print_skew = (dostat/10000000)%10;
9054 Int_t print_kurt = (dostat/100000000)%10;
9055 Int_t nlines = print_name + print_entries + 3*print_mean + 3*print_stddev + print_integral;
9056 if (print_under || print_over) nlines += 3;
9057
9058 // Pavetext with statistics
9059 if (!gStyle->GetOptFit()) fit = nullptr;
9060 Bool_t done = kFALSE;
9061 if (!dostat && !fit) {
9062 if (stats) { fFunctions->Remove(stats); delete stats;}
9063 return;
9064 }
9065 Double_t statw = gStyle->GetStatW();
9066 if (fit) statw = 1.8*gStyle->GetStatW();
9067 Double_t stath = nlines*gStyle->GetStatFontSize();
9068 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
9069 stath = 0.25*nlines*gStyle->GetStatH();
9070 }
9071 if (fit) stath += gStyle->GetStatH();
9072 if (stats) {
9073 stats->Clear();
9074 done = kTRUE;
9075 } else {
9076 stats = new TPaveStats(
9077 gStyle->GetStatX()-statw,
9078 gStyle->GetStatY()-stath,
9079 gStyle->GetStatX(),
9080 gStyle->GetStatY(),"brNDC");
9081
9082 stats->SetParent(fH);
9083 stats->SetOptFit(dofit);
9084 stats->SetOptStat(dostat);
9085 stats->SetFillColor(gStyle->GetStatColor());
9086 stats->SetFillStyle(gStyle->GetStatStyle());
9088 stats->SetName("stats");
9089
9091 stats->SetTextAlign(12);
9092 stats->SetTextFont(gStyle->GetStatFont());
9093 stats->SetFitFormat(gStyle->GetFitFormat());
9095 stats->SetBit(kCanDelete);
9096 stats->SetBit(kMustCleanup);
9097 }
9098 if (print_name) stats->AddText(h3->GetName());
9099 if (print_entries) {
9100 if (h3->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(h3->GetEntries()+0.5));
9101 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(h3->GetEntries()+0.5));
9102 stats->AddText(tt.Data());
9103 }
9104 if (print_mean) {
9105 if (print_mean == 1) {
9106 tf.Form("%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
9107 tt.Form(tf.Data(),h3->GetMean(1));
9108 stats->AddText(tt.Data());
9109 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
9110 tt.Form(tf.Data(),h3->GetMean(2));
9111 stats->AddText(tt.Data());
9112 tf.Form("%s = %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat());
9113 tt.Form(tf.Data(),h3->GetMean(3));
9114 stats->AddText(tt.Data());
9115 } else {
9116 tf.Form("%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
9117 ,"%",stats->GetStatFormat());
9118 tt.Form(tf.Data(),h3->GetMean(1),h3->GetMeanError(1));
9119 stats->AddText(tt.Data());
9120 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
9121 ,"%",stats->GetStatFormat());
9122 tt.Form(tf.Data(),h3->GetMean(2),h3->GetMeanError(2));
9123 stats->AddText(tt.Data());
9124 tf.Form("%s = %s%s #pm %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat()
9125 ,"%",stats->GetStatFormat());
9126 tt.Form(tf.Data(),h3->GetMean(3),h3->GetMeanError(3));
9127 stats->AddText(tt.Data());
9128 }
9129 }
9130 if (print_stddev) {
9131 if (print_stddev == 1) {
9132 tf.Form("%s = %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat());
9133 tt.Form(tf.Data(),h3->GetStdDev(1));
9134 stats->AddText(tt.Data());
9135 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
9136 tt.Form(tf.Data(),h3->GetStdDev(2));
9137 stats->AddText(tt.Data());
9138 tf.Form("%s = %s%s",gStringStdDevZ.Data(),"%",stats->GetStatFormat());
9139 tt.Form(tf.Data(),h3->GetStdDev(3));
9140 stats->AddText(tt.Data());
9141 } else {
9142 tf.Form("%s = %s%s #pm %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat()
9143 ,"%",stats->GetStatFormat());
9144 tt.Form(tf.Data(),h3->GetStdDev(1),h3->GetStdDevError(1));
9145 stats->AddText(tt.Data());
9146 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
9147 ,"%",stats->GetStatFormat());
9148 tt.Form(tf.Data(),h3->GetStdDev(2),h3->GetStdDevError(2));
9149 stats->AddText(tt.Data());
9150 tf.Form("%s = %s%s #pm %s%s",gStringStdDevZ.Data(),"%",stats->GetStatFormat()
9151 ,"%",stats->GetStatFormat());
9152 tt.Form(tf.Data(),h3->GetStdDev(3),h3->GetStdDevError(3));
9153 stats->AddText(tt.Data());
9154 }
9155 }
9156 if (print_integral) {
9157 tt.Form("%s = %6.4g",gStringIntegral.Data(),h3->Integral());
9158 stats->AddText(tt.Data());
9159 }
9160 if (print_skew) {
9161 if (print_skew == 1) {
9162 tf.Form("%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
9163 tt.Form(tf.Data(),h3->GetSkewness(1));
9164 stats->AddText(tt.Data());
9165 tf.Form("%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
9166 tt.Form(tf.Data(),h3->GetSkewness(2));
9167 stats->AddText(tt.Data());
9168 tf.Form("%s = %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat());
9169 tt.Form(tf.Data(),h3->GetSkewness(3));
9170 stats->AddText(tt.Data());
9171 } else {
9172 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
9173 ,"%",stats->GetStatFormat());
9174 tt.Form(tf.Data(),h3->GetSkewness(1),h3->GetSkewness(11));
9175 stats->AddText(tt.Data());
9176 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
9177 ,"%",stats->GetStatFormat());
9178 tt.Form(tf.Data(),h3->GetSkewness(2),h3->GetSkewness(12));
9179 stats->AddText(tt.Data());
9180 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat()
9181 ,"%",stats->GetStatFormat());
9182 tt.Form(tf.Data(),h3->GetSkewness(3),h3->GetSkewness(13));
9183 stats->AddText(tt.Data());
9184 }
9185 }
9186 if (print_kurt) {
9187 if (print_kurt == 1) {
9188 tf.Form("%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
9189 tt.Form(tf.Data(),h3->GetKurtosis(1));
9190 stats->AddText(tt.Data());
9191 tf.Form("%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
9192 tt.Form(tf.Data(),h3->GetKurtosis(2));
9193 stats->AddText(tt.Data());
9194 tf.Form("%s = %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat());
9195 tt.Form(tf.Data(),h3->GetKurtosis(3));
9196 stats->AddText(tt.Data());
9197 } else {
9198 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
9199 ,"%",stats->GetStatFormat());
9200 tt.Form(tf.Data(),h3->GetKurtosis(1),h3->GetKurtosis(11));
9201 stats->AddText(tt.Data());
9202 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
9203 ,"%",stats->GetStatFormat());
9204 tt.Form(tf.Data(),h3->GetKurtosis(2),h3->GetKurtosis(12));
9205 stats->AddText(tt.Data());
9206 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat()
9207 ,"%",stats->GetStatFormat());
9208 tt.Form(tf.Data(),h3->GetKurtosis(3),h3->GetKurtosis(13));
9209 stats->AddText(tt.Data());
9210 }
9211 }
9212 if (print_under || print_over) {
9213 // no underflow - overflow printing for a 3D histogram
9214 // one would need a 3D table
9215 }
9216
9217 // Draw Fit parameters
9218 if (fit) {
9219 Int_t ndf = fit->GetNDF();
9220 tt.Form("#chi^{2} / ndf = %6.4g / %d",fit->GetChisquare(),ndf);
9221 stats->AddText(tt.Data());
9222 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
9223 tt.Form("%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
9224 ,fit->GetParameter(ipar)
9225 ,fit->GetParError(ipar));
9226 stats->AddText(tt.Data());
9227 }
9228 }
9229
9230 if (!done) fFunctions->Add(stats);
9231 stats->Paint(stats->GetOption());
9232}
9233
9234////////////////////////////////////////////////////////////////////////////////
9235/// [Control function to draw a 2D histogram as a surface plot.](\ref HP18)
9236
9238{
9239
9240 const Double_t ydiff = 1;
9241 const Double_t yligh1 = 10;
9242 const Double_t qa = 0.15;
9243 const Double_t qd = 0.15;
9244 const Double_t qs = 0.8;
9245 Double_t fmin, fmax;
9246 Int_t raster = 0;
9247 Int_t irep = 0;
9248
9249 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
9252 Double_t zmin = Hparam.zmin;
9253 Double_t zmax = Hparam.zmax;
9254 Double_t xlab1 = Hparam.xmin;
9255 Double_t xlab2 = Hparam.xmax;
9256 Double_t ylab1 = Hparam.ymin;
9257 Double_t ylab2 = Hparam.ymax;
9258 Double_t dangle = 10*3.141592/180; //Delta angle for Rapidity option
9259 Double_t deltaz = TMath::Abs(zmin);
9260 if (deltaz == 0) deltaz = 1;
9261 if (zmin >= zmax) {
9262 zmin -= 0.5*deltaz;
9263 zmax += 0.5*deltaz;
9264 }
9265 Double_t z1c = zmin;
9266 Double_t z2c = zmin + (zmax-zmin)*(1+gStyle->GetHistTopMargin());
9267 // Compute the lego limits and instantiate a lego object
9268 fXbuf[0] = -1;
9269 fYbuf[0] = 1;
9270 fXbuf[1] = -1;
9271 fYbuf[1] = 1;
9272 if (Hoption.System >= kPOLAR && (Hoption.Surf == 1 || Hoption.Surf == 13)) raster = 1;
9273 if (Hoption.System == kPOLAR) {
9274 fXbuf[2] = z1c;
9275 fYbuf[2] = z2c;
9276 } else if (Hoption.System == kCYLINDRICAL) {
9277 if (Hoption.Logy) {
9278 if (ylab1 > 0) fXbuf[2] = TMath::Log10(ylab1);
9279 else fXbuf[2] = 0;
9280 if (ylab2 > 0) fYbuf[2] = TMath::Log10(ylab2);
9281 else fYbuf[2] = 0;
9282 } else {
9283 fXbuf[2] = ylab1;
9284 fYbuf[2] = ylab2;
9285 }
9286 z1c = 0; z2c = 1;
9287 } else if (Hoption.System == kSPHERICAL) {
9288 fXbuf[2] = -1;
9289 fYbuf[2] = 1;
9290 z1c = 0; z2c = 1;
9291 } else if (Hoption.System == kRAPIDITY) {
9292 fXbuf[2] = -1/TMath::Tan(dangle);
9293 fYbuf[2] = 1/TMath::Tan(dangle);
9294 } else {
9295 fXbuf[0] = xlab1;
9296 fYbuf[0] = xlab2;
9297 fXbuf[1] = ylab1;
9298 fYbuf[1] = ylab2;
9299 fXbuf[2] = z1c;
9300 fYbuf[2] = z2c;
9301 }
9302
9303 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data(), Hoption.System);
9304 fLego->SetEdgeAtt(fH->GetLineColor(),fH->GetLineStyle(),fH->GetLineWidth(),0);
9305 fLego->SetFillColor(fH->GetFillColor());
9306
9307 // Initialize the levels on the Z axis
9308 Int_t ndiv = fH->GetContour();
9309 if (ndiv == 0 ) {
9310 ndiv = gStyle->GetNumberContours();
9311 fH->SetContour(ndiv);
9312 }
9313 Int_t ndivz = TMath::Abs(ndiv);
9314 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
9315
9316 if (Hoption.Surf == 13 || Hoption.Surf == 15) fLego->SetMesh(3);
9317 if (Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) fLego->SetMesh(0);
9318
9319 // Close the surface in case of non cartesian coordinates.
9320
9321 if (Hoption.System != kCARTESIAN) {nx++; ny++;}
9322
9323 // Now ready to draw the surface plot
9324
9325 TView *view = gPad ? gPad->GetView() : nullptr;
9326 if (!view) {
9327 Error("PaintSurface", "no TView in current pad");
9328 return;
9329 }
9330
9331 Double_t thedeg = 90 - gPad->GetTheta();
9332 Double_t phideg = -90 - gPad->GetPhi();
9333 Double_t psideg = view->GetPsi();
9334 view->SetView(phideg, thedeg, psideg, irep);
9335
9336 // Set color/style for back box
9337 if (Hoption.Same) {
9338 fLego->SetFillStyle(0);
9339 fLego->SetFillColor(1);
9340 } else {
9341 fLego->SetFillStyle(gPad->GetFrameFillStyle());
9342 fLego->SetFillColor(gPad->GetFrameFillColor());
9343 }
9344 fLego->TAttFill::Modify();
9345
9346 Int_t backcolor = gPad->GetFrameFillColor();
9347 if (Hoption.System != kCARTESIAN) backcolor = 0;
9348 view->PadRange(backcolor);
9349
9350 fLego->SetFillStyle(fH->GetFillStyle());
9351 fLego->SetFillColor(fH->GetFillColor());
9352 fLego->TAttFill::Modify();
9353
9354 // Draw the filled contour on top
9355 Int_t icol1 = fH->GetFillColor();
9356
9357 Int_t hoption35 = Hoption.Surf;
9358 if (Hoption.Surf == 13 || Hoption.Surf == 15) {
9359 DefineColorLevels(ndivz);
9360 Hoption.Surf = 23;
9361 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9363 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"BF");
9364 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9365 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9366 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9367 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"BF");
9368 Hoption.Surf = hoption35;
9369 fLego->SetMesh(1);
9370 }
9371
9372 if (raster) fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
9373 else fLego->InitMoveScreen(-1.1,1.1);
9374
9375 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) {
9376 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9379 fLego->BackBox(90);
9380 }
9381 }
9382
9383 // Gouraud Shading surface
9384 if (Hoption.Surf == 14) {
9385 // Set light sources
9386 fLego->LightSource(0, ydiff, 0,0,0,irep);
9387 fLego->LightSource(1, yligh1 ,1,1,1,irep);
9388 fLego->SurfaceProperty(qa, qd, qs, 1, irep);
9389 fmin = ydiff*qa;
9390 fmax = fmin + (yligh1+0.1)*(qd+qs);
9391 Int_t nbcol = 28;
9392 icol1 = 201;
9393 Double_t dcol = 0.5/Double_t(nbcol);
9394 TColor *colref = gROOT->GetColor(fH->GetFillColor());
9395 if (!colref) return;
9396 Float_t r,g,b,hue,light,satur;
9397 colref->GetRGB(r,g,b);
9398 TColor::RGBtoHLS(r,g,b,hue,light,satur);
9399 TColor *acol;
9400 for (Int_t col=0;col<nbcol;col++) {
9401 acol = gROOT->GetColor(col+icol1);
9402 TColor::HLStoRGB(hue,.4+col*dcol,satur,r,g,b);
9403 if (acol) acol->SetRGB(r,g,b);
9404 }
9405 fLego->Spectrum(nbcol, fmin, fmax, icol1, 1, irep);
9406 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::GouraudFunction);
9408 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"BF");
9409 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9410 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9411 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9412 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"BF");
9413 } else if (Hoption.Surf == 15) {
9414 // The surface is not drawn in this case.
9415 } else {
9416 // Draw the surface
9417 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 16 || Hoption.Surf == 17) {
9418 DefineColorLevels(ndivz);
9419 } else {
9420 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9421 }
9422 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9423 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceRaster1);
9424 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode2);
9425 if (Hoption.System == kPOLAR) {
9426 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfacePolar(1,nx,ny,"FB");
9427 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfacePolar(1,nx,ny,"BF");
9428 } else if (Hoption.System == kCYLINDRICAL) {
9429 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceCylindrical(1,nx,ny,"FB");
9430 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9431 } else if (Hoption.System == kSPHERICAL) {
9432 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceSpherical(0,1,nx,ny,"FB");
9433 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9434 } else if (Hoption.System == kRAPIDITY) {
9435 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceSpherical(1,1,nx,ny,"FB");
9436 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9437 } else {
9438 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove1);
9439 if (Hoption.Surf == 16) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove3);
9440 if (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16) fLego->SurfaceCartesian(90,nx,ny,"FB");
9441 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCartesian(90,nx,ny,"BF");
9442 }
9443 }
9444
9445 // Paint the line contour on top for option SURF7
9446 if (Hoption.Surf == 17) {
9447 fLego->InitMoveScreen(-1.1,1.1);
9448 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9449 Hoption.Surf = 23;
9450 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9452 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"FB");
9453 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"FB");
9454 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"FB");
9455 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"FB");
9456 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"FB");
9457 }
9458
9459 if ((!Hoption.Same) &&
9460 (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16)) {
9463 fLego->BackBox(90);
9464 }
9465 }
9466 if (Hoption.System == kCARTESIAN) {
9467 fLego->InitMoveScreen(-1.1,1.1);
9469 if (Hoption.FrontBox) fLego->FrontBox(90);
9470 }
9471 if (!Hoption.Axis && !Hoption.Same) {
9472 TGaxis axis;
9473 PaintLegoAxis(&axis, 90);
9474 }
9475
9477
9478 fLego.reset();
9479}
9480
9481////////////////////////////////////////////////////////////////////////////////
9482/// Control function to draw a table using Delaunay triangles.
9483
9485{
9486
9487 TGraphDelaunay2D *dt = nullptr;
9488 TGraphDelaunay *dtOld = nullptr;
9489
9490 // Check if fH contains a TGraphDelaunay2D
9491 TList *hl = fH->GetListOfFunctions();
9492 dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
9493 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
9494 if (!dt && !dtOld) return;
9495
9496 // If needed, create a TGraph2DPainter
9497 if (!fGraph2DPainter)
9498 fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
9499
9500 // Define the 3D view
9501 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
9502 if (Hoption.Same) {
9503 TView *viewsame = gPad ? gPad->GetView() : nullptr;
9504 if (!viewsame) {
9505 Error("PaintTriangles", "no TView in current pad, do not use option SAME");
9506 return;
9507 }
9508 Double_t *rmin = viewsame->GetRmin();
9509 Double_t *rmax = viewsame->GetRmax();
9510 if (!rmin || !rmax) return;
9511 fXbuf[0] = rmin[0];
9512 fYbuf[0] = rmax[0];
9513 fXbuf[1] = rmin[1];
9514 fYbuf[1] = rmax[1];
9515 fXbuf[2] = rmin[2];
9516 fYbuf[2] = rmax[2];
9517 fH->SetMaximum(rmax[2]);
9518 fH->SetMinimum(rmin[2]);
9519 fH->GetXaxis()->SetRangeUser(rmin[0],rmax[0]);
9520 fH->GetYaxis()->SetRangeUser(rmin[1],rmax[1]);
9521 } else {
9522 fXbuf[0] = Hparam.xmin;
9523 fYbuf[0] = Hparam.xmax;
9524 fXbuf[1] = Hparam.ymin;
9525 fYbuf[1] = Hparam.ymax;
9526 fXbuf[2] = Hparam.zmin;
9527 fYbuf[2] = Hparam.zmax;
9528 }
9529
9530 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
9531 TView *view = gPad ? gPad->GetView() : nullptr;
9532 if (!view) {
9533 Error("PaintTriangles", "no TView in current pad");
9534 return;
9535 }
9536 Double_t thedeg = 90 - gPad->GetTheta();
9537 Double_t phideg = -90 - gPad->GetPhi();
9538 Double_t psideg = view->GetPsi();
9539 Int_t irep;
9540 view->SetView(phideg, thedeg, psideg, irep);
9541
9542 // Set color/style for back box
9543 fLego->SetFillStyle(gPad->GetFrameFillStyle());
9544 fLego->SetFillColor(gPad->GetFrameFillColor());
9545 fLego->TAttFill::Modify();
9546 Int_t backcolor = gPad->GetFrameFillColor();
9547 if (Hoption.System != kCARTESIAN) backcolor = 0;
9548 view->PadRange(backcolor);
9549 fLego->SetFillStyle(fH->GetFillStyle());
9550 fLego->SetFillColor(fH->GetFillColor());
9551 fLego->TAttFill::Modify();
9552
9553 // Paint the Back Box if needed
9554 if (Hoption.BackBox && !Hoption.Same) {
9555 fLego->InitMoveScreen(-1.1,1.1);
9556 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9558 fLego->BackBox(90);
9559 }
9560
9561 // Paint the triangles
9562 fGraph2DPainter->Paint(option);
9563
9564 // Paint the Front Box if needed
9565 if (Hoption.FrontBox) {
9566 fLego->InitMoveScreen(-1.1,1.1);
9568 fLego->FrontBox(90);
9569 }
9570
9571 // Paint the Axis if needed
9572 if (!Hoption.Axis && !Hoption.Same) {
9573 TGaxis axis;
9574 PaintLegoAxis(&axis, 90);
9575 }
9576
9578
9579 fLego.reset();
9580}
9581
9582////////////////////////////////////////////////////////////////////////////////
9583/// Define the color levels used to paint legos, surfaces etc..
9584
9586{
9587
9588 Int_t i, irep;
9589
9590 // Initialize the color levels
9591 if (ndivz >= 100) {
9592 Warning("PaintSurface", "too many color levels, %d >= 100, reset to 99", ndivz);
9593 ndivz = 99;
9594 }
9595 std::vector<Double_t> funlevel(ndivz+1);
9596 std::vector<Int_t> colorlevel(ndivz+1);
9597 Int_t theColor;
9598 Int_t ncolors = gStyle->GetNumberOfColors();
9599 for (i = 0; i < ndivz; ++i) {
9600 funlevel[i] = fH->GetContourLevelPad(i);
9601 theColor = Int_t((i+0.99)*Float_t(ncolors)/Float_t(ndivz));
9602 colorlevel[i] = gStyle->GetColorPalette(theColor);
9603 }
9604 colorlevel[ndivz] = gStyle->GetColorPalette(ncolors-1);
9605 fLego->ColorFunction(ndivz, funlevel.data(), colorlevel.data(), irep);
9606}
9607
9608////////////////////////////////////////////////////////////////////////////////
9609/// [Control function to draw 2D/3D histograms (tables).](\ref HP01c)
9610
9612{
9613
9614 // Fill Hparam structure with histo parameters
9615 if (!TableInit()) return;
9616
9617 // Draw histogram frame
9618 PaintFrame();
9619
9620 // If palette option not specified, delete a possible existing palette
9621 if (!Hoption.Zscale) {
9622 TObject *palette = fFunctions->FindObject("palette");
9623 if (palette) { fFunctions->Remove(palette); delete palette;}
9624 }
9625
9626 // Do not draw the histogram. Only the attached functions will be drawn.
9627 if (Hoption.Func == 2) {
9628 if (Hoption.Zscale) {
9629 Int_t ndiv = fH->GetContour();
9630 if (ndiv == 0 ) {
9631 ndiv = gStyle->GetNumberContours();
9632 fH->SetContour(ndiv);
9633 }
9634 PaintPalette();
9635 }
9636
9637 // Draw the histogram according to the option
9638 } else {
9639 if (fH->InheritsFrom(TH2Poly::Class()) && Hoption.Axis<=0) {
9640 if (Hoption.Fill) PaintTH2PolyBins("f");
9644 if (Hoption.Line) PaintTH2PolyBins("l");
9645 if (Hoption.Mark) PaintTH2PolyBins("P");
9646 } else if (fH->GetEntries() != 0 && Hoption.Axis<=0) {
9650 if (Hoption.Color) {
9653 }
9656 if (Hoption.Error >= 100) Paint2DErrors(option);
9658 }
9662 }
9663
9664 // Draw histogram title
9665 PaintTitle();
9666
9667 // Draw the axes
9668 if (!Hoption.Lego && !Hoption.Surf &&
9669 !Hoption.Tri && !(Hoption.Error >= 100)) PaintAxis(kFALSE);
9670
9671 TF1 *fit = nullptr;
9672 TIter next(fFunctions);
9673 while (auto obj = next()) {
9674 if (obj->InheritsFrom(TF1::Class())) {
9675 fit = (TF1*)obj;
9676 break;
9677 }
9678 }
9679 if ((Hoption.Same%10) != 1) {
9680 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
9681 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
9682 //ALWAYS executed on non-iOS platform.
9683 //On iOS, depends on mode.
9685 }
9686 }
9687 }
9688}
9689
9690////////////////////////////////////////////////////////////////////////////////
9691/// Control function to draw a TH2Poly bins' contours.
9692///
9693/// - option = "F" draw the bins as filled areas.
9694/// - option = "L" draw the bins as line.
9695/// - option = "P" draw the bins as markers.
9696
9698{
9699
9700 //Do not highlight the histogram, if its part was picked.
9701 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH) return;
9702
9703 TString opt = option;
9704 opt.ToLower();
9705 Bool_t line = kFALSE;
9706 Bool_t fill = kFALSE;
9707 Bool_t mark = kFALSE;
9708 if (opt.Contains("l")) line = kTRUE;
9709 if (opt.Contains("f")) fill = kTRUE;
9710 if (opt.Contains("p")) mark = kTRUE;
9711
9712 TH2PolyBin *b;
9713 Double_t z;
9714
9715 TIter next(((TH2Poly*)fH)->GetBins());
9716 TObject *obj, *poly;
9717
9718 while ((obj=next())) {
9719 b = (TH2PolyBin*)obj;
9720 z = b->GetContent();
9721 if (z==0 && Hoption.Zero) continue; // Do not draw empty bins in case of option "COL0 L"
9722 poly = b->GetPolygon();
9723
9724 // Paint the TGraph bins.
9725 if (poly->IsA() == TGraph::Class()) {
9726 TGraph *g = (TGraph*)poly;
9727 g->TAttLine::Modify();
9728 g->TAttMarker::Modify();
9729 g->TAttFill::Modify();
9730 if (line) {
9731 Int_t fs = g->GetFillStyle();
9732 Int_t db = gStyle->GetDrawBorder();
9733 g->SetFillStyle(0);
9735 g->Paint("F");
9736 gStyle->SetDrawBorder(db);
9737 g->SetFillStyle(fs);
9738 }
9739 if (fill) g->Paint("F");
9740 if (mark) g->Paint("P");
9741 }
9742
9743 // Paint the TMultiGraph bins.
9744 if (poly->IsA() == TMultiGraph::Class()) {
9745 TMultiGraph *mg = (TMultiGraph*)poly;
9746 TList *gl = mg->GetListOfGraphs();
9747 if (!gl) return;
9748 TGraph *g;
9749 TIter nextg(gl);
9750 while ((g = (TGraph*) nextg())) {
9751 g->TAttLine::Modify();
9752 g->TAttMarker::Modify();
9753 g->TAttFill::Modify();
9754 if (line) {
9755 Int_t fs = g->GetFillStyle();
9756 Int_t db = gStyle->GetDrawBorder();
9757 g->SetFillStyle(0);
9759 g->Paint("F");
9760 gStyle->SetDrawBorder(db);
9761 g->SetFillStyle(fs);
9762 }
9763 if (fill) g->Paint("F");
9764 if (mark) g->Paint("P");
9765 }
9766 }
9767 }
9768}
9769
9770////////////////////////////////////////////////////////////////////////////////
9771/// [Control function to draw a TH2Poly as a color plot.](\ref HP20a)
9772
9774{
9775
9776 //Do not highlight the histogram, if its part was picked.
9777 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
9778 return;
9779
9780 Int_t ncolors, color, theColor;
9781 Double_t z, zc;
9782 Double_t zmin = fH->GetMinimum();
9783 Double_t zmax = fH->GetMaximum();
9784 if (Hoption.Logz) {
9785 if (zmax > 0) {
9786 if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
9787 zmin = TMath::Log10(zmin);
9788 zmax = TMath::Log10(zmax);
9789 } else {
9790 return;
9791 }
9792 }
9793 Double_t dz = zmax - zmin;
9794
9795 // Initialize the levels on the Z axis
9796 ncolors = gStyle->GetNumberOfColors();
9797 Int_t ndiv = fH->GetContour();
9798 if (ndiv == 0 ) {
9799 ndiv = gStyle->GetNumberContours();
9800 fH->SetContour(ndiv);
9801 }
9802 Int_t ndivz = TMath::Abs(ndiv);
9803 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
9804 Double_t scale = ndivz/dz;
9805
9806 TIter next(((TH2Poly*)fH)->GetBins());
9807
9808 while (auto obj = next()) {
9809 TH2PolyBin *b = (TH2PolyBin*)obj;
9810 TObject *poly = b->GetPolygon();
9811
9812 z = b->GetContent();
9813 if (z==0 && Hoption.Zero) continue;
9814 if (Hoption.Logz) {
9815 if (z > 0) z = TMath::Log10(z);
9816 else z = zmin;
9817 }
9818 if (z < zmin) continue;
9819
9820 // Define the bin color.
9822 zc = fH->GetContourLevelPad(0);
9823 if (z < zc) continue;
9824 color = -1;
9825 for (Int_t k=0; k<ndiv; k++) {
9826 zc = fH->GetContourLevelPad(k);
9827 if (z < zc) {
9828 continue;
9829 } else {
9830 color++;
9831 }
9832 }
9833 } else {
9834 color = Int_t(0.01+(z-zmin)*scale);
9835 }
9836 theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
9837 if (theColor > ncolors-1) theColor = ncolors-1;
9838
9839 // Paint the TGraph bins.
9840 if (poly->IsA() == TGraph::Class()) {
9841 TGraph *g = (TGraph*)poly;
9842 g->SetFillColor(gStyle->GetColorPalette(theColor));
9843 g->TAttFill::Modify();
9844 g->Paint("F");
9845 }
9846
9847 // Paint the TMultiGraph bins.
9848 if (poly->IsA() == TMultiGraph::Class()) {
9849 TMultiGraph *mg = (TMultiGraph*)poly;
9850 TList *gl = mg->GetListOfGraphs();
9851 if (!gl) return;
9852 TGraph *g;
9853 TIter nextg(gl);
9854 while ((g = (TGraph*) nextg())) {
9855 g->SetFillColor(gStyle->GetColorPalette(theColor));
9856 g->TAttFill::Modify();
9857 g->Paint("F");
9858 }
9859 }
9860 }
9862}
9863
9864////////////////////////////////////////////////////////////////////////////////
9865/// [Control function to draw a TH2Poly as a scatter plot.](\ref HP20a)
9866
9868{
9869
9870 //Do not highlight the histogram, if its part was selected.
9871 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
9872 return;
9873
9874 Int_t k, loop, marker=0;
9875 Double_t z, xk,xstep, yk, ystep, xp, yp;
9876 Double_t scale = 1;
9877 Double_t zmin = fH->GetMinimum();
9878 Double_t zmax = fH->GetMaximum();
9879 if (Hoption.Logz) {
9880 if (zmax > 0) {
9881 if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
9882 zmin = TMath::Log10(zmin);
9883 zmax = TMath::Log10(zmax);
9884 } else {
9885 return;
9886 }
9887 }
9888 Double_t dz = zmax - zmin;
9889 scale = (kNMAX-1)/dz;
9890
9891
9892 // use an independent instance of a random generator
9893 // instead of gRandom to avoid conflicts and
9894 // to get same random numbers when drawing the same histogram
9895 TRandom2 random;
9896
9897 TH2PolyBin *b;
9898
9899 TIter next(((TH2Poly*)fH)->GetBins());
9900 TObject *obj, *poly;
9901
9902 Double_t maxarea = 0, a;
9903 while ((obj=next())) {
9904 b = (TH2PolyBin*)obj;
9905 a = b->GetArea();
9906 if (a>maxarea) maxarea = a;
9907 }
9908
9909 next.Reset();
9910
9911 while ((obj=next())) {
9912 b = (TH2PolyBin*)obj;
9913 poly = b->GetPolygon();
9914 z = b->GetContent();
9915 if (z < zmin) z = zmin;
9916 if (z > zmax) z = zmax;
9917 if (Hoption.Logz) {
9918 if (z > 0) z = TMath::Log10(z) - zmin;
9919 } else {
9920 z -= zmin;
9921 }
9922 k = Int_t((z*scale)*(b->GetArea()/maxarea));
9923 xk = b->GetXMin();
9924 yk = b->GetYMin();
9925 xstep = b->GetXMax()-xk;
9926 ystep = b->GetYMax()-yk;
9927
9928 // Paint the TGraph bins.
9929 if (poly->IsA() == TGraph::Class()) {
9930 TGraph *g = (TGraph*)poly;
9931 if (k <= 0 || z <= 0) continue;
9932 loop = 0;
9933 while (loop<k) {
9934 if (k+marker >= kNMAX) {
9935 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
9936 marker=0;
9937 }
9938 xp = (random.Rndm()*xstep) + xk;
9939 yp = (random.Rndm()*ystep) + yk;
9940 if (g->IsInside(xp,yp)) {
9941 fXbuf[marker] = xp;
9942 fYbuf[marker] = yp;
9943 marker++;
9944 loop++;
9945 }
9946 }
9947 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
9948 }
9949
9950 // Paint the TMultiGraph bins.
9951 if (poly->IsA() == TMultiGraph::Class()) {
9952 TMultiGraph *mg = (TMultiGraph*)poly;
9953 TList *gl = mg->GetListOfGraphs();
9954 if (!gl) return;
9955 if (k <= 0 || z <= 0) continue;
9956 loop = 0;
9957 while (loop<k) {
9958 if (k+marker >= kNMAX) {
9959 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
9960 marker=0;
9961 }
9962 xp = (random.Rndm()*xstep) + xk;
9963 yp = (random.Rndm()*ystep) + yk;
9964 if (mg->IsInside(xp,yp)) {
9965 fXbuf[marker] = xp;
9966 fYbuf[marker] = yp;
9967 marker++;
9968 loop++;
9969 }
9970 }
9971 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
9972 }
9973 }
9974 PaintTH2PolyBins("l");
9975}
9976
9977////////////////////////////////////////////////////////////////////////////////
9978/// [Control function to draw a TH2Poly as a text plot.](\ref HP20a)
9979
9981{
9982
9983 TLatex text;
9984 text.SetTextFont(gStyle->GetTextFont());
9985 text.SetTextColor(fH->GetMarkerColor());
9986 text.SetTextSize(0.02*fH->GetMarkerSize());
9987
9988 Double_t x, y, z, e, angle = 0;
9989 TString tt, tf;
9990 tf.Form("%s%s","%",gStyle->GetPaintTextFormat());
9991 if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
9992 Int_t opt = (Int_t)Hoption.Text/1000;
9993
9994 text.SetTextAlign(22);
9995 if (Hoption.Text == 1) angle = 0;
9996 text.SetTextAngle(angle);
9997 text.TAttText::Modify();
9998
9999 TH2PolyBin *b;
10000
10001 TIter next(((TH2Poly*)fH)->GetBins());
10002 TObject *obj, *p;
10003
10004 while ((obj=next())) {
10005 b = (TH2PolyBin*)obj;
10006 p = b->GetPolygon();
10007 x = (b->GetXMin()+b->GetXMax())/2;
10008 if (Hoption.Logx) {
10009 if (x > 0) x = TMath::Log10(x);
10010 else continue;
10011 }
10012 y = (b->GetYMin()+b->GetYMax())/2;
10013 if (Hoption.Logy) {
10014 if (y > 0) y = TMath::Log10(y);
10015 else continue;
10016 }
10017 z = b->GetContent();
10018 if (z < fH->GetMinimum() || (z == 0 && !Hoption.MinimumZero)) continue;
10019 if (opt==2) {
10020 e = fH->GetBinError(b->GetBinNumber());
10021 tf.Form("#splitline{%s%s}{#pm %s%s}",
10023 "%",gStyle->GetPaintTextFormat());
10024 tt.Form(tf.Data(),z,e);
10025 } else {
10026 tt.Form(tf.Data(),z);
10027 }
10028 if (opt==3) text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),p->GetName());
10029 else text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),tt.Data());
10030 }
10031
10032 PaintTH2PolyBins("l");
10033}
10034
10035////////////////////////////////////////////////////////////////////////////////
10036/// [Control function to draw a 1D/2D histograms with the bin values.](\ref HP15)
10037
10039{
10040
10041 TLatex text;
10042 text.SetTextFont(gStyle->GetTextFont());
10043 text.SetTextColor(fH->GetMarkerColor());
10044 text.SetTextSize(0.02*fH->GetMarkerSize());
10045
10046 Double_t x, y, z, e, angle = 0;
10047 TString tt, tf;
10048 tf.Form("%s%s","%",gStyle->GetPaintTextFormat());
10049 if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
10050
10051 // 1D histograms
10052 if (fH->GetDimension() == 1) {
10053 Bool_t getentries = kFALSE;
10054 Double_t yt;
10055 TProfile *hp = (TProfile*)fH;
10056 if (Hoption.Text>2000 && fH->InheritsFrom(TProfile::Class())) {
10057 Hoption.Text = Hoption.Text-2000;
10058 getentries = kTRUE;
10059 }
10060 if (Hoption.Text == 1) angle = 90;
10061 text.SetTextAlign(11);
10062 if (angle == 90) text.SetTextAlign(12);
10063 if (angle == 0) text.SetTextAlign(21);
10064 text.TAttText::Modify();
10065 Double_t dt = 0.02*(gPad->GetY2()-gPad->GetY1());
10066 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10067 if (Hoption.Bar) {
10068 x = fH->GetXaxis()->GetBinLowEdge(i)+
10069 fH->GetXaxis()->GetBinWidth(i)*
10070 (fH->GetBarOffset()+0.5*fH->GetBarWidth());
10071 } else {
10072 x = fH->GetXaxis()->GetBinCenter(i);
10073 }
10074 y = fH->GetBinContent(i);
10075 yt = y;
10076 if (Hoption.MinimumZero && y<0) y = 0;
10077 if (getentries) yt = hp->GetBinEntries(i);
10078 if (yt == 0.) continue;
10079 tt.Form(tf.Data(),yt);
10080 if (Hoption.Logx) {
10081 if (x > 0) x = TMath::Log10(x);
10082 else continue;
10083 }
10084 if (Hoption.Logy) {
10085 if (y > 0) y = TMath::Log10(y);
10086 else continue;
10087 }
10088 if (y >= gPad->GetY2()) continue;
10089 if (y <= gPad->GetY1()) continue;
10090 text.PaintLatex(x,y+0.2*dt,angle,0.02*fH->GetMarkerSize(),tt.Data());
10091 }
10092
10093 // 2D histograms
10094 } else {
10095 text.SetTextAlign(22);
10096 if (Hoption.Text == 1) angle = 0;
10097 text.SetTextAngle(angle);
10098 text.TAttText::Modify();
10099 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
10100 y = fYaxis->GetBinCenter(j);
10101 if (Hoption.Logy) {
10102 if (y > 0) y = TMath::Log10(y);
10103 else continue;
10104 }
10105 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10106 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
10107 x = fXaxis->GetBinCenter(i);
10108 if (Hoption.Logx) {
10109 if (x > 0) x = TMath::Log10(x);
10110 else continue;
10111 }
10112 if (!IsInside(x,y)) continue;
10113 z = fH->GetBinContent(bin);
10114 if (z < Hparam.zmin || (z == 0 && !Hoption.MinimumZero)) continue;
10115 if (Hoption.Text>2000) {
10116 e = fH->GetBinError(bin);
10117 tf.Form("#splitline{%s%s}{#pm %s%s}",
10119 "%",gStyle->GetPaintTextFormat());
10120 tt.Form(tf.Data(),z,e);
10121 } else {
10122 tt.Form(tf.Data(),z);
10123 }
10124 text.PaintLatex(x,y+fH->GetBarOffset()*fYaxis->GetBinWidth(j),
10125 angle,0.02*fH->GetMarkerSize(),tt.Data());
10126 }
10127 }
10128 }
10129}
10130
10131////////////////////////////////////////////////////////////////////////////////
10132/// [Control function to draw a 3D implicit functions.](\ref HP27)
10133
10135{
10136
10137 Int_t irep;
10138
10139 TAxis *xaxis = fH->GetXaxis();
10140 TAxis *yaxis = fH->GetYaxis();
10141 TAxis *zaxis = fH->GetZaxis();
10142
10143 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
10144 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
10145 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
10146 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
10147 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
10148 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
10149
10150 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
10151
10152 TView *view = gPad ? gPad->GetView() : nullptr;
10153 if (!view) {
10154 Error("PaintTF3", "no TView in current pad");
10155 return;
10156 }
10157 Double_t thedeg = 90 - gPad->GetTheta();
10158 Double_t phideg = -90 - gPad->GetPhi();
10159 Double_t psideg = view->GetPsi();
10160 view->SetView(phideg, thedeg, psideg, irep);
10161
10162 fLego->InitMoveScreen(-1.1,1.1);
10163
10164 if (Hoption.BackBox) {
10165 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
10167 fLego->BackBox(90);
10168 }
10169
10171
10172 fLego->ImplicitFunction(fCurrentF3, fXbuf.data(), fYbuf.data(), fH->GetNbinsX(),
10173 fH->GetNbinsY(),
10174 fH->GetNbinsZ(), "BF");
10175
10176 if (Hoption.FrontBox) {
10177 fLego->InitMoveScreen(-1.1,1.1);
10179 fLego->FrontBox(90);
10180 }
10181 if (!Hoption.Axis && !Hoption.Same) {
10182 TGaxis axis;
10183 PaintLegoAxis(&axis, 90);
10184 }
10185
10186 PaintTitle();
10187
10188 fLego.reset();
10189}
10190
10191/////////////////////////////////////////////////////////////new TGaxis///////////////////
10192/// Draw the histogram title
10193///
10194/// The title is drawn according to the title alignment returned by
10195/// `GetTitleAlign()`. It is a 2 digits integer): hv
10196///
10197/// where `h` is the horizontal alignment and `v` is the
10198/// vertical alignment.
10199///
10200/// - `h` can get the values 1 2 3 for left, center, and right
10201/// - `v` can get the values 1 2 3 for bottom, middle and top
10202///
10203/// for instance the default alignment is: 13 (left top)
10204
10206{
10207 // probably best place for calls PaintHighlightBin
10208 // calls after paint histo (1D or 2D) and before paint title and stats
10209 if (!gPad->GetView()) PaintHighlightBin();
10210
10211 if (Hoption.Same) return;
10212 if (fH->TestBit(TH1::kNoTitle)) return;
10213 Int_t nt = strlen(fH->GetTitle());
10214 TPaveText *title = nullptr;
10215 TObject *obj;
10216 TIter next(gPad->GetListOfPrimitives());
10217 while ((obj = next())) {
10218 if (!obj->InheritsFrom(TPaveText::Class())) continue;
10219 title = (TPaveText*)obj;
10220 if (strcmp(title->GetName(),"title")) {title = nullptr; continue;}
10221 break;
10222 }
10223 if (nt == 0 || gStyle->GetOptTitle() <= 0) {
10224 if (title) delete title;
10225 return;
10226 }
10227 Double_t ht = gStyle->GetTitleH();
10228 Double_t wt = gStyle->GetTitleW();
10229
10230 if (ht <= 0) {
10231 if (gStyle->GetTitleFont("")%10 == 3) {
10232 Double_t hw = TMath::Max((Double_t)gPad->XtoPixel(gPad->GetX2()),
10233 (Double_t)gPad->YtoPixel(gPad->GetY1()));
10234 ht = 1.1*(gStyle->GetTitleSize("")/hw);
10235 } else {
10236 ht = 1.1*gStyle->GetTitleFontSize();
10237 }
10238 }
10239 if (ht <= 0) ht = 0.05;
10240 if (wt <= 0) {
10241 TLatex l;
10242 l.SetTextSize(ht);
10243 l.SetTitle(fH->GetTitle());
10244 // adjustment in case the title has several lines (#splitline)
10245 ht = TMath::Max(ht, 1.2*l.GetYsize()/(gPad->GetY2() - gPad->GetY1()));
10246 Double_t wndc = l.GetXsize()/(gPad->GetX2() - gPad->GetX1());
10247 wt = TMath::Min(0.7, 0.02+wndc);
10248 }
10249 if (title) {
10250 TText *t0 = (TText*)title->GetLine(0);
10251 if (t0) {
10252 if (!strcmp(t0->GetTitle(),fH->GetTitle())) return;
10253 t0->SetTitle(fH->GetTitle());
10254 if (wt > 0) title->SetX2NDC(title->GetX1NDC()+wt);
10255 }
10256 return;
10257 }
10258
10259 Int_t talh = gStyle->GetTitleAlign()/10;
10260 if (talh < 1) talh = 1; else if (talh > 3) talh = 3;
10261 Int_t talv = gStyle->GetTitleAlign()%10;
10262 if (talv < 1) talv = 1; else if (talv > 3) talv = 3;
10264 xpos = gStyle->GetTitleX();
10265 ypos = gStyle->GetTitleY();
10266 if (talh == 2) xpos = xpos-wt/2.;
10267 if (talh == 3) xpos = xpos-wt;
10268 if (talv == 2) ypos = ypos+ht/2.;
10269 if (talv == 1) ypos = ypos+ht;
10270
10271 TPaveText *ptitle = new TPaveText(xpos, ypos-ht, xpos+wt, ypos,"blNDC");
10272
10273 // box with the histogram title
10275 ptitle->SetFillStyle(gStyle->GetTitleStyle());
10276 ptitle->SetName("title");
10279 ptitle->SetTextFont(gStyle->GetTitleFont(""));
10280 if (gStyle->GetTitleFont("")%10 > 2)
10282 ptitle->AddText(fH->GetTitle());
10283 ptitle->SetBit(kCanDelete);
10284 ptitle->Draw();
10285 ptitle->Paint("blNDC");
10286
10287 if(!gPad->IsEditable()) delete ptitle;
10288}
10289
10290////////////////////////////////////////////////////////////////////////////////
10291/// Process message `mess`.
10292
10293void THistPainter::ProcessMessage(const char *mess, const TObject *obj)
10294{
10295 if (!strcmp(mess,"SetF3")) {
10296 fCurrentF3 = (TF3 *)obj;
10297 }
10298}
10299
10300////////////////////////////////////////////////////////////////////////////////
10301/// Static function.
10302///
10303/// Convert Right Ascension, Declination to X,Y using an AITOFF projection.
10304/// This procedure can be used to create an all-sky map in Galactic
10305/// coordinates with an equal-area Aitoff projection. Output map
10306/// coordinates are zero longitude centered.
10307/// Also called Hammer-Aitoff projection (first presented by Ernst von Hammer in 1892)
10308///
10309/// source: GMT
10310///
10311/// code from Ernst-Jan Buis
10312
10314{
10315
10316 Double_t x, y;
10317
10318 Double_t alpha2 = (l/2)*TMath::DegToRad();
10319 Double_t delta = b*TMath::DegToRad();
10320 Double_t r2 = TMath::Sqrt(2.);
10321 Double_t f = 2*r2/TMath::Pi();
10322 Double_t cdec = TMath::Cos(delta);
10323 Double_t denom = TMath::Sqrt(1. + cdec*TMath::Cos(alpha2));
10324 x = cdec*TMath::Sin(alpha2)*2.*r2/denom;
10325 y = TMath::Sin(delta)*r2/denom;
10326 x *= TMath::RadToDeg()/f;
10327 y *= TMath::RadToDeg()/f;
10328 // x *= -1.; // for a skymap swap left<->right
10329 Al = x;
10330 Ab = y;
10331
10332 return 0;
10333}
10334
10335////////////////////////////////////////////////////////////////////////////////
10336/// Static function
10337///
10338/// Probably the most famous of the various map projections, the Mercator projection
10339/// takes its name from Mercator who presented it in 1569. It is a cylindrical, conformal projection
10340/// with no distortion along the equator.
10341/// The Mercator projection has been used extensively for world maps in which the distortion towards
10342/// the polar regions grows rather large, thus incorrectly giving the impression that, for example,
10343/// Greenland is larger than South America. In reality, the latter is about eight times the size of
10344/// Greenland. Also, the Former Soviet Union looks much bigger than Africa or South America. One may wonder
10345/// whether this illusion has had any influence on U.S. foreign policy.' (Source: GMT)
10346/// code from Ernst-Jan Buis
10347
10349{
10350
10351 Al = l;
10353 Ab = TMath::Log(aid);
10354 return 0;
10355}
10356
10357////////////////////////////////////////////////////////////////////////////////
10358/// Static function code for sinusoidal projection
10359/// from Ernst-Jan Buis
10360/// Source https://en.wikipedia.org/wiki/Sinusoidal_projection
10361
10363{
10364
10365 Al = l*cos(b*TMath::DegToRad());
10366 Ab = b;
10367 return 0;
10368}
10369
10370////////////////////////////////////////////////////////////////////////////////
10371/// Static function code for parabolic projection
10372/// from Ernst-Jan Buis
10373
10375{
10376
10377 Al = l*(2.*TMath::Cos(2*b*TMath::DegToRad()/3) - 1);
10378 Ab = 180*TMath::Sin(b*TMath::DegToRad()/3);
10379 return 0;
10380}
10381
10382////////////////////////////////////////////////////////////////////////////////
10383/// Static function.
10384///
10385/// Convert Right Ascension, Declination to X,Y using an MOLLWEIDE projection.
10386/// This procedure can be used to create an all-sky map in Galactic
10387/// coordinates with an equal-area Mollweide projection. Output map
10388/// coordinates are zero longitude centered.
10389/// It is also known as the Babinet projection, homalographic projection, homolographic projection, and elliptical projection.
10390/// Source: https://en.wikipedia.org/wiki/Mollweide_projection
10391///
10392/// code from Marco Meyer-Conde
10393
10395{
10396
10397 Double_t theta0 = b * TMath::DegToRad(), theta = theta0;
10398
10399 for (int i = 0; i < 100; i++) {
10400 Double_t num = 2 * theta + TMath::Sin(2 * theta) - TMath::Pi() * TMath::Sin(theta0);
10401 Double_t den = 4 * TMath::Power(TMath::Cos(theta), 2);
10402
10403 if (den < 1e-20) {
10404 theta = theta0;
10405 break;
10406 }
10407
10408 theta -= num / den;
10409
10410 if (TMath::Abs(num / den) < 1e-4) break;
10411 }
10412
10413 Al = l * TMath::Cos(theta);
10414 Ab = 90 * TMath::Sin(theta);
10415
10416 return 0;
10417}
10418
10419////////////////////////////////////////////////////////////////////////////////
10420/// Recompute the histogram range following graphics operations.
10421
10423{
10424
10425 if (Hoption.Same) return;
10426
10427 // Compute x,y range
10429 xmax = Hparam.xmax,
10430 ymin = Hparam.ymin,
10431 ymax = Hparam.ymax,
10432 xscale = 1;
10433
10434 std::function<Int_t(Double_t,Double_t,Double_t&,Double_t&)> func;
10435
10436 if (Hoption.Proj == 1) {
10437 func = ProjectAitoff2xy;
10438 xscale = 0.9999;
10439 } else if (Hoption.Proj == 2) {
10440 if (Hparam.ymin <= -90 || Hparam.ymax >= 90) {
10441 Warning("Mercator Projection", "Latitude out of range %f or %f", Hparam.ymin, Hparam.ymax);
10442 Hoption.Proj = 0;
10443 } else {
10446 }
10447 } else if (Hoption.Proj == 3) {
10448 func = ProjectSinusoidal2xy;
10449 } else if (Hoption.Proj == 4) {
10450 func = ProjectParabolic2xy;
10451 } else if (Hoption.Proj == 5) {
10452 func = ProjectMollweide2xy;
10453 }
10454
10455 if (func) {
10456 Double_t xmin_aid, ymin_aid, xmax_aid, ymax_aid;
10457
10458 func(Hparam.xmin, Hparam.ymin, xmin_aid, ymin_aid);
10459 func(Hparam.xmin, Hparam.ymax, xmin, ymax_aid);
10460 func(Hparam.xmax, Hparam.ymax, xmax_aid, ymax);
10461 func(Hparam.xmax, Hparam.ymin, xmax, ymin);
10462
10463 if (xmin > xmin_aid) xmin = xmin_aid;
10464 if (ymin > ymin_aid) ymin = ymin_aid;
10465 if (xmax < xmax_aid) xmax = xmax_aid;
10466 if (ymax < ymax_aid) ymax = ymax_aid;
10467 if (Hparam.ymin < 0 && Hparam.ymax > 0) {
10468 // there is an 'equator', check its range in the plot..
10469 func(Hparam.xmin*xscale, 0, xmin_aid, ymin_aid);
10470 func(Hparam.xmax*xscale, 0, xmax_aid, ymin_aid);
10471 if (xmin > xmin_aid) xmin = xmin_aid;
10472 if (xmax < xmax_aid) xmax = xmax_aid;
10473 }
10474 if (Hparam.xmin < 0 && Hparam.xmax > 0) {
10475 func(0, Hparam.ymin, xmin_aid, ymin_aid);
10476 func(0, Hparam.ymax, xmax_aid, ymax_aid);
10477 if (ymin > ymin_aid) ymin = ymin_aid;
10478 if (ymax < ymax_aid) ymax = ymax_aid;
10479 }
10480 }
10481
10482 Hparam.xmin = xmin;
10483 Hparam.xmax = xmax;
10484 Hparam.ymin = ymin;
10485 Hparam.ymax = ymax;
10486
10487 Double_t dx = xmax-xmin;
10488 Double_t dy = ymax-ymin;
10489 Double_t dxr = dx/(1 - gPad->GetLeftMargin() - gPad->GetRightMargin());
10490 Double_t dyr = dy/(1 - gPad->GetBottomMargin() - gPad->GetTopMargin());
10491
10492 // Range() could change the size of the pad pixmap and therefore should
10493 // be called before the other paint routines
10494 gPad->Range(xmin - dxr*gPad->GetLeftMargin(),
10495 ymin - dyr*gPad->GetBottomMargin(),
10496 xmax + dxr*gPad->GetRightMargin(),
10497 ymax + dyr*gPad->GetTopMargin());
10498 gPad->RangeAxis(xmin, ymin, xmax, ymax);
10499}
10500
10501////////////////////////////////////////////////////////////////////////////////
10502/// Set current histogram to `h`
10503
10505{
10506
10507 if (h == nullptr) return;
10508 fH = h;
10509 fXaxis = h->GetXaxis();
10510 fYaxis = h->GetYaxis();
10511 fZaxis = h->GetZaxis();
10513}
10514
10515////////////////////////////////////////////////////////////////////////////////
10516/// Initialize various options to draw 2D histograms.
10517
10519{
10520
10521 static const char *where = "TableInit";
10522
10523 Int_t first, last;
10524 Double_t yMARGIN= gStyle->GetHistTopMargin();
10525 Double_t zmin, zmax;
10526 Int_t maximum = 0;
10527 Int_t minimum = 0;
10528 if (fH->GetMaximumStored() != -1111) maximum = 1;
10529 if (fH->GetMinimumStored() != -1111) minimum = 1;
10530
10531 // ----------------- Compute X axis parameters
10532 first = fXaxis->GetFirst();
10533 last = fXaxis->GetLast();
10534 Hparam.xlast = last;
10535 Hparam.xfirst = first;
10540
10541 // if log scale in X, replace xmin,max by the log
10542 if (Hoption.Logx) {
10543 // find the first edge of a bin that is > 0
10544 if (Hparam.xlowedge <=0 ) {
10547 }
10548 if (Hparam.xmin <=0 || Hparam.xmax <=0) {
10549 Error(where, "cannot set X axis to log scale");
10550 return 0;
10551 }
10553 if (Hparam.xfirst < first) Hparam.xfirst = first;
10555 if (Hparam.xlast > last) Hparam.xlast = last;
10558 }
10559
10560 // ----------------- Compute Y axis parameters
10561 first = fYaxis->GetFirst();
10562 last = fYaxis->GetLast();
10563 Hparam.ylast = last;
10564 Hparam.yfirst = first;
10567 if (!Hparam.ybinsize) Hparam.ybinsize = 1;
10570
10571 // if log scale in Y, replace ymin,max by the log
10572 if (Hoption.Logy) {
10573 if (Hparam.ylowedge <=0 ) {
10576 }
10577 if (Hparam.ymin <=0 || Hparam.ymax <=0) {
10578 Error(where, "cannot set Y axis to log scale");
10579 return 0;
10580 }
10582 if (Hparam.yfirst < first) Hparam.yfirst = first;
10584 if (Hparam.ylast > last) Hparam.ylast = last;
10587 }
10588
10589
10590 // ----------------- Compute Z axis parameters
10591 Double_t bigp = TMath::Power(10,32);
10592 zmax = -bigp;
10593 zmin = bigp;
10594 Double_t c1, e1;
10595 Double_t allchan = 0;
10596 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
10597 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10598 c1 = fH->GetBinContent(i,j);
10599 zmax = TMath::Max(zmax,c1);
10600 if (Hoption.Error) {
10601 e1 = fH->GetBinError(i,j);
10602 zmax = TMath::Max(zmax,c1+e1);
10603 }
10604 zmin = TMath::Min(zmin,c1);
10605 allchan += c1;
10606 }
10607 }
10608
10609 // Take into account maximum , minimum
10610
10611 if (maximum) zmax = fH->GetMaximumStored();
10612 if (minimum) zmin = fH->GetMinimumStored();
10613 if (Hoption.Logz && zmax < 0) {
10614 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10615 return 0;
10616 } else if (Hoption.Logz && zmin>=0 && zmax==0) { // empty histogram in log scale
10617 zmin = 0.01;
10618 zmax = 10.;
10619 }
10620 if (zmin >= zmax) {
10621 if (Hoption.Logz) {
10622 if (zmax > 0) zmin = 0.001*zmax;
10623 else {
10624 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10625 return 0;
10626 }
10627 }
10628 }
10629
10630 // take into account normalization factor
10631 Hparam.allchan = allchan;
10632 Double_t factor = allchan;
10633 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
10634 if (allchan) factor /= allchan;
10635 if (factor == 0) factor = 1;
10636 Hparam.factor = factor;
10637 zmax = factor*zmax;
10638 zmin = factor*zmin;
10639 c1 = zmax;
10640 if (TMath::Abs(zmin) > TMath::Abs(c1)) c1 = zmin;
10641
10642 // For log scales, histogram coordinates are log10(ymin) and
10643 // log10(ymax). Final adjustment (if not option "Same")
10644 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
10645 // Maximum and Minimum are not defined.
10646 if (Hoption.Logz) {
10647 if (zmin <= 0) {
10648 zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
10649 fH->SetMinimum(zmin);
10650 }
10651 zmin = TMath::Log10(zmin);
10652 if (!minimum) zmin += TMath::Log10(0.5);
10653 zmax = TMath::Log10(zmax);
10654 if (!maximum) zmax += TMath::Log10(2*(0.9/0.95));
10655 goto LZMIN;
10656 }
10657
10658 // final adjustment of YMAXI for linear scale (if not option "Same"):
10659 // decrease histogram height to MAX% of allowed height if HMAXIM
10660 // has not been called.
10661 // MAX% is the value in percent which has been set in HPLSET
10662 // (default is 90%).
10663 if (!maximum) {
10664 zmax += yMARGIN*(zmax-zmin);
10665 }
10666
10667 // final adjustment of ymin for linear scale.
10668 // if minimum is not set , then ymin is set to zero if >0
10669 // or to ymin - yMARGIN if <0.
10670 if (!minimum) {
10671 if (Hoption.MinimumZero) {
10672 if (zmin >= 0) zmin = 0;
10673 else zmin -= yMARGIN*(zmax-zmin);
10674 } else {
10675 Double_t dzmin = yMARGIN*(zmax-zmin);
10676 if (zmin >= 0 && (zmin-dzmin <= 0)) zmin = 0;
10677 else zmin -= dzmin;
10678 }
10679 }
10680
10681LZMIN:
10682 Hparam.zmin = zmin;
10683 Hparam.zmax = zmax;
10684
10685 // Set bar offset and width
10688
10689 return 1;
10690}
10691
10692////////////////////////////////////////////////////////////////////////////////
10693/// This function returns the best format to print the error value (e)
10694/// knowing the parameter value (v) and the format (f) used to print it.
10695
10697{
10698
10699 static TString ef;
10700 TString tf, tv;
10701
10702 // print v with the format f in tv.
10703 tf.Form("%s%s","%",f);
10704 tv.Form(tf.Data(),v);
10705
10706 // Analyse tv.
10707 int ie = tv.Index("e");
10708 int iE = tv.Index("E");
10709 int id = tv.Index(".");
10710
10711 // v has been printed with the exponent notation.
10712 // There is 2 cases, the exponent is positive or negative
10713 if (ie >= 0 || iE >= 0) {
10714 if (tv.Index("+") >= 0) {
10715 if (e < 1) {
10716 ef.Form("%s.1f","%");
10717 } else {
10718 if (ie >= 0) {
10719 ef.Form("%s.%de","%",ie-id-1);
10720 } else {
10721 ef.Form("%s.%dE","%",iE-id-1);
10722 }
10723 }
10724 } else {
10725 if (ie >= 0) {
10726 ef.Form("%s.%de","%",ie-id-1);
10727 } else {
10728 ef.Form("%s.%dE","%",iE-id-1);
10729 }
10730 }
10731
10732 // There is not '.' in tv. e will be printed with one decimal digit.
10733 } else if (id < 0) {
10734 ef.Form("%s.1f","%");
10735
10736 // There is a '.' in tv and no exponent notation. e's decimal part will
10737 // have the same number of digits as v's one.
10738 } else {
10739 ef.Form("%s.%df","%",tv.Length()-id-1);
10740 }
10741
10742 return ef.Data();
10743}
10744
10745////////////////////////////////////////////////////////////////////////////////
10746/// Set projection.
10747
10749{
10750 if (fShowProjection2) {
10751 auto name2 = TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2);
10752 auto c2 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name2.Data()));
10753 if (c2) c2->Close();
10754 fShowProjection2 = 0;
10755 }
10756 if (fShowProjection) {
10757 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10758 auto c1 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name1.Data()));
10759 if (c1) c1->Close();
10760 fShowProjection = 0;
10761 }
10762
10763 if (nbins <= 0) return;
10764
10765 TString opt = option;
10766 opt.ToLower();
10767 Int_t projection = 0;
10768 if (opt.Contains("x")) projection = 1;
10769 if (opt.Contains("y")) projection = 2;
10770 if (opt.Contains("z")) projection = 3;
10771 if (opt.Contains("xy")) projection = 4;
10772 if (opt.Contains("yx")) projection = 5;
10773 if (opt.Contains("xz")) projection = 6;
10774 if (opt.Contains("zx")) projection = 7;
10775 if (opt.Contains("yz")) projection = 8;
10776 if (opt.Contains("zy")) projection = 9;
10777 if (projection < 4) fShowOption = option+1;
10778 else fShowOption = option+2;
10779 fShowProjection = projection+100*nbins;
10780 fShowProjection2 = 0;
10781 gROOT->MakeDefCanvas();
10782 gPad->SetName(TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection).Data());
10783 gPad->SetGrid();
10784}
10785
10787{
10788 if (fShowProjection2) {
10789 auto name2 = TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2);
10790 auto c2 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name2.Data()));
10791 if (c2) c2->Close();
10792 fShowProjection2 = 0;
10793 }
10794 if (fShowProjection) {
10795 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10796 auto c1 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name1.Data()));
10797 if (c1) c1->Close();
10798 fShowProjection = 0;
10799 }
10800
10801 if ((nbinsX <= 0) || (nbinsY <= 0)) return;
10802
10803
10804 TString opt = option;
10805 opt.ToLower();
10806 Int_t projection = 0;
10807 if (opt.Contains("x")) projection = 1;
10808 if (opt.Contains("y")) projection = 2;
10809 if (opt.Contains("z")) projection = 3;
10810 if (opt.Contains("xy")) projection = 4;
10811 if (opt.Contains("yx")) projection = 5;
10812 if (opt.Contains("xz")) projection = 6;
10813 if (opt.Contains("zx")) projection = 7;
10814 if (opt.Contains("yz")) projection = 8;
10815 if (opt.Contains("zy")) projection = 9;
10816 if (projection < 4) fShowOption = option+1;
10817 else fShowOption = option+2;
10818 fShowProjection = projection+100*nbinsY;
10819 fShowProjection2 = projection+100*nbinsX;
10820 gROOT->MakeDefCanvas();
10821 gPad->SetName(TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection).Data());
10822 gPad->SetGrid();
10823 gROOT->MakeDefCanvas();
10824 gPad->SetName(TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2).Data());
10825 gPad->SetGrid();
10826}
10827
10828
10829////////////////////////////////////////////////////////////////////////////////
10830/// Show projection onto X.
10831
10833{
10834
10835 Int_t nbins = (Int_t)fShowProjection/100;
10836 gPad->SetDoubleBuffer(0); // turn off double buffer mode
10837 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
10838
10839 // Erase old position and draw a line at current position
10840 static int pyold1 = 0;
10841 static int pyold2 = 0;
10842 float uxmin = gPad->GetUxmin();
10843 float uxmax = gPad->GetUxmax();
10844 int pxmin = gPad->XtoAbsPixel(uxmin);
10845 int pxmax = gPad->XtoAbsPixel(uxmax);
10846 Float_t upy = gPad->AbsPixeltoY(py);
10847 Float_t y = gPad->PadtoY(upy);
10848 Int_t biny1 = fH->GetYaxis()->FindBin(y);
10849 Int_t biny2 = TMath::Min(biny1+nbins-1, fH->GetYaxis()->GetNbins());
10850 Int_t py1 = gPad->YtoAbsPixel(fH->GetYaxis()->GetBinLowEdge(biny1));
10851 Int_t py2 = gPad->YtoAbsPixel(fH->GetYaxis()->GetBinUpEdge(biny2));
10852
10853 if (pyold1 || pyold2) gVirtualX->DrawBox(pxmin,pyold1,pxmax,pyold2,TVirtualX::kFilled);
10854 gVirtualX->DrawBox(pxmin,py1,pxmax,py2,TVirtualX::kFilled);
10855 pyold1 = py1;
10856 pyold2 = py2;
10857
10858 // Create or set the new canvas proj x
10859 TVirtualPad::TContext ctxt(true);
10860 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10861 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(name1.Data());
10862 if (c) {
10863 c->Clear();
10864 } else {
10865 fShowProjection = 0;
10866 fShowProjection2 = 0;
10867 pyold1 = 0;
10868 pyold2 = 0;
10869 return;
10870 }
10871 c->cd();
10872 c->SetLogy(ctxt.GetSaved()->GetLogz());
10873 c->SetLogx(ctxt.GetSaved()->GetLogx());
10874
10875 // Draw slice corresponding to mouse position
10876 TString prjName = TString::Format("slice_px_of_%s",fH->GetName());
10877 TH1D *hp = ((TH2*)fH)->ProjectionX(prjName, biny1, biny2);
10878 if (hp) {
10879 hp->SetFillColor(38);
10880 // apply a patch from Oliver Freyermuth to set the title in the projection
10881 // using the range of the projected Y values
10882 if (biny1 == biny2) {
10883 Double_t valueFrom = fH->GetYaxis()->GetBinLowEdge(biny1);
10884 Double_t valueTo = fH->GetYaxis()->GetBinUpEdge(biny1);
10885 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
10886 Int_t valuePrecision = -TMath::Nint(TMath::Log10(valueTo-valueFrom))+1;
10887 if (fH->GetYaxis()->GetLabels() != nullptr) {
10888 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf] %s", biny1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetYaxis()->GetBinLabel(biny1)));
10889 } else {
10890 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf]", biny1, valuePrecision, valueFrom, valuePrecision, valueTo));
10891 }
10892 } else {
10893 Double_t valueFrom = fH->GetYaxis()->GetBinLowEdge(biny1);
10894 Double_t valueTo = fH->GetYaxis()->GetBinUpEdge(biny2);
10895 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
10896 // biny1 is used here to get equal precision no matter how large the binrange is,
10897 // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
10898 Int_t valuePrecision = -TMath::Nint(TMath::Log10(fH->GetYaxis()->GetBinUpEdge(biny1)-valueFrom))+1;
10899 if (fH->GetYaxis()->GetLabels() != nullptr) {
10900 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)));
10901 } else {
10902 hp->SetTitle(TString::Format("ProjectionX of biny=[%d,%d] [y=%.*lf..%.*lf]", biny1, biny2, valuePrecision, valueFrom, valuePrecision, valueTo));
10903 }
10904 }
10905 hp->SetXTitle(fH->GetXaxis()->GetTitle());
10906 hp->SetYTitle(((TH2*)fH)->GetZaxis()->GetTitle() ? ((TH2*)fH)->GetZaxis()->GetTitle() : "Number of Entries");
10907 hp->Draw();
10908 c->Update();
10909 }
10910}
10911
10912////////////////////////////////////////////////////////////////////////////////
10913/// Show projection onto Y.
10914
10916{
10917
10918 Int_t nbins = (Int_t)fShowProjection/100;
10919 if (fShowProjection2)
10920 nbins = (Int_t)fShowProjection2/100;
10921 gPad->SetDoubleBuffer(0); // turn off double buffer mode
10922 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
10923
10924 // Erase old position and draw a line at current position
10925 static int pxold1 = 0;
10926 static int pxold2 = 0;
10927 float uymin = gPad->GetUymin();
10928 float uymax = gPad->GetUymax();
10929 int pymin = gPad->YtoAbsPixel(uymin);
10930 int pymax = gPad->YtoAbsPixel(uymax);
10931 Float_t upx = gPad->AbsPixeltoX(px);
10932 Float_t x = gPad->PadtoX(upx);
10933 Int_t binx1 = fH->GetXaxis()->FindBin(x);
10934 Int_t binx2 = TMath::Min(binx1+nbins-1, fH->GetXaxis()->GetNbins());
10935 Int_t px1 = gPad->XtoAbsPixel(fH->GetXaxis()->GetBinLowEdge(binx1));
10936 Int_t px2 = gPad->XtoAbsPixel(fH->GetXaxis()->GetBinUpEdge(binx2));
10937
10938 if (pxold1 || pxold2) gVirtualX->DrawBox(pxold1,pymin,pxold2,pymax,TVirtualX::kFilled);
10939 gVirtualX->DrawBox(px1,pymin,px2,pymax,TVirtualX::kFilled);
10940 pxold1 = px1;
10941 pxold2 = px2;
10942
10943 // Create or set the new canvas proj y
10944 TVirtualPad::TContext ctxt(true);
10945
10946 TString name2 = fShowProjection2 ? TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2)
10947 : TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10948
10949 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(name2.Data());
10950 if (c) {
10951 c->Clear();
10952 } else {
10953 fShowProjection = 0;
10954 fShowProjection2 = 0;
10955 pxold1 = 0;
10956 pxold2 = 0;
10957 return;
10958 }
10959 c->cd();
10960 c->SetLogy(ctxt.GetSaved()->GetLogz());
10961 c->SetLogx(ctxt.GetSaved()->GetLogy());
10962
10963 // Draw slice corresponding to mouse position
10964 TString prjName = TString::Format("slice_py_of_%s",fH->GetName());
10965 TH1D *hp = ((TH2*)fH)->ProjectionY(prjName, binx1, binx2);
10966 if (hp) {
10967 hp->SetFillColor(38);
10968 // apply a patch from Oliver Freyermuth to set the title in the projection
10969 // using the range of the projected X values
10970 if (binx1 == binx2) {
10971 Double_t valueFrom = fH->GetXaxis()->GetBinLowEdge(binx1);
10972 Double_t valueTo = fH->GetXaxis()->GetBinUpEdge(binx1);
10973 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
10974 Int_t valuePrecision = -TMath::Nint(TMath::Log10(valueTo-valueFrom))+1;
10975 if (fH->GetXaxis()->GetLabels() != nullptr) {
10976 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf] [%s]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetXaxis()->GetBinLabel(binx1)));
10977 } else {
10978 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo));
10979 }
10980 } else {
10981 Double_t valueFrom = fH->GetXaxis()->GetBinLowEdge(binx1);
10982 Double_t valueTo = fH->GetXaxis()->GetBinUpEdge(binx2);
10983 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
10984 // binx1 is used here to get equal precision no matter how large the binrange is,
10985 // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
10986 Int_t valuePrecision = -TMath::Nint(TMath::Log10(fH->GetXaxis()->GetBinUpEdge(binx1)-valueFrom))+1;
10987 if (fH->GetXaxis()->GetLabels() != nullptr) {
10988 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)));
10989 } else {
10990 hp->SetTitle(TString::Format("ProjectionY of binx=[%d,%d] [x=%.*lf..%.*lf]", binx1, binx2, valuePrecision, valueFrom, valuePrecision, valueTo));
10991 }
10992 }
10993 hp->SetXTitle(fH->GetYaxis()->GetTitle());
10994 hp->SetYTitle(((TH2*)fH)->GetZaxis()->GetTitle() ? ((TH2*)fH)->GetZaxis()->GetTitle() : "Number of Entries");
10995 hp->Draw(fShowProjection2 ? "hbar" : "");
10996 c->Update();
10997 }
10998}
10999
11000////////////////////////////////////////////////////////////////////////////////
11001/// Show projection (specified by `fShowProjection`) of a `TH3`.
11002/// The drawing option for the projection is in `fShowOption`.
11003///
11004/// First implementation; R.Brun
11005///
11006/// Full implementation: Tim Tran (timtran@jlab.org) April 2006
11007
11009{
11010
11011 Int_t nbins=(Int_t)fShowProjection/100; //decode nbins
11012 if (fH->GetDimension() < 3) {
11013 if (fShowProjection2 % 100 == 1) {
11014 ShowProjectionY(px, py);
11015 }
11016 if (fShowProjection % 100 == 1) {
11017 ShowProjectionX(px, py);
11018 return;
11019 }
11020 if (fShowProjection % 100 == 2) {
11021 ShowProjectionY(px, py);
11022 return;
11023 }
11024 }
11025
11026 gPad->SetDoubleBuffer(0); // turn off double buffer mode
11027 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
11028
11029 // Erase old position and draw a line at current position
11030 TView *view = gPad->GetView();
11031 if (!view) return;
11032 TH3 *h3 = (TH3*)fH;
11033 TAxis *xaxis = h3->GetXaxis();
11034 TAxis *yaxis = h3->GetYaxis();
11035 TAxis *zaxis = h3->GetZaxis();
11036 Double_t u[3],xx[3];
11037
11038 static TPoint line1[2];//store end points of a line, initialised 0 by default
11039 static TPoint line2[2];// second line when slice thickness > 1 bin thickness
11040 static TPoint line3[2];
11041 static TPoint line4[2];
11042 static TPoint endface1[5];
11043 static TPoint endface2[5];
11044 static TPoint rect1[5];//store vertices of the polyline (rectangle), initialsed 0 by default
11045 static TPoint rect2[5];// second rectangle when slice thickness > 1 bin thickness
11046
11047 Double_t uxmin = gPad->GetUxmin();
11048 Double_t uxmax = gPad->GetUxmax();
11049 Double_t uymin = gPad->GetUymin();
11050 Double_t uymax = gPad->GetUymax();
11051
11052 int pxmin = gPad->XtoAbsPixel(uxmin);
11053 int pxmax = gPad->XtoAbsPixel(uxmax);
11054 if (pxmin==pxmax) return;
11055 int pymin = gPad->YtoAbsPixel(uymin);
11056 int pymax = gPad->YtoAbsPixel(uymax);
11057 if (pymin==pymax) return;
11058 Double_t cx = (pxmax-pxmin)/(uxmax-uxmin);
11059 Double_t cy = (pymax-pymin)/(uymax-uymin);
11060 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(TString::Format("c_%zx_projection_%d",
11061 (size_t)fH, fShowProjection).Data());
11062 if (!c) {
11063 fShowProjection = 0;
11064 return;
11065 }
11066
11067 TVirtualPad::TContext ctxt(true);
11068
11069 switch ((Int_t)fShowProjection%100) {
11070 case 1:
11071 // "x"
11072 {
11073 Int_t firstY = yaxis->GetFirst();
11074 Int_t lastY = yaxis->GetLast();
11075 Int_t biny = firstY + Int_t((lastY-firstY)*(px-pxmin)/(pxmax-pxmin));
11076 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11077 yaxis->SetRange(biny,biny2);
11078 Int_t firstZ = zaxis->GetFirst();
11079 Int_t lastZ = zaxis->GetLast();
11080 Int_t binz = firstZ + Int_t((lastZ-firstZ)*(py-pymin)/(pymax-pymin));
11081 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11082 zaxis->SetRange(binz,binz2);
11083 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11084 if (nbins>1 && line1[0].GetX()) {
11085 gVirtualX->DrawPolyLine(2,line2);
11086 gVirtualX->DrawPolyLine(2,line3);
11087 gVirtualX->DrawPolyLine(2,line4);
11088 gVirtualX->DrawPolyLine(5,endface1);
11089 gVirtualX->DrawPolyLine(5,endface2);
11090 }
11091 xx[0] = xaxis->GetXmin();
11092 xx[2] = zaxis->GetBinCenter(binz);
11093 xx[1] = yaxis->GetBinCenter(biny);
11094 view->WCtoNDC(xx,u);
11095 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11096 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11097 xx[0] = xaxis->GetXmax();
11098 view->WCtoNDC(xx,u);
11099 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11100 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11101 gVirtualX->DrawPolyLine(2,line1);
11102 if (nbins>1) {
11103 xx[0] = xaxis->GetXmin();
11104 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11105 xx[1] = yaxis->GetBinCenter(biny);
11106 view->WCtoNDC(xx,u);
11107 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11108 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11109 xx[0] = xaxis->GetXmax();
11110 view->WCtoNDC(xx,u);
11111 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11112 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11113
11114 xx[0] = xaxis->GetXmin();
11115 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11116 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11117 view->WCtoNDC(xx,u);
11118 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11119 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11120 xx[0] = xaxis->GetXmax();
11121 view->WCtoNDC(xx,u);
11122 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11123 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11124
11125 xx[0] = xaxis->GetXmin();
11126 xx[2] = zaxis->GetBinCenter(binz);
11127 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11128 view->WCtoNDC(xx,u);
11129 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11130 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11131 xx[0] = xaxis->GetXmax();
11132 view->WCtoNDC(xx,u);
11133 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11134 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11135
11136 endface1[0].SetX(line1[0].GetX());
11137 endface1[0].SetY(line1[0].GetY());
11138 endface1[1].SetX(line2[0].GetX());
11139 endface1[1].SetY(line2[0].GetY());
11140 endface1[2].SetX(line3[0].GetX());
11141 endface1[2].SetY(line3[0].GetY());
11142 endface1[3].SetX(line4[0].GetX());
11143 endface1[3].SetY(line4[0].GetY());
11144 endface1[4].SetX(line1[0].GetX());
11145 endface1[4].SetY(line1[0].GetY());
11146
11147 endface2[0].SetX(line1[1].GetX());
11148 endface2[0].SetY(line1[1].GetY());
11149 endface2[1].SetX(line2[1].GetX());
11150 endface2[1].SetY(line2[1].GetY());
11151 endface2[2].SetX(line3[1].GetX());
11152 endface2[2].SetY(line3[1].GetY());
11153 endface2[3].SetX(line4[1].GetX());
11154 endface2[3].SetY(line4[1].GetY());
11155 endface2[4].SetX(line1[1].GetX());
11156 endface2[4].SetY(line1[1].GetY());
11157
11158 gVirtualX->DrawPolyLine(2,line2);
11159 gVirtualX->DrawPolyLine(2,line3);
11160 gVirtualX->DrawPolyLine(2,line4);
11161 gVirtualX->DrawPolyLine(5,endface1);
11162 gVirtualX->DrawPolyLine(5,endface2);
11163 }
11164 c->Clear();
11165 c->cd();
11166 TH1 *hp = h3->Project3D("x");
11167 yaxis->SetRange(firstY,lastY);
11168 zaxis->SetRange(firstZ,lastZ);
11169 if (hp) {
11170 hp->SetFillColor(38);
11171 if (nbins == 1)
11172 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny),
11173 binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
11174 else {
11175 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),
11176 binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
11177 }
11178 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11179 hp->SetYTitle("Number of Entries");
11180 hp->Draw(fShowOption.Data());
11181 }
11182 }
11183 break;
11184
11185 case 2:
11186 // "y"
11187 {
11188 Int_t firstX = xaxis->GetFirst();
11189 Int_t lastX = xaxis->GetLast();
11190 Int_t binx = firstX + Int_t((lastX-firstX)*(px-pxmin)/(pxmax-pxmin));
11191 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11192 xaxis->SetRange(binx,binx2);
11193 Int_t firstZ = zaxis->GetFirst();
11194 Int_t lastZ = zaxis->GetLast();
11195 Int_t binz = firstZ + Int_t((lastZ-firstZ)*(py-pymin)/(pymax-pymin));
11196 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11197 zaxis->SetRange(binz,binz2);
11198 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11199 if (nbins>1 && line1[0].GetX()) {
11200 gVirtualX->DrawPolyLine(2,line2);
11201 gVirtualX->DrawPolyLine(2,line3);
11202 gVirtualX->DrawPolyLine(2,line4);
11203 gVirtualX->DrawPolyLine(5,endface1);
11204 gVirtualX->DrawPolyLine(5,endface2);
11205 }
11206 xx[0]=xaxis->GetBinCenter(binx);
11207 xx[2] = zaxis->GetBinCenter(binz);
11208 xx[1] = yaxis->GetXmin();
11209 view->WCtoNDC(xx,u);
11210 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11211 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11212 xx[1] = yaxis->GetXmax();
11213 view->WCtoNDC(xx,u);
11214 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11215 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11216 gVirtualX->DrawPolyLine(2,line1);
11217 if (nbins>1) {
11218 xx[1] = yaxis->GetXmin();
11219 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11220 xx[0] = xaxis->GetBinCenter(binx);
11221 view->WCtoNDC(xx,u);
11222 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11223 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11224 xx[1] = yaxis->GetXmax();
11225 view->WCtoNDC(xx,u);
11226 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11227 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11228
11229 xx[1] = yaxis->GetXmin();
11230 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11231 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11232 view->WCtoNDC(xx,u);
11233 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11234 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11235 xx[1] = yaxis->GetXmax();
11236 view->WCtoNDC(xx,u);
11237 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11238 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11239
11240 xx[1] = yaxis->GetXmin();
11241 xx[2] = zaxis->GetBinCenter(binz);
11242 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11243 view->WCtoNDC(xx,u);
11244 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11245 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11246 xx[1] = yaxis->GetXmax();
11247 view->WCtoNDC(xx,u);
11248 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11249 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11250
11251 endface1[0].SetX(line1[0].GetX());
11252 endface1[0].SetY(line1[0].GetY());
11253 endface1[1].SetX(line2[0].GetX());
11254 endface1[1].SetY(line2[0].GetY());
11255 endface1[2].SetX(line3[0].GetX());
11256 endface1[2].SetY(line3[0].GetY());
11257 endface1[3].SetX(line4[0].GetX());
11258 endface1[3].SetY(line4[0].GetY());
11259 endface1[4].SetX(line1[0].GetX());
11260 endface1[4].SetY(line1[0].GetY());
11261
11262 endface2[0].SetX(line1[1].GetX());
11263 endface2[0].SetY(line1[1].GetY());
11264 endface2[1].SetX(line2[1].GetX());
11265 endface2[1].SetY(line2[1].GetY());
11266 endface2[2].SetX(line3[1].GetX());
11267 endface2[2].SetY(line3[1].GetY());
11268 endface2[3].SetX(line4[1].GetX());
11269 endface2[3].SetY(line4[1].GetY());
11270 endface2[4].SetX(line1[1].GetX());
11271 endface2[4].SetY(line1[1].GetY());
11272
11273 gVirtualX->DrawPolyLine(2,line2);
11274 gVirtualX->DrawPolyLine(2,line3);
11275 gVirtualX->DrawPolyLine(2,line4);
11276 gVirtualX->DrawPolyLine(5,endface1);
11277 gVirtualX->DrawPolyLine(5,endface2);
11278 }
11279 c->Clear();
11280 c->cd();
11281 TH1 *hp = h3->Project3D("y");
11282 xaxis->SetRange(firstX,lastX);
11283 zaxis->SetRange(firstZ,lastZ);
11284 if (hp) {
11285 hp->SetFillColor(38);
11286 if (nbins == 1)
11287 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
11288 binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
11289 else
11290 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),
11291 binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
11292 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11293 hp->SetYTitle("Number of Entries");
11294 hp->Draw(fShowOption.Data());
11295 }
11296 }
11297 break;
11298
11299 case 3:
11300 // "z"
11301 {
11302 Int_t firstX = xaxis->GetFirst();
11303 Int_t lastX = xaxis->GetLast();
11304 Int_t binx = firstX + Int_t((lastX-firstX)*(px-pxmin)/(pxmax-pxmin));
11305 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11306 xaxis->SetRange(binx,binx2);
11307 Int_t firstY = yaxis->GetFirst();
11308 Int_t lastY = yaxis->GetLast();
11309 Int_t biny = firstY + Int_t((lastY-firstY)*(py-pymin)/(pymax-pymin));
11310 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11311 yaxis->SetRange(biny,biny2);
11312 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11313 if (nbins>1 && line1[0].GetX()) {
11314 gVirtualX->DrawPolyLine(2,line2);
11315 gVirtualX->DrawPolyLine(2,line3);
11316 gVirtualX->DrawPolyLine(2,line4);
11317 gVirtualX->DrawPolyLine(5,endface1);
11318 gVirtualX->DrawPolyLine(5,endface2);
11319 }
11320 xx[0] = xaxis->GetBinCenter(binx);
11321 xx[1] = yaxis->GetBinCenter(biny);
11322 xx[2] = zaxis->GetXmin();
11323 view->WCtoNDC(xx,u);
11324 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11325 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11326 xx[2] = zaxis->GetXmax();
11327 view->WCtoNDC(xx,u);
11328 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11329 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11330 gVirtualX->DrawPolyLine(2,line1);
11331 if (nbins>1) {
11332 xx[2] = zaxis->GetXmin();
11333 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11334 xx[0] = xaxis->GetBinCenter(binx);
11335 view->WCtoNDC(xx,u);
11336 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11337 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11338 xx[2] = zaxis->GetXmax();
11339 view->WCtoNDC(xx,u);
11340 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11341 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11342
11343 xx[2] = zaxis->GetXmin();
11344 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11345 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11346 view->WCtoNDC(xx,u);
11347 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11348 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11349 xx[2] = zaxis->GetXmax();
11350 view->WCtoNDC(xx,u);
11351 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11352 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11353
11354 xx[2] = zaxis->GetXmin();
11355 xx[1] = yaxis->GetBinCenter(biny);
11356 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11357 view->WCtoNDC(xx,u);
11358 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11359 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11360 xx[2] = zaxis->GetXmax();
11361 view->WCtoNDC(xx,u);
11362 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11363 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11364
11365 endface1[0].SetX(line1[0].GetX());
11366 endface1[0].SetY(line1[0].GetY());
11367 endface1[1].SetX(line2[0].GetX());
11368 endface1[1].SetY(line2[0].GetY());
11369 endface1[2].SetX(line3[0].GetX());
11370 endface1[2].SetY(line3[0].GetY());
11371 endface1[3].SetX(line4[0].GetX());
11372 endface1[3].SetY(line4[0].GetY());
11373 endface1[4].SetX(line1[0].GetX());
11374 endface1[4].SetY(line1[0].GetY());
11375
11376 endface2[0].SetX(line1[1].GetX());
11377 endface2[0].SetY(line1[1].GetY());
11378 endface2[1].SetX(line2[1].GetX());
11379 endface2[1].SetY(line2[1].GetY());
11380 endface2[2].SetX(line3[1].GetX());
11381 endface2[2].SetY(line3[1].GetY());
11382 endface2[3].SetX(line4[1].GetX());
11383 endface2[3].SetY(line4[1].GetY());
11384 endface2[4].SetX(line1[1].GetX());
11385 endface2[4].SetY(line1[1].GetY());
11386
11387 gVirtualX->DrawPolyLine(2,line2);
11388 gVirtualX->DrawPolyLine(2,line3);
11389 gVirtualX->DrawPolyLine(2,line4);
11390 gVirtualX->DrawPolyLine(5,endface1);
11391 gVirtualX->DrawPolyLine(5,endface2);
11392 }
11393 c->Clear();
11394 c->cd();
11395 TH1 *hp = h3->Project3D("z");
11396 xaxis->SetRange(firstX,lastX);
11397 yaxis->SetRange(firstY,lastY);
11398 if (hp) {
11399 hp->SetFillColor(38);
11400 if (nbins == 1)
11401 hp->SetTitle(TString::Format("ProjectionZ of binx=%d [x=%.1f..%.1f] biny=%d [y=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
11402 biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny)));
11403 else
11404 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),
11405 biny, biny2, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny2) ) );
11406 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11407 hp->SetYTitle("Number of Entries");
11408 hp->Draw(fShowOption.Data());
11409 }
11410 }
11411 break;
11412
11413 case 4:
11414 // "xy"
11415 {
11416 Int_t first = zaxis->GetFirst();
11417 Int_t last = zaxis->GetLast();
11418 Int_t binz = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11419 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11420 zaxis->SetRange(binz,binz2);
11421 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11422 if (nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11423 xx[0] = xaxis->GetXmin();
11424 xx[1] = yaxis->GetXmax();
11425 xx[2] = zaxis->GetBinCenter(binz);
11426 view->WCtoNDC(xx,u);
11427 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11428 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11429 rect1[4].SetX(rect1[0].GetX());
11430 rect1[4].SetY(rect1[0].GetY());
11431 xx[0] = xaxis->GetXmax();
11432 view->WCtoNDC(xx,u);
11433 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11434 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11435 xx[1] = yaxis->GetXmin();
11436 view->WCtoNDC(xx,u);
11437 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11438 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11439 xx[0] = xaxis->GetXmin();
11440 view->WCtoNDC(xx,u);
11441 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11442 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11443 gVirtualX->DrawPolyLine(5,rect1);
11444 if (nbins>1) {
11445 xx[0] = xaxis->GetXmin();
11446 xx[1] = yaxis->GetXmax();
11447 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11448 view->WCtoNDC(xx,u);
11449 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11450 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11451 rect2[4].SetX(rect2[0].GetX());
11452 rect2[4].SetY(rect2[0].GetY());
11453 xx[0] = xaxis->GetXmax();
11454 view->WCtoNDC(xx,u);
11455 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11456 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11457 xx[1] = yaxis->GetXmin();
11458 view->WCtoNDC(xx,u);
11459 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11460 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11461 xx[0] = xaxis->GetXmin();
11462 view->WCtoNDC(xx,u);
11463 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11464 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11465 gVirtualX->DrawPolyLine(5,rect2);
11466 }
11467
11468 c->Clear();
11469 c->cd();
11470 TH2 *hp = (TH2*)h3->Project3D("xy");
11471 zaxis->SetRange(first,last);
11472 if (hp) {
11473 hp->SetFillColor(38);
11474 if (nbins==1)hp->SetTitle(TString::Format("ProjectionXY of binz=%d [z=%.1f..%.f]", binz,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz)));
11475 else hp->SetTitle(TString::Format("ProjectionXY, binz=[%d,%d] [z=%.1f..%.1f]", binz,binz2,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz2)));
11476 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11477 hp->SetYTitle(fH->GetXaxis()->GetTitle());
11478 hp->SetZTitle("Number of Entries");
11479 hp->Draw(fShowOption.Data());
11480 }
11481 }
11482 break;
11483
11484 case 5:
11485 // "yx"
11486 {
11487 Int_t first = zaxis->GetFirst();
11488 Int_t last = zaxis->GetLast();
11489 Int_t binz = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11490 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11491 zaxis->SetRange(binz,binz2);
11492 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11493 if (nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11494 xx[0] = xaxis->GetXmin();
11495 xx[1] = yaxis->GetXmax();
11496 xx[2] = zaxis->GetBinCenter(binz);
11497 view->WCtoNDC(xx,u);
11498 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11499 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11500 rect1[4].SetX(rect1[0].GetX());
11501 rect1[4].SetY(rect1[0].GetY());
11502 xx[0] = xaxis->GetXmax();
11503 view->WCtoNDC(xx,u);
11504 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11505 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11506 xx[1] = yaxis->GetXmin();
11507 view->WCtoNDC(xx,u);
11508 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11509 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11510 xx[0] = xaxis->GetXmin();
11511 view->WCtoNDC(xx,u);
11512 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11513 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11514 gVirtualX->DrawPolyLine(5,rect1);
11515 if (nbins>1) {
11516 xx[0] = xaxis->GetXmin();
11517 xx[1] = yaxis->GetXmax();
11518 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11519 view->WCtoNDC(xx,u);
11520 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11521 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11522 rect2[4].SetX(rect2[0].GetX());
11523 rect2[4].SetY(rect2[0].GetY());
11524 xx[0] = xaxis->GetXmax();
11525 view->WCtoNDC(xx,u);
11526 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11527 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11528 xx[1] = yaxis->GetXmin();
11529 view->WCtoNDC(xx,u);
11530 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11531 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11532 xx[0] = xaxis->GetXmin();
11533 view->WCtoNDC(xx,u);
11534 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11535 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11536 gVirtualX->DrawPolyLine(5,rect2);
11537 }
11538 c->Clear();
11539 c->cd();
11540 TH2 *hp = (TH2*)h3->Project3D("yx");
11541 zaxis->SetRange(first,last);
11542 if (hp) {
11543 hp->SetFillColor(38);
11544 if (nbins==1)hp->SetTitle(TString::Format("ProjectionYX of binz=%d [z=%.1f..%.f]", binz,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz)));
11545 else hp->SetTitle(TString::Format("ProjectionYX, binz=[%d,%d] [z=%.1f..%.1f]", binz,binz2,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz2)));
11546 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11547 hp->SetYTitle(fH->GetYaxis()->GetTitle());
11548 hp->SetZTitle("Number of Entries");
11549 hp->Draw(fShowOption.Data());
11550 }
11551 }
11552 break;
11553
11554 case 6:
11555 // "xz"
11556 {
11557 Int_t first = yaxis->GetFirst();
11558 Int_t last = yaxis->GetLast();
11559 Int_t biny = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11560 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11561 yaxis->SetRange(biny,biny2);
11562 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11563 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11564 xx[0] = xaxis->GetXmin();
11565 xx[2] = zaxis->GetXmax();
11566 xx[1] = yaxis->GetBinCenter(biny);
11567 view->WCtoNDC(xx,u);
11568 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11569 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11570 rect1[4].SetX(rect1[0].GetX());
11571 rect1[4].SetY(rect1[0].GetY());
11572 xx[0] = xaxis->GetXmax();
11573 view->WCtoNDC(xx,u);
11574 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11575 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11576 xx[2] = zaxis->GetXmin();
11577 view->WCtoNDC(xx,u);
11578 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11579 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11580 xx[0] = xaxis->GetXmin();
11581 view->WCtoNDC(xx,u);
11582 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11583 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11584 gVirtualX->DrawPolyLine(5,rect1);
11585 if (nbins>1) {
11586 xx[0] = xaxis->GetXmin();
11587 xx[2] = zaxis->GetXmax();
11588 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11589 view->WCtoNDC(xx,u);
11590 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11591 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11592 rect2[4].SetX(rect2[0].GetX());
11593 rect2[4].SetY(rect2[0].GetY());
11594 xx[0] = xaxis->GetXmax();
11595 view->WCtoNDC(xx,u);
11596 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11597 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11598 xx[2] = zaxis->GetXmin();
11599 view->WCtoNDC(xx,u);
11600 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11601 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11602 xx[0] = xaxis->GetXmin();
11603 view->WCtoNDC(xx,u);
11604 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11605 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11606 gVirtualX->DrawPolyLine(5,rect2);
11607 }
11608 c->Clear();
11609 c->cd();
11610 TH2 *hp = (TH2*)h3->Project3D("xz");
11611 yaxis->SetRange(first,last);
11612 if (hp) {
11613 hp->SetFillColor(38);
11614 if (nbins==1)hp->SetTitle(TString::Format("ProjectionXZ of biny=%d [y=%.1f..%.f]", biny,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny)));
11615 else hp->SetTitle(TString::Format("ProjectionXZ, biny=[%d,%d] [y=%.1f..%.1f]", biny,biny2,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny2)));
11616 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11617 hp->SetYTitle(fH->GetXaxis()->GetTitle());
11618 hp->SetZTitle("Number of Entries");
11619 hp->Draw(fShowOption.Data());
11620 }
11621 }
11622 break;
11623
11624 case 7:
11625 // "zx"
11626 {
11627 Int_t first = yaxis->GetFirst();
11628 Int_t last = yaxis->GetLast();
11629 Int_t biny = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11630 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11631 yaxis->SetRange(biny,biny2);
11632 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11633 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11634 xx[0] = xaxis->GetXmin();
11635 xx[2] = zaxis->GetXmax();
11636 xx[1] = yaxis->GetBinCenter(biny);
11637 view->WCtoNDC(xx,u);
11638 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11639 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11640 rect1[4].SetX(rect1[0].GetX());
11641 rect1[4].SetY(rect1[0].GetY());
11642 xx[0] = xaxis->GetXmax();
11643 view->WCtoNDC(xx,u);
11644 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11645 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11646 xx[2] = zaxis->GetXmin();
11647 view->WCtoNDC(xx,u);
11648 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11649 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11650 xx[0] = xaxis->GetXmin();
11651 view->WCtoNDC(xx,u);
11652 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11653 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11654 gVirtualX->DrawPolyLine(5,rect1);
11655 if (nbins>1) {
11656 xx[0] = xaxis->GetXmin();
11657 xx[2] = zaxis->GetXmax();
11658 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11659 view->WCtoNDC(xx,u);
11660 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11661 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11662 rect2[4].SetX(rect2[0].GetX());
11663 rect2[4].SetY(rect2[0].GetY());
11664 xx[0] = xaxis->GetXmax();
11665 view->WCtoNDC(xx,u);
11666 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11667 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11668 xx[2] = zaxis->GetXmin();
11669 view->WCtoNDC(xx,u);
11670 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11671 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11672 xx[0] = xaxis->GetXmin();
11673 view->WCtoNDC(xx,u);
11674 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11675 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11676 gVirtualX->DrawPolyLine(5,rect2);
11677 }
11678 c->Clear();
11679 c->cd();
11680 TH2 *hp = (TH2*)h3->Project3D("zx");
11681 yaxis->SetRange(first,last);
11682 if (hp) {
11683 hp->SetFillColor(38);
11684 if (nbins==1)hp->SetTitle(TString::Format("ProjectionZX of biny=%d [y=%.1f..%.f]", biny,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny)));
11685 else hp->SetTitle(TString::Format("ProjectionZX, biny=[%d,%d] [y=%.1f..%.1f]", biny,biny2,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny2)));
11686 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11687 hp->SetYTitle(fH->GetZaxis()->GetTitle());
11688 hp->SetZTitle("Number of Entries");
11689 hp->Draw(fShowOption.Data());
11690 }
11691 }
11692 break;
11693
11694 case 8:
11695 // "yz"
11696 {
11697 Int_t first = xaxis->GetFirst();
11698 Int_t last = xaxis->GetLast();
11699 Int_t binx = first + Int_t((last-first)*(px-pxmin)/(pxmax-pxmin));
11700 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11701 xaxis->SetRange(binx,binx2);
11702 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11703 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11704 xx[2] = zaxis->GetXmin();
11705 xx[1] = yaxis->GetXmax();
11706 xx[0] = xaxis->GetBinCenter(binx);
11707 view->WCtoNDC(xx,u);
11708 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11709 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11710 rect1[4].SetX(rect1[0].GetX());
11711 rect1[4].SetY(rect1[0].GetY());
11712 xx[2] = zaxis->GetXmax();
11713 view->WCtoNDC(xx,u);
11714 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11715 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11716 xx[1] = yaxis->GetXmin();
11717 view->WCtoNDC(xx,u);
11718 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11719 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11720 xx[2] = zaxis->GetXmin();
11721 view->WCtoNDC(xx,u);
11722 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11723 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11724 gVirtualX->DrawPolyLine(5,rect1);
11725 if (nbins>1) {
11726 xx[2] = zaxis->GetXmin();
11727 xx[1] = yaxis->GetXmax();
11728 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11729 view->WCtoNDC(xx,u);
11730 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11731 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11732 rect2[4].SetX(rect2[0].GetX());
11733 rect2[4].SetY(rect2[0].GetY());
11734 xx[2] = zaxis->GetXmax();
11735 view->WCtoNDC(xx,u);
11736 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11737 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11738 xx[1] = yaxis->GetXmin();
11739 view->WCtoNDC(xx,u);
11740 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11741 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11742 xx[2] = zaxis->GetXmin();
11743 view->WCtoNDC(xx,u);
11744 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11745 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11746 gVirtualX->DrawPolyLine(5,rect2);
11747 }
11748 c->Clear();
11749 c->cd();
11750 TH2 *hp = (TH2*)h3->Project3D("yz");
11751 xaxis->SetRange(first,last);
11752 if (hp) {
11753 hp->SetFillColor(38);
11754 if (nbins==1)hp->SetTitle(TString::Format("ProjectionYZ of binx=%d [x=%.1f..%.f]", binx,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx)));
11755 else hp->SetTitle(TString::Format("ProjectionYZ, binx=[%d,%d] [x=%.1f..%.1f]", binx,binx2,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx2)));
11756 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11757 hp->SetYTitle(fH->GetYaxis()->GetTitle());
11758 hp->SetZTitle("Number of Entries");
11759 hp->Draw(fShowOption.Data());
11760 }
11761 }
11762 break;
11763
11764 case 9:
11765 // "zy"
11766 {
11767 Int_t first = xaxis->GetFirst();
11768 Int_t last = xaxis->GetLast();
11769 Int_t binx = first + Int_t((last-first)*(px-pxmin)/(pxmax-pxmin));
11770 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11771 xaxis->SetRange(binx,binx2);
11772 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11773 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11774 xx[2] = zaxis->GetXmin();
11775 xx[1] = yaxis->GetXmax();
11776 xx[0] = xaxis->GetBinCenter(binx);
11777 view->WCtoNDC(xx,u);
11778 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11779 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11780 rect1[4].SetX(rect1[0].GetX());
11781 rect1[4].SetY(rect1[0].GetY());
11782 xx[2] = zaxis->GetXmax();
11783 view->WCtoNDC(xx,u);
11784 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11785 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11786 xx[1] = yaxis->GetXmin();
11787 view->WCtoNDC(xx,u);
11788 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11789 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11790 xx[2] = zaxis->GetXmin();
11791 view->WCtoNDC(xx,u);
11792 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11793 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11794 gVirtualX->DrawPolyLine(5,rect1);
11795 if (nbins>1) {
11796 xx[2] = zaxis->GetXmin();
11797 xx[1] = yaxis->GetXmax();
11798 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11799 view->WCtoNDC(xx,u);
11800 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11801 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11802 rect2[4].SetX(rect2[0].GetX());
11803 rect2[4].SetY(rect2[0].GetY());
11804 xx[2] = zaxis->GetXmax();
11805 view->WCtoNDC(xx,u);
11806 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11807 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11808 xx[1] = yaxis->GetXmin();
11809 view->WCtoNDC(xx,u);
11810 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11811 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11812 xx[2] = zaxis->GetXmin();
11813 view->WCtoNDC(xx,u);
11814 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11815 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11816 gVirtualX->DrawPolyLine(5,rect2);
11817 }
11818 c->Clear();
11819 c->cd();
11820 TH2 *hp = (TH2*)h3->Project3D("zy");
11821 xaxis->SetRange(first,last);
11822 if (hp) {
11823 hp->SetFillColor(38);
11824 if (nbins==1)hp->SetTitle(TString::Format("ProjectionZY of binx=%d [x=%.1f..%.f]", binx,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx)));
11825 else hp->SetTitle(TString::Format("ProjectionZY, binx=[%d,%d] [x=%.1f..%.1f]", binx,binx2,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx2)));
11826 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11827 hp->SetYTitle(fH->GetZaxis()->GetTitle());
11828 hp->SetZTitle("Number of Entries");
11829 hp->Draw(fShowOption.Data());
11830 }
11831 }
11832 break;
11833 }
11834 c->Update();
11835}
@ 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:374
@ kPointer
Definition GuiTypes.h:375
Handle_t Window_t
Window handle.
Definition GuiTypes.h:29
#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
short Style_t
Definition RtypesCore.h:82
int Int_t
Definition RtypesCore.h:45
short Color_t
Definition RtypesCore.h:85
unsigned int UInt_t
Definition RtypesCore.h:46
short Width_t
Definition RtypesCore.h:84
float Float_t
Definition RtypesCore.h:57
short Short_t
Definition RtypesCore.h:39
constexpr Bool_t kFALSE
Definition RtypesCore.h:94
double Double_t
Definition RtypesCore.h:59
constexpr Bool_t kTRUE
Definition RtypesCore.h:93
const char Option_t
Definition RtypesCore.h:66
#define BIT(n)
Definition Rtypes.h:90
#define ClassImp(name)
Definition Rtypes.h:382
@ kBlack
Definition Rtypes.h:65
R__EXTERN TEnv * gEnv
Definition TEnv.h:170
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 wid
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:406
R__EXTERN TStyle * gStyle
Definition TStyle.h:436
R__EXTERN TSystem * gSystem
Definition TSystem.h:561
const Int_t kCARTESIAN
Definition TView3D.cxx:33
const Int_t kPOLAR
Definition TView3D.cxx:34
#define gPad
#define gVirtualX
Definition TVirtualX.h:337
polygon * polys
Definition X3DBuffer.c:24
Int_t fN
Definition TArray.h:38
Draw all kinds of Arrows.
Definition TArrow.h:29
virtual Int_t GetNdivisions() const
Definition TAttAxis.h:36
virtual Float_t GetLabelOffset() const
Definition TAttAxis.h:40
virtual Float_t GetLabelSize() const
Definition TAttAxis.h:41
virtual Float_t GetTickLength() const
Definition TAttAxis.h:45
virtual Float_t GetTitleOffset() const
Definition TAttAxis.h:43
virtual Color_t GetFillColor() const
Return the fill area color.
Definition TAttFill.h:30
virtual Style_t GetFillStyle() const
Return the fill area style.
Definition TAttFill.h:31
virtual void SetFillColor(Color_t fcolor)
Set the fill area color.
Definition TAttFill.h:37
virtual void SetFillStyle(Style_t fstyle)
Set the fill area style.
Definition TAttFill.h:39
virtual void SetImageQuality(EImageQuality lquality)
Definition TAttImage.h:99
virtual Color_t GetLineColor() const
Return the line color.
Definition TAttLine.h:33
virtual void SetLineStyle(Style_t lstyle)
Set the line style.
Definition TAttLine.h:42
virtual Width_t GetLineWidth() const
Return the line width.
Definition TAttLine.h:35
virtual void SetLineWidth(Width_t lwidth)
Set the line width.
Definition TAttLine.h:43
virtual void SetLineColor(Color_t lcolor)
Set the line color.
Definition TAttLine.h:40
virtual Style_t GetLineStyle() const
Return the line style.
Definition TAttLine.h:34
virtual Style_t GetMarkerStyle() const
Return the marker style.
Definition TAttMarker.h:32
virtual void SetMarkerColor(Color_t mcolor=1)
Set the marker color.
Definition TAttMarker.h:38
virtual Color_t GetMarkerColor() const
Return the marker color.
Definition TAttMarker.h:31
virtual Size_t GetMarkerSize() const
Return the marker size.
Definition TAttMarker.h:33
virtual void SetMarkerStyle(Style_t mstyle=1)
Set the marker style.
Definition TAttMarker.h:40
virtual void SetMarkerSize(Size_t msize=1)
Set the marker size.
Definition TAttMarker.h:45
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:42
virtual Font_t GetTextFont() const
Return the text font.
Definition TAttText.h:35
virtual void SetTextAngle(Float_t tangle=0)
Set the text angle.
Definition TAttText.h:43
virtual void SetTextColor(Color_t tcolor=1)
Set the text color.
Definition TAttText.h:44
virtual void SetTextFont(Font_t tfont=62)
Set the text font.
Definition TAttText.h:46
virtual void SetTextSize(Float_t tsize=1)
Set the text size.
Definition TAttText.h:47
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:473
Bool_t CanExtend() const
Definition TAxis.h:88
const TArrayD * GetXbins() const
Definition TAxis.h:138
Double_t GetXmax() const
Definition TAxis.h:142
const char * GetBinLabel(Int_t bin) const
Return label for bin.
Definition TAxis.cxx:435
virtual Int_t FindBin(Double_t x)
Find bin number corresponding to abscissa x.
Definition TAxis.cxx:288
virtual Double_t GetBinLowEdge(Int_t bin) const
Return low edge of bin.
Definition TAxis.cxx:513
virtual Int_t FindFixBin(Double_t x) const
Find bin number corresponding to abscissa x.
Definition TAxis.cxx:414
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:464
virtual const char * GetTimeFormatOnly() const
Return only the time format from the string fTimeFormat.
Definition TAxis.cxx:595
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:1081
virtual const char * GetTimeFormat() const
Definition TAxis.h:134
virtual void SetRange(Int_t first=0, Int_t last=0)
Set the viewing range for the axis using bin numbers.
Definition TAxis.cxx:1052
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width.
Definition TAxis.cxx:537
virtual Double_t GetBinUpEdge(Int_t bin) const
Return up edge of bin.
Definition TAxis.cxx:523
Int_t GetFirst() const
Return first bin on the axis i.e.
Definition TAxis.cxx:453
THashList * GetLabels() const
Definition TAxis.h:123
Create a Box.
Definition TBox.h:22
The candle plot painter class.
Definition TCandle.h:27
void SetLog(int x, int y, int z)
Definition TCandle.h:118
CandleOption
Definition TCandle.h:30
void SetHistoWidth(const Double_t width)
Definition TCandle.h:122
virtual void Paint(Option_t *option="")
Paint one candle with its current attributes.
Definition TCandle.cxx:666
Bool_t IsViolinScaled() const
Returns true if violin plot should be scaled.
Definition TCandle.cxx:191
Bool_t IsHorizontal() const
Definition TCandle.h:112
int ParseOption(char *optin)
Parsing of the option-string.
Definition TCandle.cxx:244
void SetOption(CandleOption opt)
Definition TCandle.h:117
void SetHistogram(TH1D *proj)
Definition TCandle.h:123
Bool_t IsCandleScaled() const
Returns true if candle plot should be scaled.
Definition TCandle.cxx:183
void SetCandleWidth(const Double_t width)
Definition TCandle.h:121
void SetAxisPosition(const Double_t candlePos)
Definition TCandle.h:119
static Bool_t SupportAlpha()
Static function returning "true" if transparency is supported.
Definition TCanvas.cxx:2476
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:3037
void SetName(const char *name)
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
void Paint(Option_t *option="") override
Paint all objects in this collection.
The color creation and management class.
Definition TColor.h:21
virtual void SetRGB(Float_t r, Float_t g, Float_t b)
Initialize this color and its "dark" and "bright" associated colors.
Definition TColor.cxx:1851
static void RGBtoHLS(Float_t r, Float_t g, Float_t b, Float_t &h, Float_t &l, Float_t &s)
Definition TColor.h:82
virtual void GetRGB(Float_t &r, Float_t &g, Float_t &b) const
Definition TColor.h:54
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:1921
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:2088
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:2131
static void HLStoRGB(Float_t h, Float_t l, Float_t s, Float_t &r, Float_t &g, Float_t &b)
Definition TColor.h:77
virtual void SetAlpha(Float_t a)
Definition TColor.h:70
To draw a Crown.
Definition TCrown.h:19
void Paint(Option_t *option="") override
Paint this crown with its current attributes.
Definition TCrown.cxx:218
Graphical cut class.
Definition TCutG.h:20
static TClass * Class()
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition TEnv.cxx:491
1-Dim function class
Definition TF1.h:233
virtual Double_t GetXmax() const
Definition TF1.h:584
static TClass * Class()
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:3394
virtual Double_t GetMaximumStored() const
Definition TF1.h:501
@ kNotDraw
Definition TF1.h:346
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:3407
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:1439
virtual Double_t GetXmin() const
Definition TF1.h:580
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:742
void SetRange(Double_t xmin, Double_t xmax) override
Initialize the upper and lower bounds to draw the function.
Definition TF2.h:146
static TClass * Class()
A 3-Dim function with parameters.
Definition TF3.h:28
The axis painter class.
Definition TGaxis.h:24
void SetTimeFormat(const char *tformat)
Change the format used for time plotting.
Definition TGaxis.cxx:2969
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:1008
void SetTitleOffset(Float_t titleoffset=1)
Definition TGaxis.h:128
virtual void SetTitle(const char *title="")
Change the title of the axis.
Definition TGaxis.cxx:2942
void SetLabelOffset(Float_t labeloffset)
Definition TGaxis.h:106
virtual void ImportAxisAttributes(TAxis *axis)
Internal method to import TAxis attributes to this TGaxis.
Definition TGaxis.cxx:955
void SetTickSize(Float_t ticksize)
Definition TGaxis.h:122
void SetLabelSize(Float_t labelsize)
Definition TGaxis.h:107
void SetOption(Option_t *option="")
To set axis options.
Definition TGaxis.cxx:2934
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:76
1-D histogram with a double per channel (see TH1 documentation)
Definition TH1.h:671
1-D histogram with a float per channel (see TH1 documentation)
Definition TH1.h:623
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:59
TAxis * GetZaxis()
Definition TH1.h:327
void SetTitle(const char *title) override
Change/set the title.
Definition TH1.cxx:6747
virtual EBinErrorOpt GetBinErrorOption() const
Definition TH1.h:274
virtual Float_t GetBarWidth() const
Definition TH1.h:258
virtual Double_t GetMinimumStored() const
Definition TH1.h:294
virtual Float_t GetBarOffset() const
Definition TH1.h:257
static TClass * Class()
virtual Double_t GetStdDev(Int_t axis=1) const
Returns the Standard Deviation (Sigma).
Definition TH1.cxx:7640
virtual Int_t GetNbinsY() const
Definition TH1.h:299
virtual Double_t GetBinError(Int_t bin) const
Return value of error associated to bin number bin.
Definition TH1.cxx:9096
virtual Int_t GetNbinsZ() const
Definition TH1.h:300
virtual Double_t GetNormFactor() const
Definition TH1.h:302
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:7568
virtual Double_t GetSkewness(Int_t axis=1) const
Definition TH1.cxx:7704
virtual Double_t GetContourLevelPad(Int_t level) const
Return the value of contour number "level" in Pad coordinates.
Definition TH1.cxx:8473
virtual void SetXTitle(const char *title)
Definition TH1.h:420
virtual Int_t GetDimension() const
Definition TH1.h:284
static void AddDirectory(Bool_t add=kTRUE)
Sets the flag controlling the automatic add of histograms in memory.
Definition TH1.cxx:1296
@ kNoTitle
Don't draw the histogram title.
Definition TH1.h:170
@ kUserContour
User specified contour levels.
Definition TH1.h:166
@ kNoStats
Don't draw stats box.
Definition TH1.h:165
TAxis * GetXaxis()
Definition TH1.h:325
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:4990
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:8578
virtual Int_t GetNbinsX() const
Definition TH1.h:298
virtual void SetMaximum(Double_t maximum=-1111)
Definition TH1.h:405
TAxis * GetYaxis()
Definition TH1.h:326
virtual Double_t GetBinErrorLow(Int_t bin) const
Return lower error associated to bin number bin.
Definition TH1.cxx:9112
void Draw(Option_t *option="") override
Draw this histogram with options.
Definition TH1.cxx:3068
virtual void SetMinimum(Double_t minimum=-1111)
Definition TH1.h:406
virtual Double_t Integral(Option_t *option="") const
Return integral of bin contents.
Definition TH1.cxx:7974
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:9255
virtual Double_t GetBinLowEdge(Int_t bin) const
Return bin lower edge for 1D histogram.
Definition TH1.cxx:9185
virtual Double_t GetEntries() const
Return the current number of entries.
Definition TH1.cxx:4431
virtual void SetZTitle(const char *title)
Definition TH1.h:422
TList * GetListOfFunctions() const
Definition TH1.h:245
virtual Double_t GetMeanError(Int_t axis=1) const
Return standard error of mean of this histogram along the X axis.
Definition TH1.cxx:7608
virtual Double_t GetMaximumStored() const
Definition TH1.h:290
virtual void GetMinimumAndMaximum(Double_t &min, Double_t &max) const
Retrieve the minimum and maximum values in the histogram.
Definition TH1.cxx:8764
virtual Int_t GetMaximumBin() const
Return location of bin with maximum value in the range.
Definition TH1.cxx:8610
@ kNormal
Errors with Normal (Wald) approximation: errorUp=errorLow= sqrt(N)
Definition TH1.h:65
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition TH1.cxx:5090
virtual Int_t GetContour(Double_t *levels=nullptr)
Return contour values into array levels if pointer levels is non zero.
Definition TH1.cxx:8444
const Double_t * GetBuffer() const
Definition TH1.h:240
virtual Bool_t IsHighlight() const
Definition TH1.h:339
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width for 1D histogram.
Definition TH1.cxx:9196
virtual void SetContour(Int_t nlevels, const Double_t *levels=nullptr)
Set the number and values of contour levels.
Definition TH1.cxx:8516
virtual Double_t GetBinErrorUp(Int_t bin) const
Return upper error associated to bin number bin.
Definition TH1.cxx:9143
virtual void SetYTitle(const char *title)
Definition TH1.h:421
virtual Int_t GetSumw2N() const
Definition TH1.h:316
virtual Double_t GetStdDevError(Int_t axis=1) const
Return error of standard deviation estimation for Normal distribution.
Definition TH1.cxx:7688
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:8668
virtual Double_t GetSumOfWeights() const
Return the sum of weights excluding under/overflows.
Definition TH1.cxx:7950
static Bool_t AddDirectoryStatus()
Static function: cannot be inlined on Windows/NT.
Definition TH1.cxx:756
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:5274
virtual Int_t BufferEmpty(Int_t action=0)
Fill histogram with all entries in the buffer.
Definition TH1.cxx:1416
virtual Double_t GetKurtosis(Int_t axis=1) const
Definition TH1.cxx:7777
2-D histogram with a double per channel (see TH1 documentation)
Definition TH2.h:358
2-D histogram with a float per channel (see TH1 documentation)
Definition TH2.h:308
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
static TClass * Class()
The 3-D histogram classes derived from the 1-D histogram classes.
Definition TH3.h:31
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:35
virtual void SetImage(const Double_t *, UInt_t, UInt_t, TImagePalette *=nullptr)
Definition TImage.h:116
virtual void PaintImage(Drawable_t, Int_t, Int_t, Int_t=0, Int_t=0, UInt_t=0, UInt_t=0, Option_t *="")
Definition TImage.h:243
void Reset()
To draw Mathematical Formula.
Definition TLatex.h:18
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:576
void Add(TObject *obj) override
Definition TList.h:81
TObject * Remove(TObject *obj) override
Remove object from the list.
Definition TList.cxx:820
TObject * First() const override
Return the first object in the list. Returns 0 when list is empty.
Definition TList.cxx:657
virtual TObjLink * FirstLink() const
Definition TList.h:102
void Delete(Option_t *option="") override
Remove all objects from the list AND delete all heap based objects.
Definition TList.cxx:468
TObject * At(Int_t idx) const override
Returns the object at position idx. Returns 0 if idx is out of range.
Definition TList.cxx:355
void AddFirst(TObject *obj) override
Add object at the beginning of the list.
Definition TList.cxx:98
TMatrixTBase.
static TClass * Class()
A TMultiGraph is a collection of TGraph (or derived) objects.
Definition TMultiGraph.h:34
TList * GetListOfGraphs() const
Definition TMultiGraph.h:68
static TClass * Class()
virtual Int_t IsInside(Double_t x, Double_t y) const
Return 1 if the point (x,y) is inside one of the graphs 0 otherwise.
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition TNamed.cxx:164
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:48
An array of TObjects.
Definition TObjArray.h:31
void Delete(Option_t *option="") override
Remove all objects from the array AND delete all heap based objects.
TObject * At(Int_t idx) const override
Definition TObjArray.h:164
TObject * FindObject(const char *name) const override
Find an object in this collection using its name.
void Add(TObject *obj) override
Definition TObjArray.h:68
Mother of all ROOT objects.
Definition TObject.h:41
virtual void Clear(Option_t *="")
Definition TObject.h:119
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:456
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:199
virtual Option_t * GetDrawOption() const
Get option used by the graphics system to draw this object.
Definition TObject.cxx:440
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:991
virtual TObject * FindObject(const char *name) const
Must be redefined in derived classes.
Definition TObject.cxx:420
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:798
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:542
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1005
virtual const char * GetTitle() const
Returns title of object.
Definition TObject.cxx:500
virtual TClass * IsA() const
Definition TObject.h:243
virtual void Paint(Option_t *option="")
This method must be overridden if a class wants to paint itself.
Definition TObject.cxx:624
@ kCannotPick
if object in a pad cannot be picked
Definition TObject.h:67
@ kCanDelete
if object in a list can be deleted
Definition TObject.h:62
@ kMustCleanup
if object destructor must call RecursiveRemove()
Definition TObject.h:64
void DrawFaceMove3(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 3rd variant for "MOVING SCREEN" algorithm (draw level lines only)
void DrawLevelLines(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw level lines without hidden line removal.
void SurfaceFunction(Int_t ia, Int_t ib, Double_t *f, Double_t *t)
Service function for Surfaces.
void DrawFaceMode1(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *t)
Draw face - 1st variant (2 colors: 1st for external surface, 2nd for internal)
void GouraudFunction(Int_t ia, Int_t ib, Double_t *f, Double_t *t)
Find part of surface with luminosity in the corners.
void DrawFaceMove1(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 1st variant for "MOVING SCREEN" algorithm (draw face with level lines)
void DrawFaceRaster2(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 2nd variant for "RASTER SCREEN" algorithm (draw face for stacked lego plot)
void LegoFunction(Int_t ia, Int_t ib, Int_t &nv, Double_t *ab, Double_t *vv, Double_t *t)
Service function for Legos.
void DrawFaceMove2(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 2nd variant for "MOVING SCREEN" algorithm (draw face for stacked lego plot)
void DrawFaceRaster1(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 1st variant for "RASTER SCREEN" algorithm (draw face with level lines)
void DrawFaceMode3(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *t)
Draw face - 3rd option (draw face for stacked lego plot)
void DrawFaceMode2(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *t)
Draw face - 2nd option (fill in correspondence with function levels)
The palette painting class.
void Paint(Option_t *option="") override
Paint the palette.
void SetHistogram(TH1 *h)
TH1 * GetHistogram()
The histogram statistics painter class.
Definition TPaveStats.h:18
Int_t GetOptStat() const
Return the stat option.
virtual void SetStatFormat(const char *format="6.4g")
Change (i.e. set) the format for printing statistics.
void SetOptStat(Int_t stat=1)
Set the stat option.
virtual const char * GetFitFormat() const
Definition TPaveStats.h:35
virtual void SetFitFormat(const char *format="5.4g")
Change (i.e. set) the format for printing fit parameters in statistics box.
Int_t GetOptFit() const
Return the fit option.
void SetParent(TObject *obj) override
Definition TPaveStats.h:53
void SetOptFit(Int_t fit=1)
Set the fit option.
virtual const char * GetStatFormat() const
Definition TPaveStats.h:36
void Paint(Option_t *option="") override
Paint the pave stat.
static TClass * Class()
A Pave (see TPave) with text, lines or/and boxes inside.
Definition TPaveText.h:21
virtual TText * AddText(Double_t x1, Double_t y1, const char *label)
Add a new Text line to this pavetext at given coordinates.
static TClass * Class()
void Clear(Option_t *option="") override
Clear all lines in this pavetext.
void Draw(Option_t *option="") override
Draw this pavetext with its current attributes.
void Paint(Option_t *option="") override
Paint this pavetext with its current attributes.
virtual TText * GetLine(Int_t number) const
Get Pointer to line number in this pavetext.
const char * GetName() const override
Returns name of object.
Definition TPave.h:56
virtual void SetName(const char *name="")
Definition TPave.h:79
virtual void SetBorderSize(Int_t bordersize=4)
Sets the border size of the TPave box and shadow.
Definition TPave.h:77
Option_t * GetOption() const override
Definition TPave.h:57
Double_t GetX1NDC() const
Definition TPave.h:59
virtual void SetX2NDC(Double_t x2)
Definition TPave.h:83
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()
virtual Double_t GetBinEntries(Int_t bin) const
Return bin entries of a Profile2D histogram.
Profile Histogram.
Definition TProfile.h:32
virtual Double_t GetBinEntries(Int_t bin) const
Return bin entries of a Profile histogram.
Definition TProfile.cxx:837
static TClass * Class()
Random number generator class based on the maximally quidistributed combined Tausworthe generator by ...
Definition TRandom2.h:27
Double_t Rndm() override
TausWorth generator from L'Ecuyer, uses as seed 3x32bits integers Use a mask of 0xffffffffUL to make ...
Definition TRandom2.cxx:55
Sequenceable collection abstract base class.
Basic string class.
Definition TString.h:139
Ssiz_t Length() const
Definition TString.h:417
void ToLower()
Change string to lower-case.
Definition TString.cxx:1182
const char * Data() const
Definition TString.h:376
TString & Remove(Ssiz_t pos)
Definition TString.h:685
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:2378
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2356
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:632
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:651
Int_t GetOptStat() const
Definition TStyle.h:245
Color_t GetStatTextColor() const
Definition TStyle.h:258
Float_t GetTitleX() const
Definition TStyle.h:280
Int_t GetOptTitle() const
Definition TStyle.h:246
Float_t GetStatFontSize() const
Definition TStyle.h:261
Float_t GetBarOffset() const
Definition TStyle.h:182
Float_t GetStatX() const
Definition TStyle.h:264
Float_t GetTitleSize(Option_t *axis="X") const
Return title size.
Definition TStyle.cxx:1240
Float_t GetTitleY() const
Definition TStyle.h:281
Style_t GetTitleFont(Option_t *axis="X") const
Return title font.
Definition TStyle.cxx:1216
Bool_t GetHistMinimumZero() const
Definition TStyle.h:237
Float_t GetStatY() const
Definition TStyle.h:265
Color_t GetTitleFillColor() const
Definition TStyle.h:271
Style_t GetTitleStyle() const
Definition TStyle.h:273
Color_t GetStatColor() const
Definition TStyle.h:257
Float_t GetBarWidth() const
Definition TStyle.h:183
void SetDrawBorder(Int_t drawborder=1)
Definition TStyle.h:342
Float_t GetStatH() const
Definition TStyle.h:267
Width_t GetTitleBorderSize() const
Definition TStyle.h:275
Int_t GetColorPalette(Int_t i) const
Return color number i in current palette.
Definition TStyle.cxx:1101
Float_t GetErrorX() const
Definition TStyle.h:186
Double_t GetHistTopMargin() const
Definition TStyle.h:238
void SetBarOffset(Float_t baroff=0.5)
Definition TStyle.h:335
Float_t GetEndErrorSize() const
Definition TStyle.h:185
Int_t GetDrawBorder() const
Definition TStyle.h:184
Width_t GetStatBorderSize() const
Definition TStyle.h:259
Color_t GetTitleTextColor() const
Definition TStyle.h:272
void SetBarWidth(Float_t barwidth=0.5)
Definition TStyle.h:336
Float_t GetTitleH() const
Definition TStyle.h:283
Style_t GetStatStyle() const
Definition TStyle.h:262
Float_t GetStatW() const
Definition TStyle.h:266
const char * GetFitFormat() const
Definition TStyle.h:199
const char * GetStatFormat() const
Definition TStyle.h:263
Int_t GetNumberOfColors() const
Return number of colors in the color palette.
Definition TStyle.cxx:1175
Int_t GetOptFit() const
Definition TStyle.h:244
Int_t GetNumberContours() const
Definition TStyle.h:241
const char * GetPaintTextFormat() const
Definition TStyle.h:250
Style_t GetStatFont() const
Definition TStyle.h:260
Float_t GetTitleFontSize() const
Definition TStyle.h:274
Int_t GetTitleAlign() const
Definition TStyle.h:270
Float_t GetTitleW() const
Definition TStyle.h:282
virtual int Load(const char *module, const char *entry="", Bool_t system=kFALSE)
Load a shared library.
Definition TSystem.cxx:1857
Base class for several text objects.
Definition TText.h:22
TVectorT.
Definition TVectorT.h:29
static TClass * Class()
See TView3D.
Definition TView.h:25
virtual Double_t GetPsi()=0
virtual Double_t * GetRmax()=0
virtual void SetAxisNDC(const Double_t *x1, const Double_t *x2, const Double_t *y1, const Double_t *y2, const Double_t *z1, const Double_t *z2)=0
virtual Double_t * GetRmin()=0
virtual void WCtoNDC(const Float_t *pw, Float_t *pn)=0
virtual void SetOutlineToCube()=0
virtual Int_t GetDistancetoAxis(Int_t axis, Int_t px, Int_t py, Double_t &ratio)=0
virtual Double_t * GetTnorm()=0
virtual void ExecuteRotateView(Int_t event, Int_t px, Int_t py)=0
virtual TSeqCollection * GetOutline()=0
virtual void PadRange(Int_t rback)=0
virtual void SetRange(const Double_t *min, const Double_t *max)=0
virtual void FindNormal(Double_t x, Double_t y, Double_t z, Double_t &zn)=0
virtual void AxisVertex(Double_t ang, Double_t *av, Int_t &ix1, Int_t &ix2, Int_t &iy1, Int_t &iy2, Int_t &iz1, Int_t &iz2)=0
virtual void SetView(Double_t longitude, Double_t latitude, Double_t psi, Int_t &irep)=0
Abstract base class used by ROOT graphics editor.
static TVirtualPadEditor * GetPadEditor(Bool_t load=kTRUE)
Returns the pad editor dialog. Static method.
virtual void Show()
small helper class to store/restore gPad context in TPad methods
Definition TVirtualPad.h:61
auto GetSaved() const
Definition TVirtualPad.h:69
TVirtualPad is an abstract base class for the Pad and Canvas classes.
Definition TVirtualPad.h:51
virtual void Close(Option_t *option="")=0
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:697
Short_t Max(Short_t a, Short_t b)
Returns the largest of a and b.
Definition TMathBase.h:250
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:644
constexpr Double_t PiOver2()
Definition TMath.h:51
Double_t Log(Double_t x)
Returns the natural logarithm of x.
Definition TMath.h:760
constexpr Double_t DegToRad()
Conversion from degree to radian: .
Definition TMath.h:79
Double_t Sqrt(Double_t x)
Returns the square root of x.
Definition TMath.h:666
LongDouble_t Power(LongDouble_t x, LongDouble_t y)
Returns x raised to the power y.
Definition TMath.h:725
Short_t Min(Short_t a, Short_t b)
Returns the smallest of a and b.
Definition TMathBase.h:198
Double_t Cos(Double_t)
Returns the cosine of an angle of x radians.
Definition TMath.h:598
constexpr Double_t Pi()
Definition TMath.h:37
Bool_t AreEqualRel(Double_t af, Double_t bf, Double_t relPrec)
Comparing floating points.
Definition TMath.h:426
Double_t Sin(Double_t)
Returns the sine of an angle of x radians.
Definition TMath.h:592
Double_t Tan(Double_t)
Returns the tangent of an angle of x radians.
Definition TMath.h:604
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:347
constexpr Double_t RadToDeg()
Conversion from radian to degree: .
Definition TMath.h:72
Double_t Log10(Double_t x)
Returns the common (base-10) logarithm of x.
Definition TMath.h:766
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:123
Definition graph.py:1
Histograms' drawing options structure.
Definition Hoption.h:24
int Curve
"C" A smooth Curve is drawn.
Definition Hoption.h:32
int Proj
"AITOFF", "MERCATOR", "SINUSOIDAL" and "PARABOLIC" projections for 2d plots.
Definition Hoption.h:59
int Axis
"A" Axis are not drawn around the graph.
Definition Hoption.h:30
int Box
"BOX" Draw 2D plot with proportional Boxes.
Definition Hoption.h:41
int Scat
"SCAT" Draw 2D plot a Scatter plot.
Definition Hoption.h:48
int Text
"TEXT" Draw 2D plot with the content of each cell.
Definition Hoption.h:50
int Color
"COL" Draw 2D plot with Colored boxes.
Definition Hoption.h:43
int AxisPos
"X+" and "Y+" Axis position
Definition Hoption.h:60
int List
"LIST" Generate the TObjArray "contours". To be used with option "CONT"
Definition Hoption.h:58
int Logx
log scale in X. Also set by histogram option
Definition Hoption.h:70
int Zscale
"Z" Display the color palette.
Definition Hoption.h:55
int MinimumZero
"MIN0" or gStyle->GetHistMinimumZero()
Definition Hoption.h:63
int Contour
"CONTn" Draw 2D plot as a Contour plot (0 <= n <= 5).
Definition Hoption.h:44
int Off
"][" The first and last vertical lines are not drawn.
Definition Hoption.h:35
int Func
"FUNC" Draw only the function (for example in case of fit).
Definition Hoption.h:45
long Candle
"CANDLE" and "VIOLIN" Draw a 2D histogram as candle/box plot or violin plot.
Definition Hoption.h:53
int Spec
"SPEC" TSpectrum graphics
Definition Hoption.h:61
int FrontBox
"FB" Suppress the front box for the 3D plots.
Definition Hoption.h:56
int Pie
"PIE" Draw 1D plot as a pie chart.
Definition Hoption.h:52
int Star
"*" With option "P", a * is plotted at each point.
Definition Hoption.h:39
int Zero
"0" if selected with any LEGO option the empty bins are not drawn.
Definition Hoption.h:62
int Logz
log scale in Z. Also set by histogram option
Definition Hoption.h:72
int Tri
"TRI" Draw TGraph2D with Delaunay triangles.
Definition Hoption.h:51
int BackBox
"BB" Suppress the back box for the 3D plots.
Definition Hoption.h:57
int Mark
"P" The current Marker is drawn at each point.
Definition Hoption.h:37
int Arrow
"ARR" Draw 2D plot with Arrows.
Definition Hoption.h:40
int Line
"L" A simple polyline through every point is drawn.
Definition Hoption.h:36
int Same
"SAME" Histogram is plotted in the current pad.
Definition Hoption.h:38
int Lego
"LEGO" and "LEGOn" Draw as a Lego plot(1 <= n <= 4).
Definition Hoption.h:47
int Bar
"B", "BAR" and "HBAR" A Bar chart is drawn at each point.
Definition Hoption.h:31
int Fill
"F" A fill area is drawn ("CF" draw a smooth fill area).
Definition Hoption.h:34
int Hist
"HIST" Draw only the histogram.
Definition Hoption.h:46
int Surf
"SURF" and "SURFn" Draw as a Surface ((1 <= n <= 4).
Definition Hoption.h:49
int Logy
log scale in Y. Also set by histogram option
Definition Hoption.h:71
int System
"POL", "CYL", "SPH" and "PSR" Type of coordinate system for 3D plots.
Definition Hoption.h:54
int Error
"En" Draw Errors with current marker type and size (0 <= n <=6).
Definition Hoption.h:33
Histogram parameters structure.
Definition Hparam.h:27
Double_t baroffset
Offset of bin for bars or legos [0,1].
Definition Hparam.h:42
Double_t ylowedge
Low edge of axis.
Definition Hparam.h:33
Double_t xmin
Minimum value along X.
Definition Hparam.h:30
Int_t ylast
Last bin number along Y.
Definition Hparam.h:47
Int_t xfirst
First bin number along X.
Definition Hparam.h:44
Double_t zmin
Minimum value along Z.
Definition Hparam.h:38
Double_t xbinsize
Bin size in case of equidistant bins.
Definition Hparam.h:28
Double_t ymin
Minimum value along y.
Definition Hparam.h:34
Double_t allchan
Integrated sum of contents.
Definition Hparam.h:41
Double_t xlowedge
Low edge of axis.
Definition Hparam.h:29
Double_t ymax
Maximum value along y.
Definition Hparam.h:35
Double_t factor
Multiplication factor (normalization)
Definition Hparam.h:40
Int_t xlast
Last bin number along X.
Definition Hparam.h:45
Double_t ybinsize
Bin size in case of equidistant bins.
Definition Hparam.h:32
Double_t barwidth
Width of bin for bars and legos [0,1].
Definition Hparam.h:43
Double_t zmax
Maximum value along Z.
Definition Hparam.h:39
Double_t xmax
Maximum value along X.
Definition Hparam.h:31
Int_t yfirst
First bin number along Y.
Definition Hparam.h:46
auto * th2
Definition textalign.C:18
TMarker m
Definition textangle.C:8
TLine l
Definition textangle.C:4
auto * tt
Definition textangle.C:16