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 without errors use the option "HIST" together with the required option (eg "hist same c"). The "HIST" option can also be used to plot only the histogram and not the associated function(s). |
229| "FUNC" | When an histogram has a fitted function, this option allows to draw the fit result only. |
230| "SAME" | Superimpose on previous picture in the same pad. |
231| "SAMES" | Same as "SAME" and draw the statistics box|
232| "PFC" | Palette Fill Color: histogram's fill color is taken in the current palette. |
233| "PLC" | Palette Line Color: histogram's line color is taken in the current palette. |
234| "PMC" | Palette Marker Color: histogram's marker color is taken in the current palette. |
235| "LEGO" | Draw a lego plot with hidden line removal. |
236| "LEGO1" | Draw a lego plot with hidden surface removal. |
237| "LEGO2" | Draw a lego plot using colors to show the cell contents When the option "0" is used with any LEGO option, the empty bins are not drawn.|
238| "LEGO3" | Draw a lego plot with hidden surface removal, like LEGO1 but the border lines of each lego-bar are not drawn.|
239| "LEGO4" | Draw a lego plot with hidden surface removal, like LEGO1 but without the shadow effect on each lego-bar.|
240| "TEXT" | Draw bin contents as text (format set via `gStyle->SetPaintTextFormat`).|
241| "TEXTnn" | Draw bin contents as text at angle nn (0 < nn <= 90). |
242| "X+" | The X-axis is drawn on the top side of the plot. |
243| "Y+" | The Y-axis is drawn on the right side of the plot. |
244| "MIN0" | Set minimum value for the Y axis to 0, equivalent to gStyle->SetHistMinimumZero(). |
245
246\anchor HP01b
247#### Options supported for 1D histograms
248
249| Option | Description |
250|----------|-------------------------------------------------------------------|
251| " " | Default. |
252| "AH" | Draw histogram without axis. "A" can be combined with any drawing option. For instance, "AC" draws the histogram as a smooth Curve without axis.|
253| "][" | When this option is selected the first and last vertical lines of the histogram are not drawn.|
254| "B" | Bar chart option.|
255| "BAR" | Like option "B", but bars can be drawn with a 3D effect.|
256| "HBAR" | Like option "BAR", but bars are drawn horizontally.|
257| "C" | Draw a smooth Curve through the histogram bins.|
258| "E0" | Draw error bars. Markers are drawn for bins with 0 contents. Combined with E1 or E2 it avoids error bars clipping|
259| "E1" | Draw error bars with perpendicular lines at the edges.|
260| "E2" | Draw error bars with rectangles.|
261| "E3" | Draw a fill area through the end points of the vertical error bars.|
262| "E4" | Draw a smoothed filled area through the end points of the error bars.|
263| "E5" | Like E3 but ignore the bins with 0 contents.|
264| "E6" | Like E4 but ignore the bins with 0 contents.|
265| "X0" | When used with one of the "E" option, it suppress the error bar along X as `gStyle->SetErrorX(0)` would do.|
266| "L" | Draw a line through the bin contents.|
267| "P" | Draw current marker at each bin except empty bins.|
268| "P*" | Draw a star marker at each bin except empty bins.|
269| "P0" | Draw current marker at each bin including empty bins.|
270| "PIE" | Draw histogram as a Pie Chart.|
271| "*H" | Draw histogram with a * at each bin.|
272| "LF2" | Draw histogram like with option "L" but with a fill area. Note that "L" draws also a fill area if the hist fill color is set but the fill area corresponds to the histogram contour.|
273
274
275\anchor HP01c
276#### Options supported for 2D histograms
277
278| Option | Description |
279|--------------|------------------------------------------------------------------|
280| " " | Default (color plot).|
281| "ARR" | Arrow mode. Shows gradient between adjacent cells.|
282| "BOX" | A box is drawn for each cell with surface proportional to the content's absolute value. A negative content is marked with a X. |
283| "BOX1" | A button is drawn for each cell with surface proportional to content's absolute value. A sunken button is drawn for negative values a raised one for positive.|
284| "COL" | A box is drawn for each cell with a color scale varying with contents. All the none empty bins are painted. Empty bins are not painted unless some bins have a negative content because in that case the null bins might be not empty. `TProfile2D` histograms are handled differently because, for this type of 2D histograms, it is possible to know if an empty bin has been filled or not. So even if all the bins' contents are positive some empty bins might be painted. And vice versa, if some bins have a negative content some empty bins might be not painted (default).|
285| "COLZ" | Same as "COL". In addition the color palette is also drawn.|
286| "COL2" | Alternative rendering algorithm to "COL". Can significantly improve rendering performance for large, non-sparse 2-D histograms.|
287| "COLZ2" | Same as "COL2". In addition the color palette is also drawn.|
288| "Z CJUST" | In combination with colored options "COL","CONT0" etc: Justify labels in the color palette at color boundaries. For more details see `TPaletteAxis`|
289| "CANDLE" | Draw a candle plot along X axis.|
290| "CANDLEX" | Same as "CANDLE".|
291| "CANDLEY" | Draw a candle plot along Y axis.|
292| "CANDLEXn" | Draw a candle plot along X axis. Different candle-styles with n from 1 to 6.|
293| "CANDLEYn" | Draw a candle plot along Y axis. Different candle-styles with n from 1 to 6.|
294| "VIOLIN" | Draw a violin plot along X axis.|
295| "VIOLINX" | Same as "VIOLIN".|
296| "VIOLINY" | Draw a violin plot along Y axis.|
297| "VIOLINXn" | Draw a violin plot along X axis. Different violin-styles with n being 1 or 2.|
298| "VIOLINYn" | Draw a violin plot along Y axis. Different violin-styles with n being 1 or 2.|
299| "CONT" | Draw a contour plot (same as CONT0).|
300| "CONT0" | Draw a contour plot using surface colors to distinguish contours.|
301| "CONT1" | Draw a contour plot using line styles to distinguish contours.|
302| "CONT2" | Draw a contour plot using the same line style for all contours.|
303| "CONT3" | Draw a contour plot using fill area colors.|
304| "CONT4" | Draw a contour plot using surface colors (SURF option at theta = 0).|
305| "LIST" | Generate a list of TGraph objects for each contour.|
306| "SAME0" | Same as "SAME" but do not use the z-axis range of the first plot. |
307| "SAMES0" | Same as "SAMES" but do not use the z-axis range of the first plot. |
308| "CYL" | Use Cylindrical coordinates. The X coordinate is mapped on the angle and the Y coordinate on the cylinder length.|
309| "POL" | Use Polar coordinates. The X coordinate is mapped on the angle and the Y coordinate on the radius.|
310| "SPH" | Use Spherical coordinates. The X coordinate is mapped on the latitude and the Y coordinate on the longitude.|
311| "PSR" | Use PseudoRapidity/Phi coordinates. The X coordinate is mapped on Phi.|
312| "SURF" | Draw a surface plot with hidden line removal.|
313| "SURF1" | Draw a surface plot with hidden surface removal.|
314| "SURF2" | Draw a surface plot using colors to show the cell contents.|
315| "SURF3" | Same as SURF with in addition a contour view drawn on the top.|
316| "SURF4" | Draw a surface using Gouraud shading.|
317| "SURF5" | Same as SURF3 but only the colored contour is drawn. Used with option CYL, SPH or PSR it allows to draw colored contours on a sphere, a cylinder or a in pseudo rapidity space. In cartesian or polar coordinates, option SURF3 is used.|
318| "AITOFF" | Draw a contour via an AITOFF projection.|
319| "MERCATOR" | Draw a contour via an Mercator projection.|
320| "SINUSOIDAL" | Draw a contour via an Sinusoidal projection.|
321| "PARABOLIC" | Draw a contour via an Parabolic projection.|
322| "MOLLWEIDE" | Draw a contour via an Mollweide projection.|
323| "LEGO9" | Draw the 3D axis only. Mainly needed for internal use |
324| "FB" | With LEGO or SURFACE, suppress the Front-Box.|
325| "BB" | With LEGO or SURFACE, suppress the Back-Box.|
326| "A" | With LEGO or SURFACE, suppress the axis.|
327| "SCAT" | Draw a scatter-plot (legacy draw option).|
328| "[cutg]" | Draw only the sub-range selected by the TCutG named "cutg".|
329
330
331\anchor HP01d
332#### Options supported for 3D histograms
333
334| Option | Description |
335|----------|-------------------------------------------------------------------|
336| " " | Default (color plot).|
337| "ISO" | Draw a Gouraud shaded 3d iso surface through a 3d histogram. It paints one surface at the value computed as follow: `SumOfWeights/(NbinsX*NbinsY*NbinsZ)`.|
338| "BOX" | Draw a for each cell with volume proportional to the content's absolute value. An hidden line removal algorithm is used|
339| "BOX1" | Same as BOX but an hidden surface removal algorithm is used|
340| "BOX2" | The boxes' colors are picked in the current palette according to the bins' contents|
341| "BOX2Z" | Same as "BOX2". In addition the color palette is also drawn.|
342| "BOX3" | Same as BOX1, but the border lines of each lego-bar are not drawn.|
343| "LEGO" | Same as `BOX`.|
344
345
346\anchor HP01e
347#### Options supported for histograms' stacks (`THStack`)
348
349| Option | Description |
350|------------|-----------------------------------------------------------------|
351| " " | Default, the histograms are drawn on top of each other (as lego plots for 2D histograms).|
352| "NOSTACK" | Histograms in the stack are all paint in the same pad as if the option `SAME` had been specified.|
353| "NOSTACKB" | Histograms are drawn next to each other as bar charts.|
354| "PADS" | The current pad/canvas is subdivided into a number of pads equal to the number of histograms in the stack and each histogram is paint into a separate pad.|
355| "PFC" | Palette Fill Color: stack's fill color is taken in the current palette. |
356| "PLC" | Palette Line Color: stack's line color is taken in the current palette. |
357| "PMC" | Palette Marker Color: stack's marker color is taken in the current palette. |
358
359
360
361\anchor HP02
362### Setting the Style
363
364
365Histograms use the current style (`gStyle`). When one changes the current
366style and would like to propagate the changes to the histogram,
367`TH1::UseCurrentStyle` should be called. Call `UseCurrentStyle` on
368each histogram is needed.
369
370To force all the histogram to use the current style use:
371
372 gROOT->ForceStyle();
373
374All the histograms read after this call will use the current style.
375
376
377\anchor HP03
378### Setting line, fill, marker, and text attributes
379
380
381The histogram classes inherit from the attribute classes:
382`TAttLine`, `TAttFill` and `TAttMarker`.
383See the description of these classes for the list of options.
384
385
386\anchor HP04
387### Setting Tick marks on the histogram axis
388
389
390The `TPad::SetTicks` method specifies the type of tick marks on the axis.
391If ` tx = gPad->GetTickx()` and `ty = gPad->GetTicky()` then:
392
393 tx = 1; tick marks on top side are drawn (inside)
394 tx = 2; tick marks and labels on top side are drawn
395 ty = 1; tick marks on right side are drawn (inside)
396 ty = 2; tick marks and labels on right side are drawn
397
398By default only the left Y axis and X bottom axis are drawn
399(`tx = ty = 0`)
400
401`TPad::SetTicks(tx,ty)` allows to set these options.
402See also The `TAxis` functions to set specific axis attributes.
403
404In case multiple color filled histograms are drawn on the same pad, the fill
405area may hide the axis tick marks. One can force a redraw of the axis over all
406the histograms by calling:
407
408 gPad->RedrawAxis();
409
410
411\anchor HP05
412### Giving titles to the X, Y and Z axis
413
414
415 h->GetXaxis()->SetTitle("X axis title");
416 h->GetYaxis()->SetTitle("Y axis title");
417
418The histogram title and the axis titles can be any `TLatex` string.
419The titles are part of the persistent histogram.
420
421
422\anchor HP060
423### The option "SAME"
424
425
426By default, when an histogram is drawn, the current pad is cleared before
427drawing. In order to keep the previous drawing and draw on top of it the
428option `SAME` should be use. The histogram drawn with the option
429`SAME` uses the coordinates system available in the current pad.
430
431This option can be used alone or combined with any valid drawing option but
432some combinations must be use with care.
433
434\anchor HP060a
435#### Limitations
436
437- It does not work when combined with the `LEGO` and `SURF` options unless the
438 histogram plotted with the option `SAME` has exactly the same
439 ranges on the X, Y and Z axis as the currently drawn histogram. To superimpose
440 lego plots [histograms' stacks](\ref HP26) should be used.
441
442
443\anchor HP061
444### Colors automatically picked in palette
445
446\since **ROOT version 6.09/01**
447
448When several histograms are painted in the same canvas thanks to the option "SAME"
449or via a `THStack` it might be useful to have an easy and automatic way to choose
450their color. The simplest way is to pick colors in the current active color
451palette. Palette coloring for histogram is activated thanks to the options `PFC`
452(Palette Fill Color), `PLC` (Palette Line Color) and `PMC` (Palette Marker Color).
453When one of these options is given to `TH1::Draw` the histogram get its color
454from the current color palette defined by `gStyle->SetPalette(...)`. The color
455is determined according to the number of objects having palette coloring in
456the current pad.
457
458Begin_Macro(source)
459../../../tutorials/hist/histpalettecolor.C
460End_Macro
461
462Begin_Macro(source)
463../../../tutorials/hist/thstackpalettecolor.C
464End_Macro
465
466Begin_Macro(source)
467../../../tutorials/hist/thstack2palettecolor.C
468End_Macro
469
470\anchor HP06
471### Superimposing two histograms with different scales in the same pad
472
473
474The following example creates two histograms, the second histogram is the bins
475integral of the first one. It shows a procedure to draw the two histograms in
476the same pad and it draws the scale of the second histogram using a new vertical
477axis on the right side. See also the tutorial `transpad.C` for a variant
478of this example.
479
480Begin_Macro(source)
481{
482 auto c1 = new TCanvas("c1","c1",600,400);
483 // create/fill draw h1
484 gStyle->SetOptStat(kFALSE);
485 auto h1 = new TH1F("h1","Superimposing two histograms with different scales",100,-3,3);
486 Int_t i;
487 for (i=0;i<10000;i++) h1->Fill(gRandom->Gaus(0,1));
488 h1->Draw();
489 c1->Update();
490
491 // create hint1 filled with the bins integral of h1
492 auto hint1 = new TH1F("hint1","h1 bins integral",100,-3,3);
493 float sum = 0.f;
494 for (i=1;i<=100;i++) {
495 sum += h1->GetBinContent(i);
496 hint1->SetBinContent(i,sum);
497 }
498
499 // scale hint1 to the pad coordinates
500 float rightmax = 1.1*hint1->GetMaximum();
501 float scale = gPad->GetUymax()/rightmax;
502 hint1->SetLineColor(kRed);
503 hint1->Scale(scale);
504 hint1->Draw("same");
505
506 // draw an axis on the right side
507 auto axis = new TGaxis(gPad->GetUxmax(),gPad->GetUymin(),
508 gPad->GetUxmax(), gPad->GetUymax(),0,rightmax,510,"+L");
509 axis->SetLineColor(kRed);
510 axis->SetTextColor(kRed);
511 axis->Draw();
512}
513End_Macro
514
515
516\anchor HP07
517### Statistics Display
518
519
520The type of information shown in the histogram statistics box can be selected
521with:
522
523 gStyle->SetOptStat(mode);
524
525The `mode` has up to nine digits that can be set to on (1 or 2), off (0).
526
527 mode = ksiourmen (default = 000001111)
528 k = 1; kurtosis printed
529 k = 2; kurtosis and kurtosis error printed
530 s = 1; skewness printed
531 s = 2; skewness and skewness error printed
532 i = 1; integral of bins printed
533 i = 2; integral of bins with option "width" printed
534 o = 1; number of overflows printed
535 u = 1; number of underflows printed
536 r = 1; standard deviation printed
537 r = 2; standard deviation and standard deviation error printed
538 m = 1; mean value printed
539 m = 2; mean and mean error values printed
540 e = 1; number of entries printed
541 n = 1; name of histogram is printed
542
543For example:
544
545 gStyle->SetOptStat(11);
546
547displays only the name of histogram and the number of entries, whereas:
548
549 gStyle->SetOptStat(1101);
550
551displays the name of histogram, mean value and standard deviation.
552
553<b>WARNING 1:</b> never do:
554
555 gStyle->SetOptStat(0001111);
556
557but instead do:
558
559 gStyle->SetOptStat(1111);
560
561because `0001111` will be taken as an octal number!
562
563<b>WARNING 2:</b> for backward compatibility with older versions
564
565 gStyle->SetOptStat(1);
566
567is taken as:
568
569 gStyle->SetOptStat(1111)
570
571To print only the name of the histogram do:
572
573 gStyle->SetOptStat(1000000001);
574
575<b>NOTE</b> that in case of 2D histograms, when selecting only underflow
576(10000) or overflow (100000), the statistics box will show all combinations
577of underflow/overflows and not just one single number.
578
579The parameter mode can be any combination of the letters `kKsSiIourRmMen`
580
581 k : kurtosis printed
582 K : kurtosis and kurtosis error printed
583 s : skewness printed
584 S : skewness and skewness error printed
585 i : integral of bins printed
586 I : integral of bins with option "width" printed
587 o : number of overflows printed
588 u : number of underflows printed
589 r : standard deviation printed
590 R : standard deviation and standard deviation error printed
591 m : mean value printed
592 M : mean value mean error values printed
593 e : number of entries printed
594 n : name of histogram is printed
595
596For example, to print only name of histogram and number of entries do:
597
598 gStyle->SetOptStat("ne");
599
600To print only the name of the histogram do:
601
602 gStyle->SetOptStat("n");
603
604The default value is:
605
606 gStyle->SetOptStat("nemr");
607
608When a histogram is painted, a `TPaveStats` object is created and added
609to the list of functions of the histogram. If a `TPaveStats` object
610already exists in the histogram list of functions, the existing object is just
611updated with the current histogram parameters.
612
613Once a histogram is painted, the statistics box can be accessed using
614`h->FindObject("stats")`. In the command line it is enough to do:
615
616 Root > h->Draw()
617 Root > TPaveStats *st = (TPaveStats*)h->FindObject("stats")
618
619because after `h->Draw()` the histogram is automatically painted. But
620in a script file the painting should be forced using `gPad->Update()`
621in order to make sure the statistics box is created:
622
623 h->Draw();
624 gPad->Update();
625 TPaveStats *st = (TPaveStats*)h->FindObject("stats");
626
627Without `gPad->Update()` the line `h->FindObject("stats")` returns a null pointer.
628
629When a histogram is drawn with the option `SAME`, the statistics box
630is not drawn. To force the statistics box drawing with the option
631`SAME`, the option `SAMES` must be used.
632If the new statistics box hides the previous statistics box, one can change
633its position with these lines (`h` being the pointer to the histogram):
634
635 Root > TPaveStats *st = (TPaveStats*)h->FindObject("stats")
636 Root > st->SetX1NDC(newx1); //new x start position
637 Root > st->SetX2NDC(newx2); //new x end position
638
639To change the type of information for an histogram with an existing
640`TPaveStats` one should do:
641
642 st->SetOptStat(mode);
643
644Where `mode` has the same meaning than when calling `gStyle->SetOptStat(mode)`
645(see above).
646
647One can delete the statistics box for a histogram `TH1* h` with:
648
649 h->SetStats(0)
650
651and activate it again with:
652
653 h->SetStats(1).
654
655Labels used in the statistics box ("Mean", "Std Dev", ...) can be changed from
656`$ROOTSYS/etc/system.rootrc` or `.rootrc` (look for the string `Hist.Stats.`).
657
658
659\anchor HP08
660### Fit Statistics
661
662
663The type of information about fit parameters printed in the histogram statistics
664box can be selected via the parameter mode. The parameter mode can be
665`= pcev` (default `= 0111`)
666
667 p = 1; print Probability
668 c = 1; print Chisquare/Number of degrees of freedom
669 e = 1; print errors (if e=1, v must be 1)
670 v = 1; print name/values of parameters
671
672Example:
673
674 gStyle->SetOptFit(1011);
675
676print fit probability, parameter names/values and errors.
677
6781. When `v = 1` is specified, only the non-fixed parameters are shown.
6792. When `v = 2` all parameters are shown.
680
681Note: `gStyle->SetOptFit(1)` means "default value", so it is equivalent
682to `gStyle->SetOptFit(111)`
683
684
685\anchor HP09
686### The error bars options
687
688
689| Option | Description |
690|----------|-------------------------------------------------------------------|
691| "E" | Default. Shows only the error bars, not a marker.|
692| "E1" | Small lines are drawn at the end of the error bars.|
693| "E2" | Error rectangles are drawn.|
694| "E3" | A filled area is drawn through the end points of the vertical error bars.|
695| "E4" | A smoothed filled area is drawn through the end points of the vertical error bars.|
696| "E0" | Draw error bars. Markers are drawn for bins with 0 contents. Combined with E1 or E2 it avoids error bars clipping|
697| "E5" | Like E3 but ignore the bins with 0 contents.|
698| "E6" | Like E4 but ignore the bins with 0 contents.|
699| "X0" | When used with one of the "E" option, it suppress the error bar along X as `gStyle->SetErrorX(0)` would do.|
700
701Begin_Macro(source)
702{
703 auto c1 = new TCanvas("c1","c1",600,400);
704 auto he = new TH1F("he","Distribution drawn with error bars (option E1) ",100,-3,3);
705 for (int i=0; i<10000; i++) he->Fill(gRandom->Gaus(0,1));
706 gStyle->SetEndErrorSize(3);
707 gStyle->SetErrorX(1.);
708 he->SetMarkerStyle(20);
709 he->Draw("E1");
710}
711End_Macro
712
713The options "E3" and "E4" draw an error band through the end points of the
714vertical error bars. With "E4" the error band is smoothed. Because of the
715smoothing algorithm used some artefacts may appear at the end of the band
716like in the following example. In such cases "E3" should be used instead
717of "E4".
718
719Begin_Macro(source)
720{
721 auto ce4 = new TCanvas("ce4","ce4",600,400);
722 ce4->Divide(2,1);
723 auto he4 = new TH1F("he4","Distribution drawn with option E4",100,-3,3);
724 Int_t i;
725 for (i=0;i<10000;i++) he4->Fill(gRandom->Gaus(0,1));
726 he4->SetFillColor(kRed);
727 he4->GetXaxis()->SetRange(40,48);
728 ce4->cd(1);
729 he4->Draw("E4");
730 ce4->cd(2);
731 auto he3 = (TH1F*)he4->DrawClone("E3");
732 he3->SetTitle("Distribution drawn option E3");
733}
734End_Macro
735
7362D histograms can be drawn with error bars as shown is the following example:
737
738Begin_Macro(source)
739{
740 auto c2e = new TCanvas("c2e","c2e",600,400);
741 auto h2e = new TH2F("h2e","TH2 drawn with option E",40,-4,4,40,-20,20);
742 float px, py;
743 for (Int_t i = 0; i < 25000; i++) {
744 gRandom->Rannor(px,py);
745 h2e->Fill(px,5*py);
746 }
747 h2e->Draw("E");
748}
749End_Macro
750
751
752\anchor HP100
753### The bar chart option
754
755
756The option "B" allows to draw simple vertical bar charts.
757The bar width is controlled with `TH1::SetBarWidth()`,
758and the bar offset within the bin, with `TH1::SetBarOffset()`.
759These two settings are useful to draw several histograms on the
760same plot as shown in the following example:
761
762Begin_Macro(source)
763{
764 int i;
765 const Int_t nx = 8;
766 string os_X[nx] = {"8","32","128","512","2048","8192","32768","131072"};
767 float d_35_0[nx] = {0.75, -3.30, -0.92, 0.10, 0.08, -1.69, -1.29, -2.37};
768 float d_35_1[nx] = {1.01, -3.02, -0.65, 0.37, 0.34, -1.42, -1.02, -2.10};
769
770 auto cb = new TCanvas("cb","cb",600,400);
771 cb->SetGrid();
772
773 gStyle->SetHistMinimumZero();
774
775 auto h1b = new TH1F("h1b","Option B example",nx,0,nx);
776 h1b->SetFillColor(4);
777 h1b->SetBarWidth(0.4);
778 h1b->SetBarOffset(0.1);
779 h1b->SetStats(0);
780 h1b->SetMinimum(-5);
781 h1b->SetMaximum(5);
782
783 for (i=1; i<=nx; i++) {
784 h1b->SetBinContent(i, d_35_0[i-1]);
785 h1b->GetXaxis()->SetBinLabel(i,os_X[i-1].c_str());
786 }
787
788 h1b->Draw("b");
789
790 auto h2b = new TH1F("h2b","h2b",nx,0,nx);
791 h2b->SetFillColor(38);
792 h2b->SetBarWidth(0.4);
793 h2b->SetBarOffset(0.5);
794 h2b->SetStats(0);
795 for (i=1;i<=nx;i++) h2b->SetBinContent(i, d_35_1[i-1]);
796
797 h2b->Draw("b same");
798}
799End_Macro
800
801
802\anchor HP10
803### The "BAR" and "HBAR" options
804
805
806When the option `bar` or `hbar` is specified, a bar chart is drawn. A vertical
807bar-chart is drawn with the options `bar`, `bar0`, `bar1`, `bar2`, `bar3`, `bar4`.
808An horizontal bar-chart is drawn with the options `hbar`, `hbar0`, `hbar1`,
809`hbar2`, `hbar3`, `hbar4` (hbars.C).
810
811- The bar is filled with the histogram fill color.
812- The left side of the bar is drawn with a light fill color.
813- The right side of the bar is drawn with a dark fill color.
814- The percentage of the bar drawn with either the light or dark color is:
815 - 0% for option "(h)bar" or "(h)bar0"
816 - 10% for option "(h)bar1"
817 - 20% for option "(h)bar2"
818 - 30% for option "(h)bar3"
819 - 40% for option "(h)bar4"
820
821When an histogram has errors the option ["HIST"](\ref OPTHIST) together with the `(h)bar` option.
822
823Begin_Macro(source)
824../../../tutorials/hist/hbars.C
825End_Macro
826
827To control the bar width (default is the bin width) `TH1::SetBarWidth()`
828should be used.
829
830To control the bar offset (default is 0) `TH1::SetBarOffset()` should
831be used.
832
833These two parameters are useful when several histograms are plotted using
834the option `SAME`. They allow to plot the histograms next to each other.
835
836
837\anchor HP11
838### The SCATter plot option (legacy draw option)
839
840\attention
841Use of option `SCAT` has been deprecated. It was the default drawing option for 2D and
8423D histograms. The new default option is `COL` (heat-map).
843
844
845For each cell (i,j) a number of points proportional to the cell content is
846drawn. A maximum of `kNMAX` points per cell is drawn. If the maximum is above
847`kNMAX` contents are normalized to `kNMAX` (`kNMAX=2000`).
848If option is of the form `scat=ff`, (eg `scat=1.8`,
849`scat=1e-3`), then `ff` is used as a scale factor to compute the
850number of dots. `scat=1` is the default.
851
852By default the scatter plot is painted with a "dot marker" which not scalable
853(see the `TAttMarker` documentation). To change the marker size, a scalable marker
854type should be used. For instance a circle (marker style 20).
855
856Begin_Macro(source)
857{
858 auto c1 = new TCanvas("c1","c1",600,400);
859 auto hscat = new TH2F("hscat","Option SCATter example (default for 2D histograms) ",40,-4,4,40,-20,20);
860 float px, py;
861 for (Int_t i = 0; i < 25000; i++) {
862 gRandom->Rannor(px,py);
863 hscat->Fill(px,5*py);
864 hscat->Fill(3+0.5*px,2*py-10.);
865 }
866 hscat->Draw("scat=0.5"); // This a legacy draw option. Please consider using TScatter
867}
868End_Macro
869
870
871\anchor HP12
872### The ARRow option
873
874
875Shows gradient between adjacent cells. For each cell (i,j) an arrow is drawn
876The orientation of the arrow follows the cell gradient.
877
878Begin_Macro(source)
879{
880 auto c1 = new TCanvas("c1","c1",600,400);
881 auto harr = new TH2F("harr","Option ARRow example",20,-4,4,20,-20,20);
882 harr->SetLineColor(kRed);
883 float px, py;
884 for (Int_t i = 0; i < 25000; i++) {
885 gRandom->Rannor(px,py);
886 harr->Fill(px,5*py);
887 harr->Fill(3+0.5*px,2*py-10.,0.1);
888 }
889 harr->Draw("ARR");
890}
891End_Macro
892
893\since **ROOT version 6.17/01**
894
895The option `ARR` can be combined with the option `COL` or `COLZ`.
896
897Begin_Macro(source)
898{
899 auto c1 = new TCanvas("c1","c1",600,400);
900 auto harr = new TH2F("harr","Option ARR + COLZ example",20,-4,4,20,-20,20);
901 harr->SetStats(0);
902 float px, py;
903 for (Int_t i = 0; i < 25000; i++) {
904 gRandom->Rannor(px,py);
905 harr->Fill(px,5*py);
906 harr->Fill(3+0.5*px,2*py-10.,0.1);
907 }
908 harr->Draw("ARR COLZ");
909}
910End_Macro
911
912
913\anchor HP13
914### The BOX option
915
916
917For each cell (i,j) a box is drawn. The size (surface) of the box is
918proportional to the absolute value of the cell content.
919The cells with a negative content are drawn with a `X` on top of the box.
920
921Begin_Macro(source)
922{
923 auto c1 = new TCanvas("c1","c1",600,400);
924 auto hbox = new TH2F("hbox","Option BOX example",3,0,3,3,0,3);
925 hbox->SetFillColor(42);
926 hbox->Fill(0.5, 0.5, 1.);
927 hbox->Fill(0.5, 1.5, 4.);
928 hbox->Fill(0.5, 2.5, 3.);
929 hbox->Fill(1.5, 0.5, 2.);
930 hbox->Fill(1.5, 1.5, 12.);
931 hbox->Fill(1.5, 2.5, -6.);
932 hbox->Fill(2.5, 0.5, -4.);
933 hbox->Fill(2.5, 1.5, 6.);
934 hbox->Fill(2.5, 2.5, 0.5);
935 hbox->Draw("BOX");
936}
937End_Macro
938
939With option `BOX1` a button is drawn for each cell with surface
940proportional to content's absolute value. A sunken button is drawn for
941negative values a raised one for positive.
942
943Begin_Macro(source)
944{
945 auto c1 = new TCanvas("c1","c1",600,400);
946 auto hbox1 = new TH2F("hbox1","Option BOX1 example",3,0,3,3,0,3);
947 hbox1->SetFillColor(42);
948 hbox1->Fill(0.5, 0.5, 1.);
949 hbox1->Fill(0.5, 1.5, 4.);
950 hbox1->Fill(0.5, 2.5, 3.);
951 hbox1->Fill(1.5, 0.5, 2.);
952 hbox1->Fill(1.5, 1.5, 12.);
953 hbox1->Fill(1.5, 2.5, -6.);
954 hbox1->Fill(2.5, 0.5, -4.);
955 hbox1->Fill(2.5, 1.5, 6.);
956 hbox1->Fill(2.5, 2.5, 0.5);
957 hbox1->Draw("BOX1");
958}
959End_Macro
960
961When the option `SAME` (or "SAMES") is used with the option `BOX`,
962the boxes' sizes are computed taking the previous plots into account. The range
963along the Z axis is imposed by the first plot (the one without option
964`SAME`); therefore the order in which the plots are done is relevant.
965
966Begin_Macro(source)
967{
968 auto c1 = new TCanvas("c1","c1",600,400);
969 auto hb1 = new TH2F("hb1","Example of BOX plots with option SAME ",40,-3,3,40,-3,3);
970 auto hb2 = new TH2F("hb2","hb2",40,-3,3,40,-3,3);
971 auto hb3 = new TH2F("hb3","hb3",40,-3,3,40,-3,3);
972 auto hb4 = new TH2F("hb4","hb4",40,-3,3,40,-3,3);
973 for (Int_t i=0;i<1000;i++) {
974 double x,y;
975 gRandom->Rannor(x,y);
976 if (x>0 && y>0) hb1->Fill(x,y,4);
977 if (x<0 && y<0) hb2->Fill(x,y,3);
978 if (x>0 && y<0) hb3->Fill(x,y,2);
979 if (x<0 && y>0) hb4->Fill(x,y,1);
980 }
981 hb1->SetFillColor(1);
982 hb2->SetFillColor(2);
983 hb3->SetFillColor(3);
984 hb4->SetFillColor(4);
985 hb1->Draw("box");
986 hb2->Draw("box same");
987 hb3->Draw("box same");
988 hb4->Draw("box same");
989}
990End_Macro
991
992\since **ROOT version 6.17/01:**
993
994Sometimes the change of the range of the Z axis is unwanted, in which case, one
995can use `SAME0` (or `SAMES0`) option to opt out of this change.
996
997Begin_Macro(source)
998{
999 auto h2 = new TH2F("h2"," ",10,0,10,10,20,30);
1000 auto hf = (TH2F*)h2->Clone("hf");
1001 h2->SetBit(TH1::kNoStats);
1002 hf->SetBit(TH1::kNoStats);
1003 h2->Fill(5,22);
1004 h2->Fill(5,23);
1005 h2->Fill(6,22);
1006 h2->Fill(6,23);
1007 hf->Fill(6,23);
1008 hf->Fill(6,23);
1009 hf->Fill(6,23);
1010 hf->Fill(6,23);
1011 hf->Fill(5,23);
1012
1013 auto hf_copy1 = hf->Clone("hf_copy1");
1014 TLatex lt;
1015
1016 auto cx = new TCanvas(); cx->Divide(2,1);
1017
1018 cx->cd(1);
1019 h2->Draw("box");
1020 hf->Draw("text colz same");
1021 lt.DrawLatexNDC(0.3,0.5,"SAME");
1022
1023 cx->cd(2);
1024 h2->Draw("box");
1025 hf_copy1->Draw("text colz same0");
1026 lt.DrawLatexNDC(0.3,0.5,"SAME0");
1027}
1028End_Macro
1029
1030
1031\anchor HP14
1032### The COLor option (default for 2D histograms)
1033
1034The magnitude of individual cell (i,j) is represented as a color picked in the current color palette.
1035This data visualization technique is often called a heat map (or heat-map).
1036
1037The color table used is defined in the current style.
1038
1039If the histogram's minimum and maximum are the same (flat histogram), the
1040mapping on colors is not possible, therefore nothing is painted. To paint a
1041flat histogram it is enough to set the histogram minimum
1042(`TH1::SetMinimum()`) different from the bins' content.
1043
1044The default number of color levels used to paint the cells is 20.
1045It can be changed with `TH1::SetContour()` or
1046`TStyle::SetNumberContours()`. The higher this number is, the smoother
1047is the color change between cells.
1048
1049The color palette in TStyle can be modified via `gStyle->SetPalette()`.
1050
1051All the non-empty bins are painted. Empty bins are not painted unless
1052some bins have a negative content because in that case the null bins
1053might be not empty.
1054
1055`TProfile2D` histograms are handled differently because, for this type of 2D
1056histograms, it is possible to know if an empty bin has been filled or not. So even
1057if all the bins' contents are positive some empty bins might be painted. And vice versa,
1058if some bins have a negative content some empty bins might be not painted.
1059
1060Combined with the option `COL`, the option `Z` allows to
1061display the color palette defined by `gStyle->SetPalette()`.
1062
1063In the following example, the histogram has only positive bins; the empty
1064bins (containing 0) are not drawn.
1065
1066Begin_Macro(source)
1067{
1068 auto c1 = new TCanvas("c1","c1",600,400);
1069 auto hcol1 = new TH2F("hcol1","Option COLor example ",40,-4,4,40,-20,20);
1070 float px, py;
1071 for (Int_t i = 0; i < 25000; i++) {
1072 gRandom->Rannor(px,py);
1073 hcol1->Fill(px,5*py);
1074 }
1075 hcol1->Draw("COLZ");
1076}
1077End_Macro
1078
1079In the first plot of following example, the histogram has some negative bins;
1080the empty bins (containing 0) are drawn. In some cases one wants to not draw
1081empty bins (containing 0) of histograms having a negative minimum. The option
1082`1`, used to produce the second plot in the following picture, allows to do that.
1083
1084Begin_Macro(source)
1085{
1086 auto c1 = new TCanvas("c1","c1",600,600);
1087 c1->Divide(1,2);
1088 auto hcol23 = new TH2F("hcol23","Option COLZ example ",40,-4,4,40,-20,20);
1089 auto hcol24 = new TH2F("hcol24","Option COLZ1 example ",40,-4,4,40,-20,20);
1090 float px, py;
1091 for (Int_t i = 0; i < 25000; i++) {
1092 gRandom->Rannor(px,py);
1093 hcol23->Fill(px,5*py);
1094 hcol24->Fill(px,5*py);
1095 }
1096 hcol23->Fill(0.,0.,-200.);
1097 hcol24->Fill(0.,0.,-200.);
1098 c1->cd(1); hcol23->Draw("COLZ");
1099 c1->cd(2); hcol24->Draw("COLZ1");
1100}
1101End_Macro
1102
1103When the maximum of the histogram is set to a smaller value than the real maximum,
1104 the bins having a content between the new maximum and the real maximum are
1105painted with the color corresponding to the new maximum.
1106
1107When the minimum of the histogram is set to a greater value than the real minimum,
1108 the bins having a value between the real minimum and the new minimum are not drawn
1109 unless the option `0` is set.
1110
1111The following example illustrates the option `0` combined with the option `COL`.
1112
1113Begin_Macro(source)
1114{
1115 auto c1 = new TCanvas("c1","c1",600,600);
1116 c1->Divide(1,2);
1117 auto hcol21 = new TH2F("hcol21","Option COLZ",40,-4,4,40,-20,20);
1118 auto hcol22 = new TH2F("hcol22","Option COLZ0",40,-4,4,40,-20,20);
1119 float px, py;
1120 for (Int_t i = 0; i < 25000; i++) {
1121 gRandom->Rannor(px,py);
1122 hcol21->Fill(px,5*py);
1123 hcol22->Fill(px,5*py);
1124 }
1125 hcol21->SetBit(TH1::kNoStats);
1126 hcol22->SetBit(TH1::kNoStats);
1127 c1->cd(1); hcol21->Draw("COLZ");
1128 c1->cd(2); hcol22->Draw("COLZ0");
1129 hcol22->SetMaximum(100);
1130 hcol22->SetMinimum(40);
1131}
1132End_Macro
1133
1134\since **ROOT version 6.09/01:**
1135
1136When the option SAME (or "SAMES") is used with the option COL, the boxes' color
1137are computed taking the previous plots into account. The range along the Z axis
1138is imposed by the first plot (the one without option SAME); therefore the order
1139in which the plots are done is relevant. Same as [in the `BOX` option](\ref HP13), one can use
1140`SAME0` (or `SAMES0`) to opt out of this imposition.
1141
1142Begin_Macro(source)
1143{
1144 auto c = new TCanvas("c","Example of col plots with option SAME",200,10,700,500);
1145 auto h1 = new TH2F("h1","h1",40,-3,3,40,-3,3);
1146 auto h2 = new TH2F("h2","h2",40,-3,3,40,-3,3);
1147 auto h3 = new TH2F("h3","h3",40,-3,3,40,-3,3);
1148 auto h4 = new TH2F("h4","h4",40,-3,3,40,-3,3);
1149 h1->SetBit(TH1::kNoStats);
1150 for (Int_t i=0;i<5000;i++) {
1151 double x,y;
1152 gRandom->Rannor(x,y);
1153 if(x>0 && y>0) h1->Fill(x,y,4);
1154 if(x<0 && y<0) h2->Fill(x,y,3);
1155 if(x>0 && y<0) h3->Fill(x,y,2);
1156 if(x<0 && y>0) h4->Fill(x,y,1);
1157 }
1158 h1->Draw("colz");
1159 h2->Draw("col same");
1160 h3->Draw("col same");
1161 h4->Draw("col same");
1162}
1163End_Macro
1164
1165The option `COL` can be combined with the option `POL`:
1166
1167Begin_Macro(source)
1168{
1169 auto c1 = new TCanvas("c1","c1",600,400);
1170 auto hcol1 = new TH2F("hcol1","Option COLor combined with POL",40,-4,4,40,-4,4);
1171 float px, py;
1172 for (Int_t i = 0; i < 25000; i++) {
1173 gRandom->Rannor(px,py);
1174 hcol1->Fill(px,py);
1175 }
1176 hcol1->Draw("COLZPOL");
1177}
1178End_Macro
1179
1180\since **ROOT version 6.07/03:**
1181
1182A second rendering technique is also available with the COL2 and COLZ2 options.
1183
1184These options provide potential performance improvements compared to the standard
1185COL option. The performance comparison of the COL2 to the COL option depends on
1186the histogram and the size of the rendering region in the current pad. In general,
1187a small (approx. less than 100 bins per axis), sparsely populated TH2 will render
1188faster with the COL option.
1189
1190However, for larger histograms (approx. more than 100 bins per axis)
1191that are not sparse, the COL2 option will provide up to 20 times performance improvements.
1192For example, a 1000x1000 bin TH2 that is not sparse will render an order of magnitude
1193faster with the COL2 option.
1194
1195The COL2 option will also scale its performance based on the size of the
1196pixmap the histogram image is being rendered into. It also is much better optimized for
1197sessions where the user is forwarding X11 windows through an `ssh` connection.
1198
1199For the most part, the COL2 and COLZ2 options are a drop in replacement to the COL
1200and COLZ options. There is one major difference and that concerns the treatment of
1201bins with zero content. The COL2 and COLZ2 options color these bins the color of zero.
1202
1203COL2 option renders the histogram as a bitmap. Therefore it cannot be saved in vector
1204graphics file format like PostScript or PDF (an empty image will be generated). It can
1205be saved only in bitmap files like PNG format for instance.
1206
1207
1208\anchor HP140
1209### The CANDLE and VIOLIN options
1210
1211The mechanism behind Candle plots and Violin plots is very similar. Because of this they are
1212implemented in the same class TCandle. The keywords CANDLE or VIOLIN will initiate the drawing of
1213the corresponding plots. Followed by the keyword the user can select a plot direction (X or V for
1214vertical projections, or Y or H for horizontal projections) and/or predefined definitions
1215(1-6 for candles, 1-2 for violins). The order doesn't matter. Default is X and 1.
1216
1217Instead of using the predefined representations, the candle and violin parameters can be
1218changed individually. In that case the option have the following form:
1219
1220 CANDLEX(<option-string>)
1221 CANDLEY(<option-string>)
1222 VIOLINX(<option-string>)
1223 VIOLINY(<option-string>).
1224
1225All zeros at the beginning of `option-string` can be omitted.
1226
1227`option-string` consists eight values, defined as follow:
1228
1229 "CANDLEX(zhpawMmb)"
1230
1231Where:
1232
1233 - `b = 0`; no box drawn
1234 - `b = 1`; the box is drawn. As the candle-plot is also called a box-plot it
1235 makes sense in the very most cases to always draw the box
1236 - `b = 2`; draw a filled box with border
1237
1238 - `m = 0`; no median drawn
1239 - `m = 1`; median is drawn as a line
1240 - `m = 2`; median is drawn with errors (notches)
1241 - `m = 3`; median is drawn as a circle
1242
1243 - `M = 0`; no mean drawn
1244 - `M = 1`; mean is drawn as a dashed line
1245 - `M = 3`; mean is drawn as a circle
1246
1247 - `w = 0`; no whisker drawn
1248 - `w = 1`; whisker is drawn to end of distribution.
1249 - `w = 2`; whisker is drawn to max 1.5*iqr
1250
1251 - `a = 0`; no anchor drawn
1252 - `a = 1`; the anchors are drawn
1253
1254 - `p = 0`; no points drawn
1255 - `p = 1`; only outliers are drawn
1256 - `p = 2`; all datapoints are drawn
1257 - `p = 3`: all datapoints are drawn scattered
1258
1259 - `h = 0`; no histogram is drawn
1260 - `h = 1`; histogram at the left or bottom side is drawn
1261 - `h = 2`; histogram at the right or top side is drawn
1262 - `h = 3`; histogram at left and right or top and bottom (violin-style) is drawn
1263
1264 - `z = 0`; no zero indicator line is drawn
1265 - `z = 1`; zero indicator line is drawn.
1266
1267As one can see all individual options for both candle and violin plots can be accessed by this
1268mechanism. In deed the keywords CANDLE(<option-string>) and VIOLIN(<option-string>) have the same
1269meaning. So you can parametrise an option-string for a candle plot and use the keywords VIOLIN and
1270vice versa, if you wish.
1271
1272Using a logarithmic x- or y-axis is possible for candle and violin charts.
1273
1274\since **ROOT version 6.11/01**
1275
1276a logarithmic z-axis is possible, too but will only affect violin charts of course.
1277
1278\anchor HP140a
1279#### The CANDLE option
1280
1281<a href="http://en.wikipedia.org/wiki/Box_plot">A Candle plot</a> (also known as
1282a "box plot" or "whisker plot") was invented in 1977 by John Tukey. It is a convenient
1283way to describe graphically a data distribution (D) with only five numbers:
1284
1285 1. The minimum value of the distribution D (bottom or left whisker).
1286 2. The lower quartile (Q1): 25% of the data points in D are less than Q1 (bottom of the box).
1287 3. The median (M): 50% of the data points in D are less than M.
1288 4. The upper quartile (Q3): 75% of the data points in D are less than Q3 (top of the box).
1289 5. The maximum value of the distribution D (top or right whisker).
1290
1291In this implementation a TH2 is considered as a collection of TH1 along
1292X (option `CANDLE` or `CANDLEX`) or Y (option `CANDLEY`).
1293Each TH1 is represented as one candle.
1294
1295Begin_Macro(source)
1296../../../tutorials/hist/candleplotwhiskers.C
1297End_Macro
1298
1299The candle reduces the information coming from a whole distribution into few values.
1300Independently from the number of entries or the significance of the underlying distribution
1301a candle will always look like a candle. So candle plots should be used carefully in
1302particular with unknown distributions. The definition of a candle is based on
1303__unbinned data__. Here, candles are created from binned data. Because of this, the
1304deviation is connected to the bin width used. The calculation of the quantiles
1305normally done on unbinned data also. Because data are binned, this will
1306only work the best possible way within the resolution of one bin
1307
1308Because of all these facts one should take care that:
1309
1310 - there are enough points per candle
1311 - the bin width is small enough (more bins will increase the maximum
1312 available resolution of the quantiles although there will be some
1313 bins with no entries)
1314 - never make a candle-plot if the underlying distribution is double-distributed
1315 - only create candles of distributions that are more-or-less gaussian (the
1316 MPV should be not too far away from the mean).
1317
1318#### What a candle is made of
1319
1320\since **ROOT version 6.07/05**
1321
1322##### The box
1323The box displays the position of the inter-quantile-range of the underlying
1324distribution. The box contains 25% of the distribution below the median
1325and 25% of the distribution above the median. If the underlying distribution is large
1326enough and gaussian shaped the end-points of the box represent \f$ 0.6745\times\sigma \f$
1327(Where \f$ \sigma \f$ is the standard deviation of the gaussian). The width and
1328the position of the box can be modified by SetBarWidth() and SetBarOffset().
1329The +-25% quantiles are calculated by the GetQuantiles() methods.
1330
1331\since **ROOT version 6.11/01**
1332
1333Using the static function TCandle::SetBoxRange(double) the box definition will be
1334overwritten. E.g. using a box range of 0.68 will redefine the area of the lower box edge
1335to the upper box edge in order to cover 68% of the distribution illustrated by that candle.
1336The static function will affect all candle-charts in the running program.
1337Default is 0.5.
1338
1339Using the static function TCandle::SetScaledCandle(bool) the width of the box (and the
1340whole candle) can be influenced. Deactivated, the width is constant (to be set by
1341SetBarWidth() ). Activated, the width of the boxes will be scaled to each other based on the
1342amount of data in the corresponding candle, the maximum width can be influenced by
1343SetBarWidth(). The static function will affect all candle-charts in the running program.
1344Default is false. Scaling between multiple candle-charts (using "same" or THStack) is not
1345supported, yet
1346
1347##### The Median
1348For a sorted list of numbers, the median is the value in the middle of the list.
1349E.g. if a sorted list is made of five numbers "1,2,3,6,7" 3 will be the median
1350because it is in the middle of the list. If the number of entries is even the
1351average of the two values in the middle will be used. As histograms are binned
1352data, the situation is a bit more complex. The following example shows this:
1353
1354~~~ {.cpp}
1355void quantiles() {
1356 auto h = new TH1I("h","h",10,0,10);
1357 //h->Fill(3);
1358 //h->Fill(3);
1359 h->Fill(4);
1360 h->Draw();
1361 double p = 0.;
1362 double q = 0.;
1363 h->GetQuantiles(1,&q,&p);
1364
1365 cout << "Median is: " << q << std::endl;
1366}
1367~~~
1368
1369Here the bin-width is 1.0. If the two Fill(3) are commented out, as there are currently,
1370the example will return a calculated median of 4.5, because that's the bin center
1371of the bin in which the value 4.0 has been dropped. If the two Fill(3) are not
1372commented out, it will return 3.75, because the algorithm tries to evenly distribute
1373the individual values of a bin with bin content > 0. It means the sorted list
1374would be "3.25, 3.75, 4.5".
1375
1376The consequence is a median of 3.75. This shows how important it is to use a
1377small enough bin-width when using candle-plots on binned data.
1378If the distribution is large enough and gaussian shaped the median will be exactly
1379equal to the mean.
1380The median can be shown as a line or as a circle or not shown at all.
1381
1382In order to show the significance of the median notched candle plots apply a "notch" or
1383narrowing of the box around the median. The significance is defined by
1384\f$ 1.57\times\frac{iqr}{N} \f$ and will be represented as the size of the notch
1385(where iqr is the size of the box and N is the number of entries of the whole
1386distribution). Candle plots like these are usually called "notched candle plots".
1387
1388In case the significance of the median is greater that the size of the box, the
1389box will have an unnatural shape. Usually it means the chart has not enough data,
1390or that representing this uncertainty is not useful
1391
1392##### The Mean
1393The mean can be drawn as a dashed line or as a circle or not drawn at all.
1394The mean is the arithmetic average of the values in the distribution.
1395It is calculated using GetMean(). Because histograms are
1396binned data, the mean value can differ from a calculation on the raw-data.
1397If the distribution is large enough and gaussian shaped the mean will be
1398exactly the median.
1399
1400##### The Whiskers
1401The whiskers represent the part of the distribution not covered by the box.
1402The upper 25% and the lower 25% of the distribution are located within the whiskers.
1403Two representations are available.
1404
1405 - A simple one (using w=1) defining the lower whisker from the lowest data value
1406 to the bottom of the box, and the upper whisker from the top of the box to the
1407 highest data value. In this representation the whisker-lines are dashed.
1408 - A more complex one having a further restriction. The whiskers are still connected
1409 to the box but their length cannot exceed \f$ 1.5\times iqr \f$. So it might
1410 be that the outermost part of the underlying distribution will not be covered
1411 by the whiskers. Usually these missing parts will be represented by the outliers
1412 (see points). Of course the upper and the lower whisker may differ in length.
1413 In this representation the whiskers are drawn as solid lines.
1414
1415\since **ROOT version 6.11/01**
1416
1417Using the static function TCandle::SetWhiskerRange(double) the whisker definition w=1
1418will be overwritten. E.g. using a whisker-range of 0.95 and w=1 will redefine the area of
1419the lower whisker to the upper whisker in order to cover 95% of the distribution inside
1420that candle. The static function will affect all candle-charts in the running program.
1421Default is 1.
1422
1423If the distribution is large enough and gaussian shaped, the maximum length of
1424the whisker will be located at \f$ \pm 2.698 \sigma \f$ (when using the
14251.5*iqr-definition (w=2), where \f$ \sigma \f$ is the standard deviation
1426(see picture above). In that case 99.3% of the total distribution will be covered
1427by the box and the whiskers, whereas 0.7% are represented by the outliers.
1428
1429##### The Anchors
1430The anchors have no special meaning in terms of statistical calculation. They mark
1431the end of the whiskers and they have the width of the box. Both representation
1432with and without anchors are common.
1433
1434##### The Points
1435Depending on the configuration the points can have different meanings:
1436 - If p=1 the points represent the outliers. If they are shown, it means
1437 some parts of the underlying distribution are not covered by the whiskers.
1438 This can only occur when the whiskers are set to option w=2. Here the whiskers
1439 can have a maximum length of \f$ 1.5 \times iqr \f$. So any points outside the
1440 whiskers will be drawn as outliers. The outliers will be represented by crosses.
1441 - If p=2 all points in the distribution will be painted as crosses. This is
1442 useful for small datasets only (up to 10 or 20 points per candle).
1443 The outliers are shown along the candle. Because the underlying distribution
1444 is binned, is frequently occurs that a bin contains more than one value.
1445 Because of this the points will be randomly scattered within their bin along
1446 the candle axis. If the bin content for a bin is exactly 1 (usually
1447 this happens for the outliers) if will be drawn in the middle of the bin along
1448 the candle axis. As the maximum number of points per candle is limited by kNMax/2
1449 on very large datasets scaling will be performed automatically. In that case one
1450 would loose all outliers because they have usually a bin content of 1 (and a
1451 bin content between 0 and 1 after the scaling). Because of this all bin contents
1452 between 0 and 1 - after the scaling - will be forced to be 1.
1453 - As the drawing of all values on large datasets can lead to big amounts of crosses,
1454 one can show all values as a scatter plot instead by choosing p=3. The points will be
1455 drawn as dots and will be scattered within the width of the candle. The color
1456 of the points will be the color of the candle-chart.
1457
1458##### Other Options
1459Is is possible to combine all options of candle and violin plots with each other. E.g. a box-plot
1460with a histogram.
1461
1462#### How to use the candle-plots drawing option
1463
1464There are six predefined candle-plot representations:
1465
1466 - "CANDLEX1": Standard candle (whiskers cover the whole distribution)
1467 - "CANDLEX2": Standard candle with better whisker definition + outliers.
1468 It is a good compromise
1469 - "CANDLEX3": Like candle2 but with a mean as a circle.
1470 It is easier to distinguish mean and median
1471 - "CANDLEX4": Like candle3 but showing the uncertainty of the median as well
1472 (notched candle plots).
1473 For bigger datasets per candle
1474 - "CANDLEX5": Like candle2 but showing all data points.
1475 For very small datasets
1476 - "CANDLEX6": Like candle2 but showing all datapoints scattered.
1477 For huge datasets
1478
1479
1480The following picture shows how the six predefined representations look.
1481
1482Begin_Macro
1483{
1484 auto c1 = new TCanvas("c1","c1",700,800);
1485 c1->Divide(2,3);
1486 gStyle->SetOptStat(kFALSE);
1487
1488 auto hcandle = new TH2F("hcandle"," ",10,-4,4,40,-20,20);
1489 float px, py;
1490 for (Int_t i = 0; i < 15000; i++) {
1491 gRandom->Rannor(px,py);
1492 hcandle->Fill(px,5*py);
1493 }
1494 hcandle->SetMarkerSize(0.5);
1495
1496 TH2F *h2;
1497 for (Int_t i=1; i<7; i++) {
1498 c1->cd(i);
1499 h2 = (TH2F*)hcandle->DrawClone(Form("CANDLE%d",i));
1500 h2->SetTitle(Form("CANDLE%d",i));
1501 }
1502}
1503End_Macro
1504
1505
1506#### Example 1
1507Box and improved whisker, no mean, no median, no anchor no outliers
1508
1509 h1->Draw("CANDLEX(2001)");
1510
1511#### Example 2
1512A Candle-definition like "CANDLEX2" (New standard candle with better whisker definition + outliers)
1513
1514 h1->Draw("CANDLEX(112111)");
1515
1516#### Example 3
1517The following example shows how several candle plots can be super-imposed using
1518the option SAME. Note that the bar-width and bar-offset are active on candle plots.
1519Also the color, the line width, the size of the points and so on can be changed by the
1520standard attribute setting methods such as SetLineColor() SetLineWidth().
1521
1522Begin_Macro(source)
1523../../../tutorials/hist/candleplot.C
1524End_Macro
1525
1526\anchor HP140b
1527#### The VIOLIN option
1528
1529<a href="http://en.wikipedia.org/wiki/Violin_plot">A violin plot</a> is a candle plot
1530that also encodes the pdf information at each point.
1531
1532
1533Quartiles and mean are also represented at each point, with a marker
1534and two lines.
1535
1536In this implementation a TH2 is considered as a collection of TH1 along
1537X (option `VIOLIN` or `VIOLINX`) or Y (option `VIOLINY`).
1538
1539#### What a violin is made of
1540
1541\since **ROOT version 6.09/02**
1542
1543##### The histogram
1544The histogram is typically drawn to both directions with respect to the middle-line of the
1545corresponding bin. This can be achieved by using h=3. It is possible to draw a histogram only to
1546one side (h=1, or h=2).
1547The maximum number of bins in the histogram is limited to 500, if the number of bins in the used
1548histogram is higher it will be rebinned automatically. The maximum height of the histogram can
1549be modified by using SetBarWidth() and the position can be changed with SetBarOffset().
1550A solid fill style is recommended.
1551
1552\since **ROOT version 6.11/01**
1553
1554Using the static function TCandle::SetScaledViolin(bool) the height of the histogram or the
1555violin can be influenced. Activated, the height of the bins of the individual violins will be
1556scaled with respect to each other, the maximum height can be influenced by SetBarWidth().
1557Deactivated, the height of the bin with the maximum content of each individual violin is
1558set to a constant value using SetBarWidth(). The static function will affect all violin-charts
1559in the running program. Default is true. Scaling between multiple violin-charts
1560(using "same" or THStack) is not supported, yet.
1561
1562##### The zero indicator line
1563Typical for violin charts is a line in the background over the whole histogram indicating
1564the bins with zero entries. The zero indicator line can be activated with z=1. The line color
1565will always be the same as the fill-color of the histogram.
1566
1567##### The Mean
1568The Mean is illustrated with the same mechanism as used for candle plots. Usually a circle is used.
1569
1570##### Whiskers
1571The whiskers are illustrated by the same mechanism as used for candle plots. There is only one
1572difference. When using the simple whisker definition (w=1) and the zero indicator line (z=1), then
1573the whiskers will be forced to be solid (usually hashed)
1574
1575##### Points
1576The points are illustrated by the same mechanism as used for candle plots. E.g. VIOLIN2 uses
1577better whisker definition (w=2) and outliers (p=1).
1578
1579##### Other options
1580It is possible to combine all options of candle or violin plots with each other. E.g. a violin plot
1581including a box-plot.
1582
1583#### How to use the violin-plots drawing option
1584
1585There are two predefined violin-plot representations:
1586 - "VIOLINX1": Standard violin (histogram, mean, whisker over full distribution,
1587 zero indicator line)
1588 - "VIOLINX2": Line VIOLINX1 both with better whisker definition + outliers.
1589
1590A solid fill style is recommended for this plot (as opposed to a hollow or
1591hashed style).
1592
1593Begin_Macro(source)
1594{
1595 auto c1 = new TCanvas("c1","c1",600,400);
1596 Int_t nx(6), ny(40);
1597 double xmin(0.0), xmax(+6.0), ymin(0.0), ymax(+4.0);
1598 auto hviolin = new TH2F("hviolin", "Option VIOLIN example", nx, xmin, xmax, ny, ymin, ymax);
1599 TF1 f1("f1", "gaus", +0,0 +4.0);
1600 double x,y;
1601 for (Int_t iBin=1; iBin<hviolin->GetNbinsX(); ++iBin) {
1602 double xc = hviolin->GetXaxis()->GetBinCenter(iBin);
1603 f1.SetParameters(1, 2.0+TMath::Sin(1.0+xc), 0.2+0.1*(xc-xmin)/xmax);
1604 for(Int_t i=0; i<10000; ++i){
1605 x = xc;
1606 y = f1.GetRandom();
1607 hviolin->Fill(x, y);
1608 }
1609 }
1610 hviolin->SetFillColor(kGray);
1611 hviolin->SetMarkerStyle(20);
1612 hviolin->SetMarkerSize(0.5);
1613 hviolin->Draw("VIOLIN");
1614 c1->Update();
1615}
1616End_Macro
1617
1618The next example illustrates a time development of a certain value:
1619
1620Begin_Macro(source)
1621../../../tutorials/hist/candledecay.C
1622End_Macro
1623
1624
1625\anchor HP15
1626### The TEXT and TEXTnn Option
1627
1628
1629For each bin the content is printed. The text attributes are:
1630
1631- text font = current TStyle font (`gStyle->SetTextFont()`).
1632- text size = 0.02*padheight*markersize (if `h` is the histogram drawn
1633 with the option `TEXT` the marker size can be changed with
1634 `h->SetMarkerSize(markersize)`).
1635- text color = marker color.
1636
1637By default the format `g` is used. This format can be redefined
1638by calling `gStyle->SetPaintTextFormat()`.
1639
1640It is also possible to use `TEXTnn` in order to draw the text with
1641the angle `nn` (`0 < nn <= 90`).
1642
1643For 2D histograms the text is plotted in the center of each non empty cells.
1644It is possible to plot empty cells by calling `gStyle->SetHistMinimumZero()`
1645or providing MIN0 draw option. For 1D histogram the text is plotted at a y
1646position equal to the bin content.
1647
1648For 2D histograms when the option "E" (errors) is combined with the option
1649text ("TEXTE"), the error for each bin is also printed.
1650
1651Begin_Macro(source)
1652{
1653 auto c01 = new TCanvas("c01","c01",700,400);
1654 c01->Divide(2,1);
1655 auto htext1 = new TH1F("htext1","Option TEXT on 1D histograms ",10,-4,4);
1656 auto htext2 = new TH2F("htext2","Option TEXT on 2D histograms ",10,-4,4,10,-20,20);
1657 float px, py;
1658 for (Int_t i = 0; i < 25000; i++) {
1659 gRandom->Rannor(px,py);
1660 htext1->Fill(px,0.1);
1661 htext2->Fill(px,5*py,0.1);
1662 }
1663 gStyle->SetPaintTextFormat("4.1f m");
1664 htext2->SetMarkerSize(1.8);
1665 c01->cd(1);
1666 htext2->Draw("TEXT45");
1667 c01->cd(2);
1668 htext1->Draw();
1669 htext1->Draw("HIST TEXT0 SAME");
1670}
1671End_Macro
1672
1673\since **ROOT version 6.07/07:**
1674
1675In case several histograms are drawn on top ot each other (using option `SAME`),
1676the text can be shifted using `SetBarOffset()`. It specifies an offset for the
1677text position in each cell, in percentage of the bin width.
1678
1679Begin_Macro(source)
1680{
1681 auto c03 = new TCanvas("c03","c03",700,400);
1682 gStyle->SetOptStat(0);
1683 auto htext3 = new TH2F("htext3","Several 2D histograms drawn with option TEXT",10,-4,4,10,-20,20);
1684 auto htext4 = new TH2F("htext4","htext4",10,-4,4,10,-20,20);
1685 auto htext5 = new TH2F("htext5","htext5",10,-4,4,10,-20,20);
1686 float px, py;
1687 for (Int_t i = 0; i < 25000; i++) {
1688 gRandom->Rannor(px,py);
1689 htext3->Fill(4*px,20*py,0.1);
1690 htext4->Fill(4*px,20*py,0.5);
1691 htext5->Fill(4*px,20*py,1.0);
1692 }
1693 htext4->SetMarkerSize(1.8);
1694 htext5->SetMarkerSize(1.8);
1695 htext5->SetMarkerColor(kRed);
1696 htext4->SetBarOffset(0.2);
1697 htext4->Draw("COL TEXT SAME");
1698 htext5->SetBarOffset(-0.2);
1699 htext5->Draw("TEXT SAME");
1700}
1701End_Macro
1702
1703In the case of profile histograms it is possible to print the number
1704of entries instead of the bin content. It is enough to combine the
1705option "E" (for entries) with the option "TEXT".
1706
1707Begin_Macro(source)
1708{
1709 auto c02 = new TCanvas("c02","c02",700,400);
1710 c02->Divide(2,1);
1711 gStyle->SetPaintTextFormat("g");
1712
1713 auto profile = new TProfile("profile","profile",10,0,10);
1714 profile->SetMarkerSize(2.2);
1715 profile->Fill(0.5,1);
1716 profile->Fill(1.5,2);
1717 profile->Fill(2.5,3);
1718 profile->Fill(3.5,4);
1719 profile->Fill(4.5,5);
1720 profile->Fill(5.5,5);
1721 profile->Fill(6.5,4);
1722 profile->Fill(7.5,3);
1723 profile->Fill(8.5,2);
1724 profile->Fill(9.5,1);
1725 c02->cd(1); profile->Draw("HIST TEXT0");
1726 c02->cd(2); profile->Draw("HIST TEXT0E");
1727}
1728End_Macro
1729
1730\anchor HP16
1731### The CONTour options
1732
1733
1734The following contour options are supported:
1735
1736| Option | Description |
1737|----------|-----------------------------------------------------------------------------|
1738| "CONT" | Draw a contour plot (same as CONT0). |
1739| "CONT0" | Draw a contour plot using surface colors to distinguish contours. |
1740| "CONT1" | Draw a contour plot using the line colors to distinguish contours. |
1741| "CONT2" | Draw a contour plot using the line styles (1 to 5) to distinguish contours. |
1742| "CONT3" | Draw a contour plot using the same line style for all contours. |
1743| "CONT4" | Draw a contour plot using surface colors (`SURF` option at theta = 0). |
1744
1745
1746The following example shows a 2D histogram plotted with the option
1747`CONTZ`. The option `CONT` draws a contour plot using surface
1748colors to distinguish contours. Combined with the option `CONT` (or
1749`CONT0`), the option `Z` allows to display the color palette
1750defined by `gStyle->SetPalette()`.
1751
1752Begin_Macro(source)
1753{
1754 auto c1 = new TCanvas("c1","c1",600,400);
1755 auto hcontz = new TH2F("hcontz","Option CONTZ example ",40,-4,4,40,-20,20);
1756 float px, py;
1757 for (Int_t i = 0; i < 25000; i++) {
1758 gRandom->Rannor(px,py);
1759 hcontz->Fill(px-1,5*py);
1760 hcontz->Fill(2+0.5*px,2*py-10.,0.1);
1761 }
1762 hcontz->Draw("CONTZ");
1763}
1764End_Macro
1765
1766The following example shows a 2D histogram plotted with the option
1767`CONT1Z`. The option `CONT1` draws a contour plot using the
1768line colors to distinguish contours. Combined with the option `CONT1`,
1769the option `Z` allows to display the color palette defined by
1770`gStyle->SetPalette()`.
1771
1772Begin_Macro(source)
1773{
1774 auto c1 = new TCanvas("c1","c1",600,400);
1775 auto hcont1 = new TH2F("hcont1","Option CONT1Z example ",40,-4,4,40,-20,20);
1776 float px, py;
1777 for (Int_t i = 0; i < 25000; i++) {
1778 gRandom->Rannor(px,py);
1779 hcont1->Fill(px-1,5*py);
1780 hcont1->Fill(2+0.5*px,2*py-10.,0.1);
1781 }
1782 hcont1->Draw("CONT1Z");
1783}
1784End_Macro
1785
1786The following example shows a 2D histogram plotted with the option
1787`CONT2`. The option `CONT2` draws a contour plot using the
1788line styles (1 to 5) to distinguish contours.
1789
1790Begin_Macro(source)
1791{
1792 auto c1 = new TCanvas("c1","c1",600,400);
1793 auto hcont2 = new TH2F("hcont2","Option CONT2 example ",40,-4,4,40,-20,20);
1794 float px, py;
1795 for (Int_t i = 0; i < 25000; i++) {
1796 gRandom->Rannor(px,py);
1797 hcont2->Fill(px-1,5*py);
1798 hcont2->Fill(2+0.5*px,2*py-10.,0.1);
1799 }
1800 hcont2->Draw("CONT2");
1801}
1802End_Macro
1803
1804The following example shows a 2D histogram plotted with the option
1805`CONT3`. The option `CONT3` draws contour plot using the same line style for
1806all contours.
1807
1808Begin_Macro(source)
1809{
1810 auto c1 = new TCanvas("c1","c1",600,400);
1811 auto hcont3 = new TH2F("hcont3","Option CONT3 example ",40,-4,4,40,-20,20);
1812 float px, py;
1813 for (Int_t i = 0; i < 25000; i++) {
1814 gRandom->Rannor(px,py);
1815 hcont3->Fill(px-1,5*py);
1816 hcont3->Fill(2+0.5*px,2*py-10.,0.1);
1817 }
1818 hcont3->SetLineStyle(kDotted);
1819 hcont3->Draw("CONT3");
1820}
1821End_Macro
1822
1823The following example shows a 2D histogram plotted with the option
1824`CONT4`. The option `CONT4` draws a contour plot using surface
1825colors to distinguish contours (`SURF` option at theta = 0). Combined
1826with the option `CONT` (or `CONT0`), the option `Z`
1827allows to display the color palette defined by `gStyle->SetPalette()`.
1828
1829Begin_Macro(source)
1830{
1831 auto c1 = new TCanvas("c1","c1",600,400);
1832 auto hcont4 = new TH2F("hcont4","Option CONT4Z example ",40,-4,4,40,-20,20);
1833 float px, py;
1834 for (Int_t i = 0; i < 25000; i++) {
1835 gRandom->Rannor(px,py);
1836 hcont4->Fill(px-1,5*py);
1837 hcont4->Fill(2+0.5*px,2*py-10.,0.1);
1838 }
1839 hcont4->Draw("CONT4Z");
1840}
1841End_Macro
1842
1843The default number of contour levels is 20 equidistant levels and can be changed
1844with `TH1::SetContour()` or `TStyle::SetNumberContours()`.
1845
1846\anchor HP16a
1847#### The LIST option
1848
1849When option `LIST` is specified together with option
1850`CONT`, the points used to draw the contours are saved in
1851`TGraph` objects:
1852
1853 h->Draw("CONT LIST");
1854 gPad->Update();
1855
1856The contour are saved in `TGraph` objects once the pad is painted.
1857Therefore to use this functionality in a macro, `gPad->Update()`
1858should be performed after the histogram drawing. Once the list is
1859built, the contours are accessible in the following way:
1860
1861 TObjArray *contours = (TObjArray*)gROOT->GetListOfSpecials()->FindObject("contours");
1862 Int_t ncontours = contours->GetSize();
1863 TList *list = (TList*)contours->At(i);
1864
1865Where `i` is a contour number, and list contains a list of
1866`TGraph` objects.
1867For one given contour, more than one disjoint polyline may be generated.
1868The number of TGraphs per contour is given by:
1869
1870 list->GetSize();
1871
1872To access the first graph in the list one should do:
1873
1874 TGraph *gr1 = (TGraph*)list->First();
1875
1876
1877The following example (ContourList.C) shows how to use this functionality.
1878
1879Begin_Macro(source)
1880../../../tutorials/hist/ContourList.C
1881End_Macro
1882
1883\anchor HP16b
1884#### The AITOFF, MERCATOR, SINUSOIDAL and PARABOLIC options
1885
1886The following options select the `CONT4` option and are useful for
1887sky maps or exposure maps (earth.C).
1888
1889| Option | Description |
1890|--------------|---------------------------------------------------------------|
1891| "AITOFF" | Draw a contour via an AITOFF projection.|
1892| "MERCATOR" | Draw a contour via an Mercator projection.|
1893| "SINUSOIDAL" | Draw a contour via an Sinusoidal projection.|
1894| "PARABOLIC" | Draw a contour via an Parabolic projection.|
1895
1896Begin_Macro(source)
1897../../../tutorials/graphics/earth.C
1898End_Macro
1899
1900
1901\anchor HP17
1902### The LEGO options
1903
1904
1905In a lego plot the cell contents are drawn as 3-d boxes. The height of each box
1906is proportional to the cell content. The lego aspect is control with the
1907following options:
1908
1909| Option | Description |
1910|----------|-------------------------------------------------------------------|
1911| "LEGO" | Draw a lego plot using the hidden lines removal technique.|
1912| "LEGO1" | Draw a lego plot using the hidden surface removal technique.|
1913| "LEGO2" | Draw a lego plot using colors to show the cell contents.|
1914| "LEGO3" | Draw a lego plot with hidden surface removal, like LEGO1 but the border lines of each lego-bar are not drawn.|
1915| "LEGO4" | Draw a lego plot with hidden surface removal, like LEGO1 but without the shadow effect on each lego-bar.|
1916| "0" | When used with any LEGO option, the empty bins are not drawn.|
1917
1918
1919See the limitations with [the option "SAME"](\ref HP060a).
1920
1921Line attributes can be used in lego plots to change the edges' style.
1922
1923The following example shows a 2D histogram plotted with the option
1924`LEGO`. The option `LEGO` draws a lego plot using the hidden
1925lines removal technique.
1926
1927Begin_Macro(source)
1928{
1929 auto c2 = new TCanvas("c2","c2",600,400);
1930 auto hlego = new TH2F("hlego","Option LEGO example ",40,-4,4,40,-20,20);
1931 float px, py;
1932 for (Int_t i = 0; i < 25000; i++) {
1933 gRandom->Rannor(px,py);
1934 hlego->Fill(px-1,5*py);
1935 hlego->Fill(2+0.5*px,2*py-10.,0.1);
1936 }
1937 hlego->Draw("LEGO");
1938}
1939End_Macro
1940
1941The following example shows a 2D histogram plotted with the option
1942`LEGO1`. The option `LEGO1` draws a lego plot using the
1943hidden surface removal technique. Combined with any `LEGOn` option, the
1944option `0` allows to not drawn the empty bins.
1945
1946Begin_Macro(source)
1947{
1948 auto c2 = new TCanvas("c2","c2",600,400);
1949 auto hlego1 = new TH2F("hlego1","Option LEGO1 example (with option 0) ",40,-4,4,40,-20,20);
1950 float px, py;
1951 for (Int_t i = 0; i < 25000; i++) {
1952 gRandom->Rannor(px,py);
1953 hlego1->Fill(px-1,5*py);
1954 hlego1->Fill(2+0.5*px,2*py-10.,0.1);
1955 }
1956 hlego1->SetFillColor(kYellow);
1957 hlego1->Draw("LEGO1 0");
1958}
1959End_Macro
1960
1961The following example shows a 2D histogram plotted with the option
1962`LEGO3`. Like the option `LEGO1`, the option `LEGO3`
1963draws a lego plot using the hidden surface removal technique but doesn't draw
1964the border lines of each individual lego-bar. This is very useful for histograms
1965having many bins. With such histograms the option `LEGO1` gives a black
1966image because of the border lines. This option also works with stacked legos.
1967
1968Begin_Macro(source)
1969{
1970 auto c2 = new TCanvas("c2","c2",600,400);
1971 auto hlego3 = new TH2F("hlego3","Option LEGO3 example",40,-4,4,40,-20,20);
1972 float px, py;
1973 for (Int_t i = 0; i < 25000; i++) {
1974 gRandom->Rannor(px,py);
1975 hlego3->Fill(px-1,5*py);
1976 hlego3->Fill(2+0.5*px,2*py-10.,0.1);
1977 }
1978 hlego3->SetFillColor(kRed);
1979 hlego3->Draw("LEGO3");
1980}
1981End_Macro
1982
1983The following example shows a 2D histogram plotted with the option
1984`LEGO2`. The option `LEGO2` draws a lego plot using colors to
1985show the cell contents. Combined with the option `LEGO2`, the option
1986`Z` allows to display the color palette defined by
1987`gStyle->SetPalette()`.
1988
1989Begin_Macro(source)
1990{
1991 auto c2 = new TCanvas("c2","c2",600,400);
1992 auto hlego2 = new TH2F("hlego2","Option LEGO2Z example ",40,-4,4,40,-20,20);
1993 float px, py;
1994 for (Int_t i = 0; i < 25000; i++) {
1995 gRandom->Rannor(px,py);
1996 hlego2->Fill(px-1,5*py);
1997 hlego2->Fill(2+0.5*px,2*py-10.,0.1);
1998 }
1999 hlego2->Draw("LEGO2Z");
2000}
2001End_Macro
2002
2003
2004
2005\anchor HP18
2006### The "SURFace" options
2007
2008
2009In a surface plot, cell contents are represented as a mesh.
2010The height of the mesh is proportional to the cell content.
2011
2012| Option | Description |
2013|----------|-------------------------------------------------------------------|
2014| "SURF" | Draw a surface plot using the hidden line removal technique.|
2015| "SURF1" | Draw a surface plot using the hidden surface removal technique.|
2016| "SURF2" | Draw a surface plot using colors to show the cell contents.|
2017| "SURF3" | Same as `SURF` with an additional filled contour plot on top.|
2018| "SURF4" | Draw a surface using the Gouraud shading technique.|
2019| "SURF5" | Used with one of the options CYL, PSR and CYL this option allows to draw a filled contour plot.|
2020| "SURF6" | This option should not be used directly. It is used internally when the CONT is used with option the option SAME on a 3D plot.|
2021| "SURF7" | Same as `SURF2` with an additional line contour plot on top.|
2022
2023
2024
2025See the limitations with [the option "SAME"](\ref HP060a).
2026
2027The following example shows a 2D histogram plotted with the option
2028`SURF`. The option `SURF` draws a lego plot using the hidden
2029lines removal technique.
2030
2031Begin_Macro(source)
2032{
2033 auto c2 = new TCanvas("c2","c2",600,400);
2034 auto hsurf = new TH2F("hsurf","Option SURF example ",30,-4,4,30,-20,20);
2035 float px, py;
2036 for (Int_t i = 0; i < 25000; i++) {
2037 gRandom->Rannor(px,py);
2038 hsurf->Fill(px-1,5*py);
2039 hsurf->Fill(2+0.5*px,2*py-10.,0.1);
2040 }
2041 hsurf->Draw("SURF");
2042}
2043End_Macro
2044
2045The following example shows a 2D histogram plotted with the option
2046`SURF1`. The option `SURF1` draws a surface plot using the
2047hidden surface removal technique. Combined with the option `SURF1`,
2048the option `Z` allows to display the color palette defined by
2049`gStyle->SetPalette()`.
2050
2051Begin_Macro(source)
2052{
2053 auto c2 = new TCanvas("c2","c2",600,400);
2054 auto hsurf1 = new TH2F("hsurf1","Option SURF1 example ",30,-4,4,30,-20,20);
2055 float px, py;
2056 for (Int_t i = 0; i < 25000; i++) {
2057 gRandom->Rannor(px,py);
2058 hsurf1->Fill(px-1,5*py);
2059 hsurf1->Fill(2+0.5*px,2*py-10.,0.1);
2060 }
2061 hsurf1->Draw("SURF1");
2062}
2063End_Macro
2064
2065The following example shows a 2D histogram plotted with the option
2066`SURF2`. The option `SURF2` draws a surface plot using colors
2067to show the cell contents. Combined with the option `SURF2`, the option
2068`Z` allows to display the color palette defined by
2069`gStyle->SetPalette()`.
2070
2071Begin_Macro(source)
2072{
2073 auto c2 = new TCanvas("c2","c2",600,400);
2074 auto hsurf2 = new TH2F("hsurf2","Option SURF2 example ",30,-4,4,30,-20,20);
2075 float px, py;
2076 for (Int_t i = 0; i < 25000; i++) {
2077 gRandom->Rannor(px,py);
2078 hsurf2->Fill(px-1,5*py);
2079 hsurf2->Fill(2+0.5*px,2*py-10.,0.1);
2080 }
2081 hsurf2->Draw("SURF2");
2082}
2083End_Macro
2084
2085The following example shows a 2D histogram plotted with the option
2086`SURF3`. The option `SURF3` draws a surface plot using the
2087hidden line removal technique with, in addition, a filled contour view drawn on the
2088top. Combined with the option `SURF3`, the option `Z` allows
2089to display the color palette defined by `gStyle->SetPalette()`.
2090
2091Begin_Macro(source)
2092{
2093 auto c2 = new TCanvas("c2","c2",600,400);
2094 auto hsurf3 = new TH2F("hsurf3","Option SURF3 example ",30,-4,4,30,-20,20);
2095 float px, py;
2096 for (Int_t i = 0; i < 25000; i++) {
2097 gRandom->Rannor(px,py);
2098 hsurf3->Fill(px-1,5*py);
2099 hsurf3->Fill(2+0.5*px,2*py-10.,0.1);
2100 }
2101 hsurf3->Draw("SURF3");
2102}
2103End_Macro
2104
2105The following example shows a 2D histogram plotted with the option
2106`SURF4`. The option `SURF4` draws a surface using the Gouraud
2107shading technique.
2108
2109Begin_Macro(source)
2110{
2111 auto c2 = new TCanvas("c2","c2",600,400);
2112 auto hsurf4 = new TH2F("hsurf4","Option SURF4 example ",30,-4,4,30,-20,20);
2113 float px, py;
2114 for (Int_t i = 0; i < 25000; i++) {
2115 gRandom->Rannor(px,py);
2116 hsurf4->Fill(px-1,5*py);
2117 hsurf4->Fill(2+0.5*px,2*py-10.,0.1);
2118 }
2119 hsurf4->SetFillColor(kOrange);
2120 hsurf4->Draw("SURF4");
2121}
2122End_Macro
2123
2124The following example shows a 2D histogram plotted with the option
2125`SURF5 CYL`. Combined with the option `SURF5`, the option
2126`Z` allows to display the color palette defined by `gStyle->SetPalette()`.
2127
2128Begin_Macro(source)
2129{
2130 auto c2 = new TCanvas("c2","c2",600,400);
2131 auto hsurf5 = new TH2F("hsurf4","Option SURF5 example ",30,-4,4,30,-20,20);
2132 float px, py;
2133 for (Int_t i = 0; i < 25000; i++) {
2134 gRandom->Rannor(px,py);
2135 hsurf5->Fill(px-1,5*py);
2136 hsurf5->Fill(2+0.5*px,2*py-10.,0.1);
2137 }
2138 hsurf5->Draw("SURF5 CYL");
2139}
2140End_Macro
2141
2142The following example shows a 2D histogram plotted with the option
2143`SURF7`. The option `SURF7` draws a surface plot using the
2144hidden surfaces removal technique with, in addition, a line contour view drawn on the
2145top. Combined with the option `SURF7`, the option `Z` allows
2146to display the color palette defined by `gStyle->SetPalette()`.
2147
2148Begin_Macro(source)
2149{
2150 auto c2 = new TCanvas("c2","c2",600,400);
2151 auto hsurf7 = new TH2F("hsurf3","Option SURF7 example ",30,-4,4,30,-20,20);
2152 float px, py;
2153 for (Int_t i = 0; i < 25000; i++) {
2154 gRandom->Rannor(px,py);
2155 hsurf7->Fill(px-1,5*py);
2156 hsurf7->Fill(2+0.5*px,2*py-10.,0.1);
2157 }
2158 hsurf7->Draw("SURF7");
2159}
2160End_Macro
2161
2162As shown in the following example, when a contour plot is painted on top of a
2163surface plot using the option `SAME`, the contours appear in 3D on the
2164surface.
2165
2166Begin_Macro(source)
2167{
2168 auto c20=new TCanvas("c20","c20",600,400);
2169 int NBins = 50;
2170 double d = 2;
2171 auto hsc = new TH2F("hsc", "Surface and contour with option SAME ", NBins, -d, d, NBins, -d, d);
2172 for (int bx = 1; bx <= NBins; ++bx) {
2173 for (int by = 1; by <= NBins; ++by) {
2174 double x = hsc->GetXaxis()->GetBinCenter(bx);
2175 double y = hsc->GetYaxis()->GetBinCenter(by);
2176 hsc->SetBinContent(bx, by, exp(-x*x)*exp(-y*y));
2177 }
2178 }
2179 hsc->Draw("surf2");
2180 hsc->Draw("CONT1 SAME");
2181}
2182End_Macro
2183
2184
2185\anchor HP19
2186### Cylindrical, Polar, Spherical and PseudoRapidity/Phi options
2187
2188
2189Legos and surfaces plots are represented by default in Cartesian coordinates.
2190Combined with any `LEGOn` or `SURFn` options the following
2191options allow to draw a lego or a surface in other coordinates systems.
2192
2193| Option | Description |
2194|----------|-------------------------------------------------------------------|
2195| "CYL" | Use Cylindrical coordinates. The X coordinate is mapped on the angle and the Y coordinate on the cylinder length.|
2196| "POL" | Use Polar coordinates. The X coordinate is mapped on the angle and the Y coordinate on the radius.|
2197| "SPH" | Use Spherical coordinates. The X coordinate is mapped on the latitude and the Y coordinate on the longitude.|
2198| "PSR" | Use PseudoRapidity/Phi coordinates. The X coordinate is mapped on Phi.|
2199
2200
2201
2202<b>WARNING:</b> Axis are not drawn with these options.
2203
2204The following example shows the same histogram as a lego plot is the four
2205different coordinates systems.
2206
2207Begin_Macro(source)
2208{
2209 auto c3 = new TCanvas("c3","c3",600,400);
2210 c3->Divide(2,2);
2211 auto hlcc = new TH2F("hlcc","Cylindrical coordinates",20,-4,4,20,-20,20);
2212 float px, py;
2213 for (Int_t i = 0; i < 25000; i++) {
2214 gRandom->Rannor(px,py);
2215 hlcc->Fill(px-1,5*py);
2216 hlcc->Fill(2+0.5*px,2*py-10.,0.1);
2217 }
2218 hlcc->SetFillColor(kYellow);
2219 c3->cd(1); hlcc->Draw("LEGO1 CYL");
2220 c3->cd(2); auto hlpc = (TH2F*) hlcc->DrawClone("LEGO1 POL");
2221 hlpc->SetTitle("Polar coordinates");
2222 c3->cd(3); auto hlsc = (TH2F*) hlcc->DrawClone("LEGO1 SPH");
2223 hlsc->SetTitle("Spherical coordinates");
2224 c3->cd(4); auto hlprpc = (TH2F*) hlcc->DrawClone("LEGO1 PSR");
2225 hlprpc->SetTitle("PseudoRapidity/Phi coordinates");
2226}
2227End_Macro
2228
2229The following example shows the same histogram as a surface plot is the four different coordinates systems.
2230
2231Begin_Macro(source)
2232{
2233 auto c4 = new TCanvas("c4","c4",600,400);
2234 c4->Divide(2,2);
2235 auto hscc = new TH2F("hscc","Cylindrical coordinates",20,-4,4,20,-20,20);
2236 float px, py;
2237 for (Int_t i = 0; i < 25000; i++) {
2238 gRandom->Rannor(px,py);
2239 hscc->Fill(px-1,5*py);
2240 hscc->Fill(2+0.5*px,2*py-10.,0.1);
2241 }
2242 c4->cd(1); hscc->Draw("SURF1 CYL");
2243 c4->cd(2); auto hspc = (TH2F*) hscc->DrawClone("SURF1 POL");
2244 hspc->SetTitle("Polar coordinates");
2245 c4->cd(3); auto hssc = (TH2F*) hscc->DrawClone("SURF1 SPH");
2246 hssc->SetTitle("Spherical coordinates");
2247 c4->cd(4); auto hsprpc = (TH2F*) hscc->DrawClone("SURF1 PSR");
2248 hsprpc->SetTitle("PseudoRapidity/Phi coordinates");
2249}
2250End_Macro
2251
2252
2253\anchor HP20
2254### Base line for bar-charts and lego plots
2255
2256
2257By default the base line used to draw the boxes for bar-charts and lego plots is
2258the histogram minimum. It is possible to force this base line to be 0, using MIN0 draw
2259option or with the command:
2260
2261 gStyle->SetHistMinimumZero();
2262
2263Begin_Macro(source)
2264{
2265 auto c5 = new TCanvas("c5","c5",700,400);
2266 c5->Divide(2,1);
2267 auto hz1 = new TH1F("hz1","Bar-chart drawn from 0",20,-3,3);
2268 auto hz2 = new TH2F("hz2","Lego plot drawn from 0",20,-3,3,20,-3,3);
2269 Int_t i;
2270 double x,y;
2271 hz1->SetFillColor(kBlue);
2272 hz2->SetFillColor(kBlue);
2273 for (i=0;i<10000;i++) {
2274 x = gRandom->Gaus(0,1);
2275 y = gRandom->Gaus(0,1);
2276 if (x>0) {
2277 hz1->Fill(x,1);
2278 hz2->Fill(x,y,1);
2279 } else {
2280 hz1->Fill(x,-1);
2281 hz2->Fill(x,y,-2);
2282 }
2283 }
2284 c5->cd(1); hz1->Draw("bar2 min0");
2285 c5->cd(2); hz2->Draw("lego1 min0");
2286}
2287End_Macro
2288
2289This option also works for horizontal plots. The example given in the section
2290["The bar chart option"](\ref HP100) appears as follow:
2291
2292Begin_Macro(source)
2293{
2294 int i;
2295 const Int_t nx = 8;
2296 string os_X[nx] = {"8","32","128","512","2048","8192","32768","131072"};
2297 float d_35_0[nx] = {0.75, -3.30, -0.92, 0.10, 0.08, -1.69, -1.29, -2.37};
2298 float d_35_1[nx] = {1.01, -3.02, -0.65, 0.37, 0.34, -1.42, -1.02, -2.10};
2299
2300 auto cbh = new TCanvas("cbh","cbh",400,600);
2301 cbh->SetGrid();
2302
2303 auto h1bh = new TH1F("h1bh","Option HBAR centered on 0",nx,0,nx);
2304 h1bh->SetFillColor(4);
2305 h1bh->SetBarWidth(0.4);
2306 h1bh->SetBarOffset(0.1);
2307 h1bh->SetStats(0);
2308 h1bh->SetMinimum(-5);
2309 h1bh->SetMaximum(5);
2310
2311 for (i=1; i<=nx; i++) {
2312 h1bh->Fill(os_X[i-1].c_str(), d_35_0[i-1]);
2313 h1bh->GetXaxis()->SetBinLabel(i,os_X[i-1].c_str());
2314 }
2315
2316 h1bh->Draw("hbar min0");
2317
2318 auto h2bh = new TH1F("h2bh","h2bh",nx,0,nx);
2319 h2bh->SetFillColor(38);
2320 h2bh->SetBarWidth(0.4);
2321 h2bh->SetBarOffset(0.5);
2322 h2bh->SetStats(0);
2323 for (i=1;i<=nx;i++) h2bh->Fill(os_X[i-1].c_str(), d_35_1[i-1]);
2324
2325 h2bh->Draw("hbar min0 same");
2326}
2327End_Macro
2328
2329
2330\anchor HP20a
2331### TH2Poly Drawing
2332
2333
2334The following options are supported:
2335
2336| Option | Description |
2337|----------|-------------------------------------------------------------------|
2338| "SCAT" | Draw a scatter plot (legacy draw option).|
2339| "COL" | Draw a color plot. All the bins are painted even the empty bins (default).|
2340| "COLZ" | Same as "COL". In addition the color palette is also drawn.|
2341| "0" | When used with any COL options, the empty bins are not drawn.|
2342| "TEXT" | Draw bin contents as text (format set via `gStyle->SetPaintTextFormat`).|
2343| "TEXTN" | Draw bin names as text.|
2344| "TEXTnn" | Draw bin contents as text at angle nn (0 < nn <= 90).|
2345| "L" | Draw the bins boundaries as lines. The lines attributes are the TGraphs ones.|
2346| "P" | Draw the bins boundaries as markers. The markers attributes are the TGraphs ones.|
2347| "F" | Draw the bins boundaries as filled polygons. The filled polygons attributes are the TGraphs ones.|
2348
2349
2350
2351`TH2Poly` can be drawn as a color plot (option COL). `TH2Poly` bins can have any
2352shapes. The bins are defined as graphs. The following macro is a very simple
2353example showing how to book a TH2Poly and draw it.
2354
2355Begin_Macro(source)
2356{
2357 auto ch2p1 = new TCanvas("ch2p1","ch2p1",600,400);
2358 auto h2p = new TH2Poly();
2359 h2p->SetName("h2poly_name");
2360 h2p->SetTitle("h2poly_title");
2361 double px1[] = {0, 5, 6};
2362 double py1[] = {0, 0, 5};
2363 double px2[] = {0, -1, -1, 0};
2364 double py2[] = {0, 0, -1, 3};
2365 double px3[] = {4, 3, 0, 1, 2.4};
2366 double py3[] = {4, 3.7, 1, 3.7, 2.5};
2367 h2p->AddBin(3, px1, py1);
2368 h2p->AddBin(4, px2, py2);
2369 h2p->AddBin(5, px3, py3);
2370 h2p->Fill(0.1, 0.01, 3);
2371 h2p->Fill(-0.5, -0.5, 7);
2372 h2p->Fill(-0.7, -0.5, 1);
2373 h2p->Fill(1, 3, 1.5);
2374 double fx[] = {0.1, -0.5, -0.7, 1};
2375 double fy[] = {0.01, -0.5, -0.5, 3};
2376 double fw[] = {3, 1, 1, 1.5};
2377 h2p->FillN(4, fx, fy, fw);
2378 h2p->Draw("col");
2379}
2380End_Macro
2381
2382Rectangular bins are a frequent case. The special version of
2383the `AddBin` method allows to define them more easily like
2384shown in the following example (th2polyBoxes.C).
2385
2386Begin_Macro(source)
2387../../../tutorials/hist/th2polyBoxes.C
2388End_Macro
2389
2390One `TH2Poly` bin can be a list of polygons. Such bins are defined
2391by calling `AddBin` with a `TMultiGraph`. The following example
2392shows a such case:
2393
2394Begin_Macro(source)
2395{
2396 auto ch2p2 = new TCanvas("ch2p2","ch2p2",600,400);
2397
2398 Int_t i, bin;
2399 const Int_t nx = 48;
2400 const char *states [nx] = {
2401 "alabama", "arizona", "arkansas", "california",
2402 "colorado", "connecticut", "delaware", "florida",
2403 "georgia", "idaho", "illinois", "indiana",
2404 "iowa", "kansas", "kentucky", "louisiana",
2405 "maine", "maryland", "massachusetts", "michigan",
2406 "minnesota", "mississippi", "missouri", "montana",
2407 "nebraska", "nevada", "new_hampshire", "new_jersey",
2408 "new_mexico", "new_york", "north_carolina", "north_dakota",
2409 "ohio", "oklahoma", "oregon", "pennsylvania",
2410 "rhode_island", "south_carolina", "south_dakota", "tennessee",
2411 "texas", "utah", "vermont", "virginia",
2412 "washington", "west_virginia", "wisconsin", "wyoming"
2413 };
2414 Double_t pop[nx] = {
2415 4708708, 6595778, 2889450, 36961664, 5024748, 3518288, 885122, 18537969,
2416 9829211, 1545801, 12910409, 6423113, 3007856, 2818747, 4314113, 4492076,
2417 1318301, 5699478, 6593587, 9969727, 5266214, 2951996, 5987580, 974989,
2418 1796619, 2643085, 1324575, 8707739, 2009671, 19541453, 9380884, 646844,
2419 11542645, 3687050, 3825657, 12604767, 1053209, 4561242, 812383, 6296254,
2420 24782302, 2784572, 621760, 7882590, 6664195, 1819777, 5654774, 544270
2421 };
2422
2423 Double_t lon1 = -130;
2424 Double_t lon2 = -65;
2425 Double_t lat1 = 24;
2426 Double_t lat2 = 50;
2427 auto p = new TH2Poly("USA","USA Population",lon1,lon2,lat1,lat2);
2428
2429 TFile::SetCacheFileDir(".");
2430 auto f = TFile::Open("http://root.cern/files/usa.root", "CACHEREAD");
2431
2432 TMultiGraph *mg;
2433 TKey *key;
2434 TIter nextkey(gDirectory->GetListOfKeys());
2435 while ((key = (TKey*)nextkey())) {
2436 TObject *obj = key->ReadObj();
2437 if (obj->InheritsFrom("TMultiGraph")) {
2438 mg = (TMultiGraph*)obj;
2439 bin = p->AddBin(mg);
2440 }
2441 }
2442
2443 for (i=0; i<nx; i++) p->Fill(states[i], pop[i]);
2444
2445 gStyle->SetOptStat(11);
2446 p->Draw("COLZ L");
2447}
2448End_Macro
2449
2450`TH2Poly` histograms can also be plotted using the GL interface using
2451the option "GLLEGO".
2452
2453\since **ROOT version 6.09/01**
2454
2455In some cases it can be useful to not draw the empty bins. the option "0"
2456combined with the option "COL" et COLZ allows to do that.
2457
2458Begin_Macro(source)
2459{
2460 auto chc = new TCanvas("chc","chc",600,400);
2461
2462 auto hc = new TH2Poly();
2463 hc->Honeycomb(0,0,.1,25,25);
2464 hc->SetName("hc");
2465 hc->SetTitle("Option COLZ 0");
2466 TRandom ran;
2467 for (int i = 0; i<300; i++) hc->Fill(ran.Gaus(2.,1), ran.Gaus(2.,1));
2468 hc->Draw("colz 0");
2469}
2470End_Macro
2471
2472\anchor HP21
2473### The SPEC option
2474
2475
2476This option allows to use the `TSpectrum2Painter` tools. See the full
2477documentation in `TSpectrum2Painter::PaintSpectrum`.
2478
2479
2480\anchor HP22
2481### Option "Z" : Adding the color palette on the right side of the pad
2482
2483
2484When this option is specified, a color palette with an axis indicating the value
2485of the corresponding color is drawn on the right side of the picture. In case,
2486not enough space is left, one can increase the size of the right margin by
2487calling `TPad::SetRightMargin()`. The attributes used to display the
2488palette axis values are taken from the Z axis of the object. For example, to
2489set the labels size on the palette axis do:
2490
2491 hist->GetZaxis()->SetLabelSize().
2492
2493<b>WARNING:</b> The palette axis is always drawn vertically.
2494
2495
2496\anchor HP23
2497### Setting the color palette
2498
2499
2500To change the color palette `TStyle::SetPalette` should be used, eg:
2501
2502 gStyle->SetPalette(ncolors,colors);
2503
2504For example the option `COL` draws a 2D histogram with cells
2505represented by a box filled with a color index which is a function
2506of the cell content.
2507If the cell content is N, the color index used will be the color number
2508in `colors[N]`, etc. If the maximum cell content is greater than
2509`ncolors`, all cell contents are scaled to `ncolors`.
2510
2511If ` ncolors <= 0`, a default palette (see below) of 50 colors is
2512defined. This palette is recommended for pads, labels ...
2513
2514`if ncolors == 1 && colors == 0`, then a Pretty Palette with a
2515Spectrum Violet->Red is created with 50 colors. That's the default rain bow
2516palette.
2517
2518Other pre-defined palettes with 255 colors are available when `colors == 0`.
2519The following value of `ncolors` give access to:
2520
2521
2522 if ncolors = 51 and colors=0, a Deep Sea palette is used.
2523 if ncolors = 52 and colors=0, a Grey Scale palette is used.
2524 if ncolors = 53 and colors=0, a Dark Body Radiator palette is used.
2525 if ncolors = 54 and colors=0, a two-color hue palette palette is used.(dark blue through neutral gray to bright yellow)
2526 if ncolors = 55 and colors=0, a Rain Bow palette is used.
2527 if ncolors = 56 and colors=0, an inverted Dark Body Radiator palette is used.
2528
2529
2530If `ncolors > 0 && colors == 0`, the default palette is used with a maximum of ncolors.
2531
2532The default palette defines:
2533
2534- index 0 to 9 : shades of grey
2535- index 10 to 19 : shades of brown
2536- index 20 to 29 : shades of blue
2537- index 30 to 39 : shades of red
2538- index 40 to 49 : basic colors
2539
2540The color numbers specified in the palette can be viewed by selecting
2541the item `colors` in the `VIEW` menu of the canvas tool bar.
2542The red, green, and blue components of a color can be changed thanks to
2543`TColor::SetRGB()`.
2544
2545\since **ROOT version 6.19/01**
2546
2547As default labels and ticks are drawn by `TGAxis` at equidistant (lin or log)
2548points as controlled by SetNdivisions.
2549If option "CJUST" is given labels and ticks are justified at the
2550color boundaries defined by the contour levels.
2551For more details see `TPaletteAxis`
2552
2553\anchor HP24
2554### Drawing a sub-range of a 2D histogram; the [cutg] option
2555
2556
2557Using a `TCutG` object, it is possible to draw a sub-range of a 2D
2558histogram. One must create a graphical cut (mouse or C++) and specify the name
2559of the cut between `[]` in the `Draw()` option.
2560For example (fit2a.C), with a `TCutG` named `cutg`, one can call:
2561
2562 myhist->Draw("surf1 [cutg]");
2563
2564To invert the cut, it is enough to put a `-` in front of its name:
2565
2566 myhist->Draw("surf1 [-cutg]");
2567
2568It is possible to apply several cuts (`,` means logical AND):
2569
2570 myhist->Draw("surf1 [cutg1,cutg2]");
2571
2572Begin_Macro(source)
2573../../../tutorials/fit/fit2a.C
2574End_Macro
2575
2576\anchor HP25
2577### Drawing options for 3D histograms
2578
2579
2580| Option | Description |
2581|----------|-------------------------------------------------------------------|
2582| "SCAT" | Draw a scatter plot (legacy draw option).|
2583| "ISO" | Draw a Gouraud shaded 3d iso surface through a 3d histogram. It paints one surface at the value computed as follow: `SumOfWeights/(NbinsX*NbinsY*NbinsZ)`|
2584| "BOX" | Draw a for each cell with volume proportional to the content's absolute value. An hidden line removal algorithm is used|
2585| "BOX1" | Same as BOX but an hidden surface removal algorithm is used|
2586| "BOX2" | Same as "COL". The boxes' colors are picked in the current palette according to the bins' contents (default)|
2587| "BOX2Z" | Same as "BOX2". In addition the color palette is also drawn.|
2588| "BOX3" | Same as BOX1, but the border lines of each lego-bar are not drawn.|
2589
2590Note that instead of `BOX` one can also use `LEGO`.
2591
2592By default, 3D histograms are drawn as a colored box plots.
2593
2594The following example shows a 3D histogram plotted as a scatter plot.
2595
2596Begin_Macro(source)
2597{
2598 auto c06 = new TCanvas("c06","c06",600,400);
2599 gStyle->SetOptStat(kFALSE);
2600 auto h3scat = new TH3F("h3scat","Option SCAT",15,-2,2,15,-2,2,15,0,4);
2601 double x, y, z;
2602 for (Int_t i=0;i<10000;i++) {
2603 gRandom->Rannor(x, y);
2604 z = x*x + y*y;
2605 h3scat->Fill(x,y,z);
2606 }
2607 h3scat->Draw("SCAT"); // This a legacy draw option
2608}
2609End_Macro
2610
2611The following example shows a 3D histogram plotted with the option `BOX`.
2612
2613Begin_Macro(source)
2614{
2615 auto c16 = new TCanvas("c16","c16",600,400);
2616 gStyle->SetOptStat(kFALSE);
2617 auto h3box = new TH3F("h3box","Option BOX",15,-2,2,15,-2,2,15,0,4);
2618 double x, y, z;
2619 for (Int_t i=0;i<10000;i++) {
2620 gRandom->Rannor(x, y);
2621 z = x*x + y*y;
2622 h3box->Fill(x,y,z);
2623 }
2624 h3box->Draw("BOX");
2625}
2626End_Macro
2627
2628The following example shows a 3D histogram plotted with the option `BOX1`.
2629
2630Begin_Macro(source)
2631{
2632 auto c36 = new TCanvas("c36","c36",600,400);
2633 gStyle->SetOptStat(kFALSE);
2634 auto h3box = new TH3F("h3box","Option BOX1",10,-2.,2.,10,-2.,2.,10,-0.5,2.);
2635 double x, y, z;
2636 for (Int_t i=0;i<10000;i++) {
2637 gRandom->Rannor(x, y);
2638 z = abs(sin(x)/x + cos(y)*y);
2639 h3box->Fill(x,y,z);
2640 }
2641 h3box->SetFillColor(9);
2642 h3box->Draw("BOX1");
2643}
2644End_Macro
2645
2646The following example shows a 3D histogram plotted with the option `BOX2`.
2647
2648Begin_Macro(source)
2649{
2650 auto c56 = new TCanvas("c56","c56",600,400);
2651 gStyle->SetOptStat(kFALSE);
2652 auto h3box = new TH3F("h3box","Option BOX2 (default)",10,-2.,2.,10,-2.,2.,10,-0.5,2.);
2653 double x, y, z;
2654 for (Int_t i=0;i<10000;i++) {
2655 gRandom->Rannor(x, y);
2656 z = abs(sin(x)/x + cos(y)*y);
2657 h3box->Fill(x,y,z);
2658 }
2659 h3box->Draw("BOX2 Z");
2660}
2661End_Macro
2662
2663The following example shows a 3D histogram plotted with the option `BOX3`.
2664
2665Begin_Macro(source)
2666{
2667 auto c46 = new TCanvas("c46","c46",600,400);
2668 c46->SetFillColor(38);
2669 gStyle->SetOptStat(kFALSE);
2670 auto h3box = new TH3F("h3box","Option BOX3",15,-2,2,15,-2,2,15,0,4);
2671 double x, y, z;
2672 for (Int_t i=0;i<10000;i++) {
2673 gRandom->Rannor(x, y);
2674 z = x*x + y*y;
2675 h3box->Fill(x,y,z);
2676 }
2677 h3box->Draw("BOX3");
2678}
2679End_Macro
2680
2681For all the `BOX` options each bin is drawn as a 3D box with a volume proportional
2682to the absolute value of the bin content. The bins with a negative content are
2683drawn with a X on each face of the box as shown in the following example:
2684
2685Begin_Macro(source)
2686{
2687 auto c = new TCanvas("c","c",600,400);
2688 gStyle->SetOptStat(kFALSE);
2689 auto h3box = new TH3F("h3box","Option BOX1 with negative bins",3, 0., 4., 3, 0.,4., 3, 0., 4.);
2690 h3box->Fill(0., 2., 2., 10.);
2691 h3box->Fill(2., 2., 2., 5.);
2692 h3box->Fill(2., 2., .5, 2.);
2693 h3box->Fill(2., 2., 3., -1.);
2694 h3box->Fill(3., 2., 2., -10.);
2695 h3box->SetFillColor(8);
2696 h3box->Draw("box1");
2697}
2698End_Macro
2699
2700The following example shows a 3D histogram plotted with the option `ISO`.
2701
2702Begin_Macro(source)
2703{
2704 auto c26 = new TCanvas("c26","c26",600,400);
2705 gStyle->SetOptStat(kFALSE);
2706 auto h3iso = new TH3F("h3iso","Option ISO",15,-2,2,15,-2,2,15,0,4);
2707 double x, y, z;
2708 for (Int_t i=0;i<10000;i++) {
2709 gRandom->Rannor(x, y);
2710 z = x*x + y*y;
2711 h3iso->Fill(x,y,z);
2712 }
2713 h3iso->SetFillColor(kCyan);
2714 h3iso->Draw("ISO");
2715}
2716End_Macro
2717
2718
2719\anchor HP26
2720### Drawing option for histograms' stacks
2721
2722
2723Stacks of histograms are managed with the `THStack`. A `THStack`
2724is a collection of `TH1` (or derived) objects. For painting only the
2725`THStack` containing `TH1` only or
2726`THStack` containing `TH2` only will be considered.
2727
2728By default, histograms are shown stacked:
2729
27301. The first histogram is paint.
27312. The sum of the first and second, etc...
2732
2733If the option `NOSTACK` is specified, the histograms are all paint in
2734the same pad as if the option `SAME` had been specified. This allows to
2735compute X and Y scales common to all the histograms, like
2736`TMultiGraph` does for graphs.
2737
2738If the option `PADS` is specified, the current pad/canvas is
2739subdivided into a number of pads equal to the number of histograms and each
2740histogram is paint into a separate pad.
2741
2742The following example shows various types of stacks (hstack.C).
2743
2744Begin_Macro(source)
2745../../../tutorials/hist/hstack.C
2746End_Macro
2747
2748The option `nostackb` allows to draw the histograms next to each
2749other as bar charts:
2750
2751Begin_Macro(source)
2752{
2753 auto cst0 = new TCanvas("cst0","cst0",600,400);
2754 auto hs = new THStack("hs","Stacked 1D histograms: option #font[82]{\"nostackb\"}");
2755
2756 auto h1 = new TH1F("h1","h1",10,-4,4);
2757 h1->FillRandom("gaus",20000);
2758 h1->SetFillColor(kRed);
2759 hs->Add(h1);
2760
2761 auto h2 = new TH1F("h2","h2",10,-4,4);
2762 h2->FillRandom("gaus",15000);
2763 h2->SetFillColor(kBlue);
2764 hs->Add(h2);
2765
2766 auto h3 = new TH1F("h3","h3",10,-4,4);
2767 h3->FillRandom("gaus",10000);
2768 h3->SetFillColor(kGreen);
2769 hs->Add(h3);
2770
2771 hs->Draw("nostackb");
2772 hs->GetXaxis()->SetNdivisions(-10);
2773 cst0->SetGridx();
2774}
2775End_Macro
2776
2777If at least one of the histograms in the stack has errors, the whole stack is
2778visualized by default with error bars. To visualize it without errors the
2779option `HIST` should be used.
2780
2781Begin_Macro(source)
2782{
2783 auto cst1 = new TCanvas("cst1","cst1",700,400);
2784 cst1->Divide(2,1);
2785
2786 auto hst11 = new TH1F("hst11", "", 20, -10, 10);
2787 hst11->Sumw2();
2788 hst11->FillRandom("gaus", 1000);
2789 hst11->SetFillColor(kViolet);
2790 hst11->SetLineColor(kViolet);
2791
2792 auto hst12 = new TH1F("hst12", "", 20, -10, 10);
2793 hst12->FillRandom("gaus", 500);
2794 hst12->SetFillColor(kBlue);
2795 hst12->SetLineColor(kBlue);
2796
2797 THStack st1("st1", "st1");
2798 st1.Add(hst11);
2799 st1.Add(hst12);
2800
2801 cst1->cd(1); st1.Draw();
2802 cst1->cd(2); st1.Draw("hist");
2803}
2804End_Macro
2805
2806\anchor HP27
2807### Drawing of 3D implicit functions
2808
2809
28103D implicit functions (`TF3`) can be drawn as iso-surfaces.
2811The implicit function f(x,y,z) = 0 is drawn in cartesian coordinates.
2812In the following example the options "FB" and "BB" suppress the
2813"Front Box" and "Back Box" around the plot.
2814
2815Begin_Macro(source)
2816{
2817 auto c2 = new TCanvas("c2","c2",600,400);
2818 auto f3 = new TF3("f3","sin(x*x+y*y+z*z-36)",-2,2,-2,2,-2,2);
2819 f3->SetClippingBoxOn(0,0,0);
2820 f3->SetFillColor(30);
2821 f3->SetLineColor(15);
2822 f3->Draw("FBBB");
2823}
2824End_Macro
2825
2826
2827\anchor HP28
2828### Associated functions drawing
2829
2830
2831An associated function is created by `TH1::Fit`. More than on fitted
2832function can be associated with one histogram (see `TH1::Fit`).
2833
2834A `TF1` object `f1` can be added to the list of associated
2835functions of an histogram `h` without calling `TH1::Fit`
2836simply doing:
2837
2838 h->GetListOfFunctions()->Add(f1);
2839
2840or
2841
2842 h->GetListOfFunctions()->Add(f1,someoption);
2843
2844To retrieve a function by name from this list, do:
2845
2846 TF1 *f1 = (TF1*)h->GetListOfFunctions()->FindObject(name);
2847
2848or
2849
2850 TF1 *f1 = h->GetFunction(name);
2851
2852Associated functions are automatically painted when an histogram is drawn.
2853To avoid the painting of the associated functions the option `HIST`
2854should be added to the list of the options used to paint the histogram.
2855
2856
2857\anchor HP29
2858### Drawing using OpenGL
2859
2860
2861The class `TGLHistPainter` allows to paint data set using the OpenGL 3D
2862graphics library. The plotting options start with `GL` keyword.
2863In addition, in order to inform canvases that OpenGL should be used to render
28643D representations, the following option should be set:
2865
2866 gStyle->SetCanvasPreferGL(true);
2867
2868
2869\anchor HP29a
2870#### General information: plot types and supported options
2871
2872The following types of plots are provided:
2873
2874For lego plots the supported options are:
2875
2876| Option | Description |
2877|----------|-------------------------------------------------------------------|
2878| "GLLEGO" | Draw a lego plot. It works also for `TH2Poly`.|
2879| "GLLEGO2"| Bins with color levels.|
2880| "GLLEGO3"| Cylindrical bars.|
2881
2882
2883
2884Lego painter in cartesian supports logarithmic scales for X, Y, Z.
2885In polar only Z axis can be logarithmic, in cylindrical only Y.
2886
2887For surface plots (`TF2` and `TH2`) the supported options are:
2888
2889| Option | Description |
2890|-----------|------------------------------------------------------------------|
2891| "GLSURF" | Draw a surface.|
2892| "GLSURF1" | Surface with color levels|
2893| "GLSURF2" | The same as "GLSURF1" but without polygon outlines.|
2894| "GLSURF3" | Color level projection on top of plot (works only in cartesian coordinate system).|
2895| "GLSURF4" | Same as "GLSURF" but without polygon outlines.|
2896
2897
2898
2899The surface painting in cartesian coordinates supports logarithmic scales along
2900X, Y, Z axis. In polar coordinates only the Z axis can be logarithmic,
2901in cylindrical coordinates only the Y axis.
2902
2903Additional options to SURF and LEGO - Coordinate systems:
2904
2905| Option | Description |
2906|----------|-------------------------------------------------------------------|
2907| " " | Default, cartesian coordinates system.|
2908| "POL" | Polar coordinates system.|
2909| "CYL" | Cylindrical coordinates system.|
2910| "SPH" | Spherical coordinates system.|
2911
2912
2913
2914\anchor HP290
2915#### TH3 as color boxes
2916
2917The supported option is:
2918
2919| Option | Description |
2920|----------|-------------------------------------------------------------------|
2921| "GLCOL" | H3 is drawn using semi-transparent colored boxes. See `$ROOTSYS/tutorials/gl/glvox1.C`.|
2922
2923
2924
2925\anchor HP29b
2926#### TH3 as boxes (spheres)
2927
2928The supported options are:
2929
2930| Option | Description |
2931|----------|-------------------------------------------------------------------|
2932| "GLBOX" | TH3 as a set of boxes, size of box is proportional to bin content.|
2933| "GLBOX1" | The same as "glbox", but spheres are drawn instead of boxes.|
2934
2935
2936
2937\anchor HP29c
2938#### TH3 as iso-surface(s)
2939
2940The supported option is:
2941
2942| Option | Description |
2943|----------|-------------------------------------------------------------------|
2944| "GLISO" | TH3 is drawn using iso-surfaces.|
2945
2946
2947
2948\anchor HP29d
2949#### TF3 (implicit function)
2950
2951The supported option is:
2952
2953| Option | Description |
2954|----------|-------------------------------------------------------------------|
2955| "GL" | Draw a TF3.|
2956
2957
2958
2959\anchor HP29e
2960#### Parametric surfaces
2961
2962`$ROOTSYS/tutorials/gl/glparametric.C` shows how to create parametric
2963equations and visualize the surface.
2964
2965\anchor HP29f
2966#### Interaction with the plots
2967
2968All the interactions are implemented via standard methods
2969`DistancetoPrimitive()` and `ExecuteEvent()`. That's why all the
2970interactions with the OpenGL plots are possible only when the mouse cursor is
2971in the plot's area (the plot's area is the part of a the pad occupied by
2972gl-produced picture). If the mouse cursor is not above gl-picture, the standard
2973pad interaction is performed.
2974
2975\anchor HP29g
2976#### Selectable parts
2977
2978Different parts of the plot can be selected:
2979
2980- xoz, yoz, xoy back planes: When such a plane selected, it's highlighted in green
2981 if the dynamic slicing by this plane is supported, and it's highlighted in red,
2982 if the dynamic slicing is not supported.
2983- The plot itself:
2984 On surfaces, the selected surface is outlined in red. (TF3 and
2985 ISO are not outlined). On lego plots, the selected bin is
2986 highlighted. The bin number and content are displayed in pad's
2987 status bar. In box plots, the box or sphere is highlighted and
2988 the bin info is displayed in pad's status bar.
2989
2990
2991\anchor HP29h
2992#### Rotation and zooming
2993
2994
2995- Rotation:
2996 When the plot is selected, it can be rotated by pressing and
2997 holding the left mouse button and move the cursor.
2998- Zoom/Unzoom:
2999 Mouse wheel or 'j', 'J', 'k', 'K' keys.
3000
3001
3002\anchor HP29i
3003#### Panning
3004
3005The selected plot can be moved in a pad's area by pressing and
3006holding the left mouse button and the shift key.
3007
3008\anchor HP29j
3009#### Box cut
3010
3011Surface, iso, box, TF3 and parametric painters support box cut by
3012pressing the 'c' or 'C' key when the mouse cursor is in a plot's
3013area. That will display a transparent box, cutting away part of the
3014surface (or boxes) in order to show internal part of plot. This box
3015can be moved inside the plot's area (the full size of the box is
3016equal to the plot's surrounding box) by selecting one of the box
3017cut axes and pressing the left mouse button to move it.
3018
3019\anchor HP29k
3020#### Plot specific interactions (dynamic slicing etc.)
3021
3022Currently, all gl-plots support some form of slicing. When back plane
3023is selected (and if it's highlighted in green) you can press and hold
3024left mouse button and shift key and move this back plane inside
3025plot's area, creating the slice. During this "slicing" plot becomes
3026semi-transparent. To remove all slices (and projected curves for
3027surfaces) double click with left mouse button in a plot's area.
3028
3029\anchor HP29l
3030#### Surface with option "GLSURF"
3031
3032The surface profile is displayed on the slicing plane.
3033The profile projection is drawn on the back plane
3034by pressing `'p'` or `'P'` key.
3035
3036\anchor HP29m
3037#### TF3
3038
3039The contour plot is drawn on the slicing plane. For TF3 the color
3040scheme can be changed by pressing 's' or 'S'.
3041
3042\anchor HP29n
3043#### Box
3044
3045The contour plot corresponding to slice plane position is drawn in real time.
3046
3047\anchor HP29o
3048#### Iso
3049
3050Slicing is similar to "GLBOX" option.
3051
3052\anchor HP29p
3053#### Parametric plot
3054
3055No slicing. Additional keys: 's' or 'S' to change color scheme -
3056about 20 color schemes supported ('s' for "scheme"); 'l' or 'L' to
3057increase number of polygons ('l' for "level" of details), 'w' or 'W'
3058to show outlines ('w' for "wireframe").
3059
3060\anchor HP30
3061#### Highlight mode for histogram
3062
3063\since **ROOT version 6.15/01**
3064
3065\image html hlHisto3_top.gif "Highlight mode"
3066
3067Highlight mode is implemented for `TH1` (and for `TGraph`) class. When
3068highlight mode is on, mouse movement over the bin will be represented
3069graphically. Bin will be highlighted as "bin box" (presented by box
3070object). Moreover, any highlight (change of bin) emits signal
3071`TCanvas::Highlighted()` which allows the user to react and call their own
3072function. For a better understanding see also the tutorials
3073`$ROOTSYS/tutorials/hist/hlHisto*.C` files.
3074
3075Highlight mode is switched on/off by `TH1::SetHighlight()` function
3076or interactively from `TH1` context menu. `TH1::IsHighlight()` to verify
3077whether the highlight mode enabled or disabled, default it is disabled.
3078
3079~~~ {.cpp}
3080 root [0] .x $ROOTSYS/tutorials/hsimple.C
3081 root [1] hpx->SetHighlight(kTRUE) // or interactively from TH1 context menu
3082 root [2] hpx->IsHighlight()
3083 (bool) true
3084~~~
3085
3086\image html hlsimple_nofun.gif "Highlight mode for histogram"
3087
3088\anchor HP30a
3089#### Highlight mode and user function
3090
3091The user can use (connect) `TCanvas::Highlighted()` signal, which is always
3092emitted if there is a highlight bin and call user function via signal
3093and slot communication mechanism. `TCanvas::Highlighted()` is similar
3094`TCanvas::Picked()`
3095
3096- when selected object (histogram as a whole) is different from previous
3097then emit `Picked()` signal
3098- when selected (highlighted) bin from histogram is different from previous
3099then emit `Highlighted()` signal
3100
3101Any user function (or functions) has to be defined
3102`UserFunction(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)`.
3103In example (see below) has name `PrintInfo()`. All parameters of user
3104function are taken from
3105
3106 void TCanvas::Highlighted(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)
3107
3108- `pad` is pointer to pad with highlighted histogram
3109- `obj` is pointer to highlighted histogram
3110- `x` is highlighted x bin for 1D histogram
3111- `y` is highlighted y bin for 2D histogram (for 1D histogram not in use)
3112
3113Example how to create a connection from any `TCanvas` object to a user
3114`UserFunction()` slot (see also `TQObject::Connect()` for additional info)
3115
3116 TQObject::Connect("TCanvas", "Highlighted(TVirtualPad*,TObject*,Int_t,Int_t)",
3117 0, 0, "UserFunction(TVirtualPad*,TObject*,Int_t,Int_t)");
3118
3119or use non-static "simplified" function
3120`TCanvas::HighlightConnect(const char *slot)`
3121
3122 c1->HighlightConnect("UserFunction(TVirtualPad*,TObject*,Int_t,Int_t)");
3123
3124NOTE the signal and slot string must have a form
3125"(TVirtualPad*,TObject*,Int_t,Int_t)"
3126
3127 root [0] .x $ROOTSYS/tutorials/hsimple.C
3128 root [1] hpx->SetHighlight(kTRUE)
3129 root [2] .x hlprint.C
3130
3131file `hlprint.C`
3132~~~ {.cpp}
3133void PrintInfo(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)
3134{
3135 auto h = (TH1F *)obj;
3136 if (!h->IsHighlight()) // after highlight disabled
3137 h->SetTitle("highlight disable");
3138 else
3139 h->SetTitle(TString::Format("bin[%03d] (%5.2f) content %g", x,
3140 h->GetBinCenter(x), h->GetBinContent(x)));
3141 pad->Update();
3142}
3143
3144void hlprint()
3145{
3146 if (!gPad) return;
3147 gPad->GetCanvas()->HighlightConnect("PrintInfo(TVirtualPad*,TObject*,Int_t,Int_t)");
3148}
3149~~~
3150
3151\image html hlsimple.gif "Highlight mode and simple user function"
3152
3153For more complex demo please see for example `$ROOTSYS/tutorials/tree/temperature.C` file.
3154
3155*/
3156
3158
3161
3162const Int_t kNMAX = 2000;
3163
3164const Int_t kMAXCONTOUR = 104;
3166
3167static std::unique_ptr<TBox> gXHighlightBox, gYHighlightBox; // highlight X and Y box
3168
3190
3192
3193////////////////////////////////////////////////////////////////////////////////
3194/// Default constructor.
3195
3197{
3198 fH = nullptr;
3199 fXaxis = nullptr;
3200 fYaxis = nullptr;
3201 fZaxis = nullptr;
3202 fFunctions = nullptr;
3203 fNcuts = 0;
3204 fStack = nullptr;
3205 fShowProjection = 0;
3206 fShowProjection2 = 0;
3207 fShowOption = "";
3208 for (int i=0; i<kMaxCuts; i++) {
3209 fCuts[i] = nullptr;
3210 fCutsOpt[i] = 0;
3211 }
3212 fXHighlightBin = -1;
3213 fYHighlightBin = -1;
3214 fCurrentF3 = nullptr;
3215
3216 gStringEntries = gEnv->GetValue("Hist.Stats.Entries", "Entries");
3217 gStringMean = gEnv->GetValue("Hist.Stats.Mean", "Mean");
3218 gStringMeanX = gEnv->GetValue("Hist.Stats.MeanX", "Mean x");
3219 gStringMeanY = gEnv->GetValue("Hist.Stats.MeanY", "Mean y");
3220 gStringMeanZ = gEnv->GetValue("Hist.Stats.MeanZ", "Mean z");
3221 gStringStdDev = gEnv->GetValue("Hist.Stats.StdDev", "Std Dev");
3222 gStringStdDevX = gEnv->GetValue("Hist.Stats.StdDevX", "Std Dev x");
3223 gStringStdDevY = gEnv->GetValue("Hist.Stats.StdDevY", "Std Dev y");
3224 gStringStdDevZ = gEnv->GetValue("Hist.Stats.StdDevZ", "Std Dev z");
3225 gStringUnderflow = gEnv->GetValue("Hist.Stats.Underflow", "Underflow");
3226 gStringOverflow = gEnv->GetValue("Hist.Stats.Overflow", "Overflow");
3227 gStringIntegral = gEnv->GetValue("Hist.Stats.Integral", "Integral");
3228 gStringIntegralBinWidth = gEnv->GetValue("Hist.Stats.IntegralBinWidth", "Integral(w)");
3229 gStringSkewness = gEnv->GetValue("Hist.Stats.Skewness", "Skewness");
3230 gStringSkewnessX = gEnv->GetValue("Hist.Stats.SkewnessX", "Skewness x");
3231 gStringSkewnessY = gEnv->GetValue("Hist.Stats.SkewnessY", "Skewness y");
3232 gStringSkewnessZ = gEnv->GetValue("Hist.Stats.SkewnessZ", "Skewness z");
3233 gStringKurtosis = gEnv->GetValue("Hist.Stats.Kurtosis", "Kurtosis");
3234 gStringKurtosisX = gEnv->GetValue("Hist.Stats.KurtosisX", "Kurtosis x");
3235 gStringKurtosisY = gEnv->GetValue("Hist.Stats.KurtosisY", "Kurtosis y");
3236 gStringKurtosisZ = gEnv->GetValue("Hist.Stats.KurtosisZ", "Kurtosis z");
3237}
3238
3239////////////////////////////////////////////////////////////////////////////////
3240/// destructor.
3241
3243{
3244}
3245
3246////////////////////////////////////////////////////////////////////////////////
3247/// Compute the distance from the point px,py to a line.
3248///
3249/// Compute the closest distance of approach from point px,py to elements of
3250/// an histogram. The distance is computed in pixels units.
3251///
3252/// Algorithm: Currently, this simple model computes the distance from the mouse
3253/// to the histogram contour only.
3254
3256{
3257
3258 Double_t defaultLabelSize = 0.04; // See TAttAxis.h for source of this value
3259
3260 const Int_t big = 9999;
3261 const Int_t kMaxDiff = 7;
3262
3263 if (fPie)
3264 return fPie->DistancetoPrimitive(px, py);
3265
3266 Double_t x = gPad->AbsPixeltoX(px);
3267 Double_t x1 = gPad->AbsPixeltoX(px+1);
3268
3269 Int_t puxmin = gPad->XtoAbsPixel(gPad->GetUxmin());
3270 Int_t puymin = gPad->YtoAbsPixel(gPad->GetUymin());
3271 Int_t puxmax = gPad->XtoAbsPixel(gPad->GetUxmax());
3272 Int_t puymax = gPad->YtoAbsPixel(gPad->GetUymax());
3273 Int_t curdist = big;
3274 Int_t yxaxis, dyaxis,xyaxis, dxaxis;
3275 Bool_t dsame;
3276 TObject *PadPointer = gPad->GetPadPointer();
3277 if (!PadPointer) return 0;
3278 TString doption = PadPointer->GetDrawOption();
3279 Double_t factor = 1;
3280 if (fH->GetNormFactor() != 0) {
3281 factor = fH->GetNormFactor()/fH->GetSumOfWeights();
3282 }
3283 // return if point is not in the histogram area
3284
3285 // If a 3D view exists, check distance to axis
3286 TView *view = gPad->GetView();
3287 Int_t d1,d2,d3;
3288 if (view && Hoption.Contour != 14) {
3289 Double_t ratio;
3290 d3 = view->GetDistancetoAxis(3, px, py, ratio);
3291 if (d3 <= kMaxDiff) {gPad->SetSelected(fZaxis); return 0;}
3292 d1 = view->GetDistancetoAxis(1, px, py, ratio);
3293 if (d1 <= kMaxDiff) {gPad->SetSelected(fXaxis); return 0;}
3294 d2 = view->GetDistancetoAxis(2, px, py, ratio);
3295 if (d2 <= kMaxDiff) {gPad->SetSelected(fYaxis); return 0;}
3296 if ( px > puxmin && px < puxmax && py > puymax && py < puymin) curdist = 1;
3297 goto FUNCTIONS;
3298 }
3299 // check if point is close to an axis
3300 doption.ToLower();
3301 dsame = kFALSE;
3302 if (doption.Contains("same")) dsame = kTRUE;
3303
3304 dyaxis = Int_t(2*(puymin-puymax)*TMath::Max(Double_t(fYaxis->GetLabelSize()), defaultLabelSize));
3305 if (doption.Contains("y+")) {
3306 xyaxis = puxmax + Int_t((puxmax-puxmin)*fYaxis->GetLabelOffset());
3307 if (px <= xyaxis+dyaxis && px >= xyaxis && py >puymax && py < puymin) {
3308 if (!dsame) {
3309 if (gPad->IsVertical()) gPad->SetSelected(fYaxis);
3310 else gPad->SetSelected(fXaxis);
3311 return 0;
3312 }
3313 }
3314 } else {
3315 xyaxis = puxmin - Int_t((puxmax-puxmin)*fYaxis->GetLabelOffset());
3316 if (px >= xyaxis-dyaxis && px <= xyaxis && py >puymax && py < puymin) {
3317 if (!dsame) {
3318 if (gPad->IsVertical()) gPad->SetSelected(fYaxis);
3319 else gPad->SetSelected(fXaxis);
3320 return 0;
3321 }
3322 }
3323 }
3324
3325 dxaxis = Int_t((puymin-puymax)*TMath::Max(Double_t(fXaxis->GetLabelSize()), defaultLabelSize));
3326 if (doption.Contains("x+")) {
3327 yxaxis = puymax - Int_t((puymin-puymax)*fXaxis->GetLabelOffset());
3328 if (py >= yxaxis-dxaxis && py <= yxaxis && px <puxmax && px > puxmin) {
3329 if (!dsame) {
3330 if (gPad->IsVertical()) gPad->SetSelected(fXaxis);
3331 else gPad->SetSelected(fYaxis);
3332 return 0;
3333 }
3334 }
3335 } else {
3336 yxaxis = puymin + Int_t((puymin-puymax)*fXaxis->GetLabelOffset());
3337 if (yxaxis < puymin) yxaxis = puymin;
3338 if (py <= yxaxis+dxaxis && py >= yxaxis && px <puxmax && px > puxmin) {
3339 if (!dsame) {
3340 if (gPad->IsVertical()) gPad->SetSelected(fXaxis);
3341 else gPad->SetSelected(fYaxis);
3342 return 0;
3343 }
3344 }
3345 }
3346
3347 if (fH->IsHighlight()) { // only if highlight is enable
3348 if ((px > puxmin) && (py < puymin) && (px < puxmax) && (py > puymax))
3349 HighlightBin(px, py);
3350 }
3351
3352 // if object is 2D or 3D return this object
3353 if (fH->GetDimension() == 2) {
3354 if (fH->InheritsFrom(TH2Poly::Class())) {
3355 TH2Poly *th2 = (TH2Poly*)fH;
3357 gPad->GetRangeAxis(xmin, ymin, xmax, ymax);
3358 Double_t pxu = gPad->AbsPixeltoX(px);
3359 Double_t pyu = gPad->AbsPixeltoY(py);
3360 if ((pxu>xmax) || (pxu < xmin) || (pyu>ymax) || (pyu < ymin)) {
3361 curdist = big;
3362 goto FUNCTIONS;
3363 } else {
3364 Int_t bin = th2->FindBin(pxu, pyu);
3365 if (bin>0) curdist = 1;
3366 else curdist = big;
3367 goto FUNCTIONS;
3368 }
3369 }
3370 Int_t delta2 = 5; //Give a margin of delta2 pixels to be in the 2-d area
3371 if ( px > puxmin + delta2
3372 && px < puxmax - delta2
3373 && py > puymax + delta2
3374 && py < puymin - delta2) {curdist =1; goto FUNCTIONS;}
3375 }
3376
3377 // point is inside histogram area. Find channel number
3378 if (gPad->IsVertical()) {
3379 Int_t bin = fXaxis->FindFixBin(gPad->PadtoX(x));
3380 Int_t binsup = fXaxis->FindFixBin(gPad->PadtoX(x1));
3381 Double_t binval = factor*fH->GetBinContent(bin);
3382 Int_t pybin = gPad->YtoAbsPixel(gPad->YtoPad(binval));
3383 if (binval == 0 && pybin < puymin) pybin = 10000;
3384 // special case if more than one bin for the pixel
3385 if (binsup-bin>1) {
3386 Double_t binvalmin, binvalmax;
3387 binvalmin=binval;
3388 binvalmax=binval;
3389 for (Int_t ibin=bin+1; ibin<binsup; ibin++) {
3390 Double_t binvaltmp = factor*fH->GetBinContent(ibin);
3391 if (binvalmin>binvaltmp) binvalmin=binvaltmp;
3392 if (binvalmax<binvaltmp) binvalmax=binvaltmp;
3393 }
3394 Int_t pybinmin = gPad->YtoAbsPixel(gPad->YtoPad(binvalmax));
3395 Int_t pybinmax = gPad->YtoAbsPixel(gPad->YtoPad(binvalmin));
3396 if (py<pybinmax+kMaxDiff/2 && py>pybinmin-kMaxDiff/2) pybin = py;
3397 }
3398 if (bin != binsup) { // Mouse on bin border
3399 Double_t binsupval = factor*fH->GetBinContent(binsup);
3400 Int_t pybinsub = gPad->YtoAbsPixel(gPad->YtoPad(binsupval));
3401 if (py <= TMath::Max(pybinsub,pybin) && py >= TMath::Min(pybinsub,pybin) && pybin != 10000) return 0;
3402 }
3403 if (TMath::Abs(py - pybin) <= kMaxDiff) return TMath::Abs(py - pybin);
3404 } else {
3405 Double_t y = gPad->AbsPixeltoY(py);
3406 Double_t y1 = gPad->AbsPixeltoY(py+1);
3407 Int_t bin = fXaxis->FindFixBin(gPad->PadtoY(y));
3408 Int_t binsup = fXaxis->FindFixBin(gPad->PadtoY(y1));
3409 Double_t binval = factor*fH->GetBinContent(bin);
3410 Int_t pxbin = gPad->XtoAbsPixel(gPad->XtoPad(binval));
3411 if (binval == 0 && pxbin > puxmin) pxbin = 10000;
3412 // special case if more than one bin for the pixel
3413 if (binsup-bin>1) {
3414 Double_t binvalmin, binvalmax;
3415 binvalmin=binval;
3416 binvalmax=binval;
3417 for (Int_t ibin=bin+1; ibin<binsup; ibin++) {
3418 Double_t binvaltmp = factor*fH->GetBinContent(ibin);
3419 if (binvalmin>binvaltmp) binvalmin=binvaltmp;
3420 if (binvalmax<binvaltmp) binvalmax=binvaltmp;
3421 }
3422 Int_t pxbinmin = gPad->XtoAbsPixel(gPad->XtoPad(binvalmax));
3423 Int_t pxbinmax = gPad->XtoAbsPixel(gPad->XtoPad(binvalmin));
3424 if (px<pxbinmax+kMaxDiff/2 && px>pxbinmin-kMaxDiff/2) pxbin = px;
3425 }
3426 if (TMath::Abs(px - pxbin) <= kMaxDiff) return TMath::Abs(px - pxbin);
3427 }
3428 // Loop on the list of associated functions and user objects
3429FUNCTIONS:
3430 TObject *f;
3431 TIter next(fFunctions);
3432 while ((f = (TObject*) next())) {
3433 Int_t dist;
3434 if (f->InheritsFrom(TF1::Class())) dist = f->DistancetoPrimitive(-px,py);
3435 else dist = f->DistancetoPrimitive(px,py);
3436 if (dist < kMaxDiff) {gPad->SetSelected(f); return dist;}
3437 }
3438 return curdist;
3439}
3440
3441////////////////////////////////////////////////////////////////////////////////
3442/// Display a panel with all histogram drawing options.
3443
3445{
3446
3447 gCurrentHist = fH;
3448 if (!gPad) {
3449 Error("DrawPanel", "need to draw histogram first");
3450 return;
3451 }
3453 editor->Show();
3454 gROOT->ProcessLine(TString::Format("((TCanvas*)0x%zx)->Selected((TVirtualPad*)0x%zx,(TObject*)0x%zx,1)",
3455 (size_t)gPad->GetCanvas(), (size_t)gPad, (size_t)fH).Data());
3456}
3457
3458////////////////////////////////////////////////////////////////////////////////
3459/// Execute the actions corresponding to `event`.
3460///
3461/// This function is called when a histogram is clicked with the locator at
3462/// the pixel position px,py.
3463
3465{
3466
3467 if (!gPad) return;
3468
3469 static Int_t bin, px1, py1, px2, py2, pyold;
3470 static std::unique_ptr<TBox> zoombox;
3471 Double_t zbx1,zbx2,zby1,zby2;
3472
3473 Int_t bin1, bin2;
3474 Double_t xlow, xup, ylow, binval, x, baroffset, barwidth, binwidth;
3475 Bool_t opaque = gPad->OpaqueMoving();
3476
3477 if (!gPad->IsEditable()) return;
3478
3479 if (fPie) {
3480 fPie->ExecuteEvent(event, px, py);
3481 return;
3482 }
3483 // come here if we have a lego/surface in the pad
3484 TView *view = gPad->GetView();
3485
3486 if (!fShowProjection && view && !view->TestBit(kCannotRotate)) {
3487 view->ExecuteRotateView(event, px, py);
3488 return;
3489 }
3490
3491 TAxis *xaxis = fH->GetXaxis();
3492 TAxis *yaxis = fH->GetYaxis();
3493 Int_t dimension = fH->GetDimension();
3494
3495 // In case of option SAME the axis must be the ones of the first drawn histogram
3496 TString IsSame = fH->GetDrawOption();
3497 IsSame.ToLower();
3498 if (IsSame.Index("same")>=0) {
3499 TH1 *h1;
3500 TIter next(gPad->GetListOfPrimitives());
3501 while ((h1 = (TH1 *)next())) {
3502 if (!h1->InheritsFrom(TH1::Class())) continue;
3503 xaxis = h1->GetXaxis();
3504 yaxis = h1->GetYaxis();
3505 break;
3506 }
3507 }
3508
3509 Double_t factor = 1;
3510 if (fH->GetNormFactor() != 0) {
3511 factor = fH->GetNormFactor()/fH->GetSumOfWeights();
3512 }
3513
3514 switch (event) {
3515
3516 case kButton1Down:
3517
3518 if (!opaque) gVirtualX->SetLineColor(-1);
3519 fH->TAttLine::Modify();
3520
3521 if (opaque && dimension ==2) {
3522 zbx1 = gPad->AbsPixeltoX(px);
3523 zbx2 = gPad->AbsPixeltoX(px);
3524 zby1 = gPad->AbsPixeltoY(py);
3525 zby2 = gPad->AbsPixeltoY(py);
3526 px1 = px;
3527 py1 = py;
3528 if (gPad->GetLogx()) {
3529 zbx1 = TMath::Power(10,zbx1);
3530 zbx2 = TMath::Power(10,zbx2);
3531 }
3532 if (gPad->GetLogy()) {
3533 zby1 = TMath::Power(10,zby1);
3534 zby2 = TMath::Power(10,zby2);
3535 }
3536 if (zoombox) Error("ExecuteEvent", "Last zoom box was not deleted");
3537 zoombox = std::make_unique<TBox>(zbx1, zby1, zbx2, zby2);
3538 Int_t ci = TColor::GetColor("#7d7dff");
3539 TColor *zoomcolor = gROOT->GetColor(ci);
3540 if (!TCanvas::SupportAlpha() || !zoomcolor) zoombox->SetFillStyle(3002);
3541 else zoomcolor->SetAlpha(0.5);
3542 zoombox->SetFillColor(ci);
3543 zoombox->Draw();
3544 gPad->Modified();
3545 gPad->Update();
3546 }
3547 // No break !!!
3548
3549 case kMouseMotion:
3550
3551 if (fShowProjection) {ShowProjection3(px,py); break;}
3552
3553 gPad->SetCursor(kPointer);
3554 if (dimension ==1) {
3555 if (Hoption.Bar) {
3556 baroffset = fH->GetBarOffset();
3557 barwidth = fH->GetBarWidth();
3558 } else {
3559 baroffset = 0;
3560 barwidth = 1;
3561 }
3562 x = gPad->AbsPixeltoX(px);
3563 bin = fXaxis->FindFixBin(gPad->PadtoX(x));
3564 binwidth = fXaxis->GetBinWidth(bin);
3565 xlow = gPad->XtoPad(fXaxis->GetBinLowEdge(bin) + baroffset*binwidth);
3566 xup = gPad->XtoPad(xlow + barwidth*binwidth);
3567 ylow = gPad->GetUymin();
3568 px1 = gPad->XtoAbsPixel(xlow);
3569 px2 = gPad->XtoAbsPixel(xup);
3570 py1 = gPad->YtoAbsPixel(ylow);
3571 py2 = py;
3572 pyold = py;
3573 if (gROOT->GetEditHistograms()) gPad->SetCursor(kArrowVer);
3574 }
3575
3576 break;
3577
3578 case kButton1Motion:
3579
3580 if (dimension ==1) {
3581 if (gROOT->GetEditHistograms()) {
3582 if (!opaque) {
3583 gVirtualX->DrawBox(px1, py1, px2, py2,TVirtualX::kHollow); // Draw the old box
3584 py2 += py - pyold;
3585 gVirtualX->DrawBox(px1, py1, px2, py2,TVirtualX::kHollow); // Draw the new box
3586 pyold = py;
3587 } else {
3588 py2 += py - pyold;
3589 pyold = py;
3590 binval = gPad->PadtoY(gPad->AbsPixeltoY(py2))/factor;
3591 fH->SetBinContent(bin,binval);
3592 gPad->Modified(kTRUE);
3593 }
3594 }
3595 }
3596
3597 if (opaque && dimension ==2) {
3598 if (TMath::Abs(px1-px)>5 && TMath::Abs(py1-py)>5) {
3599 zbx2 = gPad->AbsPixeltoX(px);
3600 zby2 = gPad->AbsPixeltoY(py);
3601 if (gPad->GetLogx()) zbx2 = TMath::Power(10,zbx2);
3602 if (gPad->GetLogy()) zby2 = TMath::Power(10,zby2);
3603 if (zoombox) {
3604 zoombox->SetX2(zbx2);
3605 zoombox->SetY2(zby2);
3606 }
3607 gPad->Modified();
3608 gPad->Update();
3609 }
3610 }
3611
3612 break;
3613
3614 case kWheelUp:
3615
3616 if (dimension ==2) {
3617 bin1 = xaxis->GetFirst()+1;
3618 bin2 = xaxis->GetLast()-1;
3619 bin1 = TMath::Max(bin1, 1);
3620 bin2 = TMath::Min(bin2, xaxis->GetNbins());
3621 if (bin2>bin1) xaxis->SetRange(bin1,bin2);
3622 bin1 = yaxis->GetFirst()+1;
3623 bin2 = yaxis->GetLast()-1;
3624 bin1 = TMath::Max(bin1, 1);
3625 bin2 = TMath::Min(bin2, yaxis->GetNbins());
3626 if (bin2>bin1) yaxis->SetRange(bin1,bin2);
3627 }
3628 gPad->Modified();
3629 gPad->Update();
3630
3631 break;
3632
3633 case kWheelDown:
3634
3635 if (dimension == 2) {
3636 bin1 = xaxis->GetFirst()-1;
3637 bin2 = xaxis->GetLast()+1;
3638 bin1 = TMath::Max(bin1, 1);
3639 bin2 = TMath::Min(bin2, xaxis->GetNbins());
3640 if (bin2>bin1) xaxis->SetRange(bin1,bin2);
3641 bin1 = yaxis->GetFirst()-1;
3642 bin2 = yaxis->GetLast()+1;
3643 bin1 = TMath::Max(bin1, 1);
3644 bin2 = TMath::Min(bin2, yaxis->GetNbins());
3645 if (bin2>bin1) yaxis->SetRange(bin1,bin2);
3646 }
3647 gPad->Modified();
3648 gPad->Update();
3649
3650 break;
3651
3652 case kButton1Up:
3653 if (dimension ==1) {
3654 if (gROOT->GetEditHistograms()) {
3655 binval = gPad->PadtoY(gPad->AbsPixeltoY(py2))/factor;
3656 fH->SetBinContent(bin,binval);
3657 PaintInit(); // recalculate Hparam structure and recalculate range
3658 }
3659
3660 // might resize pad pixmap so should be called before any paint routine
3662 }
3663 if (opaque && dimension ==2) {
3664 if (zoombox) {
3665 Double_t x1 = TMath::Min(zoombox->GetX1(), zoombox->GetX2());
3666 Double_t x2 = TMath::Max(zoombox->GetX1(), zoombox->GetX2());
3667 Double_t y1 = TMath::Min(zoombox->GetY1(), zoombox->GetY2());
3668 Double_t y2 = TMath::Max(zoombox->GetY1(), zoombox->GetY2());
3669 x1 = TMath::Max(x1,xaxis->GetXmin());
3670 x2 = TMath::Min(x2,xaxis->GetXmax());
3671 y1 = TMath::Max(y1,yaxis->GetXmin());
3672 y2 = TMath::Min(y2,yaxis->GetXmax());
3673 if (x1<x2 && y1<y2) {
3674 xaxis->SetRangeUser(x1, x2);
3675 yaxis->SetRangeUser(y1, y2);
3676 }
3677 zoombox.reset();
3678 }
3679 }
3680 gPad->Modified(kTRUE);
3681 if (opaque) gVirtualX->SetLineColor(-1);
3682
3683 break;
3684
3685 case kButton1Locate:
3686
3687 ExecuteEvent(kButton1Down, px, py);
3688
3689 while (true) {
3690 px = py = 0;
3691 event = gVirtualX->RequestLocator(1, 1, px, py);
3692
3694
3695 if (event != -1) { // button is released
3696 ExecuteEvent(kButton1Up, px, py);
3697 return;
3698 }
3699 }
3700 }
3701}
3702
3703////////////////////////////////////////////////////////////////////////////////
3704/// Get a contour (as a list of TGraphs) using the Delaunay triangulation.
3705
3707{
3708 // Check if fH contains a TGraphDelaunay2D
3709 TList *hl = fH->GetListOfFunctions();
3710 TGraphDelaunay2D *dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
3711 // try with the old painter
3712 TGraphDelaunay *dtOld = nullptr;
3713 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
3714
3715 if (!dt && !dtOld) return nullptr;
3716
3717 gCurrentHist = fH;
3718
3719 if (!fGraph2DPainter)
3720 ((THistPainter*)this)->fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
3721
3722 return fGraph2DPainter->GetContourList(contour);
3723}
3724
3725////////////////////////////////////////////////////////////////////////////////
3726/// Display the histogram info (bin number, contents, integral up to bin
3727/// corresponding to cursor position px,py.
3728
3730{
3731
3732 if (!gPad) return (char*)"";
3733
3734 Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
3735 Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
3736 Double_t x1 = gPad->PadtoX(gPad->AbsPixeltoX(px+1));
3737 TString drawOption = fH->GetDrawOption();
3738 drawOption.ToLower();
3739 Double_t xmin, xmax, uxmin,uxmax;
3740 Double_t ymin, ymax, uymin,uymax;
3741 if (fH->GetDimension() == 2) {
3742 if (gPad->GetView() || drawOption.Index("cont") >= 0) {
3743 uxmin=gPad->GetUxmin();
3744 uxmax=gPad->GetUxmax();
3747 x = xmin +(xmax-xmin)*(x-uxmin)/(uxmax-uxmin);
3748 uymin=gPad->GetUymin();
3749 uymax=gPad->GetUymax();
3752 y = ymin +(ymax-ymin)*(y-uymin)/(uymax-uymin);
3753 }
3754 }
3755 Int_t binx,biny,binmin=0,binx1;
3756 if (gPad->IsVertical()) {
3757 binx = fXaxis->FindFixBin(x);
3758 if (drawOption.Index("same") >= 0) {
3759 TH1 *h1;
3760 TIter next(gPad->GetListOfPrimitives());
3761 while ((h1 = (TH1 *)next())) {
3762 if (!h1->InheritsFrom(TH1::Class())) continue;
3763 binmin = h1->GetXaxis()->GetFirst();
3764 break;
3765 }
3766 } else {
3767 binmin = fXaxis->GetFirst();
3768 }
3769 binx1 = fXaxis->FindFixBin(x1);
3770 // special case if more than 1 bin in x per pixel
3771 if (binx1-binx>1 && fH->GetDimension() == 1) {
3772 Double_t binval=fH->GetBinContent(binx);
3773 Int_t binnear=binx;
3774 for (Int_t ibin=binx+1; ibin<binx1; ibin++) {
3775 Double_t binvaltmp = fH->GetBinContent(ibin);
3776 if (TMath::Abs(y-binvaltmp) < TMath::Abs(y-binval)) {
3777 binval=binvaltmp;
3778 binnear=ibin;
3779 }
3780 }
3781 binx = binnear;
3782 }
3783 } else {
3784 x1 = gPad->PadtoY(gPad->AbsPixeltoY(py+1));
3785 binx = fXaxis->FindFixBin(y);
3786 if (drawOption.Index("same") >= 0) {
3787 TH1 *h1;
3788 TIter next(gPad->GetListOfPrimitives());
3789 while ((h1 = (TH1 *)next())) {
3790 if (!h1->InheritsFrom(TH1::Class())) continue;
3791 binmin = h1->GetXaxis()->GetFirst();
3792 break;
3793 }
3794 } else {
3795 binmin = fXaxis->GetFirst();
3796 }
3797 binx1 = fXaxis->FindFixBin(x1);
3798 // special case if more than 1 bin in x per pixel
3799 if (binx1-binx>1 && fH->GetDimension() == 1) {
3800 Double_t binval=fH->GetBinContent(binx);
3801 Int_t binnear=binx;
3802 for (Int_t ibin=binx+1; ibin<binx1; ibin++) {
3803 Double_t binvaltmp = fH->GetBinContent(ibin);
3804 if (TMath::Abs(x-binvaltmp) < TMath::Abs(x-binval)) {
3805 binval=binvaltmp;
3806 binnear=ibin;
3807 }
3808 }
3809 binx = binnear;
3810 }
3811 }
3812 if (fH->GetDimension() == 1) {
3814 TProfile *tp = (TProfile*)fH;
3815 fObjectInfo.Form("(x=%g, y=%g, binx=%d, binc=%g, bine=%g, binn=%d)",
3816 x, y, binx, fH->GetBinContent(binx), fH->GetBinError(binx),
3817 (Int_t) tp->GetBinEntries(binx));
3818 }
3819 else {
3820 Double_t integ = 0;
3821 for (Int_t bin=binmin;bin<=binx;bin++) {integ += fH->GetBinContent(bin);}
3822 fObjectInfo.Form("(x=%g, y=%g, binx=%d, binc=%g, Sum=%g)",
3823 x,y,binx,fH->GetBinContent(binx),integ);
3824 }
3825 } else if (fH->GetDimension() == 2) {
3826 if (fH->InheritsFrom(TH2Poly::Class())) {
3827 TH2Poly *th2 = (TH2Poly*)fH;
3828 biny = th2->FindBin(x,y);
3829 fObjectInfo.Form("%s (x=%g, y=%g, bin=%d, binc=%g)",
3830 th2->GetBinTitle(biny),x,y,biny,th2->GetBinContent(biny));
3831 }
3832 else if (fH->InheritsFrom(TProfile2D::Class())) {
3833 TProfile2D *tp = (TProfile2D*)fH;
3834 biny = fYaxis->FindFixBin(y);
3835 Int_t bin = fH->GetBin(binx,biny);
3836 fObjectInfo.Form("(x=%g, y=%g, binx=%d, biny=%d, binc=%g, bine=%g, binn=%d)",
3837 x, y, binx, biny, fH->GetBinContent(bin),
3838 fH->GetBinError(bin), (Int_t) tp->GetBinEntries(bin));
3839 } else {
3840 biny = fYaxis->FindFixBin(y);
3841 fObjectInfo.Form("(x=%g, y=%g, binx=%d, biny=%d, binc=%g bine=%g)",
3842 x,y,binx,biny,fH->GetBinContent(binx,biny),
3843 fH->GetBinError(binx,biny));
3844 }
3845 } else {
3846 // 3d case: retrieving the x,y,z bin is not yet implemented
3847 // print just the x,y info
3848 fObjectInfo.Form("(x=%g, y=%g)",x,y);
3849 }
3850
3851 return (char *)fObjectInfo.Data();
3852}
3853
3854////////////////////////////////////////////////////////////////////////////////
3855/// Set highlight (enable/disable) mode for fH
3856
3858{
3859 if (fH->IsHighlight()) return;
3860
3861 fXHighlightBin = -1;
3862 fYHighlightBin = -1;
3863 // delete previous highlight box
3864 if (gXHighlightBox) gXHighlightBox.reset();
3865 if (gYHighlightBox) gYHighlightBox.reset();
3866 // emit Highlighted() signal (user can check on disabled)
3867 if (gPad->GetCanvas()) gPad->GetCanvas()->Highlighted(gPad, fH, fXHighlightBin, fYHighlightBin);
3868}
3869
3870////////////////////////////////////////////////////////////////////////////////
3871/// Check on highlight bin
3872
3874{
3875 // call from DistancetoPrimitive (only if highlight is enable)
3876
3877 Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
3878 Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
3879 Int_t binx = fXaxis->FindFixBin(x);
3880 Int_t biny = fYaxis->FindFixBin(y);
3881 if (!gPad->IsVertical()) binx = fXaxis->FindFixBin(y);
3882
3883 Bool_t changedBin = kFALSE;
3884 if (binx != fXHighlightBin) {
3885 fXHighlightBin = binx;
3886 changedBin = kTRUE;
3887 } else if (fH->GetDimension() == 1) return;
3888 if (biny != fYHighlightBin) {
3889 fYHighlightBin = biny;
3890 changedBin = kTRUE;
3891 }
3892 if (!changedBin) return;
3893
3894 // Info("HighlightBin", "histo: %p '%s'\txbin: %d, ybin: %d",
3895 // (void *)fH, fH->GetName(), fXHighlightBin, fYHighlightBin);
3896
3897 // paint highlight bin as box (recursive calls PaintHighlightBin)
3898 gPad->Modified(kTRUE);
3899 gPad->Update();
3900
3901 // emit Highlighted() signal
3902 if (gPad->GetCanvas()) gPad->GetCanvas()->Highlighted(gPad, fH, fXHighlightBin, fYHighlightBin);
3903}
3904
3905////////////////////////////////////////////////////////////////////////////////
3906/// Paint highlight bin as TBox object
3907
3909{
3910 // call from PaintTitle
3911
3912 if (!fH->IsHighlight()) return;
3913
3914 Double_t uxmin = gPad->GetUxmin();
3915 Double_t uxmax = gPad->GetUxmax();
3916 Double_t uymin = gPad->GetUymin();
3917 Double_t uymax = gPad->GetUymax();
3918 if (gPad->GetLogx()) {
3919 uxmin = TMath::Power(10.0, uxmin);
3920 uxmax = TMath::Power(10.0, uxmax);
3921 }
3922 if (gPad->GetLogy()) {
3923 uymin = TMath::Power(10.0, uymin);
3924 uymax = TMath::Power(10.0, uymax);
3925 }
3926
3927 // testing specific possibility (after zoom, draw with "same", log, etc.)
3928 Double_t hcenter;
3929 if (gPad->IsVertical()) {
3931 if ((hcenter < uxmin) || (hcenter > uxmax)) return;
3932 } else {
3934 if ((hcenter < uymin) || (hcenter > uymax)) return;
3935 }
3936 if (fH->GetDimension() == 2) {
3938 if ((hcenter < uymin) || (hcenter > uymax)) return;
3939 }
3940
3941 // paint X highlight bin (for 1D or 2D)
3942 Double_t hbx1, hbx2, hby1, hby2;
3943 if (gPad->IsVertical()) {
3946 hby1 = uymin;
3947 hby2 = uymax;
3948 } else {
3949 hbx1 = uxmin;
3950 hbx2 = uxmax;
3953 }
3954
3955 if (!gXHighlightBox) {
3956 gXHighlightBox = std::make_unique<TBox>(hbx1, hby1, hbx2, hby2);
3957 gXHighlightBox->SetBit(kCannotPick);
3958 gXHighlightBox->SetFillColor(TColor::GetColor("#9797ff"));
3959 if (!TCanvas::SupportAlpha()) gXHighlightBox->SetFillStyle(3001);
3960 else gROOT->GetColor(gXHighlightBox->GetFillColor())->SetAlpha(0.5);
3961 }
3962 gXHighlightBox->SetX1(hbx1);
3963 gXHighlightBox->SetX2(hbx2);
3964 gXHighlightBox->SetY1(hby1);
3965 gXHighlightBox->SetY2(hby2);
3966 gXHighlightBox->Paint();
3967
3968 // Info("PaintHighlightBin", "histo: %p '%s'\txbin: %d, ybin: %d",
3969 // (void *)fH, fH->GetName(), fXHighlightBin, fYHighlightBin);
3970
3971 // paint Y highlight bin (only for 2D)
3972 if (fH->GetDimension() != 2) return;
3973 hbx1 = uxmin;
3974 hbx2 = uxmax;
3977
3978 if (!gYHighlightBox) {
3979 gYHighlightBox = std::make_unique<TBox>(hbx1, hby1, hbx2, hby2);
3980 gYHighlightBox->SetBit(kCannotPick);
3981 gYHighlightBox->SetFillColor(gXHighlightBox->GetFillColor());
3982 gYHighlightBox->SetFillStyle(gXHighlightBox->GetFillStyle());
3983 }
3984 gYHighlightBox->SetX1(hbx1);
3985 gYHighlightBox->SetX2(hbx2);
3986 gYHighlightBox->SetY1(hby1);
3987 gYHighlightBox->SetY2(hby2);
3988 gYHighlightBox->Paint();
3989}
3990
3991////////////////////////////////////////////////////////////////////////////////
3992/// Return `kTRUE` if the cell `ix`, `iy` is inside one of the graphical cuts.
3993
3995{
3996
3997 for (Int_t i=0;i<fNcuts;i++) {
4000 if (fCutsOpt[i] > 0) {
4001 if (!fCuts[i]->IsInside(x,y)) return kFALSE;
4002 } else {
4003 if (fCuts[i]->IsInside(x,y)) return kFALSE;
4004 }
4005 }
4006 return kTRUE;
4007}
4008
4009////////////////////////////////////////////////////////////////////////////////
4010/// Return `kTRUE` if the point `x`, `y` is inside one of the graphical cuts.
4011
4013{
4014
4015 for (Int_t i=0;i<fNcuts;i++) {
4016 if (fCutsOpt[i] > 0) {
4017 if (!fCuts[i]->IsInside(x,y)) return kFALSE;
4018 } else {
4019 if (fCuts[i]->IsInside(x,y)) return kFALSE;
4020 }
4021 }
4022 return kTRUE;
4023}
4024
4025////////////////////////////////////////////////////////////////////////////////
4026/// Decode string `choptin` and fill Hoption structure.
4027
4029{
4030
4031 char *l;
4032 char chopt[128];
4033 Int_t nch = strlen(choptin);
4034 strlcpy(chopt,choptin,128);
4035 Int_t hdim = fH->GetDimension();
4036 Bool_t explicitColor = kFALSE;
4037
4045 Hoption.Candle = 0;
4046
4047 // special 2D options
4048 Hoption.List = 0;
4049 Hoption.Zscale = 0;
4050 Hoption.FrontBox = 1;
4051 Hoption.BackBox = 1;
4053
4054 Hoption.Zero = 0;
4055
4057
4058 //check for graphical cuts
4059 MakeCuts(chopt);
4060
4061 for (Int_t i=0;i<nch;i++) chopt[i] = toupper(chopt[i]);
4062 if (hdim > 1) Hoption.Color = 1; // Default drawing option for 2D and 3D histograms
4063 if (!nch) Hoption.Hist = 1;
4064 if (fFunctions->First()) Hoption.Func = 1;
4065 if (fH->GetSumw2N() && hdim == 1) Hoption.Error = 2;
4066
4067 char *l1 = strstr(chopt,"PFC"); // Automatic Fill Color
4068 char *l2 = strstr(chopt,"PLC"); // Automatic Line Color
4069 char *l3 = strstr(chopt,"PMC"); // Automatic Marker Color
4070 if (l1 || l2 || l3) {
4071 Int_t i = gPad->NextPaletteColor();
4072 if (l1) {memcpy(l1," ",3); fH->SetFillColor(i);}
4073 if (l2) {memcpy(l2," ",3); fH->SetLineColor(i);}
4074 if (l3) {memcpy(l3," ",3); fH->SetMarkerColor(i);}
4075 Hoption.Hist = 1; // Make sure something is drawn in case there is no drawing option specified.
4076 }
4077
4078 l = strstr(chopt,"MIN0");
4079 if (l) {
4080 Hoption.MinimumZero = 1;
4081 memcpy(l," ",4);
4082 }
4083
4084 l = strstr(chopt,"SPEC");
4085 if (l) {
4086 Hoption.Color = 0;
4087 memcpy(l," ",4);
4088 Int_t bs=0;
4089 l = strstr(chopt,"BF(");
4090 if (l) {
4091 if (sscanf(&l[3],"%d",&bs) > 0) {
4092 Int_t i=0;
4093 while (l[i]!=')') {
4094 l[i] = ' ';
4095 i++;
4096 }
4097 l[i] = ' ';
4098 }
4099 }
4100 Hoption.Spec = TMath::Max(1600,bs);
4101 return 1;
4102 }
4103
4104 l = strstr(chopt,"GL");
4105 if (l) {
4106 memcpy(l," ",2);
4107 }
4108 l = strstr(chopt,"X+");
4109 if (l) {
4110 Hoption.AxisPos = 10;
4111 memcpy(l," ",2);
4112 }
4113 l = strstr(chopt,"Y+");
4114 if (l) {
4115 Hoption.AxisPos += 1;
4116 memcpy(l," ",2);
4117 }
4118 if ((Hoption.AxisPos == 10 || Hoption.AxisPos == 1) && (nch == 2)) Hoption.Hist = 1;
4119 if (Hoption.AxisPos == 11 && nch == 4) Hoption.Hist = 1;
4120
4121 l = strstr(chopt,"SAMES");
4122 if (l) {
4123 if (nch == 5) Hoption.Hist = 1;
4124 Hoption.Same = 2;
4125 memcpy(l," ",5);
4126 if (l[5] == '0') { Hoption.Same += 10; l[5] = ' '; }
4127 }
4128 l = strstr(chopt,"SAME");
4129 if (l) {
4130 if (nch == 4) Hoption.Hist = 1;
4131 Hoption.Same = 1;
4132 memcpy(l," ",4);
4133 if (l[4] == '0') { Hoption.Same += 10; l[4] = ' '; }
4134 }
4135
4136 l = strstr(chopt,"SCAT");
4137 if (l) {
4138 Warning("MakeChopt","option SCAT is deprecated.");
4139 Hoption.Scat = 1;
4140 memcpy(l," ",4);
4141 Hoption.Color = 0;
4142 }
4143
4144 l = strstr(chopt,"PIE");
4145 if (l) {
4146 Hoption.Pie = 1;
4147 memcpy(l," ",3);
4148 }
4149
4150
4151 l = strstr(chopt,"CANDLE");
4152 if (l) {
4153 TCandle candle;
4154 Hoption.Candle = candle.ParseOption(l);
4155 Hoption.Color = 0;
4156 }
4157
4158 l = strstr(chopt,"VIOLIN");
4159 if (l) {
4160 TCandle candle;
4161 Hoption.Candle = candle.ParseOption(l);
4162 Hoption.Color = 0;
4163 }
4164
4165 l = strstr(chopt,"LEGO");
4166 if (l) {
4167 Hoption.Color = 0;
4168 Hoption.Lego = 1; memcpy(l," ",4);
4169 if (l[4] == '1') { Hoption.Lego = 11; l[4] = ' '; }
4170 if (l[4] == '2') { Hoption.Lego = 12; l[4] = ' '; }
4171 if (l[4] == '3') { Hoption.Lego = 13; l[4] = ' '; }
4172 if (l[4] == '4') { Hoption.Lego = 14; l[4] = ' '; }
4173 if (l[4] == '9') { Hoption.Lego = 19; l[4] = ' '; }
4174 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4175 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4176 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4177 }
4178
4179 l = strstr(chopt,"SURF");
4180 if (l) {
4181 Hoption.Color = 0;
4182 Hoption.Surf = 1; memcpy(l," ",4);
4183 if (l[4] == '1') { Hoption.Surf = 11; l[4] = ' '; }
4184 if (l[4] == '2') { Hoption.Surf = 12; l[4] = ' '; }
4185 if (l[4] == '3') { Hoption.Surf = 13; l[4] = ' '; }
4186 if (l[4] == '4') { Hoption.Surf = 14; l[4] = ' '; }
4187 if (l[4] == '5') { Hoption.Surf = 15; l[4] = ' '; }
4188 if (l[4] == '6') { Hoption.Surf = 16; l[4] = ' '; }
4189 if (l[4] == '7') { Hoption.Surf = 17; l[4] = ' '; }
4190 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4191 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4192 }
4193
4194 l = strstr(chopt,"TF3");
4195 if (l) {
4196 memcpy(l," ",3);
4197 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4198 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4199 }
4200
4201 l = strstr(chopt,"ISO");
4202 if (l) {
4203 memcpy(l," ",3);
4204 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4205 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4206 Hoption.Color = 0;
4207 }
4208
4209 l = strstr(chopt,"LIST"); if (l) { Hoption.List = 1; memcpy(l," ",4);}
4210
4211 l = strstr(chopt,"CONT");
4212 if (l) {
4213 memcpy(l," ",4);
4214 if (hdim>1) {
4215 Hoption.Color = 0;
4216 Hoption.Contour = 1;
4217 if (l[4] == '1') { Hoption.Contour = 11; l[4] = ' '; }
4218 if (l[4] == '2') { Hoption.Contour = 12; l[4] = ' '; }
4219 if (l[4] == '3') { Hoption.Contour = 13; l[4] = ' '; }
4220 if (l[4] == '4') { Hoption.Contour = 14; l[4] = ' '; }
4221 if (l[4] == '5') { Hoption.Contour = 15; l[4] = ' '; }
4222 } else {
4223 Hoption.Hist = 1;
4224 }
4225 }
4226 l = strstr(chopt,"HBAR");
4227 if (l) {
4228 Hoption.Hist = 0;
4229 Hoption.Bar = 20; memcpy(l," ",4);
4230 if (l[4] == '1') { Hoption.Bar = 21; l[4] = ' '; }
4231 if (l[4] == '2') { Hoption.Bar = 22; l[4] = ' '; }
4232 if (l[4] == '3') { Hoption.Bar = 23; l[4] = ' '; }
4233 if (l[4] == '4') { Hoption.Bar = 24; l[4] = ' '; }
4234 }
4235 l = strstr(chopt,"BAR");
4236 if (l) {
4237 Hoption.Hist = 0;
4238 Hoption.Bar = 10; memcpy(l," ",3);
4239 if (l[3] == '1') { Hoption.Bar = 11; l[3] = ' '; }
4240 if (l[3] == '2') { Hoption.Bar = 12; l[3] = ' '; }
4241 if (l[3] == '3') { Hoption.Bar = 13; l[3] = ' '; }
4242 if (l[3] == '4') { Hoption.Bar = 14; l[3] = ' '; }
4243 }
4244
4245 l = strstr(chopt,"ARR" );
4246 if (l) {
4247 memcpy(l," ", 3);
4248 if (hdim>1) {
4249 Hoption.Arrow = 1;
4250 Hoption.Color = 0;
4251 l = strstr(chopt,"COL"); if (l) { Hoption.Arrow = 2; memcpy(l," ",3); }
4252 l = strstr(chopt,"Z"); if (l) { Hoption.Zscale = 1; memcpy(l," ",1); }
4253 } else {
4254 Hoption.Hist = 1;
4255 }
4256 }
4257 l = strstr(chopt,"BOX" );
4258 if (l) {
4259 memcpy(l," ", 3);
4260 if (hdim>1) {
4261 Hoption.Color = 0;
4262 Hoption.Box = 1;
4263 if (l[3] == '1') { Hoption.Box = 11; l[3] = ' '; }
4264 if (l[3] == '2') { Hoption.Box = 12; l[3] = ' '; }
4265 if (l[3] == '3') { Hoption.Box = 13; l[3] = ' '; }
4266 } else {
4267 Hoption.Hist = 1;
4268 }
4269 }
4270 l = strstr(chopt,"TEXT");
4271 if (l) {
4272 Int_t angle;
4273 if (sscanf(&l[4],"%d",&angle) > 0) {
4274 if (angle < 0) angle=0;
4275 if (angle > 90) angle=90;
4276 Hoption.Text = 1000+angle;
4277 } else {
4278 Hoption.Text = 1;
4279 }
4280 memcpy(l," ", 4);
4281 l = strstr(chopt,"N");
4282 if (l && fH->InheritsFrom(TH2Poly::Class())) Hoption.Text += 3000;
4283 Hoption.Color = 0;
4284 }
4285 l = strstr(chopt,"COLZ");
4286 if (l) {
4287 memcpy(l," ",4);
4288 if (hdim > 1) {
4289 explicitColor = kTRUE;
4290 Hoption.Color = 1;
4291 Hoption.Zscale = 1;
4292 if (l[4] == '2') { Hoption.Color = 3; l[4] = ' '; }
4293 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4294 l = strstr(chopt,"1"); if (l) { Hoption.Color = 2; memcpy(l," ",1); }
4295 } else {
4296 Hoption.Hist = 1;
4297 }
4298 }
4299 l = strstr(chopt,"COL" );
4300 if (l) {
4301 memcpy(l," ", 3);
4302 if (hdim > 1) {
4303 explicitColor = kTRUE;
4304 Hoption.Color = 1;
4305 if (l[3] == '2') { Hoption.Color = 3; l[3] = ' '; }
4306 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4307 l = strstr(chopt,"1"); if (l) { Hoption.Color = 2; memcpy(l," ",1); }
4308 } else {
4309 Hoption.Hist = 1;
4310 }
4311 }
4312 l = strstr(chopt,"FUNC"); if (l) { Hoption.Func = 2; memcpy(l," ",4); Hoption.Hist = 0; }
4313 l = strstr(chopt,"HIST"); if (l) { Hoption.Hist = 2; memcpy(l," ",4); Hoption.Func = 0; Hoption.Error = 0;}
4314 l = strstr(chopt,"AXIS"); if (l) { Hoption.Axis = 1; memcpy(l," ",4); }
4315 l = strstr(chopt,"AXIG"); if (l) { Hoption.Axis = 2; memcpy(l," ",4); }
4316 l = strstr(chopt,"SCAT"); if (l) { Hoption.Scat = 1; memcpy(l," ",4); }
4317 l = strstr(chopt,"POL"); if (l) { Hoption.System = kPOLAR; memcpy(l," ",3); }
4318 l = strstr(chopt,"CYL"); if (l) { Hoption.System = kCYLINDRICAL; memcpy(l," ",3); }
4319 l = strstr(chopt,"SPH"); if (l) { Hoption.System = kSPHERICAL; memcpy(l," ",3); }
4320 l = strstr(chopt,"PSR"); if (l) { Hoption.System = kRAPIDITY; memcpy(l," ",3); }
4321
4322 l = strstr(chopt,"TRI");
4323 if (l) {
4324 if (!explicitColor) Hoption.Color = 0;
4325 Hoption.Tri = 1; memcpy(l," ",3);
4326 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4327 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4328 l = strstr(chopt,"ERR"); if (l) memcpy(l," ",3);
4329 }
4330
4331 l = strstr(chopt,"AITOFF");
4332 if (l) {
4333 Hoption.Proj = 1; memcpy(l," ",6); //Aitoff projection
4334 }
4335 l = strstr(chopt,"MERCATOR");
4336 if (l) {
4337 Hoption.Proj = 2; memcpy(l," ",8); //Mercator projection
4338 }
4339 l = strstr(chopt,"SINUSOIDAL");
4340 if (l) {
4341 Hoption.Proj = 3; memcpy(l," ",10); //Sinusoidal projection
4342 }
4343 l = strstr(chopt,"PARABOLIC");
4344 if (l) {
4345 Hoption.Proj = 4; memcpy(l," ",9); //Parabolic projection
4346 }
4347 l = strstr(chopt,"MOLLWEIDE");
4348 if (l) {
4349 Hoption.Proj = 5; memcpy(l," ",9); //Mollweide projection
4350 }
4351 if (Hoption.Proj > 0) {
4352 if (!explicitColor) Hoption.Color = 0;
4353 Hoption.Contour = 14;
4354 }
4355
4356 if (strstr(chopt,"A")) Hoption.Axis = -1;
4357 if (strstr(chopt,"B")) Hoption.Bar = 1;
4358 if (strstr(chopt,"C") && !strstr(chopt,"CJUST")) { Hoption.Curve =1; Hoption.Hist = -1;}
4359 if (strstr(chopt,"F")) Hoption.Fill =1;
4360 if (strstr(chopt,"][")) {Hoption.Off =1; Hoption.Hist =1;}
4361 if (strstr(chopt,"F2")) Hoption.Fill =2;
4362 if (strstr(chopt,"L")) { Hoption.Line =1; Hoption.Hist = -1;}
4363 if (strstr(chopt,"P")) { Hoption.Mark =1; Hoption.Hist = -1;}
4364 if (strstr(chopt,"Z")) Hoption.Zscale =1;
4365 if (strstr(chopt,"*")) Hoption.Star =1;
4366 if (strstr(chopt,"H")) Hoption.Hist =2;
4367 if (strstr(chopt,"P0")) Hoption.Mark =10;
4368
4369 if (fH->InheritsFrom(TH2Poly::Class())) {
4370 if ((Hoption.Fill+Hoption.Line+Hoption.Mark != 0) && !explicitColor) Hoption.Color = 0;
4371 }
4372
4373 if (strstr(chopt,"E")) {
4374 if (hdim == 1) {
4375 Hoption.Error = 1;
4376 if (strstr(chopt,"E1")) Hoption.Error = 11;
4377 if (strstr(chopt,"E2")) Hoption.Error = 12;
4378 if (strstr(chopt,"E3")) Hoption.Error = 13;
4379 if (strstr(chopt,"E4")) Hoption.Error = 14;
4380 if (strstr(chopt,"E5")) Hoption.Error = 15;
4381 if (strstr(chopt,"E6")) Hoption.Error = 16;
4382 if (strstr(chopt,"E0")) Hoption.Error += 40;
4383 if (strstr(chopt,"X0")) {
4384 if (Hoption.Error == 1) Hoption.Error += 20;
4385 Hoption.Error += 10;
4386 }
4388 Hoption.Text += 2000;
4389 Hoption.Error = 0;
4390 }
4391 } else {
4392 if (Hoption.Error == 0) {
4393 Hoption.Error = 100;
4394 if (!explicitColor) Hoption.Color = 0;
4395 }
4396 if (Hoption.Text) {
4397 Hoption.Text += 2000;
4398 Hoption.Error = 0;
4399 }
4400 }
4401 }
4402
4403 if (Hoption.Surf == 15) {
4405 Hoption.Surf = 13;
4406 Warning("MakeChopt","option SURF5 is not supported in Cartesian and Polar modes");
4407 }
4408 }
4409
4410 // Copy options from current style
4411 Hoption.Logx = gPad->GetLogx();
4412 Hoption.Logy = gPad->GetLogy();
4413 Hoption.Logz = gPad->GetLogz();
4414
4415 // Check options incompatibilities
4416 if (Hoption.Bar == 1) Hoption.Hist = -1;
4417 return 1;
4418}
4419
4420////////////////////////////////////////////////////////////////////////////////
4421/// Decode string `choptin` and fill Graphical cuts structure.
4422
4424{
4425
4426 fNcuts = 0;
4427 char *left = (char*)strchr(choptin,'[');
4428 if (!left) return 0;
4429 char *right = (char*)strchr(choptin,']');
4430 if (!right) return 0;
4431 Int_t nch = right-left;
4432 if (nch < 2) return 0;
4433 char *cuts = left+1;
4434 *right = 0;
4435 char *comma, *minus;
4436 Int_t i;
4437 while (true) {
4438 comma = strchr(cuts,',');
4439 if (comma) *comma = 0;
4440 minus = strchr(cuts,'-');
4441 if (minus) cuts = minus+1;
4442 while (*cuts == ' ') cuts++;
4443 Int_t nc = strlen(cuts);
4444 while (cuts[nc-1] == ' ') {cuts[nc-1] = 0; nc--;}
4445 TIter next(gROOT->GetListOfSpecials());
4446 TCutG *cut=nullptr;
4447 TObject *obj;
4448 while ((obj = next())) {
4449 if (!obj->InheritsFrom(TCutG::Class())) continue;
4450 if (strcmp(obj->GetName(),cuts)) continue;
4451 cut = (TCutG*)obj;
4452 break;
4453 }
4454 if (cut) {
4455 fCuts[fNcuts] = cut;
4456 fCutsOpt[fNcuts] = 1;
4457 if (minus) fCutsOpt[fNcuts] = -1;
4458 fNcuts++;
4459 }
4460 if (!comma) break;
4461 cuts = comma+1;
4462 }
4463 for (i=0;i<=nch;i++) left[i] = ' ';
4464 return fNcuts;
4465}
4466
4467////////////////////////////////////////////////////////////////////////////////
4468/// [Control routine to paint any kind of histograms](\ref HP00)
4469
4471{
4472
4473 if (fH->GetBuffer()) fH->BufferEmpty(-1);
4474
4475 //For iOS: put the histogram on the top of stack of pickable objects.
4476 const TPickerStackGuard topPush(fH);
4477
4478 gPad->SetVertical(kTRUE);
4479
4480 TH1 *oldhist = gCurrentHist;
4481 gCurrentHist = fH;
4482 TH1 *hsave = fH;
4483 Double_t minsav = fH->GetMinimumStored();
4484
4485 if (!MakeChopt(option)) return; //check options and fill Hoption structure
4486
4487 // Paint using TSpectrum2Painter
4488 if (Hoption.Spec) {
4489 if (!TableInit()) return;
4490 if (!TClass::GetClass("TSpectrum2Painter")) gSystem->Load("libSpectrumPainter");
4491 gROOT->ProcessLineFast(TString::Format("TSpectrum2Painter::PaintSpectrum((TH2F*)0x%zx,\"%s\",%d)",
4492 (size_t)fH, option, Hoption.Spec).Data());
4493 return;
4494 }
4495
4496 // Deflate the labels in case of alphanumeric labels
4500
4501 if (Hoption.Pie) {
4502 if (fH->GetDimension() == 1) {
4503 if (!fPie)
4504 fPie = std::make_unique<TPie>(fH);
4505 fPie->Paint(option);
4506 } else {
4507 Error("Paint", "Option PIE is for 1D histograms only");
4508 }
4509 return;
4510 } else {
4511 fPie.reset();
4512 }
4513
4514 fXbuf.resize(kNMAX);
4515 fYbuf.resize(kNMAX);
4516 if (fH->GetDimension() > 2) {
4517 PaintH3(option);
4518 fH->SetMinimum(minsav);
4519 if (Hoption.Func) {
4520 Hoption_t hoptsave = Hoption;
4521 Hparam_t hparsave = Hparam;
4523 SetHistogram(hsave);
4524 Hoption = hoptsave;
4525 Hparam = hparsave;
4526 }
4527 gCurrentHist = oldhist;
4528 fXbuf.clear();
4529 fYbuf.clear();
4530 return;
4531 }
4532 TView *view = gPad->GetView();
4533 if (view) {
4534 if (!Hoption.Lego && !Hoption.Surf && !Hoption.Tri) {
4535 delete view;
4536 gPad->SetView(nullptr);
4537 }
4538 }
4539 if (fH->GetDimension() > 1 || Hoption.Lego || Hoption.Surf) {
4540 // In case of 1D histogram, Z axis becomes Y axis.
4541 Int_t logysav=0, logzsav=0;
4542 if (fH->GetDimension() == 1) {
4543 logysav = Hoption.Logy;
4544 logzsav = Hoption.Logz;
4545 Hoption.Logz = 0;
4546 if (Hoption.Logy) {
4547 Hoption.Logz = 1;
4548 Hoption.Logy = 0;
4549 }
4550 }
4552 if (Hoption.Func) {
4553 Hoption_t hoptsave = Hoption;
4554 Hparam_t hparsave = Hparam;
4556 SetHistogram(hsave);
4557 Hoption = hoptsave;
4558 Hparam = hparsave;
4559 }
4560 fH->SetMinimum(minsav);
4561 gCurrentHist = oldhist;
4562 fXbuf.clear();
4563 fYbuf.clear();
4564 if (fH->GetDimension() == 1) {
4565 Hoption.Logy = logysav;
4566 Hoption.Logz = logzsav;
4567 }
4568 return;
4569 }
4570
4571 if (Hoption.Bar >= 20) {
4573 fXbuf.clear();
4574 fYbuf.clear();
4575 return;
4576 }
4577
4578 gPad->RangeAxisChanged(); //emit RangeAxisChanged() signal to sync axes
4579 // fill Hparam structure with histo parameters
4580 if (!PaintInit()) {
4581 fXbuf.clear();
4582 fYbuf.clear();
4583 return;
4584 }
4585
4586 // Picture surround (if new page) and page number (if requested).
4587 // Histogram surround (if not option "Same").
4588 PaintFrame();
4589
4590 // Paint histogram axis only
4591 Bool_t gridx = gPad->GetGridx();
4592 Bool_t gridy = gPad->GetGridy();
4593 if (Hoption.Axis > 0) {
4594 if (Hoption.Axis > 1) PaintAxis(kTRUE); //axis with grid
4595 else {
4596 if (gridx) gPad->SetGridx(0);
4597 if (gridy) gPad->SetGridy(0);
4599 if (gridx) gPad->SetGridx(1);
4600 if (gridy) gPad->SetGridy(1);
4601 }
4602 if ((Hoption.Same%10) ==1) Hoption.Same += 1;
4603 goto paintstat;
4604 }
4605 if (gridx || gridy) PaintAxis(kTRUE); // Draw the grid only
4606
4607 // test for options BAR or HBAR
4608 if (Hoption.Bar >= 10) {
4610 }
4611
4612 // do not draw histogram if error bars required
4613 if (!Hoption.Error) {
4614 if (Hoption.Hist && Hoption.Bar<10) PaintHist(option);
4615 }
4616
4617 // test for error bars or option E
4618 if (Hoption.Error) {
4620 if (Hoption.Hist == 2) PaintHist(option);
4621 }
4622
4624
4625 // test for associated function
4626 if (Hoption.Func) {
4627 Hoption_t hoptsave = Hoption;
4628 Hparam_t hparsave = Hparam;
4630 SetHistogram(hsave);
4631 Hoption = hoptsave;
4632 Hparam = hparsave;
4633 }
4634
4635 if (gridx) gPad->SetGridx(0);
4636 if (gridy) gPad->SetGridy(0);
4638 if (gridx) gPad->SetGridx(1);
4639 if (gridy) gPad->SetGridy(1);
4640
4641 PaintTitle(); // Draw histogram title
4642
4643 // Draw box with histogram statistics and/or fit parameters
4644paintstat:
4645 if ((Hoption.Same%10) != 1 && !fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
4646 TIter next(fFunctions);
4647 TObject *obj = nullptr;
4648 while ((obj = next())) {
4649 if (obj->InheritsFrom(TF1::Class())) break;
4650 obj = nullptr;
4651 }
4652
4653 //Stat is painted twice (first, it will be in canvas' list of primitives),
4654 //second, it will be here, this is not required on iOS.
4655 //Condition is ALWAYS true on a platform different from iOS.
4656 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode())
4657 PaintStat(gStyle->GetOptStat(),(TF1*)obj);
4658 }
4659 fH->SetMinimum(minsav);
4660 gCurrentHist = oldhist;
4661 fXbuf.clear();
4662 fYbuf.clear();
4663}
4664
4665////////////////////////////////////////////////////////////////////////////////
4666/// [Control function to draw a table as an arrow plot](\ref HP12)
4667
4669{
4670 Double_t xk, xstep, yk, ystep;
4671 Double_t dx, dy, x1, x2, y1, y2, xc, yc, dxn, dyn;
4674 Double_t xrg = gPad->GetUxmin();
4675 Double_t yrg = gPad->GetUymin();
4676 Double_t xln = gPad->GetUxmax() - xrg;
4677 Double_t yln = gPad->GetUymax() - yrg;
4678 Double_t cx = (xln/Double_t(ncx))/2.;
4679 Double_t cy = (yln/Double_t(ncy))/2.;
4680 Double_t dn = 1.E-30;
4681
4682 auto arrow = new TArrow();
4683 arrow->SetAngle(30);
4684 arrow->SetFillStyle(1001);
4685 arrow->SetFillColor(fH->GetLineColor());
4686 arrow->SetLineColor(fH->GetLineColor());
4687 arrow->SetLineWidth(fH->GetLineWidth());
4688
4689 // Initialize the levels on the Z axis
4690 Int_t ncolors=0, ndivz=0;
4691 Double_t scale=0.;
4692 if (Hoption.Arrow>1) {
4693 ncolors = gStyle->GetNumberOfColors();
4694 Int_t ndiv = fH->GetContour();
4695 if (ndiv == 0 ) {
4696 ndiv = gStyle->GetNumberContours();
4697 fH->SetContour(ndiv);
4698 }
4699 ndivz = TMath::Abs(ndiv);
4700 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
4701 scale = ndivz/(fH->GetMaximum()-fH->GetMinimum());
4702 }
4703
4704 for (Int_t id=1;id<=2;id++) {
4705 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
4706 yk = fYaxis->GetBinLowEdge(j);
4707 ystep = fYaxis->GetBinWidth(j);
4708 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
4709 xk = fXaxis->GetBinLowEdge(i);
4710 xstep = fXaxis->GetBinWidth(i);
4711 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
4712 if (i == Hparam.xfirst) {
4713 dx = fH->GetBinContent(i+1, j) - fH->GetBinContent(i, j);
4714 } else if (i == Hparam.xlast) {
4715 dx = fH->GetBinContent(i, j) - fH->GetBinContent(i-1, j);
4716 } else {
4717 dx = 0.5*(fH->GetBinContent(i+1, j) - fH->GetBinContent(i-1, j));
4718 }
4719 if (j == Hparam.yfirst) {
4720 dy = fH->GetBinContent(i, j+1) - fH->GetBinContent(i, j);
4721 } else if (j == Hparam.ylast) {
4722 dy = fH->GetBinContent(i, j) - fH->GetBinContent(i, j-1);
4723 } else {
4724 dy = 0.5*(fH->GetBinContent(i, j+1) - fH->GetBinContent(i, j-1));
4725 }
4726 if (id == 1) {
4727 dn = TMath::Max(dn, TMath::Abs(dx));
4728 dn = TMath::Max(dn, TMath::Abs(dy));
4729 } else if (id == 2) {
4730 xc = xrg + xln*(Double_t(i - Hparam.xfirst+1)-0.5)/Double_t(ncx);
4731 dxn = cx*dx/dn;
4732 x1 = xc - dxn;
4733 x2 = xc + dxn;
4734 yc = yrg + yln*(Double_t(j - Hparam.yfirst+1)-0.5)/Double_t(ncy);
4735 dyn = cy*dy/dn;
4736 y1 = yc - dyn;
4737 y2 = yc + dyn;
4738 if (Hoption.Arrow>1) {
4739 int color = Int_t(0.01+(fH->GetBinContent(i, j)-fH->GetMinimum())*scale);
4740 Int_t theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
4741 if (theColor > ncolors-1) theColor = ncolors-1;
4742 arrow->SetFillColor(gStyle->GetColorPalette(theColor));
4743 arrow->SetLineColor(gStyle->GetColorPalette(theColor));
4744 }
4745 if (TMath::Abs(x2-x1) > 0. || TMath::Abs(y2-y1) > 0.) {
4746 arrow->PaintArrow(x1, y1, x2, y2, 0.015, "|>");
4747 } else {
4748 arrow->PaintArrow(x1, y1, x2, y2, 0.005, "|>");
4749 }
4750 }
4751 }
4752 }
4753 }
4754
4756}
4757
4758////////////////////////////////////////////////////////////////////////////////
4759/// Draw axis (2D case) of an histogram.
4760///
4761/// If `drawGridOnly` is `TRUE`, only the grid is painted (if needed). This allows
4762/// to draw the grid and the axis separately. In `THistPainter::Paint` this
4763/// feature is used to make sure that the grid is drawn in the background and
4764/// the axis tick marks in the foreground of the pad.
4765
4767{
4768
4769 //On iOS, grid should not be pickable and can not be highlighted.
4770 //Condition is never true on a platform different from iOS.
4771 if (drawGridOnly && (gPad->PadInHighlightMode() || gPad->PadInSelectionMode()))
4772 return;
4773
4774 if (Hoption.Axis == -1) return;
4775 if (Hoption.Same && Hoption.Axis <= 0) return;
4776
4777 // Repainting alphanumeric labels axis on a plot done with
4778 // the option HBAR (horizontal) needs some adjustments.
4779 TAxis *xaxis = nullptr;
4780 TAxis *yaxis = nullptr;
4781 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4782 if (fXaxis->GetLabels() || fYaxis->GetLabels()) { // One axis has alphanumeric labels
4783 TIter next(gPad->GetListOfPrimitives());
4784 TObject *obj;
4785 // Check if the first TH1 of THStack in the pad is drawn with the option HBAR
4786 while ((obj = next())) {
4787 if (!obj->InheritsFrom(TH1::Class()) &&
4788 !obj->InheritsFrom(THStack::Class())) continue;
4789 TString opt = obj->GetDrawOption();
4790 opt.ToLower();
4791 // if drawn with HBAR, the axis should be inverted and the pad set to horizontal
4792 if (strstr(opt,"hbar")) {
4793 gPad->SetVertical(kFALSE);
4794 xaxis = fXaxis;
4795 yaxis = fYaxis;
4796 if (!strcmp(xaxis->GetName(),"xaxis")) {
4797 fXaxis = yaxis;
4798 fYaxis = xaxis;
4799 }
4800 }
4801 break;
4802 }
4803 }
4804 }
4805
4806 static char chopt[10] = "";
4807 Double_t gridl = 0;
4808 Int_t ndiv, ndivx, ndivy, nx1, nx2, ndivsave;
4809 Int_t useHparam = 0;
4810 Double_t umin, umax, uminsave, umaxsave;
4811 Short_t xAxisPos = Hoption.AxisPos/10;
4812 Short_t yAxisPos = Hoption.AxisPos - 10*xAxisPos;
4813
4814 Double_t axmin = gPad->GetUxmin();
4815 Double_t axmax = gPad->GetUxmax();
4816 Double_t aymin = gPad->GetUymin();
4817 Double_t aymax = gPad->GetUymax();
4818 char *cw = nullptr;
4819 TGaxis axis;
4820
4821 // In case of option 'cont4' or in case of option 'same' over a 'cont4 plot'
4822 // Hparam must be use for the axis limits.
4823 if (Hoption.Contour == 14) useHparam = 1;
4824 if (Hoption.Same) {
4825 TObject *obj;
4826 TIter next(gPad->GetListOfPrimitives());
4827 while ((obj=next())) {
4828 if (strstr(obj->GetDrawOption(),"cont4")) {
4829 useHparam = 1;
4830 break;
4831 }
4832 }
4833 }
4834
4835 // Paint X axis
4836
4837 //To make X-axis selectable on iOS device.
4838 if (gPad->PadInSelectionMode())
4839 gPad->PushSelectableObject(fXaxis);
4840
4841 //This condition is ALWAYS true, unless it works on iOS (can be false on iOS).
4842 if (gPad->PadInSelectionMode() || !gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && gPad->GetSelected() == fXaxis)) {
4843 ndivx = fXaxis->GetNdivisions();
4844 if (ndivx > 1000) {
4845 nx2 = ndivx/100;
4846 nx1 = TMath::Max(1, ndivx%100);
4847 ndivx = 100*nx2 + Int_t(Float_t(nx1)*gPad->GetAbsWNDC());
4848 }
4849 axis.SetTextAngle(0);
4851
4852 chopt[0] = 0;
4853 strlcat(chopt, "SDH",10);
4854 if (ndivx < 0) strlcat(chopt, "N",10);
4855 if (gPad->GetGridx()) {
4856 gridl = (aymax-aymin)/(gPad->GetY2() - gPad->GetY1());
4857 strlcat(chopt, "W",10);
4858 }
4859
4860 // Define X-Axis limits
4861 if (Hoption.Logx) {
4862 strlcat(chopt, "G",10);
4863 ndiv = TMath::Abs(ndivx);
4864 if (useHparam) {
4865 umin = TMath::Power(10,Hparam.xmin);
4866 umax = TMath::Power(10,Hparam.xmax);
4867 } else {
4868 umin = TMath::Power(10,axmin);
4869 umax = TMath::Power(10,axmax);
4870 }
4871 } else {
4872 ndiv = TMath::Abs(ndivx);
4873 if (useHparam) {
4874 umin = Hparam.xmin;
4875 umax = Hparam.xmax;
4876 } else {
4877 umin = axmin;
4878 umax = axmax;
4879 }
4880 }
4881
4882 // Display axis as time
4883 if (fXaxis->GetTimeDisplay()) {
4884 strlcat(chopt,"t",10);
4885 if (strlen(fXaxis->GetTimeFormatOnly()) == 0) {
4887 }
4888 }
4889
4890 // The main X axis can be on the bottom or on the top of the pad
4891 Double_t xAxisYPos1, xAxisYPos2;
4892 if (xAxisPos == 1) {
4893 // Main X axis top
4894 xAxisYPos1 = aymax;
4895 xAxisYPos2 = aymin;
4896 } else {
4897 // Main X axis bottom
4898 xAxisYPos1 = aymin;
4899 xAxisYPos2 = aymax;
4900 }
4901
4902 // Paint the main X axis (always)
4903 uminsave = umin;
4904 umaxsave = umax;
4905 ndivsave = ndiv;
4906 axis.SetOption(chopt);
4907 if (xAxisPos) {
4908 strlcat(chopt, "-",10);
4909 gridl = -gridl;
4910 }
4911 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4912 axis.SetLabelSize(0.);
4913 axis.SetTitle("");
4914 }
4915 axis.PaintAxis(axmin, xAxisYPos1,
4916 axmax, xAxisYPos1,
4917 umin, umax, ndiv, chopt, gridl, drawGridOnly);
4918
4919 // Paint additional X axis (if needed)
4920 // On iOS, this additional X axis is neither pickable, nor highlighted.
4921 // Additional checks PadInSelectionMode etc. does not effect non-iOS platform.
4922 if (gPad->GetTickx() && !gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
4923 if (xAxisPos) {
4924 cw=strstr(chopt,"-");
4925 *cw='z';
4926 } else {
4927 strlcat(chopt, "-",10);
4928 }
4929 if (gPad->GetTickx() < 2) strlcat(chopt, "U",10);
4930 if ((cw=strstr(chopt,"W"))) *cw='z';
4931 axis.SetTitle("");
4932 axis.PaintAxis(axmin, xAxisYPos2,
4933 axmax, xAxisYPos2,
4934 uminsave, umaxsave, ndivsave, chopt, gridl, drawGridOnly);
4935 }
4936 }//End of "if pad in selection mode etc".
4937
4938 // Paint Y axis
4939 //On iOS, Y axis must pushed into the stack of selectable objects.
4940 if (gPad->PadInSelectionMode())
4941 gPad->PushSelectableObject(fYaxis);
4942
4943 //This conditions is ALWAYS true on a platform, different from iOS (on iOS can be true, can be false).
4944 if (gPad->PadInSelectionMode() || !gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && gPad->GetSelected() == fYaxis)) {
4945 ndivy = fYaxis->GetNdivisions();
4947
4948 chopt[0] = 0;
4949 strlcat(chopt, "SDH",10);
4950 if (ndivy < 0) strlcat(chopt, "N",10);
4951 if (gPad->GetGridy()) {
4952 gridl = (axmax-axmin)/(gPad->GetX2() - gPad->GetX1());
4953 strlcat(chopt, "W",10);
4954 }
4955
4956 // Define Y-Axis limits
4957 if (Hoption.Logy) {
4958 strlcat(chopt, "G",10);
4959 ndiv = TMath::Abs(ndivy);
4960 if (useHparam) {
4961 umin = TMath::Power(10,Hparam.ymin);
4962 umax = TMath::Power(10,Hparam.ymax);
4963 } else {
4964 umin = TMath::Power(10,aymin);
4965 umax = TMath::Power(10,aymax);
4966 }
4967 } else {
4968 ndiv = TMath::Abs(ndivy);
4969 if (useHparam) {
4970 umin = Hparam.ymin;
4971 umax = Hparam.ymax;
4972 } else {
4973 umin = aymin;
4974 umax = aymax;
4975 }
4976 }
4977
4978 // Display axis as time
4979 if (fYaxis->GetTimeDisplay()) {
4980 strlcat(chopt,"t",10);
4981 if (strlen(fYaxis->GetTimeFormatOnly()) == 0) {
4983 }
4984 }
4985
4986 // The main Y axis can be on the left or on the right of the pad
4987 Double_t yAxisXPos1, yAxisXPos2;
4988 if (yAxisPos == 1) {
4989 // Main Y axis left
4990 yAxisXPos1 = axmax;
4991 yAxisXPos2 = axmin;
4992 } else {
4993 // Main Y axis right
4994 yAxisXPos1 = axmin;
4995 yAxisXPos2 = axmax;
4996 }
4997
4998 // Paint the main Y axis (always)
4999 uminsave = umin;
5000 umaxsave = umax;
5001 ndivsave = ndiv;
5002 axis.SetOption(chopt);
5003 if (yAxisPos) {
5004 strlcat(chopt, "+L",10);
5005 gridl = -gridl;
5006 }
5007 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
5008 axis.SetLabelSize(0.);
5009 axis.SetTitle("");
5010 }
5011 axis.PaintAxis(yAxisXPos1, aymin,
5012 yAxisXPos1, aymax,
5013 umin, umax, ndiv, chopt, gridl, drawGridOnly);
5014
5015 // Paint the additional Y axis (if needed)
5016 // Additional checks for pad mode are required on iOS: this "second" axis is
5017 // neither pickable, nor highlighted. Additional checks have no effect on non-iOS platform.
5018 if (gPad->GetTicky() && !gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
5019 if (gPad->GetTicky() < 2) {
5020 strlcat(chopt, "U",10);
5022 } else {
5023 strlcat(chopt, "+L",10);
5024 }
5025 if ((cw=strstr(chopt,"W"))) *cw='z';
5026 axis.SetTitle("");
5027 axis.PaintAxis(yAxisXPos2, aymin,
5028 yAxisXPos2, aymax,
5029 uminsave, umaxsave, ndivsave, chopt, gridl, drawGridOnly);
5030 }
5031 }//End of "if pad is in selection mode etc."
5032
5033 // Reset the axis if they have been inverted in case of option HBAR
5034 if (xaxis) {
5035 fXaxis = xaxis;
5036 fYaxis = yaxis;
5037 }
5038}
5039
5040////////////////////////////////////////////////////////////////////////////////
5041/// [Draw a bar-chart in a normal pad.](\ref HP10)
5042
5044{
5045
5046 Int_t bar = Hoption.Bar - 10;
5047 Double_t xmin,xmax,ymin,ymax,umin,umax,w,y;
5050 TBox box;
5051 Int_t hcolor = fH->GetFillColor();
5052 if (hcolor == gPad->GetFrameFillColor()) ++hcolor;
5053 Int_t hstyle = fH->GetFillStyle();
5054 box.SetFillColor(hcolor);
5055 box.SetFillStyle(hstyle);
5056 box.SetLineStyle(fH->GetLineStyle());
5057 box.SetLineColor(fH->GetLineColor());
5058 box.SetLineWidth(fH->GetLineWidth());
5059 for (Int_t bin=fXaxis->GetFirst();bin<=fXaxis->GetLast();bin++) {
5060 y = fH->GetBinContent(bin);
5061 xmin = gPad->XtoPad(fXaxis->GetBinLowEdge(bin));
5062 xmax = gPad->XtoPad(fXaxis->GetBinUpEdge(bin));
5063 ymin = gPad->GetUymin();
5064 ymax = gPad->YtoPad(y);
5065 if (ymax < gPad->GetUymin()) continue;
5066 if (ymax > gPad->GetUymax()) ymax = gPad->GetUymax();
5067 if (ymin < gPad->GetUymin()) ymin = gPad->GetUymin();
5068 if (Hoption.MinimumZero && ymin < 0)
5069 ymin=TMath::Min(0.,gPad->GetUymax());
5070 w = (xmax-xmin)*width;
5071 xmin += offset*(xmax-xmin);
5072 xmax = xmin + w;
5073 if (bar < 1) {
5074 box.PaintBox(xmin,ymin,xmax,ymax);
5075 } else {
5076 umin = xmin + bar*(xmax-xmin)/10.;
5077 umax = xmax - bar*(xmax-xmin)/10.;
5078 box.SetFillColor(TColor::GetColorBright(hcolor)); //bright
5079 box.PaintBox(xmin,ymin,umin,ymax);
5080 box.SetFillColor(hcolor);
5081 box.PaintBox(umin,ymin,umax,ymax);
5082 box.SetFillColor(TColor::GetColorDark(hcolor)); //dark
5083 box.PaintBox(umax,ymin,xmax,ymax);
5084 }
5085 }
5086}
5087
5088////////////////////////////////////////////////////////////////////////////////
5089/// [Draw a bar char in a rotated pad (X vertical, Y horizontal)](\ref HP10)
5090
5092{
5093
5094 gPad->SetVertical(kFALSE);
5095
5096 PaintInitH();
5097
5098 TAxis *xaxis = fXaxis;
5099 TAxis *yaxis = fYaxis;
5100 if (!strcmp(xaxis->GetName(),"xaxis")) {
5101 fXaxis = yaxis;
5102 fYaxis = xaxis;
5103 }
5104
5105 PaintFrame();
5107
5108 Int_t bar = Hoption.Bar - 20;
5109 Double_t xmin,xmax,ymin,ymax,umin,umax,w;
5112 TBox box;
5113 Int_t hcolor = fH->GetFillColor();
5114 if (hcolor == gPad->GetFrameFillColor()) ++hcolor;
5115 Int_t hstyle = fH->GetFillStyle();
5116 box.SetFillColor(hcolor);
5117 box.SetFillStyle(hstyle);
5118 box.SetLineStyle(fH->GetLineStyle());
5119 box.SetLineColor(fH->GetLineColor());
5120 box.SetLineWidth(fH->GetLineWidth());
5121 for (Int_t bin=fYaxis->GetFirst();bin<=fYaxis->GetLast();bin++) {
5122 ymin = gPad->YtoPad(fYaxis->GetBinLowEdge(bin));
5123 ymax = gPad->YtoPad(fYaxis->GetBinUpEdge(bin));
5124 xmin = gPad->GetUxmin();
5125 xmax = gPad->XtoPad(fH->GetBinContent(bin));
5126 if (xmax < gPad->GetUxmin()) continue;
5127 if (xmax > gPad->GetUxmax()) xmax = gPad->GetUxmax();
5128 if (xmin < gPad->GetUxmin()) xmin = gPad->GetUxmin();
5129 if (Hoption.MinimumZero && xmin < 0)
5130 xmin=TMath::Min(0.,gPad->GetUxmax());
5131 w = (ymax-ymin)*width;
5132 ymin += offset*(ymax-ymin);
5133 ymax = ymin + w;
5134 if (bar < 1) {
5135 box.PaintBox(xmin,ymin,xmax,ymax);
5136 } else {
5137 umin = ymin + bar*(ymax-ymin)/10.;
5138 umax = ymax - bar*(ymax-ymin)/10.;
5139 box.SetFillColor(TColor::GetColorDark(hcolor)); //dark
5140 box.PaintBox(xmin,ymin,xmax,umin);
5141 box.SetFillColor(hcolor);
5142 box.PaintBox(xmin,umin,xmax,umax);
5143 box.SetFillColor(TColor::GetColorBright(hcolor)); //bright
5144 box.PaintBox(xmin,umax,xmax,ymax);
5145 }
5146 }
5147
5148 PaintTitle();
5149
5150 // Draw box with histogram statistics and/or fit parameters
5151 if ((Hoption.Same%10) != 1 && !fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
5152 TIter next(fFunctions);
5153 TObject *obj = nullptr;
5154 while ((obj = next())) {
5155 if (obj->InheritsFrom(TF1::Class())) break;
5156 obj = nullptr;
5157 }
5158 PaintStat(gStyle->GetOptStat(),(TF1*)obj);
5159 }
5160
5161 fXaxis = xaxis;
5162 fYaxis = yaxis;
5163}
5164
5165////////////////////////////////////////////////////////////////////////////////
5166/// [Control function to draw a 2D histogram as a box plot](\ref HP13)
5167
5169{
5170
5171 Style_t fillsav = fH->GetFillStyle();
5172 Style_t colsav = fH->GetFillColor();
5173 if (fH->GetFillColor() == 0) fH->SetFillStyle(0);
5174 if (Hoption.Box == 11) fH->SetFillStyle(1001);
5175 fH->TAttLine::Modify();
5176 fH->TAttFill::Modify();
5177
5178 Double_t z, xk,xstep, yk, ystep, xcent, ycent, xlow, xup, ylow, yup;
5179 Double_t ux1 = gPad->PixeltoX(1);
5180 Double_t ux0 = gPad->PixeltoX(0);
5181 Double_t uy1 = gPad->PixeltoY(1);
5182 Double_t uy0 = gPad->PixeltoY(0);
5183 Double_t dxmin = 0.51*(gPad->PadtoX(ux1)-gPad->PadtoX(ux0));
5184 Double_t dymin = 0.51*(gPad->PadtoY(uy0)-gPad->PadtoY(uy1));
5185
5186 Double_t zmin = TMath::Max(fH->GetMinimum(),0.);
5189 Double_t zminlin = zmin, zmaxlin = zmax;
5190
5191 // In case of option SAME, zmin and zmax values are taken from the
5192 // first plotted 2D histogram.
5193 if (Hoption.Same > 0 && Hoption.Same < 10) {
5194 TH2 *h2;
5195 TIter next(gPad->GetListOfPrimitives());
5196 while ((h2 = (TH2 *)next())) {
5197 if (!h2->InheritsFrom(TH2::Class())) continue;
5198 zmin = TMath::Max(h2->GetMinimum(), 0.);
5199 zmax = TMath::Max(TMath::Abs(h2->GetMaximum()),
5200 TMath::Abs(h2->GetMinimum()));
5201 zminlin = zmin;
5202 zmaxlin = zmax;
5203 if (Hoption.Logz) {
5204 if (zmin <= 0) {
5205 zmin = TMath::Log10(zmax*0.001);
5206 } else {
5207 zmin = TMath::Log10(zmin);
5208 }
5209 zmax = TMath::Log10(zmax);
5210 }
5211 break;
5212 }
5213 } else {
5214 if (Hoption.Logz) {
5215 if (zmin > 0) {
5216 zmin = TMath::Log10(zmin);
5217 zmax = TMath::Log10(zmax);
5218 } else {
5219 return;
5220 }
5221 }
5222 }
5223
5224 Double_t zratio, dz = zmax - zmin;
5225 Bool_t kZminNeg = kFALSE;
5226 if (fH->GetMinimum()<0) kZminNeg = kTRUE;
5227 Bool_t kZNeg = kFALSE;
5228
5229 // Define the dark and light colors the "button style" boxes.
5230 Color_t color = fH->GetFillColor();
5231 Color_t light=0, dark=0;
5232 if (Hoption.Box == 11) {
5233 light = TColor::GetColorBright(color);
5234 dark = TColor::GetColorDark(color);
5235 }
5236
5237 // Loop over all the bins and draw the boxes
5238 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
5239 yk = fYaxis->GetBinLowEdge(j);
5240 ystep = fYaxis->GetBinWidth(j);
5241 ycent = 0.5*ystep;
5242 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
5243 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
5244 xk = fXaxis->GetBinLowEdge(i);
5245 xstep = fXaxis->GetBinWidth(i);
5246 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
5247 xcent = 0.5*xstep;
5248 z = Hparam.factor*fH->GetBinContent(bin);
5249 kZNeg = kFALSE;
5250
5251 if (TMath::Abs(z) < zminlin) continue; // Can be the case with ...
5252 if (TMath::Abs(z) > zmaxlin) z = zmaxlin; // ... option Same
5253 if (kZminNeg && z==0) continue; // Do not draw empty bins if case of histo with negative bins.
5254
5255 if (z < 0) {
5256 if (Hoption.Logz) continue;
5257 z = -z;
5258 kZNeg = kTRUE;
5259 }
5260 if (Hoption.Logz) {
5261 if (z != 0) z = TMath::Log10(z);
5262 else z = zmin;
5263 }
5264
5265 if (dz == 0) continue;
5266 zratio = TMath::Sqrt((z-zmin)/dz);
5267 if (zratio == 0) continue;
5268
5269 xup = xcent*zratio + xk + xcent;
5270 xlow = 2*(xk + xcent) - xup;
5271 if (xup-xlow < dxmin) xup = xlow+dxmin;
5272 if (Hoption.Logx) {
5273 if (xup > 0) xup = TMath::Log10(xup);
5274 else continue;
5275 if (xlow > 0) xlow = TMath::Log10(xlow);
5276 else continue;
5277 }
5278
5279 yup = ycent*zratio + yk + ycent;
5280 ylow = 2*(yk + ycent) - yup;
5281 if (yup-ylow < dymin) yup = ylow+dymin;
5282 if (Hoption.Logy) {
5283 if (yup > 0) yup = TMath::Log10(yup);
5284 else continue;
5285 if (ylow > 0) ylow = TMath::Log10(ylow);
5286 else continue;
5287 }
5288
5289 xlow = TMath::Max(xlow, gPad->GetUxmin());
5290 ylow = TMath::Max(ylow, gPad->GetUymin());
5291 xup = TMath::Min(xup , gPad->GetUxmax());
5292 yup = TMath::Min(yup , gPad->GetUymax());
5293
5294 if (xlow >= xup) continue;
5295 if (ylow >= yup) continue;
5296
5297 if (Hoption.Box == 1) {
5298 fH->SetFillColor(color);
5299 fH->TAttFill::Modify();
5300 gPad->PaintBox(xlow, ylow, xup, yup);
5301 if (kZNeg) {
5302 gPad->PaintLine(xlow, ylow, xup, yup);
5303 gPad->PaintLine(xlow, yup, xup, ylow);
5304 }
5305 } else if (Hoption.Box == 11) {
5306 // Draw the center of the box
5307 fH->SetFillColor(color);
5308 fH->TAttFill::Modify();
5309 gPad->PaintBox(xlow, ylow, xup, yup);
5310
5311 // Draw top&left part of the box
5312 Double_t x[7], y[7];
5313 Double_t bwidth = 0.1;
5314 x[0] = xlow; y[0] = ylow;
5315 x[1] = xlow + bwidth*(xup-xlow); y[1] = ylow + bwidth*(yup-ylow);
5316 x[2] = x[1]; y[2] = yup - bwidth*(yup-ylow);
5317 x[3] = xup - bwidth*(xup-xlow); y[3] = y[2];
5318 x[4] = xup; y[4] = yup;
5319 x[5] = xlow; y[5] = yup;
5320 x[6] = xlow; y[6] = ylow;
5321 if (kZNeg) fH->SetFillColor(dark);
5322 else fH->SetFillColor(light);
5323 fH->TAttFill::Modify();
5324 gPad->PaintFillArea(7, x, y);
5325
5326 // Draw bottom&right part of the box
5327 x[0] = xlow; y[0] = ylow;
5328 x[1] = xlow + bwidth*(xup-xlow); y[1] = ylow + bwidth*(yup-ylow);
5329 x[2] = xup - bwidth*(xup-xlow); y[2] = y[1];
5330 x[3] = x[2]; y[3] = yup - bwidth*(yup-ylow);
5331 x[4] = xup; y[4] = yup;
5332 x[5] = xup; y[5] = ylow;
5333 x[6] = xlow; y[6] = ylow;
5334 if (kZNeg) fH->SetFillColor(light);
5335 else fH->SetFillColor(dark);
5336 fH->TAttFill::Modify();
5337 gPad->PaintFillArea(7, x, y);
5338 }
5339 }
5340 }
5341
5343 fH->SetFillStyle(fillsav);
5344 fH->SetFillColor(colsav);
5345 fH->TAttFill::Modify();
5346}
5347
5348
5349
5350////////////////////////////////////////////////////////////////////////////////
5351/// [Control function to draw a 2D histogram as a candle (box) plot or violin plot](\ref HP14)
5352
5354{
5355 TH1D *hproj = nullptr;
5356 TH2D *h2 = (TH2D*)fH;
5357
5358 TCandle myCandle;
5360 myCandle.SetMarkerColor(fH->GetLineColor());
5361 myCandle.SetLineColor(fH->GetLineColor());
5362 myCandle.SetLineWidth(fH->GetLineWidth());
5363 myCandle.SetFillColor(fH->GetFillColor());
5364 myCandle.SetFillStyle(fH->GetFillStyle());
5365 myCandle.SetMarkerSize(fH->GetMarkerSize());
5366 myCandle.SetMarkerStyle(fH->GetMarkerStyle());
5368
5369 Bool_t swapXY = myCandle.IsHorizontal();
5370 const Double_t standardCandleWidth = 0.66;
5371 const Double_t standardHistoWidth = 0.8;
5372
5373 double allMaxContent = 0, allMaxIntegral = 0;
5374 if (myCandle.IsViolinScaled())
5375 allMaxContent = h2->GetBinContent(h2->GetMaximumBin());
5376
5377 if (!swapXY) { // Vertical candle
5378 //Determining the slice with the maximum integral - if necessary
5379 if (myCandle.IsCandleScaled())
5380 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast; i++) {
5381 hproj = h2->ProjectionY("_px", i, i);
5382 if (hproj->Integral() > allMaxIntegral) allMaxIntegral = hproj->Integral();
5383 }
5384 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast; i++) {
5385 Double_t binPosX = fXaxis->GetBinLowEdge(i);
5386 Double_t binWidth = fXaxis->GetBinWidth(i);
5387 hproj = h2->ProjectionY("_px", i, i);
5388 if (hproj->GetEntries() != 0) {
5389 Double_t candleWidth = fH->GetBarWidth();
5390 Double_t offset = fH->GetBarOffset()*binWidth;
5391 double myMaxContent = hproj->GetBinContent(hproj->GetMaximumBin());
5392 double myIntegral = hproj->Integral();
5393 Double_t histoWidth = candleWidth;
5394 if (candleWidth > 0.999 && candleWidth < 1.001) {
5395 candleWidth = standardCandleWidth;
5396 histoWidth = standardHistoWidth;
5397 }
5398 if (Hoption.Logz && myMaxContent > 0) {
5399 histoWidth *= myMaxContent/TMath::Log10(myMaxContent);
5400 if (myCandle.IsViolinScaled() && myMaxContent > 0 && allMaxContent > 0)
5401 histoWidth *= TMath::Log10(myMaxContent)/TMath::Log10(allMaxContent);
5402 } else if (myCandle.IsViolinScaled() && (allMaxContent > 0))
5403 histoWidth *= myMaxContent/allMaxContent;
5404 if (myCandle.IsCandleScaled() && (allMaxIntegral > 0))
5405 candleWidth *= myIntegral/allMaxIntegral;
5406
5407 myCandle.SetAxisPosition(binPosX+binWidth/2. + offset);
5408 myCandle.SetCandleWidth(candleWidth*binWidth);
5409 myCandle.SetHistoWidth(histoWidth*binWidth);
5410 myCandle.SetHistogram(hproj);
5411 myCandle.Paint();
5412 }
5413 }
5414 } else { // Horizontal candle
5415 //Determining the slice with the maximum integral - if necessary
5416 if (myCandle.IsCandleScaled())
5417 for (Int_t i=Hparam.yfirst; i<=Hparam.ylast; i++) {
5418 hproj = h2->ProjectionX("_py", i, i);
5419 if (hproj->Integral() > allMaxIntegral) allMaxIntegral = hproj->Integral();
5420 }
5421 for (Int_t i=Hparam.yfirst; i<=Hparam.ylast; i++) {
5422 Double_t binPosY = fYaxis->GetBinLowEdge(i);
5423 Double_t binWidth = fYaxis->GetBinWidth(i);
5424 hproj = h2->ProjectionX("_py", i, i);
5425 if (hproj->GetEntries() != 0) {
5426 Double_t candleWidth = fH->GetBarWidth();
5427 Double_t offset = fH->GetBarOffset()*binWidth;
5428 double myMaxContent = hproj->GetBinContent(hproj->GetMaximumBin());
5429 double myIntegral = hproj->Integral();
5430 Double_t histoWidth = candleWidth;
5431 if (candleWidth > 0.999 && candleWidth < 1.001) {
5432 candleWidth = standardCandleWidth;
5433 histoWidth = standardHistoWidth;
5434 }
5435 if (Hoption.Logz && myMaxContent > 0) {
5436 histoWidth *= myMaxContent/TMath::Log10(myMaxContent);
5437 if (myCandle.IsViolinScaled() && myMaxContent > 0 && allMaxContent > 0)
5438 histoWidth *= TMath::Log10(myMaxContent)/TMath::Log10(allMaxContent);
5439 } else if (myCandle.IsViolinScaled() && (allMaxContent > 0))
5440 histoWidth *= myMaxContent/allMaxContent;
5441 if (myCandle.IsCandleScaled() && (allMaxIntegral > 0))
5442 candleWidth *= myIntegral/allMaxIntegral;
5443
5444 myCandle.SetAxisPosition(binPosY+binWidth/2. + offset);
5445 myCandle.SetCandleWidth(candleWidth*binWidth);
5446 myCandle.SetHistoWidth(histoWidth*binWidth);
5447 myCandle.SetHistogram(hproj);
5448 myCandle.Paint();
5449 }
5450 }
5451 }
5452 delete hproj;
5453}
5454
5455
5456
5457////////////////////////////////////////////////////////////////////////////////
5458/// Returns the rendering regions for an axis to use in the COL2 option
5459///
5460/// The algorithm analyses the size of the axis compared to the size of
5461/// the rendering region. It figures out the boundaries to use for each color
5462/// of the rendering region. Only one axis is computed here.
5463///
5464/// This allows for a single computation of the boundaries before iterating
5465/// through all of the bins.
5466///
5467/// \param pAxis the axis to consider
5468/// \param nPixels the number of pixels to render axis into
5469/// \param isLog whether the axis is log scale
5470
5471std::vector<THistRenderingRegion>
5473{
5474 std::vector<THistRenderingRegion> regions;
5475
5476 enum STRATEGY { Bins, Pixels } strategy;
5477
5478 Int_t nBins = (pAxis->GetLast() - pAxis->GetFirst() + 1);
5479
5480 if (nBins >= nPixels) {
5481 // more bins than pixels... we should loop over pixels and sample
5482 strategy = Pixels;
5483 } else {
5484 // fewer bins than pixels... we should loop over bins
5485 strategy = Bins;
5486 }
5487
5488 if (isLog) {
5489
5490 Double_t xMin = pAxis->GetBinLowEdge(pAxis->GetFirst());
5491 Int_t binOffset=0;
5492 while (xMin <= 0 && ((pAxis->GetFirst()+binOffset) != pAxis->GetLast()) ) {
5493 binOffset++;
5494 xMin = pAxis->GetBinLowEdge(pAxis->GetFirst()+binOffset);
5495 }
5496 if (xMin <= 0) {
5497 // this should cause an error if we have
5498 return regions;
5499 }
5500 Double_t xMax = pAxis->GetBinUpEdge(pAxis->GetLast());
5501
5502 if (strategy == Bins) {
5503 // logarithmic plot. we find the pixel for the bin
5504 // pixel = eta * log10(V) - alpha
5505 // where eta = nPixels/(log10(Vmax)-log10(Vmin))
5506 // and alpha = nPixels*log10(Vmin)/(log10(Vmax)-log10(Vmin))
5507 // and V is axis value
5508 Double_t eta = (nPixels-1.0)/(TMath::Log10(xMax) - TMath::Log10(xMin));
5509 Double_t offset = -1.0 * eta * TMath::Log10(xMin);
5510
5511 for (Int_t bin=pAxis->GetFirst()+binOffset; bin<=pAxis->GetLast(); bin++) {
5512
5513 // linear plot. we simply need to find the appropriate bin
5514 // for the
5515 Double_t xLowValue = pAxis->GetBinLowEdge(bin);
5516 Double_t xUpValue = pAxis->GetBinUpEdge(bin);
5517 Int_t xPx0 = eta*TMath::Log10(xLowValue)+ offset;
5518 Int_t xPx1 = eta*TMath::Log10(xUpValue) + offset;
5519 THistRenderingRegion region = {std::make_pair(xPx0, xPx1),
5520 std::make_pair(bin, bin+1)};
5521 regions.push_back(region);
5522 }
5523
5524 } else {
5525
5526 // loop over pixels
5527
5528 Double_t beta = (TMath::Log10(xMax) - TMath::Log10(xMin))/(nPixels-1.0);
5529
5530 for (Int_t pixelIndex=0; pixelIndex<(nPixels-1); pixelIndex++) {
5531 // linear plot
5532 Int_t binLow = pAxis->FindBin(xMin*TMath::Power(10.0, beta*pixelIndex));
5533 Int_t binHigh = pAxis->FindBin(xMin*TMath::Power(10.0, beta*(pixelIndex+1)));
5534 THistRenderingRegion region = { std::make_pair(pixelIndex, pixelIndex+1),
5535 std::make_pair(binLow, binHigh)};
5536 regions.push_back(region);
5537 }
5538 }
5539 } else {
5540 // standard linear plot
5541
5542 if (strategy == Bins) {
5543 // loop over bins
5544 for (Int_t bin=pAxis->GetFirst(); bin<=pAxis->GetLast(); bin++) {
5545
5546 // linear plot. we simply need to find the appropriate bin
5547 // for the
5548 Int_t xPx0 = ((bin - pAxis->GetFirst()) * nPixels)/nBins;
5549 Int_t xPx1 = xPx0 + nPixels/nBins;
5550
5551 // make sure we don't compute beyond our bounds
5552 if (xPx1>= nPixels) xPx1 = nPixels-1;
5553
5554 THistRenderingRegion region = {std::make_pair(xPx0, xPx1),
5555 std::make_pair(bin, bin+1)};
5556 regions.push_back(region);
5557 }
5558 } else {
5559 // loop over pixels
5560 for (Int_t pixelIndex=0; pixelIndex<nPixels-1; pixelIndex++) {
5561 // linear plot
5562 Int_t binLow = (nBins*pixelIndex)/nPixels + pAxis->GetFirst();
5563 Int_t binHigh = binLow + nBins/nPixels;
5564 THistRenderingRegion region = { std::make_pair(pixelIndex, pixelIndex+1),
5565 std::make_pair(binLow, binHigh)};
5566 regions.push_back(region);
5567 }
5568 }
5569 }
5570
5571 return regions;
5572}
5573
5574////////////////////////////////////////////////////////////////////////////////
5575/// [Rendering scheme for the COL2 and COLZ2 options] (\ref HP14)
5576
5578{
5579
5580 if (Hoption.System != kCARTESIAN) {
5581 Error("THistPainter::PaintColorLevelsFast(Option_t*)",
5582 "Only cartesian coordinates supported by 'COL2' option. Using 'COL' option instead.");
5583 PaintColorLevels(nullptr);
5584 return;
5585 }
5586
5587 Double_t z;
5588
5589 // Use existing max or min values. If either is already set
5590 // the appropriate value to use.
5591 Double_t zmin = fH->GetMinimumStored();
5592 Double_t zmax = fH->GetMaximumStored();
5593 Double_t originalZMin = zmin;
5594 Double_t originalZMax = zmax;
5595 if ((zmin == -1111) && (zmax == -1111)) {
5596 fH->GetMinimumAndMaximum(zmin, zmax);
5597 fH->SetMinimum(zmin);
5598 fH->SetMaximum(zmax);
5599 } else if (zmin == -1111) {
5600 zmin = fH->GetMinimum();
5601 fH->SetMinimum(zmin);
5602 } else if (zmax == -1111) {
5603 zmax = fH->GetMaximum();
5604 fH->SetMaximum(zmax);
5605 }
5606
5607 Double_t dz = zmax - zmin;
5608 if (dz <= 0) { // Histogram filled with a constant value
5609 zmax += 0.1*TMath::Abs(zmax);
5610 zmin -= 0.1*TMath::Abs(zmin);
5611 dz = zmax - zmin;
5612 }
5613
5614 if (Hoption.Logz) {
5615 if (zmin > 0) {
5616 zmin = TMath::Log10(zmin);
5617 zmax = TMath::Log10(zmax);
5618 dz = zmax - zmin;
5619 } else {
5620 Error("THistPainter::PaintColorLevelsFast(Option_t*)",
5621 "Cannot plot logz because bin content is less than 0.");
5622 return;
5623 }
5624 }
5625
5626 // Initialize the levels on the Z axis
5627 Int_t ndiv = fH->GetContour();
5628 if (ndiv == 0 ) {
5629 ndiv = gStyle->GetNumberContours();
5630 fH->SetContour(ndiv);
5631 }
5632 std::vector<Double_t> colorBounds(ndiv);
5633 std::vector<Double_t> contours(ndiv, 0);
5634 if (!fH->TestBit(TH1::kUserContour)) {
5635 fH->SetContour(ndiv);
5636 } else {
5637 fH->GetContour(contours.data());
5638 }
5639
5640 Double_t step = 1.0/ndiv;
5641 for (Int_t i=0; i<ndiv; ++i) {
5642 colorBounds[i] = step*i;
5643 }
5644
5645 auto pFrame = gPad->GetFrame();
5646 Int_t px0 = gPad->XtoPixel(pFrame->GetX1());
5647 Int_t px1 = gPad->XtoPixel(pFrame->GetX2());
5648 Int_t py0 = gPad->YtoPixel(pFrame->GetY1());
5649 Int_t py1 = gPad->YtoPixel(pFrame->GetY2());
5650 Int_t nXPixels = px1-px0;
5651 Int_t nYPixels = py0-py1; // y=0 is at the top of the screen
5652
5653 std::vector<Double_t> buffer(nXPixels*nYPixels, 0);
5654
5655 auto xRegions = ComputeRenderingRegions(fXaxis, nXPixels, Hoption.Logx);
5656 auto yRegions = ComputeRenderingRegions(fYaxis, nYPixels, Hoption.Logy);
5657 if (xRegions.empty() || yRegions.empty()) {
5658 Error("THistPainter::PaintColorLevelFast(Option_t*)",
5659 "Encountered error while computing rendering regions.");
5660 return;
5661 }
5662
5663 Bool_t minExists = kFALSE;
5664 Bool_t maxExists = kFALSE;
5665 Double_t minValue = 1.;
5666 Double_t maxValue = 0.;
5667 for (auto& yRegion : yRegions) {
5668 for (auto& xRegion : xRegions ) {
5669
5670 const auto& xBinRange = xRegion.fBinRange;
5671 const auto& yBinRange = yRegion.fBinRange;
5672
5673 // sample the range
5674 z = fH->GetBinContent(xBinRange.second-1, yBinRange.second-1);
5675
5676 if (Hoption.Logz) {
5677 if (z > 0) z = TMath::Log10(z);
5678 else z = zmin;
5679 }
5680
5681 // obey the user's max and min values if they were set
5682 if (z > zmax) z = zmax;
5683 if (z < zmin) z = zmin;
5684
5686 // contours are absolute values
5687 auto index = TMath::BinarySearch(contours.size(), contours.data(), z);
5688 z = colorBounds[index];
5689 } else {
5690 Int_t index = 0;
5691 if (dz != 0) {
5692 index = 0.001 + ((z - zmin)/dz)*ndiv;
5693 }
5694
5695 if (index == static_cast<Int_t>(colorBounds.size())) {
5696 index--;
5697 }
5698
5699 // Do a little bookkeeping to use later for getting libAfterImage to produce
5700 // the correct colors
5701 if (index == 0) {
5702 minExists = kTRUE;
5703 } else if (index == static_cast<Int_t>(colorBounds.size()-1)) {
5704 maxExists = kTRUE;
5705 }
5706
5707 z = colorBounds[index];
5708
5709 if (z < minValue) {
5710 minValue = z;
5711 }
5712 if (z > maxValue) {
5713 maxValue = z;
5714 }
5715 }
5716
5717 // fill in the actual pixels
5718 const auto& xPixelRange = xRegion.fPixelRange;
5719 const auto& yPixelRange = yRegion.fPixelRange;
5720 for (Int_t xPx = xPixelRange.first; xPx <= xPixelRange.second; ++xPx) {
5721 for (Int_t yPx = yPixelRange.first; yPx <= yPixelRange.second; ++yPx) {
5722 Int_t pixel = yPx*nXPixels + xPx;
5723 buffer[pixel] = z;
5724 }
5725 }
5726 } // end px loop
5727 } // end py loop
5728
5729 // This is a bit of a hack to ensure that we span the entire color range and
5730 // don't screw up the colors for a sparse histogram. No one will notice that I set a
5731 // single pixel on the edge of the image to a different color. This is even more
5732 // true because the chosen pixels will be covered by the axis.
5733 if (minValue != maxValue) {
5734 if ( !minExists) {
5735 buffer.front() = 0;
5736 }
5737
5738 if ( !maxExists) {
5739 buffer[buffer.size()-nXPixels] = 0.95;
5740 }
5741 }
5742
5743 // Generate the TImage
5745 TImage* pImage = TImage::Create();
5747 pImage->SetImage(buffer.data(), nXPixels, nYPixels, pPalette);
5748 delete pPalette;
5749
5750 Window_t wid = static_cast<Window_t>(gVirtualX->GetWindowID(gPad->GetPixmapID()));
5751 pImage->PaintImage(wid, px0, py1, 0, 0, nXPixels, nYPixels);
5752 delete pImage;
5753
5755
5756 // Reset the maximum and minimum values to their original values
5757 // when this function was called. If we don't do this, an initial
5758 // value of -1111 will be replaced with the true max or min values.
5759 fH->SetMinimum(originalZMin);
5760 fH->SetMaximum(originalZMax);
5761}
5762
5763////////////////////////////////////////////////////////////////////////////////
5764/// [Control function to draw a 2D histogram as a color plot.](\ref HP14)
5765
5767{
5768 Double_t z, zc, xk, xstep, yk, ystep, xlow, xup, ylow, yup;
5769
5770 Double_t zmin = fH->GetMinimum();
5771 Double_t zmax = fH->GetMaximum();
5772
5773 Double_t dz = zmax - zmin;
5774 if (dz <= 0) { // Histogram filled with a constant value
5775 zmax += 0.1*TMath::Abs(zmax);
5776 zmin -= 0.1*TMath::Abs(zmin);
5777 dz = zmax - zmin;
5778 }
5779
5780 // In case of option SAME, zmin and zmax values are taken from the
5781 // first plotted 2D histogram.
5782 if (Hoption.Same > 0 && Hoption.Same < 10) {
5783 TH2 *h2;
5784 TIter next(gPad->GetListOfPrimitives());
5785 while ((h2 = (TH2 *)next())) {
5786 if (!h2->InheritsFrom(TH2::Class())) continue;
5787 zmin = h2->GetMinimum();
5788 zmax = h2->GetMaximum();
5789 fH->SetMinimum(zmin);
5790 fH->SetMaximum(zmax);
5791 if (Hoption.Logz) {
5792 if (zmin <= 0) {
5793 zmin = TMath::Log10(zmax*0.001);
5794 } else {
5795 zmin = TMath::Log10(zmin);
5796 }
5797 zmax = TMath::Log10(zmax);
5798 }
5799 dz = zmax - zmin;
5800 break;
5801 }
5802 } else {
5803 if (Hoption.Logz) {
5804 if (zmin > 0) {
5805 zmin = TMath::Log10(zmin);
5806 zmax = TMath::Log10(zmax);
5807 dz = zmax - zmin;
5808 } else {
5809 return;
5810 }
5811 }
5812 }
5813
5814 Style_t fillsav = fH->GetFillStyle();
5815 Style_t colsav = fH->GetFillColor();
5816 fH->SetFillStyle(1001);
5817 fH->TAttFill::Modify();
5818
5819 // Initialize the levels on the Z axis
5820 Int_t ncolors = gStyle->GetNumberOfColors();
5821 Int_t ndiv = fH->GetContour();
5822 if (ndiv == 0 ) {
5823 ndiv = gStyle->GetNumberContours();
5824 fH->SetContour(ndiv);
5825 }
5826 Int_t ndivz = TMath::Abs(ndiv);
5827 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
5828 Double_t scale = (dz ? ndivz / dz : 1.0);
5829
5830 Int_t color;
5831 TProfile2D* prof2d = dynamic_cast<TProfile2D*>(fH);
5832 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
5833 yk = fYaxis->GetBinLowEdge(j);
5834 ystep = fYaxis->GetBinWidth(j);
5835 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
5836 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
5837 xk = fXaxis->GetBinLowEdge(i);
5838 xstep = fXaxis->GetBinWidth(i);
5839 if (Hoption.System == kPOLAR && xk<0) xk= 2*TMath::Pi()+xk;
5840 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
5841 z = fH->GetBinContent(bin);
5842 // if fH is a profile histogram do not draw empty bins
5843 if (prof2d) {
5844 const Double_t binEntries = prof2d->GetBinEntries(bin);
5845 if (binEntries == 0)
5846 continue;
5847 } else {
5848 // don't draw the empty bins for non-profile histograms
5849 // with positive content
5850 if (z == 0) {
5851 if (zmin >= 0 || Hoption.Logz) continue;
5852 if (Hoption.Color == 2) continue;
5853 }
5854 }
5855
5856 if (Hoption.Logz) {
5857 if (z > 0) z = TMath::Log10(z);
5858 else z = zmin;
5859 }
5860 if (z < zmin && !Hoption.Zero) continue;
5861 xup = xk + xstep;
5862 xlow = xk;
5863 if (Hoption.Logx) {
5864 if (xup > 0) xup = TMath::Log10(xup);
5865 else continue;
5866 if (xlow > 0) xlow = TMath::Log10(xlow);
5867 else continue;
5868 }
5869 yup = yk + ystep;
5870 ylow = yk;
5871 if (Hoption.System != kPOLAR) {
5872 if (Hoption.Logy) {
5873 if (yup > 0) yup = TMath::Log10(yup);
5874 else continue;
5875 if (ylow > 0) ylow = TMath::Log10(ylow);
5876 else continue;
5877 }
5878 if (xup < gPad->GetUxmin()) continue;
5879 if (yup < gPad->GetUymin()) continue;
5880 if (xlow > gPad->GetUxmax()) continue;
5881 if (ylow > gPad->GetUymax()) continue;
5882 if (xlow < gPad->GetUxmin()) xlow = gPad->GetUxmin();
5883 if (ylow < gPad->GetUymin()) ylow = gPad->GetUymin();
5884 if (xup > gPad->GetUxmax()) xup = gPad->GetUxmax();
5885 if (yup > gPad->GetUymax()) yup = gPad->GetUymax();
5886 }
5887
5889 zc = fH->GetContourLevelPad(0);
5890 if (z < zc) continue;
5891 color = -1;
5892 for (Int_t k=0; k<ndiv; k++) {
5893 zc = fH->GetContourLevelPad(k);
5894 if (z < zc) {
5895 continue;
5896 } else {
5897 color++;
5898 }
5899 }
5900 } else {
5901 color = Int_t(0.01+(z-zmin)*scale);
5902 }
5903
5904 Int_t theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
5905 if (theColor > ncolors-1) theColor = ncolors-1;
5907 fH->TAttFill::Modify();
5908 if (Hoption.System != kPOLAR) {
5909 gPad->PaintBox(xlow, ylow, xup, yup);
5910 } else {
5911 TCrown crown(0,0,ylow,yup,xlow*TMath::RadToDeg(),xup*TMath::RadToDeg());
5912 crown.SetFillColor(gStyle->GetColorPalette(theColor));
5913 crown.SetLineColor(fH->GetLineColor());
5914 crown.SetLineWidth(fH->GetLineWidth());
5915 crown.SetLineStyle(fH->GetLineStyle());
5916 crown.Paint();
5917 }
5918 }
5919 }
5920
5922
5923 fH->SetFillStyle(fillsav);
5924 fH->SetFillColor(colsav);
5925 fH->TAttFill::Modify();
5926
5927}
5928
5929////////////////////////////////////////////////////////////////////////////////
5930/// [Control function to draw a 2D histogram as a contour plot.](\ref HP16)
5931
5933{
5934
5935 Int_t i, j, count, ncontour, icol, n, lj, m, ix, jx, ljfill;
5936 Int_t itars, mode, ir[4];
5937 Double_t xsave, ysave, thesave,phisave,x[4], y[4], zc[4];
5938
5939 if (Hoption.Contour == 14) {
5940 Hoption.Surf = 12;
5941 Hoption.Axis = 1;
5942 thesave = gPad->GetTheta();
5943 phisave = gPad->GetPhi();
5944 gPad->SetPhi(0.);
5945 gPad->SetTheta(90.);
5947 gPad->SetPhi(phisave);
5948 gPad->SetTheta(thesave);
5949 TView *view = gPad->GetView();
5950 if (view) view->SetBit(kCannotRotate); //tested in ExecuteEvent
5951 PaintAxis();
5952 return;
5953 }
5954
5955 if (Hoption.Same) {
5956 // If the contour is painted on a 3d plot, the contour lines are
5957 // paint in 3d too.
5958 TObject *obj;
5959 TIter next(gPad->GetListOfPrimitives());
5960 while ((obj=next())) {
5961 if (strstr(obj->GetDrawOption(),"surf") ||
5962 strstr(obj->GetDrawOption(),"lego") ||
5963 strstr(obj->GetDrawOption(),"tri")) {
5964 Hoption.Surf = 16;
5966 return;
5967 }
5968 }
5969 }
5970
5971 if (Hoption.Contour == 15) {
5972 TGraphDelaunay2D *dt = nullptr;
5973 TGraphDelaunay *dtOld = nullptr;
5974 TList *hl = fH->GetListOfFunctions();
5975 dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
5976 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
5977 if (!dt && !dtOld) return;
5978 if (!fGraph2DPainter)
5979 fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
5980 fGraph2DPainter->Paint(option);
5981 return;
5982 }
5983
5984 gPad->SetBit(TGraph::kClipFrame);
5985
5986 std::vector<Double_t> levels(2*kMAXCONTOUR);
5987 std::vector<Double_t> xarr(2*kMAXCONTOUR);
5988 std::vector<Double_t> yarr(2*kMAXCONTOUR);
5989 std::vector<Int_t> itarr(2*kMAXCONTOUR);
5990
5991 Int_t npmax = 0;
5992 for (i=0;i<2*kMAXCONTOUR;i++) itarr[i] = 0;
5993
5994 ncontour = fH->GetContour();
5995 if (ncontour == 0) {
5996 ncontour = gStyle->GetNumberContours();
5997 fH->SetContour(ncontour);
5998 }
5999 if (ncontour > kMAXCONTOUR) {
6000 Warning("PaintContour", "maximum number of contours is %d, asked for %d",
6001 kMAXCONTOUR, ncontour);
6002 ncontour = kMAXCONTOUR-1;
6003 }
6004 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ncontour);
6005
6006 for (i=0;i<ncontour;i++) levels[i] = fH->GetContourLevelPad(i);
6007 Int_t linesav = fH->GetLineStyle();
6008 Int_t colorsav = fH->GetLineColor();
6009 Int_t fillsav = fH->GetFillColor();
6010 if (Hoption.Contour == 13) {
6011 fH->TAttLine::Modify();
6012 }
6013
6014 std::vector<std::unique_ptr<TPolyLine>> polys;
6015 TObjArray *contours = nullptr;
6016 TList *list = nullptr;
6017 TGraph *graph = nullptr;
6018 std::vector<Int_t> np;
6019 if (Hoption.Contour == 1) {
6020 np.resize(ncontour);
6021 for (i=0;i<ncontour;i++)
6022 np[i] = 0;
6023 for (i=0;i<ncontour;i++)
6024 polys.emplace_back(std::make_unique<TPolyLine>(100));
6025 if (Hoption.List == 1) {
6026 contours = (TObjArray*)gROOT->GetListOfSpecials()->FindObject("contours");
6027 if (contours) {
6028 gROOT->GetListOfSpecials()->Remove(contours);
6029 count = contours->GetSize();
6030 for (i=0;i<count;i++) {
6031 list = (TList*)contours->At(i);
6032 if (list) list->Delete();
6033 }
6034 contours->Delete();
6035 delete contours;
6036 }
6037 contours = new TObjArray(ncontour);
6038 contours->SetName("contours");
6039 gROOT->GetListOfSpecials()->Add(contours);
6040 for (i=0;i<ncontour;i++) {
6041 list = new TList();
6042 contours->Add(list);
6043 }
6044 }
6045 }
6046 Int_t theColor;
6047 Int_t ncolors = gStyle->GetNumberOfColors();
6048 Int_t ndivz = TMath::Abs(ncontour);
6049
6050 Int_t k,ipoly;
6051 for (j=Hparam.yfirst; j<Hparam.ylast; j++) {
6052 y[0] = fYaxis->GetBinCenter(j);
6053 y[1] = y[0];
6054 y[2] = fYaxis->GetBinCenter(j+1);
6055 y[3] = y[2];
6056 for (i=Hparam.xfirst; i<Hparam.xlast; i++) {
6057 zc[0] = fH->GetBinContent(i, j);
6058 zc[1] = fH->GetBinContent(i+1, j);
6059 zc[2] = fH->GetBinContent(i+1, j+1);
6060 zc[3] = fH->GetBinContent(i, j+1);
6061 if (!IsInside(fXaxis->GetBinCenter(i),fYaxis->GetBinCenter(j))) continue;
6062 if (Hoption.Logz) {
6063 if (zc[0] > 0) zc[0] = TMath::Log10(zc[0]);
6064 else zc[0] = Hparam.zmin;
6065 if (zc[1] > 0) zc[1] = TMath::Log10(zc[1]);
6066 else zc[1] = Hparam.zmin;
6067 if (zc[2] > 0) zc[2] = TMath::Log10(zc[2]);
6068 else zc[2] = Hparam.zmin;
6069 if (zc[3] > 0) zc[3] = TMath::Log10(zc[3]);
6070 else zc[3] = Hparam.zmin;
6071 }
6072 for (k=0;k<4;k++) {
6073 ir[k] = TMath::BinarySearch(ncontour, levels.data(), zc[k]);
6074 }
6075 if (ir[0] != ir[1] || ir[1] != ir[2] || ir[2] != ir[3] || ir[3] != ir[0]) {
6076 x[0] = fXaxis->GetBinCenter(i);
6077 x[3] = x[0];
6078 x[1] = fXaxis->GetBinCenter(i+1);
6079 x[2] = x[1];
6080 if (zc[0] <= zc[1]) n = 0; else n = 1;
6081 if (zc[2] <= zc[3]) m = 2; else m = 3;
6082 if (zc[n] > zc[m]) n = m;
6083 n++;
6084 lj=1;
6085 for (ix=1;ix<=4;ix++) {
6086 m = n%4 + 1;
6087 ljfill = PaintContourLine(zc[n-1],ir[n-1],x[n-1],y[n-1],zc[m-1],
6088 ir[m-1],x[m-1],y[m-1], xarr.data()+lj-1,yarr.data()+lj-1,itarr.data()+lj-1, levels.data());
6089 lj += 2*ljfill;
6090 n = m;
6091 }
6092
6093 if (zc[0] <= zc[1]) n = 0; else n = 1;
6094 if (zc[2] <= zc[3]) m = 2; else m = 3;
6095 if (zc[n] > zc[m]) n = m;
6096 n++;
6097 lj=2;
6098 for (ix=1;ix<=4;ix++) {
6099 if (n == 1) m = 4;
6100 else m = n-1;
6101 ljfill = PaintContourLine(zc[n-1],ir[n-1],x[n-1],y[n-1],zc[m-1],
6102 ir[m-1],x[m-1],y[m-1],xarr.data()+lj-1,yarr.data()+lj-1,itarr.data()+lj-1, levels.data());
6103 lj += 2*ljfill;
6104 n = m;
6105 }
6106
6107 // Re-order endpoints
6108
6109 count = 0;
6110 for (ix=1; ix<=lj-5; ix +=2) {
6111 //count = 0;
6112 while (itarr[ix-1] != itarr[ix]) {
6113 xsave = xarr[ix];
6114 ysave = yarr[ix];
6115 itars = itarr[ix];
6116 for (jx=ix; jx<=lj-5; jx +=2) {
6117 xarr[jx] = xarr[jx+2];
6118 yarr[jx] = yarr[jx+2];
6119 itarr[jx] = itarr[jx+2];
6120 }
6121 xarr[lj-3] = xsave;
6122 yarr[lj-3] = ysave;
6123 itarr[lj-3] = itars;
6124 if (count > 100) break;
6125 count++;
6126 }
6127 }
6128
6129 if (count > 100) continue;
6130 for (ix=1; ix<=lj-2; ix +=2) {
6131 theColor = Int_t((itarr[ix-1]+0.99)*Float_t(ncolors)/Float_t(ndivz));
6132 icol = gStyle->GetColorPalette(theColor);
6133 if (Hoption.Contour == 11) {
6134 fH->SetLineColor(icol);
6135 }
6136 if (Hoption.Contour == 12) {
6137 mode = icol%5;
6138 if (mode == 0) mode = 5;
6140 }
6141 if (Hoption.Contour != 1) {
6142 fH->TAttLine::Modify();
6143 gPad->PaintPolyLine(2,xarr.data()+ix-1,yarr.data()+ix-1);
6144 continue;
6145 }
6146
6147 ipoly = itarr[ix-1];
6148 if (ipoly >=0 && ipoly <ncontour) {
6149 polys[ipoly]->SetPoint(np[ipoly] ,xarr[ix-1],yarr[ix-1]);
6150 polys[ipoly]->SetPoint(np[ipoly]+1,xarr[ix], yarr[ix]);
6151 np[ipoly] += 2;
6152 if (npmax < np[ipoly]) npmax = np[ipoly];
6153 }
6154 }
6155 } // end of if (ir[0]
6156 } //end of for (i
6157 } //end of for (j
6158
6160 std::vector<Double_t> xp, yp;
6161 Int_t nadd,iminus,iplus;
6162 Int_t istart;
6163 Int_t first = ncontour;
6164 std::vector<Int_t> polysort;
6165 Int_t contListNb;
6166 if (Hoption.Contour != 1) goto theEND;
6167
6168 //The 2 points line generated above are now sorted/merged to generate
6169 //a list of consecutive points.
6170 // If the option "List" has been specified, the list of points is saved
6171 // in the form of TGraph objects in the ROOT list of special objects.
6172 xmin = gPad->GetUxmin();
6173 ymin = gPad->GetUymin();
6174 xp.resize(2*npmax);
6175 yp.resize(2*npmax);
6176 polysort.resize(ncontour);
6177 //find first positive contour
6178 for (ipoly=0;ipoly<ncontour;ipoly++) {
6179 if (levels[ipoly] >= 0) {first = ipoly; break;}
6180 }
6181 //store negative contours from 0 to minimum, then all positive contours
6182 k = 0;
6183 for (ipoly=first-1;ipoly>=0;ipoly--) {polysort[k] = ipoly; k++;}
6184 for (ipoly=first;ipoly<ncontour;ipoly++) {polysort[k] = ipoly; k++;}
6185 // we can now draw sorted contours
6186 contListNb = 0;
6187 fH->SetFillStyle(1001);
6188 for (k=0;k<ncontour;k++) {
6189 ipoly = polysort[k];
6190 if (np[ipoly] == 0) continue;
6191 if (Hoption.List) list = (TList*)contours->At(contListNb);
6192 contListNb++;
6193 Double_t *xx = polys[ipoly]->GetX();
6194 Double_t *yy = polys[ipoly]->GetY();
6195 istart = 0;
6196 while (true) {
6197 iminus = npmax;
6198 iplus = iminus+1;
6199 xp[iminus]= xx[istart]; yp[iminus] = yy[istart];
6200 xp[iplus] = xx[istart+1]; yp[iplus] = yy[istart+1];
6201 xx[istart] = xmin; yy[istart] = ymin;
6202 xx[istart+1] = xmin; yy[istart+1] = ymin;
6203 while (true) {
6204 nadd = 0;
6205 for (i=2;i<np[ipoly];i+=2) {
6206 if ((iplus < 2*npmax-1) && (xx[i] == xp[iplus]) && (yy[i] == yp[iplus])) {
6207 iplus++;
6208 xp[iplus] = xx[i+1]; yp[iplus] = yy[i+1];
6209 xx[i] = xmin; yy[i] = ymin;
6210 xx[i+1] = xmin; yy[i+1] = ymin;
6211 nadd++;
6212 }
6213 if ((iminus > 0) && (xx[i+1] == xp[iminus]) && (yy[i+1] == yp[iminus])) {
6214 iminus--;
6215 xp[iminus] = xx[i]; yp[iminus] = yy[i];
6216 xx[i] = xmin; yy[i] = ymin;
6217 xx[i+1] = xmin; yy[i+1] = ymin;
6218 nadd++;
6219 }
6220 }
6221 if (nadd == 0) break;
6222 }
6223 theColor = Int_t((ipoly+0.99)*Float_t(ncolors)/Float_t(ndivz));
6224 icol = gStyle->GetColorPalette(theColor);
6225 if (ndivz > 1) fH->SetFillColor(icol);
6226 fH->TAttFill::Modify();
6227 gPad->PaintFillArea(iplus-iminus+1,xp.data()+iminus,yp.data()+iminus);
6228 if (Hoption.List) {
6229 graph = new TGraph(iplus-iminus+1,xp.data()+iminus,yp.data()+iminus);
6230 graph->SetFillColor(icol);
6231 graph->SetLineWidth(fH->GetLineWidth());
6232 list->Add(graph);
6233 }
6234 //check if more points are left
6235 istart = 0;
6236 for (i=2;i<np[ipoly];i+=2) {
6237 if (xx[i] != xmin && yy[i] != ymin) {
6238 istart = i;
6239 break;
6240 }
6241 }
6242 if (istart == 0) break;
6243 }
6244 }
6245
6246theEND:
6247 gPad->ResetBit(TGraph::kClipFrame);
6249 fH->SetLineStyle(linesav);
6250 fH->SetLineColor(colorsav);
6251 fH->SetFillColor(fillsav);
6252}
6253
6254////////////////////////////////////////////////////////////////////////////////
6255/// Fill the matrix `xarr` and `yarr` for Contour Plot.
6256
6258 Double_t elev2, Int_t icont2, Double_t x2, Double_t y2,
6259 Double_t *xarr, Double_t *yarr, Int_t *itarr, Double_t *levels)
6260{
6261
6262 Bool_t vert;
6263 Double_t tlen, tdif, elev, diff, pdif, xlen;
6264 Int_t n, i, icount;
6265
6266 if (x1 == x2) {
6267 vert = kTRUE;
6268 tlen = y2 - y1;
6269 } else {
6270 vert = kFALSE;
6271 tlen = x2 - x1;
6272 }
6273
6274 n = icont1 +1;
6275 tdif = elev2 - elev1;
6276 i = 0;
6277 icount = 0;
6278 while (n <= icont2 && i <= kMAXCONTOUR/2 -3) {
6279 //elev = fH->GetContourLevel(n);
6280 elev = levels[n];
6281 diff = elev - elev1;
6282 pdif = diff/tdif;
6283 xlen = tlen*pdif;
6284 if (vert) {
6285 if (Hoption.Logx)
6286 xarr[i] = TMath::Log10(x1);
6287 else
6288 xarr[i] = x1;
6289 if (Hoption.Logy)
6290 yarr[i] = TMath::Log10(y1 + xlen);
6291 else
6292 yarr[i] = y1 + xlen;
6293 } else {
6294 if (Hoption.Logx)
6295 xarr[i] = TMath::Log10(x1 + xlen);
6296 else
6297 xarr[i] = x1 + xlen;
6298 if (Hoption.Logy)
6299 yarr[i] = TMath::Log10(y1);
6300 else
6301 yarr[i] = y1;
6302 }
6303 itarr[i] = n;
6304 icount++;
6305 i +=2;
6306 n++;
6307 }
6308 return icount;
6309}
6310
6311////////////////////////////////////////////////////////////////////////////////
6312/// [Draw 1D histograms error bars.](\ref HP09)
6313
6315{
6316
6317 // On iOS, we do not highlight histogram, if it's not picked at the moment
6318 // (but part of histogram (axis or pavestat) was picked, that's why this code
6319 // is called at all. This conditional statement never executes on non-iOS platform.
6320 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH) return;
6321
6322 const Int_t kBASEMARKER=8;
6323 Double_t xp, yp, ex1, ex2, ey1, ey2;
6324 Double_t delta;
6325 Double_t s2x, s2y, bxsize, bysize, symbolsize, xerror, sbasex, sbasey;
6326 Double_t xi1, xi2, xi3, xi4, yi1, yi2, yi3, yi4;
6328 Double_t logxmin = 0;
6329 Double_t logymin = 0;
6330 Double_t offset = 0.;
6331 Double_t width = 0.;
6332 Int_t i, k, npoints, first, last, fixbin;
6333 Int_t if1 = 0;
6334 Int_t if2 = 0;
6335 Int_t drawmarker, errormarker;
6336 Int_t option0, option1, option2, option3, option4, optionE, optionEX0, optionI0;
6337 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};
6338 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};
6339
6340 std::vector<Double_t> xline, yline;
6341 option0 = option1 = option2 = option3 = option4 = optionE = optionEX0 = optionI0 = 0;
6342 if (Hoption.Error >= 40) {Hoption.Error -=40; option0 = 1;}
6343 if (Int_t(Hoption.Error/10) == 2) {optionEX0 = 1; Hoption.Error -= 10;}
6344 if (Hoption.Error == 31) {optionEX0 = 1; Hoption.Error = 1;}
6345 if (Hoption.Error == 11) option1 = 1;
6346 if (Hoption.Error == 12) option2 = 1;
6347 if (Hoption.Error == 13) option3 = 1;
6348 if (Hoption.Error == 14) {option4 = 1; option3 = 1;}
6349 if (Hoption.Error == 15) {optionI0 = 1; option3 = 1;}
6350 if (Hoption.Error == 16) {optionI0 = 1; option4 = 1; option3 = 1;}
6351 if (option2+option3 == 0) optionE = 1;
6352 if (Hoption.Error == 0) optionE = 0;
6353 if (fXaxis->GetXbins()->fN) fixbin = 0;
6354 else fixbin = 1;
6355
6356 offset = fH->GetBarOffset();
6357 width = fH->GetBarWidth();
6358
6360 if (optionEX0) {
6361 xerror = 0;
6362 } else {
6363 xerror = gStyle->GetErrorX();
6364 }
6365 symbolsize = fH->GetMarkerSize();
6366 if (errormarker == 1) symbolsize = 0.01;
6367 sbasex = sbasey = symbolsize*kBASEMARKER;
6368 if (errormarker >= 20 && errormarker <= 49) {
6369 sbasex *= cxx[errormarker-20];
6370 sbasey *= cyy[errormarker-20];
6371 }
6372 // set the graphics attributes
6373
6374 fH->TAttLine::Modify();
6375 fH->TAttFill::Modify();
6376 fH->TAttMarker::Modify();
6377
6378 // set the first and last bin
6379
6380 Double_t factor = Hparam.factor;
6381 first = Hparam.xfirst;
6382 last = Hparam.xlast;
6383 npoints = last - first +1;
6384 xmin = gPad->GetUxmin();
6385 xmax = gPad->GetUxmax();
6386 ymin = gPad->GetUymin();
6387 ymax = gPad->GetUymax();
6388
6389
6390 if (option3) {
6391 xline.resize(2*npoints);
6392 yline.resize(2*npoints);
6393 if ((npoints > 0) && (xline.empty() || yline.empty())) {
6394 Error("PaintErrors", "too many points, out of memory");
6395 return;
6396 }
6397 if1 = 1;
6398 if2 = 2*npoints;
6399 }
6400
6401 // compute the offset of the error bars due to the symbol size
6402 s2x = gPad->PixeltoX(Int_t(0.5*sbasex)) - gPad->PixeltoX(0);
6403 s2y =-gPad->PixeltoY(Int_t(0.5*sbasey)) + gPad->PixeltoY(0);
6404
6405 // compute size of the lines at the end of the error bars
6406 Int_t dxend = Int_t(gStyle->GetEndErrorSize());
6407 bxsize = gPad->PixeltoX(dxend) - gPad->PixeltoX(0);
6408 bysize =-gPad->PixeltoY(dxend) + gPad->PixeltoY(0);
6409
6410
6411 if (fixbin) {
6412 if (Hoption.Logx) xp = TMath::Power(10,Hparam.xmin) + 0.5*Hparam.xbinsize;
6413 else xp = Hparam.xmin + 0.5*Hparam.xbinsize;
6414 } else {
6415 delta = fH->GetBinWidth(first);
6416 xp = fH->GetBinLowEdge(first) + 0.5*delta;
6417 }
6418
6419 // if errormarker = 0 or symbolsize = 0. no symbol is drawn
6420 if (Hoption.Logx) logxmin = TMath::Power(10,Hparam.xmin);
6421 if (Hoption.Logy) logymin = TMath::Power(10,Hparam.ymin);
6422
6423 // ---------------------- Loop over the points---------------------
6424 for (k=first; k<=last; k++) {
6425
6426 // get the data
6427 // xp = X position of the current point
6428 // yp = Y position of the current point
6429 // ex1 = Low X error
6430 // ex2 = Up X error
6431 // ey1 = Low Y error
6432 // ey2 = Up Y error
6433 // (xi,yi) = Error bars coordinates
6434
6435 // apply offset on errors for bar histograms
6436 Double_t xminTmp = gPad->XtoPad(fXaxis->GetBinLowEdge(k));
6437 Double_t xmaxTmp = gPad->XtoPad(fXaxis->GetBinUpEdge(k));
6438 if (Hoption.Logx) {
6439 xminTmp = TMath::Power(10, xminTmp);
6440 xmaxTmp = TMath::Power(10, xmaxTmp);
6441 }
6442 Double_t w = (xmaxTmp-xminTmp)*width;
6443 xminTmp += offset*(xmaxTmp-xminTmp);
6444 xmaxTmp = xminTmp + w;
6445 xp = (xminTmp+xmaxTmp)/2.;
6446
6447 if (Hoption.Logx) {
6448 if (xp <= 0) goto L30;
6449 if (xp < logxmin) goto L30;
6450 if (xp > TMath::Power(10,xmax)) break;
6451 } else {
6452 if (xp < xmin) goto L30;
6453 if (xp > xmax) break;
6454 }
6455 yp = factor*fH->GetBinContent(k);
6456 if (optionI0 && yp==0) goto L30;
6457 if (fixbin) {
6458 ex1 = xerror*Hparam.xbinsize;
6459 } else {
6460 delta = fH->GetBinWidth(k);
6461 ex1 = xerror*delta;
6462 }
6463 if (fH->GetBinErrorOption() == TH1::kNormal) {
6464 ey1 = factor*fH->GetBinError(k);
6465 ey2 = ey1;
6466 } else {
6467 ey1 = factor*fH->GetBinErrorLow(k);
6468 ey2 = factor*fH->GetBinErrorUp(k);
6469 }
6470 ex2 = ex1;
6471
6472 xi4 = xp;
6473 xi3 = xp;
6474 xi2 = xp + ex2;
6475 xi1 = xp - ex1;
6476
6477 yi1 = yp;
6478 yi2 = yp;
6479 yi3 = yp - ey1;
6480 yi4 = yp + ey2;
6481
6482 // take the LOG if necessary
6483 if (Hoption.Logx) {
6484 xi1 = TMath::Log10(TMath::Max(xi1,logxmin));
6485 xi2 = TMath::Log10(TMath::Max(xi2,logxmin));
6486 xi3 = TMath::Log10(TMath::Max(xi3,logxmin));
6487 xi4 = TMath::Log10(TMath::Max(xi4,logxmin));
6488 }
6489 if (Hoption.Logy) {
6490 yi1 = TMath::Log10(TMath::Max(yi1,logymin));
6491 yi2 = TMath::Log10(TMath::Max(yi2,logymin));
6492 yi3 = TMath::Log10(TMath::Max(yi3,logymin));
6493 yi4 = TMath::Log10(TMath::Max(yi4,logymin));
6494 }
6495
6496 // test if error bars are not outside the limits
6497 // otherwise they are truncated
6498
6499 xi1 = TMath::Max(xi1,xmin);
6500 xi2 = TMath::Min(xi2,xmax);
6501 yi3 = TMath::Max(yi3,ymin);
6502 yi4 = TMath::Min(yi4,ymax);
6503
6504 // test if the marker is on the frame limits. If "Yes", the
6505 // marker will not be drawn and the error bars will be readjusted.
6506
6507 drawmarker = kTRUE;
6508 if (!option0 && !option3) {
6509 if (Hoption.Logy && yp < logymin) goto L30;
6510 if (yi1 < ymin || yi1 > ymax) goto L30;
6511 if (Hoption.Error != 0 && yp == 0 && ey1 <= 0) drawmarker = kFALSE;
6512 }
6513 if (!symbolsize || !errormarker) drawmarker = kFALSE;
6514
6515 // draw the error rectangles
6516 if (option2) {
6517 if (yi3 >= ymax) goto L30;
6518 if (yi4 <= ymin) goto L30;
6519 gPad->PaintBox(xi1,yi3,xi2,yi4);
6520 }
6521
6522 // keep points for fill area drawing
6523 if (option3) {
6524 xline[if1-1] = xi3;
6525 xline[if2-1] = xi3;
6526 yline[if1-1] = yi4;
6527 yline[if2-1] = yi3;
6528 if1++;
6529 if2--;
6530 }
6531
6532 // draw the error bars
6533 if (Hoption.Logy && yp < logymin) drawmarker = kFALSE;
6534 if (optionE && drawmarker) {
6535 if ((yi3 < yi1 - s2y) && (yi3 < ymax)) gPad->PaintLine(xi3,yi3,xi4,TMath::Min(yi1 - s2y,ymax));
6536 if ((yi1 + s2y < yi4) && (yi4 > ymin)) gPad->PaintLine(xi3,TMath::Max(yi1 + s2y, ymin),xi4,yi4);
6537 // don't duplicate the horizontal line
6538 if (Hoption.Hist != 2) {
6539 if (yi1<ymax && yi1>ymin) {
6540 if (xi1 < xi3 - s2x) gPad->PaintLine(xi1,yi1,xi3 - s2x,yi2);
6541 if (xi3 + s2x < xi2) gPad->PaintLine(xi3 + s2x,yi1,xi2,yi2);
6542 }
6543 }
6544 }
6545 if (optionE && !drawmarker && (ey1 != 0 || ey2 !=0)) {
6546 if ((yi3 < yi1) && (yi3 < ymax)) gPad->PaintLine(xi3,yi3,xi4,TMath::Min(yi1,ymax));
6547 if ((yi1 < yi4) && (yi4 > ymin)) gPad->PaintLine(xi3,TMath::Max(yi1,ymin),xi4,yi4);
6548 // don't duplicate the horizontal line
6549 if (Hoption.Hist != 2) {
6550 if (yi1<ymax && yi1>ymin) {
6551 if (xi1 < xi3) gPad->PaintLine(xi1,yi1,xi3,yi2);
6552 if (xi3 < xi2) gPad->PaintLine(xi3,yi1,xi2,yi2);
6553 }
6554 }
6555 }
6556
6557 // draw line at the end of the error bars
6558
6559 if (option1 && drawmarker) {
6560
6561 if (yi3 < yi1-s2y && yi3 < ymax && yi3 > ymin) gPad->PaintLine(xi3 - bxsize, yi3 , xi3 + bxsize, yi3);
6562 if (yi4 > yi1+s2y && yi4 < ymax && yi4 > ymin) gPad->PaintLine(xi3 - bxsize, yi4 , xi3 + bxsize, yi4);
6563 if (yi1 <= ymax && yi1 >= ymin) {
6564 if (xi1 < xi3-s2x) gPad->PaintLine(xi1 , yi1 - bysize, xi1 , yi1 + bysize);
6565 if (xi2 > xi3+s2x) gPad->PaintLine(xi2 , yi1 - bysize, xi2 , yi1 + bysize);
6566 }
6567 }
6568
6569 // draw the marker
6570
6571 if (drawmarker) gPad->PaintPolyMarker(1, &xi3, &yi1);
6572
6573L30:
6574 if (fixbin) xp += Hparam.xbinsize;
6575 else {
6576 if (k < last) {
6577 delta = fH->GetBinWidth(k+1);
6578 xp = fH->GetBinLowEdge(k+1) + 0.5*delta;
6579 }
6580 }
6581 } //end of for loop
6582
6583 // draw the filled area
6584
6585 if (option3) {
6586 TGraph graph;
6587 graph.SetLineStyle(fH->GetLineStyle());
6588 graph.SetLineColor(fH->GetLineColor());
6589 graph.SetLineWidth(fH->GetLineWidth());
6590 graph.SetFillStyle(fH->GetFillStyle());
6591 graph.SetFillColor(fH->GetFillColor());
6592 Int_t logx = gPad->GetLogx();
6593 Int_t logy = gPad->GetLogy();
6594 gPad->SetLogx(0);
6595 gPad->SetLogy(0);
6596
6597 // In some cases the number of points in the fill area is smaller than
6598 // 2*npoints. In such cases the array xline and yline must be arranged
6599 // before being plotted. The next loop does that.
6600 if (if2 > npoints) {
6601 for (i=1; i<if1; i++) {
6602 xline[if1-2+i] = xline[if2-1+i];
6603 yline[if1-2+i] = yline[if2-1+i];
6604 }
6605 npoints = if1-1;
6606 }
6607 if (option4) graph.PaintGraph(2*npoints,xline.data(),yline.data(),"FC");
6608 else graph.PaintGraph(2*npoints,xline.data(),yline.data(),"F");
6609 gPad->SetLogx(logx);
6610 gPad->SetLogy(logy);
6611 }
6612}
6613
6614////////////////////////////////////////////////////////////////////////////////
6615/// Draw 2D histograms errors.
6616
6618{
6619
6620 fH->TAttMarker::Modify();
6621 fH->TAttLine::Modify();
6622
6623 // Define the 3D view
6624 fXbuf[0] = Hparam.xmin;
6625 fYbuf[0] = Hparam.xmax;
6626 fXbuf[1] = Hparam.ymin;
6627 fYbuf[1] = Hparam.ymax;
6628 fXbuf[2] = Hparam.zmin;
6629 fYbuf[2] = Hparam.zmax*(1. + gStyle->GetHistTopMargin());
6630 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
6631 TView *view = gPad ? gPad->GetView() : nullptr;
6632 if (!view) {
6633 Error("Paint2DErrors", "no TView in current pad");
6634 return;
6635 }
6636 Double_t thedeg = 90 - gPad->GetTheta();
6637 Double_t phideg = -90 - gPad->GetPhi();
6638 Double_t psideg = view->GetPsi();
6639 Int_t irep;
6640 view->SetView(phideg, thedeg, psideg, irep);
6641
6642 // Set color/style for back box
6643 fLego->SetFillStyle(gPad->GetFrameFillStyle());
6644 fLego->SetFillColor(gPad->GetFrameFillColor());
6645 fLego->TAttFill::Modify();
6646 Int_t backcolor = gPad->GetFrameFillColor();
6647 if (Hoption.System != kCARTESIAN) backcolor = 0;
6648 view->PadRange(backcolor);
6649 fLego->SetFillStyle(fH->GetFillStyle());
6650 fLego->SetFillColor(fH->GetFillColor());
6651 fLego->TAttFill::Modify();
6652
6653 // Paint the Back Box if needed
6654 if (Hoption.BackBox && !Hoption.Same && !Hoption.Lego && !Hoption.Surf) {
6655 fLego->InitMoveScreen(-1.1,1.1);
6656 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
6658 fLego->BackBox(90);
6659 }
6660
6661 // Paint the Errors
6662 Double_t x, ex, x1, x2;
6663 Double_t y, ey, y1, y2;
6664 Double_t z, ez1, ez2, z1, z2;
6665 Double_t temp1[3],temp2[3];
6666 Double_t xyerror;
6667 if (Hoption.Error == 110) {
6668 xyerror = 0;
6669 } else {
6670 xyerror = gStyle->GetErrorX();
6671 }
6672
6673 Double_t xk, xstep, yk, ystep;
6674 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
6675 y = fYaxis->GetBinCenter(j);
6676 ey = fYaxis->GetBinWidth(j)*xyerror;
6677 y1 = y-ey;
6678 y2 = y+ey;
6679 if (Hoption.Logy) {
6680 if (y > 0) y = TMath::Log10(y);
6681 else continue;
6682 if (y1 > 0) y1 = TMath::Log10(y1);
6683 else y1 = Hparam.ymin;
6684 if (y2 > 0) y2 = TMath::Log10(y2);
6685 else y2 = Hparam.ymin;
6686 }
6687 yk = fYaxis->GetBinLowEdge(j);
6688 ystep = fYaxis->GetBinWidth(j);
6689 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
6690 xk = fXaxis->GetBinLowEdge(i);
6691 xstep = fXaxis->GetBinWidth(i);
6692 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
6693 Int_t bin = fH->GetBin(i,j);
6694 x = fXaxis->GetBinCenter(i);
6695 ex = fXaxis->GetBinWidth(i)*xyerror;
6696 x1 = x-ex;
6697 x2 = x+ex;
6698 if (Hoption.Logx) {
6699 if (x > 0) x = TMath::Log10(x);
6700 else continue;
6701 if (x1 > 0) x1 = TMath::Log10(x1);
6702 else x1 = Hparam.xmin;
6703 if (x2 > 0) x2 = TMath::Log10(x2);
6704 else x2 = Hparam.xmin;
6705 }
6706 z = fH->GetBinContent(bin);
6707 if (fH->GetBinErrorOption() == TH1::kNormal) {
6708 ez1 = fH->GetBinError(bin);
6709 ez2 = ez1;
6710 }
6711 else {
6712 ez1 = fH->GetBinErrorLow(bin);
6713 ez2 = fH->GetBinErrorUp(bin);
6714 }
6715 z1 = z - ez1;
6716 z2 = z + ez2;
6717 if (Hoption.Logz) {
6718 if (z > 0) z = TMath::Log10(z);
6719 else z = Hparam.zmin;
6720 if (z1 > 0) z1 = TMath::Log10(z1);
6721 else z1 = Hparam.zmin;
6722 if (z2 > 0) z2 = TMath::Log10(z2);
6723 else z2 = Hparam.zmin;
6724
6725 }
6726 if (z <= Hparam.zmin) continue;
6727 if (z > Hparam.zmax) z = Hparam.zmax;
6728
6729 temp1[0] = x1;
6730 temp1[1] = y;
6731 temp1[2] = z;
6732 temp2[0] = x2;
6733 temp2[1] = y;
6734 temp2[2] = z;
6735 gPad->PaintLine3D(temp1, temp2);
6736 temp1[0] = x;
6737 temp1[1] = y1;
6738 temp1[2] = z;
6739 temp2[0] = x;
6740 temp2[1] = y2;
6741 temp2[2] = z;
6742 gPad->PaintLine3D(temp1, temp2);
6743 temp1[0] = x;
6744 temp1[1] = y;
6745 temp1[2] = z1;
6746 temp2[0] = x;
6747 temp2[1] = y;
6748 temp2[2] = z2;
6749 gPad->PaintLine3D(temp1, temp2);
6750 temp1[0] = x;
6751 temp1[1] = y;
6752 temp1[2] = z;
6753 view->WCtoNDC(temp1, &temp2[0]);
6754 gPad->PaintPolyMarker(1, &temp2[0], &temp2[1]);
6755 }
6756 }
6757
6758 // Paint the Front Box if needed
6759 if (Hoption.FrontBox) {
6760 fLego->InitMoveScreen(-1.1,1.1);
6762 fLego->FrontBox(90);
6763 }
6764
6765 // Paint the Axis if needed
6766 if (!Hoption.Axis && !Hoption.Same && !Hoption.Lego && !Hoption.Surf) {
6767 TGaxis axis;
6768 PaintLegoAxis(&axis, 90);
6769 }
6770
6771 fLego.reset();
6772}
6773
6774////////////////////////////////////////////////////////////////////////////////
6775/// Calculate range and clear pad (canvas).
6776
6778{
6779
6780 if (Hoption.Same) return;
6781
6783
6784 if (Hoption.Lego || Hoption.Surf || Hoption.Tri ||
6785 Hoption.Contour == 14 || Hoption.Error >= 100) {
6786 TObject *frame = gPad->FindObject("TFrame");
6787 if (frame) gPad->Remove(frame);
6788 return;
6789 }
6790
6791 //The next statement is always executed on non-iOS platform,
6792 //on iOS depends on pad mode.
6793 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode())
6794 gPad->PaintPadFrame(Hparam.xmin,Hparam.ymin,Hparam.xmax,Hparam.ymax);
6795}
6796
6797////////////////////////////////////////////////////////////////////////////////
6798/// [Paint functions associated to an histogram.](\ref HP28")
6799
6801{
6802 auto lnk = fFunctions->FirstLink();
6803
6804 while (lnk) {
6805 auto obj = lnk->GetObject();
6806 TVirtualPad::TContext ctxt(true);
6807 if (obj->InheritsFrom(TF2::Class())) {
6808 if (!obj->TestBit(TF2::kNotDraw)) {
6809 if (Hoption.Lego || Hoption.Surf || Hoption.Error >= 100) {
6810 TF2 *f2 = (TF2*)obj;
6811 f2->SetMinimum(fH->GetMinimum());
6812 f2->SetMaximum(fH->GetMaximum());
6813 f2->SetRange(fH->GetXaxis()->GetXmin(), fH->GetYaxis()->GetXmin(), fH->GetXaxis()->GetXmax(), fH->GetYaxis()->GetXmax() );
6814 f2->Paint("surf same");
6815 } else {
6816 obj->Paint("cont3 same");
6817 }
6818 }
6819 } else if (obj->InheritsFrom(TF1::Class())) {
6820 if (!obj->TestBit(TF1::kNotDraw)) obj->Paint("lsame");
6821 } else {
6822 //Let's make this 'function' selectable on iOS device (for example, it can be TPaveStat).
6823 gPad->PushSelectableObject(obj);
6824
6825 //The next statement is ALWAYS executed on non-iOS platform, on iOS it depends on pad's mode
6826 //and picked object.
6827 if (!gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && obj == gPad->GetSelected()))
6828 obj->Paint(lnk->GetOption());
6829 }
6830 lnk = lnk->Next();
6831 }
6832}
6833
6834////////////////////////////////////////////////////////////////////////////////
6835/// [Control routine to draw 1D histograms](\ref HP01b)
6836
6838{
6839
6840 //On iOS: do not highlight hist, if part of it was selected.
6841 //Never executes on non-iOS platform.
6842 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
6843 return;
6844
6845 static char chopth[17];
6846
6847 Int_t htype, oldhtype;
6848 Int_t i, j, first, last, nbins, fixbin;
6849 Double_t c1, yb;
6850 yb = 0;
6851
6852 strlcpy(chopth, " ",17);
6853
6856 Double_t baroffset = fH->GetBarOffset();
6857 Double_t barwidth = fH->GetBarWidth();
6858 Double_t baroffsetsave = gStyle->GetBarOffset();
6859 Double_t barwidthsave = gStyle->GetBarWidth();
6860 gStyle->SetBarOffset(baroffset);
6861 gStyle->SetBarWidth(barwidth);
6862
6863 // Create "LIFE" structure to keep current histogram status
6864
6865 first = Hparam.xfirst;
6866 last = Hparam.xlast;
6867 nbins = last - first + 1;
6868
6869 std::vector<Double_t> keepx, keepy;
6870 if (fXaxis->GetXbins()->fN) fixbin = 0;
6871 else fixbin = 1;
6872 if (fixbin) keepx.resize(2);
6873 else keepx.resize(nbins+1);
6874 keepy.resize(nbins);
6875 Double_t logymin = 0;
6876 if (Hoption.Logy) logymin = TMath::Power(10,ymin);
6877
6878 // Loop on histogram bins
6879
6880 for (j=first; j<=last;j++) {
6882 if (TMath::Abs(ymax-ymin) > 0) {
6883 if (Hoption.Logy) yb = TMath::Log10(TMath::Max(c1,.1*logymin));
6884 else yb = c1;
6885 }
6886 if (!Hoption.Line) {
6887 yb = TMath::Max(yb, ymin);
6888 yb = TMath::Min(yb, ymax);
6889 }
6890 keepy[j-first] = yb;
6891 }
6892
6893 // Draw histogram according to value of FillStyle and FillColor
6894
6895 if (fixbin) { keepx[0] = Hparam.xmin; keepx[1] = Hparam.xmax; }
6896 else {
6897 for (i=0; i<nbins; i++) keepx[i] = fXaxis->GetBinLowEdge(i+first);
6898 keepx[nbins] = fXaxis->GetBinUpEdge(nbins-1+first);
6899 }
6900
6901 // Prepare Fill area (systematic with option "Bar").
6902
6903 oldhtype = fH->GetFillStyle();
6904 htype = oldhtype;
6905 if (Hoption.Bar) {
6906 if (htype == 0 || htype == 1000) htype = 1001;
6907 }
6908
6909 Width_t lw = (Width_t)fH->GetLineWidth();
6910
6911 // Code option for GrapHist
6912
6913 if (Hoption.Line) chopth[0] = 'L';
6914 if (Hoption.Star) chopth[1] = '*';
6915 if (Hoption.Mark) chopth[2] = 'P';
6916 if (Hoption.Mark == 10) chopth[3] = '0';
6918 if (Hoption.Curve) chopth[3] = 'C';
6919 if (Hoption.Hist > 0) chopth[4] = 'H';
6920 else if (Hoption.Bar) chopth[5] = 'B';
6921 if (Hoption.Logy) chopth[6] = '1';
6922 if (fH->GetFillColor() && htype) {
6923 if (Hoption.Hist > 0 || Hoption.Curve || Hoption.Line) {
6924 chopth[7] = 'F';
6925 }
6926 }
6927 }
6928 if (!fixbin && strlen(chopth)) {
6929 chopth[8] = 'N';
6930 }
6931
6932 if (Hoption.Fill == 2) chopth[13] = '2';
6933
6934 // Option LOGX
6935
6936 if (Hoption.Logx) {
6937 chopth[9] = 'G';
6938 chopth[10] = 'X';
6939 if (fixbin) {
6940 keepx[0] = TMath::Power(10,keepx[0]);
6941 keepx[1] = TMath::Power(10,keepx[1]);
6942 }
6943 }
6944
6945 if (Hoption.Off) {
6946 chopth[11] = ']';
6947 chopth[12] = '[';
6948 }
6949
6950 // Draw the histogram
6951
6952 TGraph graph;
6953 graph.SetLineWidth(lw);
6954 graph.SetLineStyle(fH->GetLineStyle());
6955 graph.SetLineColor(fH->GetLineColor());
6956 graph.SetFillStyle(htype);
6957 graph.SetFillColor(fH->GetFillColor());
6958 graph.SetMarkerStyle(fH->GetMarkerStyle());
6959 graph.SetMarkerSize(fH->GetMarkerSize());
6960 graph.SetMarkerColor(fH->GetMarkerColor());
6961 if (!Hoption.Same) graph.ResetBit(TGraph::kClipFrame);
6962
6963 graph.PaintGrapHist(nbins, keepx.data(), keepy.data() ,chopth);
6964
6965 gStyle->SetBarOffset(baroffsetsave);
6966 gStyle->SetBarWidth(barwidthsave);
6967
6968 htype=oldhtype;
6969}
6970
6971////////////////////////////////////////////////////////////////////////////////
6972/// [Control function to draw a 3D histograms.](\ref HP01d)
6973
6975{
6976
6977 TString cmd;
6978 TString opt = option;
6979 opt.ToLower();
6980 Int_t irep;
6981 Float_t NEntries = fH->GetEntries();
6982
6983 if (fCurrentF3 || strstr(opt,"tf3")) {
6984 PaintTF3();
6985 return;
6986 }
6987
6988 if (NEntries > 0) {
6989 if (Hoption.Box || Hoption.Lego || Hoption.Color) {
6990 if (Hoption.Box == 11 || Hoption.Lego == 11) {
6991 PaintH3Box(1);
6992 } else if (Hoption.Box == 12 || Hoption.Lego == 12 || Hoption.Color == 1) {
6993 PaintH3Box(2);
6994 } else if (Hoption.Box == 13 || Hoption.Lego == 13) {
6995 PaintH3Box(3);
6996 } else {
6998 }
6999 return;
7000 }
7001
7002 if (strstr(opt,"iso")) {
7003 PaintH3Iso();
7004 return;
7005 }
7006 }
7007
7008 TView *view = gPad ? gPad->GetView() : nullptr;
7009 if (!view) return;
7010
7011 if (strstr(opt,"fb")) Hoption.FrontBox = 0;
7012 if (strstr(opt,"bb")) Hoption.BackBox = 0;
7013
7014 Double_t thedeg = 90 - gPad->GetTheta();
7015 Double_t phideg = -90 - gPad->GetPhi();
7016 Double_t psideg = view->GetPsi();
7017 view->SetView(phideg, thedeg, psideg, irep);
7018
7019 if(NEntries > 0) { // Paint as 3D scatter plot
7020 cmd.Form("TPolyMarker3D::PaintH3((TH1 *)0x%zx,\"%s\");",(size_t)fH,option);
7021 gROOT->ProcessLine(cmd.Data());
7022 } else {
7023 TAxis* xAxis = fH->GetXaxis();
7024 TAxis* yAxis = fH->GetYaxis();
7025 TAxis* zAxis = fH->GetZaxis();
7026 Double_t xmin = xAxis->GetXmin();
7027 Double_t xmax = xAxis->GetXmax();
7028 Double_t ymin = yAxis->GetXmin();
7029 Double_t ymax = yAxis->GetXmax();
7030 Double_t zmin = zAxis->GetXmin();
7031 Double_t zmax = zAxis->GetXmax();
7032 view->SetRange(xmin, ymin, zmin, xmax, ymax, zmax); // Set the axis limits (Xmin, Ymin, Zmin, Xmax, Ymax, Zmax)
7033 }
7034
7035 if (Hoption.Same) return;
7036
7037 // Draw axis
7038 view->SetOutlineToCube();
7039 TSeqCollection *ol = view->GetOutline();
7040 if (ol && Hoption.BackBox && Hoption.FrontBox) ol->Paint(option);
7042
7043 if (!Hoption.Axis && !Hoption.Same) {
7044 TGaxis axis;
7045 PaintLegoAxis(&axis, 90);
7046 }
7047
7048 // Draw palette. In case of 4D plot with TTree::Draw() the palette should
7049 // be painted with the option colz.
7050 if (fH->GetDrawOption() && strstr(opt,"colz")) {
7051 Int_t ndiv = fH->GetContour();
7052 if (ndiv == 0 ) {
7053 ndiv = gStyle->GetNumberContours();
7054 fH->SetContour(ndiv);
7055 }
7056 PaintPalette();
7057 }
7058
7059 // Draw title
7060 PaintTitle();
7061
7062 //Draw stats and fit results
7063 TF1 *fit = nullptr;
7064 TIter next(fFunctions);
7065 while (auto obj = next()) {
7066 if (obj->InheritsFrom(TF1::Class())) {
7067 fit = (TF1*)obj;
7068 break;
7069 }
7070 }
7071 if ((Hoption.Same%10) != 1) {
7072 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7074 }
7075 }
7076
7077}
7078
7079////////////////////////////////////////////////////////////////////////////////
7080/// Compute histogram parameters used by the drawing routines.
7081
7083{
7084
7085 if (fH->GetDimension() > 1 || Hoption.Lego || Hoption.Surf) return 1;
7086
7087 Int_t i;
7088 static const char *where = "PaintInit";
7089 Double_t yMARGIN = gStyle->GetHistTopMargin();
7090 Int_t maximum = 0;
7091 Int_t minimum = 0;
7092 if (fH->GetMaximumStored() != -1111) maximum = 1;
7093 if (fH->GetMinimumStored() != -1111) minimum = 1;
7094
7095 // Compute X axis parameters
7096
7097 Int_t last = fXaxis->GetLast();
7098 Int_t first = fXaxis->GetFirst();
7101 Hparam.xlast = last;
7102 Hparam.xfirst = first;
7105
7106 // if log scale in X, replace xmin,max by the log
7107 if (Hoption.Logx) {
7108 if (Hparam.xmax<=0) {
7109 Error(where, "cannot set X axis to log scale");
7110 return 0;
7111 }
7112 if (Hparam.xlowedge <=0 ) {
7113 if (Hoption.Same) {
7114 TH1* h1 = nullptr;
7115 TObject *obj;
7116 TIter next(gPad->GetListOfPrimitives());
7117 while ((obj = (TObject *)next())) {
7118 if (obj->InheritsFrom(TH1::Class())) { h1 = (TH1*)(obj) ; break; }
7119 if (obj->InheritsFrom(THStack::Class())) { h1 = ((THStack*)(obj))->GetHistogram() ; break; }
7120 if (obj->InheritsFrom(TGraph::Class())) { h1 = ((TGraph*)(obj))->GetHistogram() ; break; }
7121 if (obj->InheritsFrom(TMultiGraph::Class())) { h1 = ((TMultiGraph*)(obj))->GetHistogram(); break; }
7122 if (obj->InheritsFrom(TGraph2D::Class())) { h1 = ((TGraph2D*)(obj))->GetHistogram(); break; }
7123 if (obj->InheritsFrom(TF1::Class())) { h1 = ((TF1*)(obj))->GetHistogram(); break; }
7124 }
7125 if (h1) {
7127 } else {
7128 Error(where, "undefined user's coordinates. Cannot use option SAME");
7129 return 0;
7130 }
7131 } else {
7132 for (i=first; i<=last; i++) {
7133 Double_t binLow = fXaxis->GetBinLowEdge(i);
7134 if (binLow>0) {
7135 Hparam.xlowedge = binLow;
7136 break;
7137 }
7138 if (binLow == 0 && fH->GetBinContent(i) !=0) {
7139 Hparam.xlowedge = fXaxis->GetBinUpEdge(i)*0.001;
7140 break;
7141 }
7142 }
7143 if (Hparam.xlowedge<=0) {
7144 Error(where, "cannot set X axis to log scale");
7145 return 0;
7146 }
7147 }
7149 }
7154 if (Hparam.xlast > last) Hparam.xlast = last;
7155 if (Hparam.xfirst < first) Hparam.xfirst = first;
7156 }
7157
7158 // Compute Y axis parameters
7159 Double_t bigp = TMath::Power(10,32);
7160 Double_t ymax = -bigp;
7161 Double_t ymin = bigp;
7162 Double_t c1, e1;
7163 Double_t xv[1];
7164 Double_t fval;
7165 TObject *f;
7166 TF1 *f1;
7167 Double_t allchan = 0;
7168 Int_t nonNullErrors = 0;
7169 TIter next(fFunctions);
7170 for (i=first; i<=last;i++) {
7171 c1 = fH->GetBinContent(i);
7173 if (Hoption.Logy) {
7174 if (c1 > 0) ymin = TMath::Min(ymin,c1);
7175 } else {
7177 }
7178 if (Hoption.Error) {
7180 e1 = fH->GetBinError(i);
7181 else
7182 e1 = fH->GetBinErrorUp(i);
7183 if (e1 > 0) nonNullErrors++;
7184 ymax = TMath::Max(ymax,c1+e1);
7186 e1 = fH->GetBinErrorLow(i);
7187
7188 if (Hoption.Logy) {
7189 if (c1-e1>0.01*TMath::Abs(c1)) ymin = TMath::Min(ymin,c1-e1);
7190 } else {
7191 ymin = TMath::Min(ymin,c1-e1);
7192 }
7193 }
7194 if (Hoption.Func) {
7195 xv[0] = fXaxis->GetBinCenter(i);
7196 while ((f = (TObject*) next())) {
7197 if (f->IsA() == TF1::Class()) {
7198 f1 = (TF1*)f;
7199 if (xv[0] < f1->GetXmin() || xv[0] > f1->GetXmax()) continue;
7200 fval = f1->Eval(xv[0],0,0);
7201 if (f1->GetMaximumStored() != -1111) fval = TMath::Min(f1->GetMaximumStored(), fval);
7202 ymax = TMath::Max(ymax,fval);
7203 if (Hoption.Logy) {
7204 if (c1 > 0 && fval > 0.3*c1) ymin = TMath::Min(ymin,fval);
7205 }
7206 }
7207 }
7208 next.Reset();
7209 }
7210 allchan += c1;
7211 }
7212 if (!nonNullErrors) {
7213 if (Hoption.Error) {
7214 if (!Hoption.Mark && !Hoption.Line && !Hoption.Star && !Hoption.Curve) Hoption.Hist = 2;
7215 Hoption.Error=0;
7216 }
7217 }
7218
7219
7220 // Take into account maximum , minimum
7221
7222 if (Hoption.Logy && ymin <= 0) {
7223 if (ymax >= 1) ymin = TMath::Max(.005,ymax*1e-10);
7224 else ymin = 0.001*ymax;
7225 }
7226
7227 Double_t xm = ymin;
7228 if (maximum) ymax = fH->GetMaximumStored();
7229 if (minimum) xm = fH->GetMinimumStored();
7230 if (Hoption.Logy && xm < 0) {
7231 Error(where, "log scale requested with a negative argument (%f)", xm);
7232 return 0;
7233 } else if (Hoption.Logy && xm>=0 && ymax==0) { // empty histogram in log scale
7234 ymin = 0.01;
7235 ymax = 10.;
7236 } else {
7237 ymin = xm;
7238 }
7239
7240 if (ymin >= ymax) {
7241 if (Hoption.Logy) {
7242 if (ymax > 0) ymin = 0.001*ymax;
7243 else {
7244 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", ymax);
7245 return 0;
7246 }
7247 }
7248 else {
7249 if (ymin > 0) {
7250 ymin = 0;
7251 ymax *= 2;
7252 } else if (ymin < 0) {
7253 ymax = 0;
7254 ymin *= 2;
7255 } else {
7256 ymin = 0;
7257 ymax = 1;
7258 }
7259 }
7260 }
7261
7262 // In some cases, mainly because of precision issues, ymin and ymax could almost equal.
7263 if (TMath::AreEqualRel(ymin,ymax,1E-15)) {
7264 ymin = ymin*(1-1E-14);
7265 ymax = ymax*(1+1E-14);
7266 }
7267
7268 // take into account normalization factor
7269 Hparam.allchan = allchan;
7270 Double_t factor = allchan;
7271 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
7272 if (allchan) factor /= allchan;
7273 if (factor == 0) factor = 1;
7274 Hparam.factor = factor;
7275 ymax = factor*ymax;
7276 ymin = factor*ymin;
7277 //just in case the norm factor is negative
7278 // this may happen with a positive norm factor and a negative integral !
7279 if (ymax < ymin) {
7280 Double_t temp = ymax;
7281 ymax = ymin;
7282 ymin = temp;
7283 }
7284
7285 // For log scales, histogram coordinates are LOG10(ymin) and
7286 // LOG10(ymax). Final adjustment (if not option "Same"
7287 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
7288 // Maximum and Minimum are not defined.
7289 if (Hoption.Logy) {
7290 if (ymin <=0 || ymax <=0) {
7291 Error(where, "Cannot set Y axis to log scale");
7292 return 0;
7293 }
7295 if (!minimum) ymin += TMath::Log10(0.5);
7297 if (!maximum) ymax += TMath::Log10(2*(0.9/0.95));
7298 if (!Hoption.Same) {
7299 Hparam.ymin = ymin;
7300 Hparam.ymax = ymax;
7301 }
7302 return 1;
7303 }
7304
7305 // final adjustment of ymin for linear scale.
7306 // if minimum is not set , then ymin is set to zero if >0
7307 // or to ymin - margin if <0.
7308 if (!minimum) {
7309 if (Hoption.MinimumZero) {
7310 if (ymin >= 0) ymin = 0;
7311 else ymin -= yMARGIN*(ymax-ymin);
7312 } else {
7313 Double_t dymin = yMARGIN*(ymax-ymin);
7314 if (ymin >= 0 && (ymin-dymin <= 0)) ymin = 0;
7315 else ymin -= dymin;
7316 }
7317 }
7318
7319 // final adjustment of YMAXI for linear scale (if not option "Same"):
7320 // decrease histogram height to MAX% of allowed height if HMAXIM
7321 // has not been called.
7322 if (!maximum) {
7323 ymax += yMARGIN*(ymax-ymin);
7324 }
7325
7326 Hparam.ymin = ymin;
7327 Hparam.ymax = ymax;
7328 return 1;
7329}
7330
7331////////////////////////////////////////////////////////////////////////////////
7332/// Compute histogram parameters used by the drawing routines for a rotated pad.
7333
7335{
7336
7337 static const char *where = "PaintInitH";
7338 Double_t yMARGIN = gStyle->GetHistTopMargin();
7339 Int_t maximum = 0;
7340 Int_t minimum = 0;
7341 if (fH->GetMaximumStored() != -1111) maximum = 1;
7342 if (fH->GetMinimumStored() != -1111) minimum = 1;
7343
7344 // Compute X axis parameters
7345
7346 Int_t last = fXaxis->GetLast();
7347 Int_t first = fXaxis->GetFirst();
7350 Hparam.xlast = last;
7351 Hparam.xfirst = first;
7354
7355 // if log scale in Y, replace ymin,max by the log
7356 if (Hoption.Logy) {
7357 if (Hparam.xlowedge <=0 ) {
7360 }
7361 if (Hparam.ymin <=0 || Hparam.ymax <=0) {
7362 Error(where, "cannot set Y axis to log scale");
7363 return 0;
7364 }
7369 if (Hparam.xlast > last) Hparam.xlast = last;
7370 }
7371
7372 // Compute Y axis parameters
7373 Double_t bigp = TMath::Power(10,32);
7374 Double_t xmax = -bigp;
7375 Double_t xmin = bigp;
7376 Double_t c1, e1;
7377 Double_t xv[1];
7378 Double_t fval;
7379 Int_t i;
7380 TObject *f;
7381 TF1 *f1;
7382 Double_t allchan = 0;
7383 TIter next(fFunctions);
7384 for (i=first; i<=last;i++) {
7385 c1 = fH->GetBinContent(i);
7388 if (Hoption.Error) {
7389 e1 = fH->GetBinError(i);
7390 xmax = TMath::Max(xmax,c1+e1);
7391 xmin = TMath::Min(xmin,c1-e1);
7392 }
7393 if (Hoption.Func) {
7394 xv[0] = fXaxis->GetBinCenter(i);
7395 while ((f = (TObject*) next())) {
7396 if (f->IsA() == TF1::Class()) {
7397 f1 = (TF1*)f;
7398 if (xv[0] < f1->GetXmin() || xv[0] > f1->GetXmax()) continue;
7399 fval = f1->Eval(xv[0],0,0);
7400 xmax = TMath::Max(xmax,fval);
7401 if (Hoption.Logy) {
7402 if (fval > 0.3*c1) xmin = TMath::Min(xmin,fval);
7403 }
7404 }
7405 }
7406 next.Reset();
7407 }
7408 allchan += c1;
7409 }
7410
7411 // Take into account maximum , minimum
7412
7413 if (Hoption.Logx && xmin <= 0) {
7414 if (xmax >= 1) xmin = TMath::Max(.5,xmax*1e-10);
7415 else xmin = 0.001*xmax;
7416 }
7417 Double_t xm = xmin;
7418 if (maximum) xmax = fH->GetMaximumStored();
7419 if (minimum) xm = fH->GetMinimumStored();
7420 if (Hoption.Logx && xm <= 0) {
7421 Error(where, "log scale requested with zero or negative argument (%f)", xm);
7422 return 0;
7423 }
7424 else xmin = xm;
7425 if (xmin >= xmax) {
7426 if (Hoption.Logx) {
7427 if (xmax > 0) xmin = 0.001*xmax;
7428 else {
7429 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", xmax);
7430 return 0;
7431 }
7432 }
7433 else {
7434 if (xmin > 0) {
7435 xmin = 0;
7436 xmax *= 2;
7437 } else if (xmin < 0) {
7438 xmax = 0;
7439 xmin *= 2;
7440 } else {
7441 xmin = 0;
7442 xmax = 1;
7443 }
7444 }
7445 }
7446
7447 // take into account normalization factor
7448 Hparam.allchan = allchan;
7449 Double_t factor = allchan;
7450 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
7451 if (allchan) factor /= allchan;
7452 if (factor == 0) factor = 1;
7453 Hparam.factor = factor;
7454 xmax = factor*xmax;
7455 xmin = factor*xmin;
7456
7457 // For log scales, histogram coordinates are LOG10(ymin) and
7458 // LOG10(ymax). Final adjustment (if not option "Same"
7459 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
7460 // Maximum and Minimum are not defined.
7461 if (Hoption.Logx) {
7462 if (xmin <=0 || xmax <=0) {
7463 Error(where, "Cannot set Y axis to log scale");
7464 return 0;
7465 }
7467 if (!minimum) xmin += TMath::Log10(0.5);
7469 if (!maximum) xmax += TMath::Log10(2*(0.9/0.95));
7470 if (!Hoption.Same) {
7471 Hparam.xmin = xmin;
7472 Hparam.xmax = xmax;
7473 }
7474 return 1;
7475 }
7476
7477 // final adjustment of ymin for linear scale.
7478 // if minimum is not set , then ymin is set to zero if >0
7479 // or to ymin - margin if <0.
7480 if (!minimum) {
7481 if (xmin >= 0) xmin = 0;
7482 else xmin -= yMARGIN*(xmax-xmin);
7483 }
7484
7485 // final adjustment of YMAXI for linear scale (if not option "Same"):
7486 // decrease histogram height to MAX% of allowed height if HMAXIM
7487 // has not been called.
7488 if (!maximum) {
7489 xmax += yMARGIN*(xmax-xmin);
7490 }
7491 Hparam.xmin = xmin;
7492 Hparam.xmax = xmax;
7493 return 1;
7494}
7495
7496////////////////////////////////////////////////////////////////////////////////
7497/// [Control function to draw a 3D histogram with boxes.](\ref HP25)
7498
7500{
7501 // Predefined box structure
7502 Double_t wxyz[8][3] = { {-1,-1,-1}, {1,-1,-1}, {1,1,-1}, {-1,1,-1},
7503 {-1,-1, 1}, {1,-1, 1}, {1,1, 1}, {-1,1, 1} };
7504 Int_t iface[6][4] = { {0,3,2,1}, {4,5,6,7},
7505 {0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7} };
7506
7507 // Define dimensions of world space
7508 TAxis *xaxis = fH->GetXaxis();
7509 TAxis *yaxis = fH->GetYaxis();
7510 TAxis *zaxis = fH->GetZaxis();
7511
7512 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7513 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7514 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7515 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7516 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7517 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7518
7519 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7520
7521 // Set view
7522 TView *view = gPad ? gPad->GetView() : nullptr;
7523 if (!view) {
7524 Error("PaintH3", "no TView in current pad");
7525 return;
7526 }
7527 Double_t thedeg = 90 - gPad->GetTheta();
7528 Double_t phideg = -90 - gPad->GetPhi();
7529 Double_t psideg = view->GetPsi();
7530 Int_t irep;
7531 view->SetView(phideg, thedeg, psideg, irep);
7532
7533 Int_t backcolor = gPad->GetFrameFillColor();
7534 view->PadRange(backcolor);
7535
7536 // Draw back surfaces of frame box
7537 fLego->InitMoveScreen(-1.1,1.1);
7538 if (Hoption.BackBox) {
7539 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
7541 fLego->BackBox(90);
7542 }
7543
7545
7546 // Define order of drawing
7547 Double_t *tnorm = view->GetTnorm();
7548 if (!tnorm) return;
7549 Int_t incrx = (tnorm[ 8] < 0.) ? -1 : +1;
7550 Int_t incry = (tnorm[ 9] < 0.) ? -1 : +1;
7551 Int_t incrz = (tnorm[10] < 0.) ? -1 : +1;
7552 Int_t ix1 = (incrx == +1) ? xaxis->GetFirst() : xaxis->GetLast();
7553 Int_t iy1 = (incry == +1) ? yaxis->GetFirst() : yaxis->GetLast();
7554 Int_t iz1 = (incrz == +1) ? zaxis->GetFirst() : zaxis->GetLast();
7555 Int_t ix2 = (incrx == +1) ? xaxis->GetLast() : xaxis->GetFirst();
7556 Int_t iy2 = (incry == +1) ? yaxis->GetLast() : yaxis->GetFirst();
7557 Int_t iz2 = (incrz == +1) ? zaxis->GetLast() : zaxis->GetFirst();
7558
7559 // Set graphic attributes (colour, style, etc.)
7560 Style_t fillsav = fH->GetFillStyle();
7561 Style_t colsav = fH->GetFillColor();
7562 Style_t coldark = TColor::GetColorDark(colsav);
7563 Style_t colbright = TColor::GetColorBright(colsav);
7564
7565 fH->SetFillStyle(1001);
7566 fH->TAttFill::Modify();
7567 fH->TAttLine::Modify();
7568 Int_t ncolors = gStyle->GetNumberOfColors();
7569 Int_t theColor;
7570
7571 // Create bin boxes and draw
7575
7576 Double_t pmin[3], pmax[3], sxyz[8][3];
7577 for (Int_t ix = ix1; ix !=ix2+incrx; ix += incrx) {
7578 pmin[0] = xaxis->GetBinLowEdge(ix);
7579 pmax[0] = xaxis->GetBinUpEdge(ix);
7580 for (Int_t iy = iy1; iy != iy2+incry; iy += incry) {
7581 pmin[1] = yaxis->GetBinLowEdge(iy);
7582 pmax[1] = yaxis->GetBinUpEdge(iy);
7583 for (Int_t iz = iz1; iz != iz2+incrz; iz += incrz) {
7584 pmin[2] = zaxis->GetBinLowEdge(iz);
7585 pmax[2] = zaxis->GetBinUpEdge(iz);
7586 Double_t w = fH->GetBinContent(fH->GetBin(ix,iy,iz));
7587 Bool_t neg = kFALSE;
7588 Int_t n = 5;
7589 if (w<0) {
7590 w = -w;
7591 neg = kTRUE;
7592 }
7593 if (w < wmin) continue;
7594 if (w > wmax) w = wmax;
7595 Double_t scale = (TMath::Power((w-wmin)/(wmax-wmin),1./3.))/2.;
7596 if (scale == 0) continue;
7597 for (Int_t i=0; i<3; ++i) {
7598 Double_t c = (pmax[i] + pmin[i])*0.5;
7599 Double_t d = (pmax[i] - pmin[i])*scale;
7600 for (Int_t k=0; k<8; ++k) { // set bin box vertices
7601 sxyz[k][i] = wxyz[k][i]*d + c;
7602 }
7603 }
7604 for (Int_t k=0; k<8; ++k) { // transform to normalized space
7605 view->WCtoNDC(&sxyz[k][0],&sxyz[k][0]);
7606 }
7607 Double_t x[8], y[8]; // draw bin box faces
7608 for (Int_t k=0; k<6; ++k) {
7609 for (Int_t i=0; i<4; ++i) {
7610 Int_t iv = iface[k][i];
7611 x[i] = sxyz[iv][0];
7612 y[i] = sxyz[iv][1];
7613 }
7614 x[4] = x[0] ; y[4] = y[0];
7615 if (neg) {
7616 x[5] = x[2] ; y[5] = y[2];
7617 x[6] = x[3] ; y[6] = y[3];
7618 x[7] = x[1] ; y[7] = y[1];
7619 n = 8;
7620 } else {
7621 n = 5;
7622 }
7623 Double_t z = (x[2]-x[0])*(y[3]-y[1]) - (y[2]-y[0])*(x[3]-x[1]);
7624 if (z <= 0.) continue;
7625 if (iopt == 2) {
7626 theColor = ncolors*((w-wmin)/(wmax-wmin)) -1;
7628 } else {
7629 if (k == 3 || k == 5) {
7630 fH->SetFillColor(coldark);
7631 } else if (k == 0 || k == 1) {
7632 fH->SetFillColor(colbright);
7633 } else {
7634 fH->SetFillColor(colsav);
7635 }
7636 }
7637 fH->TAttFill::Modify();
7638 gPad->PaintFillArea(4, x, y);
7639 if (iopt != 3)gPad->PaintPolyLine(n, x, y);
7640 }
7641 }
7642 }
7643 }
7644
7645 // Draw front surfaces of frame box
7646 if (Hoption.FrontBox) fLego->FrontBox(90);
7647
7648 // Draw axis and title
7649 if (!Hoption.Axis && !Hoption.Same) {
7650 TGaxis axis;
7651 PaintLegoAxis(&axis, 90);
7652 }
7653 PaintTitle();
7654
7655 // Draw palette. if needed.
7656 if (Hoption.Zscale) {
7657 Int_t ndiv = fH->GetContour();
7658 if (ndiv == 0 ) {
7659 ndiv = gStyle->GetNumberContours();
7660 fH->SetContour(ndiv);
7661 }
7662 PaintPalette();
7663 }
7664
7665 //Draw stats and fit results
7666 TF1 *fit = nullptr;
7667 TIter next(fFunctions);
7668 while (auto obj = next()) {
7669 if (obj->InheritsFrom(TF1::Class())) {
7670 fit = (TF1*)obj;
7671 break;
7672 }
7673 }
7674 if ((Hoption.Same%10) != 1) {
7675 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7677 }
7678 }
7679
7680 fLego.reset();
7681
7682 fH->SetFillStyle(fillsav);
7683 fH->SetFillColor(colsav);
7684 fH->TAttFill::Modify();
7685}
7686
7687////////////////////////////////////////////////////////////////////////////////
7688/// [Control function to draw a 3D histogram with boxes.](\ref HP25)
7689
7691{
7692 // Predefined box structure
7693 Double_t wxyz[8][3] = {
7694 {-1,-1,-1}, {1,-1,-1}, {1,1,-1}, {-1,1,-1}, // bottom vertices
7695 {-1,-1, 1}, {1,-1, 1}, {1,1, 1}, {-1,1, 1} // top vertices
7696 };
7697 Int_t iface[6][4] = {
7698 {0,3,2,1}, {4,5,6,7}, // bottom and top faces
7699 {0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7} // side faces
7700 };
7701 Double_t normal[6][3] = {
7702 {0,0,-1}, {0,0,1}, // Z-, Z+
7703 {0,-1,0}, {1,0,0}, {0,1,0}, {-1,0,0} // Y-, X+, Y+, X-
7704 };
7705
7706 // Define dimensions of world space
7707 TAxis *xaxis = fH->GetXaxis();
7708 TAxis *yaxis = fH->GetYaxis();
7709 TAxis *zaxis = fH->GetZaxis();
7710
7711 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7712 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7713 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7714 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7715 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7716 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7717
7718 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7719
7720 // Set view
7721 TView *view = gPad ? gPad->GetView() : nullptr;
7722 if (!view) {
7723 Error("PaintH3", "no TView in current pad");
7724 return;
7725 }
7726 Double_t thedeg = 90 - gPad->GetTheta();
7727 Double_t phideg = -90 - gPad->GetPhi();
7728 Double_t psideg = view->GetPsi();
7729 Int_t irep;
7730 view->SetView(phideg, thedeg, psideg, irep);
7731
7732 Int_t backcolor = gPad->GetFrameFillColor();
7733 view->PadRange(backcolor);
7734
7735 // Draw front surfaces of frame box
7736 if (Hoption.FrontBox) {
7737 fLego->InitMoveScreen(-1.1,1.1);
7739 }
7740
7741 // Initialize hidden line removal algorithm "raster screen"
7742 fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
7743
7744 // Define order of drawing
7745 Double_t *tnorm = view->GetTnorm();
7746 if (!tnorm) return;
7747 Int_t incrx = (tnorm[ 8] < 0.) ? +1 : -1;
7748 Int_t incry = (tnorm[ 9] < 0.) ? +1 : -1;
7749 Int_t incrz = (tnorm[10] < 0.) ? +1 : -1;
7750 Int_t ix1 = (incrx == +1) ? xaxis->GetFirst() : xaxis->GetLast();
7751 Int_t iy1 = (incry == +1) ? yaxis->GetFirst() : yaxis->GetLast();
7752 Int_t iz1 = (incrz == +1) ? zaxis->GetFirst() : zaxis->GetLast();
7753 Int_t ix2 = (incrx == +1) ? xaxis->GetLast() : xaxis->GetFirst();
7754 Int_t iy2 = (incry == +1) ? yaxis->GetLast() : yaxis->GetFirst();
7755 Int_t iz2 = (incrz == +1) ? zaxis->GetLast() : zaxis->GetFirst();
7756
7757 // Set line attributes (colour, style, etc.)
7758 fH->TAttLine::Modify();
7759
7760 // Create bin boxes and draw
7761 const Int_t NTMAX = 100;
7762 Double_t tt[NTMAX][2];
7766 Double_t pmin[3], pmax[3], sxyz[8][3], pp[4][2];
7767 for (Int_t ix = ix1; ix !=ix2+incrx; ix += incrx) {
7768 pmin[0] = xaxis->GetBinLowEdge(ix);
7769 pmax[0] = xaxis->GetBinUpEdge(ix);
7770 for (Int_t iy = iy1; iy != iy2+incry; iy += incry) {
7771 pmin[1] = yaxis->GetBinLowEdge(iy);
7772 pmax[1] = yaxis->GetBinUpEdge(iy);
7773 for (Int_t iz = iz1; iz != iz2+incrz; iz += incrz) {
7774 pmin[2] = zaxis->GetBinLowEdge(iz);
7775 pmax[2] = zaxis->GetBinUpEdge(iz);
7776 Double_t w = fH->GetBinContent(fH->GetBin(ix,iy,iz));
7777 Bool_t neg = kFALSE;
7778 if (w<0) {
7779 w = -w;
7780 neg = kTRUE;
7781 }
7782 if (w < wmin) continue;
7783 if (w > wmax) w = wmax;
7784 Double_t scale = (TMath::Power((w-wmin)/(wmax-wmin),1./3.))/2.;
7785 if (scale == 0) continue;
7786 for (Int_t i=0; i<3; ++i) {
7787 Double_t c = (pmax[i] + pmin[i])*0.5;
7788 Double_t d = (pmax[i] - pmin[i])*scale;
7789 for (Int_t k=0; k<8; ++k) { // set bin box vertices
7790 sxyz[k][i] = wxyz[k][i]*d + c;
7791 }
7792 }
7793 for (Int_t k=0; k<8; ++k) { // transform to normalized space
7794 view->WCtoNDC(&sxyz[k][0],&sxyz[k][0]);
7795 }
7796 for (Int_t k=0; k<6; ++k) { // draw box faces
7797 Double_t zn;
7798 view->FindNormal(normal[k][0], normal[k][1], normal[k][2], zn);
7799 if (zn <= 0) continue;
7800 for (Int_t i=0; i<4; ++i) {
7801 Int_t ip = iface[k][i];
7802 pp[i][0] = sxyz[ip][0];
7803 pp[i][1] = sxyz[ip][1];
7804 }
7805 for (Int_t i=0; i<4; ++i) {
7806 Int_t i1 = i;
7807 Int_t i2 = (i == 3) ? 0 : i + 1;
7808 Int_t nt;
7809 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7810 Double_t xdel = pp[i2][0] - pp[i1][0];
7811 Double_t ydel = pp[i2][1] - pp[i1][1];
7812 Double_t x[2], y[2];
7813 for (Int_t it = 0; it < nt; ++it) {
7814 x[0] = pp[i1][0] + xdel*tt[it][0];
7815 y[0] = pp[i1][1] + ydel*tt[it][0];
7816 x[1] = pp[i1][0] + xdel*tt[it][1];
7817 y[1] = pp[i1][1] + ydel*tt[it][1];
7818 gPad->PaintPolyLine(2, x, y);
7819 }
7820 }
7821 if (neg) {
7822 Int_t i1 = 0;
7823 Int_t i2 = 2;
7824 Int_t nt;
7825 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7826 Double_t xdel = pp[i2][0] - pp[i1][0];
7827 Double_t ydel = pp[i2][1] - pp[i1][1];
7828 Double_t x[2], y[2];
7829 for (Int_t it = 0; it < nt; ++it) {
7830 x[0] = pp[i1][0] + xdel*tt[it][0];
7831 y[0] = pp[i1][1] + ydel*tt[it][0];
7832 x[1] = pp[i1][0] + xdel*tt[it][1];
7833 y[1] = pp[i1][1] + ydel*tt[it][1];
7834 gPad->PaintPolyLine(2, x, y);
7835 }
7836 i1 = 1;
7837 i2 = 3;
7838 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7839 xdel = pp[i2][0] - pp[i1][0];
7840 ydel = pp[i2][1] - pp[i1][1];
7841 for (Int_t it = 0; it < nt; ++it) {
7842 x[0] = pp[i1][0] + xdel*tt[it][0];
7843 y[0] = pp[i1][1] + ydel*tt[it][0];
7844 x[1] = pp[i1][0] + xdel*tt[it][1];
7845 y[1] = pp[i1][1] + ydel*tt[it][1];
7846 gPad->PaintPolyLine(2, x, y);
7847 }
7848 }
7849 fLego->FillPolygonBorder(4, &pp[0][0]); // update raster screen
7850 }
7851 }
7852 }
7853 }
7854
7855 // Draw frame box
7856 if (Hoption.BackBox) {
7857 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
7859 fLego->BackBox(90);
7860 }
7861
7862 if (Hoption.FrontBox) fLego->FrontBox(90);
7863
7864 // Draw axis and title
7865 if (!Hoption.Axis && !Hoption.Same) {
7866 TGaxis axis;
7867 PaintLegoAxis(&axis, 90);
7868 }
7869 PaintTitle();
7870
7871 //Draw stats and fit results
7872 TF1 *fit = nullptr;
7873 TIter next(fFunctions);
7874 while (auto obj = next()) {
7875 if (obj->InheritsFrom(TF1::Class())) {
7876 fit = (TF1*)obj;
7877 break;
7878 }
7879 }
7880 if ((Hoption.Same%10) != 1) {
7881 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7883 }
7884 }
7885
7886 fLego.reset();
7887}
7888
7889////////////////////////////////////////////////////////////////////////////////
7890/// [Control function to draw a 3D histogram with Iso Surfaces.](\ref HP25)
7891
7893{
7894
7895 const Double_t ydiff = 1;
7896 const Double_t yligh1 = 10;
7897 const Double_t qa = 0.15;
7898 const Double_t qd = 0.15;
7899 const Double_t qs = 0.8;
7900 Double_t fmin, fmax;
7901 Int_t i, irep;
7902 Int_t nbcol = 28;
7903 Int_t icol1 = 201;
7904 Int_t ic1 = icol1;
7905 Int_t ic2 = ic1+nbcol;
7906 Int_t ic3 = ic2+nbcol;
7907
7908 TAxis *xaxis = fH->GetXaxis();
7909 TAxis *yaxis = fH->GetYaxis();
7910 TAxis *zaxis = fH->GetZaxis();
7911
7912 Int_t nx = fH->GetNbinsX();
7913 Int_t ny = fH->GetNbinsY();
7914 Int_t nz = fH->GetNbinsZ();
7915
7916 std::vector<Double_t> x(nx);
7917 std::vector<Double_t> y(ny);
7918 std::vector<Double_t> z(nz);
7919
7920 for (i=0; i<nx; i++) x[i] = xaxis->GetBinCenter(i+1);
7921 for (i=0; i<ny; i++) y[i] = yaxis->GetBinCenter(i+1);
7922 for (i=0; i<nz; i++) z[i] = zaxis->GetBinCenter(i+1);
7923
7924 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7925 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7926 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7927 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7928 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7929 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7930
7931 Double_t s[3];
7932 s[0] = fH->GetSumOfWeights()/(fH->GetNbinsX()*fH->GetNbinsY()*fH->GetNbinsZ());
7933 s[1] = 0.5*s[0];
7934 s[2] = 1.5*s[0];
7935
7936 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7937
7938 TView *view = gPad ? gPad->GetView() : nullptr;
7939 if (!view) {
7940 Error("PaintH3Iso", "no TView in current pad");
7941 return;
7942 }
7943 Double_t thedeg = 90 - gPad->GetTheta();
7944 Double_t phideg = -90 - gPad->GetPhi();
7945 Double_t psideg = view->GetPsi();
7946 view->SetView(phideg, thedeg, psideg, irep);
7947
7948 Int_t backcolor = gPad->GetFrameFillColor();
7949 if (Hoption.System != kCARTESIAN) backcolor = 0;
7950 view->PadRange(backcolor);
7951
7952 Double_t dcol = 0.5/Double_t(nbcol);
7953 TColor *colref = gROOT->GetColor(fH->GetFillColor());
7954 if (!colref) {
7955 return;
7956 }
7957 Float_t r, g, b, hue, light, satur;
7958 colref->GetRGB(r,g,b);
7959 TColor::RGBtoHLS(r,g,b,hue,light,satur);
7960 TColor *acol;
7961 for (Int_t col=0;col<nbcol;col++) {
7962 acol = gROOT->GetColor(col+icol1);
7963 TColor::HLStoRGB(hue, .4+col*dcol, satur, r, g, b);
7964 if (acol) acol->SetRGB(r, g, b);
7965 }
7966
7967 fLego->InitMoveScreen(-1.1,1.1);
7968
7969 if (Hoption.BackBox) {
7970 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
7972 fLego->BackBox(90);
7973 }
7974
7975 fLego->LightSource(0, ydiff, 0, 0, 0, irep);
7976 fLego->LightSource(1, yligh1, 1, 1, 1, irep);
7977 fLego->SurfaceProperty(qa, qd, qs, 1, irep);
7978 fmin = ydiff*qa;
7979 fmax = ydiff*qa + (yligh1+0.1)*(qd+qs);
7980 fLego->SetIsoSurfaceParameters(fmin, fmax, nbcol, ic1, ic2, ic3);
7981
7982 fLego->IsoSurface(1, s, nx, ny, nz, x.data(), y.data(), z.data(), "BF");
7983
7984 if (Hoption.FrontBox) {
7985 fLego->InitMoveScreen(-1.1,1.1);
7987 fLego->FrontBox(90);
7988 }
7989 if (!Hoption.Axis && !Hoption.Same) {
7990 TGaxis axis;
7991 PaintLegoAxis(&axis, 90);
7992 }
7993
7994 PaintTitle();
7995
7996 //Draw stats and fit results
7997 TF1 *fit = nullptr;
7998 TIter next(fFunctions);
7999 while (auto obj = next()) {
8000 if (obj->InheritsFrom(TF1::Class())) {
8001 fit = (TF1*)obj;
8002 break;
8003 }
8004 }
8005 if ((Hoption.Same%10) != 1) {
8006 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
8008 }
8009 }
8010
8011 fLego.reset();
8012}
8013
8014////////////////////////////////////////////////////////////////////////////////
8015/// [Control function to draw a 2D histogram as a lego plot.](\ref HP17)
8016
8018{
8019
8020 Int_t raster = 1;
8021 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
8022 Int_t nx = Hparam.xlast - Hparam.xfirst + 1;
8023 Int_t ny = Hparam.ylast - Hparam.yfirst + 1;
8024 Double_t zmin = Hparam.zmin;
8025 Double_t zmax = Hparam.zmax;
8026 Double_t xlab1 = Hparam.xmin;
8027 Double_t xlab2 = Hparam.xmax;
8028 Double_t ylab1 = Hparam.ymin;
8029 Double_t ylab2 = Hparam.ymax;
8030 Double_t dangle = 10*3.141592/180; //Delta angle for Rapidity option
8031 Double_t deltaz = TMath::Abs(zmin);
8032 if (deltaz == 0) deltaz = 1;
8033 if (zmin >= zmax) {
8034 zmin -= 0.5*deltaz;
8035 zmax += 0.5*deltaz;
8036 }
8037 Double_t z1c = zmin;
8038 Double_t z2c = zmin + (zmax-zmin)*(1+gStyle->GetHistTopMargin());
8039
8040 // Compute the lego limits and instantiate a lego object
8041 fXbuf[0] = -1;
8042 fYbuf[0] = 1;
8043 fXbuf[1] = -1;
8044 fYbuf[1] = 1;
8045 if (Hoption.System == kPOLAR) {
8046 fXbuf[2] = z1c;
8047 fYbuf[2] = z2c;
8048 } else if (Hoption.System == kCYLINDRICAL) {
8049 if (Hoption.Logy) {
8050 if (ylab1 > 0) fXbuf[2] = TMath::Log10(ylab1);
8051 else fXbuf[2] = 0;
8052 if (ylab2 > 0) fYbuf[2] = TMath::Log10(ylab2);
8053 else fYbuf[2] = 0;
8054 } else {
8055 fXbuf[2] = ylab1;
8056 fYbuf[2] = ylab2;
8057 }
8058 z1c = 0; z2c = 1;
8059 } else if (Hoption.System == kSPHERICAL) {
8060 fXbuf[2] = -1;
8061 fYbuf[2] = 1;
8062 z1c = 0; z2c = 1;
8063 } else if (Hoption.System == kRAPIDITY) {
8064 fXbuf[2] = -1/TMath::Tan(dangle);
8065 fYbuf[2] = 1/TMath::Tan(dangle);
8066 } else {
8067 fXbuf[0] = xlab1;
8068 fYbuf[0] = xlab2;
8069 fXbuf[1] = ylab1;
8070 fYbuf[1] = ylab2;
8071 fXbuf[2] = z1c;
8072 fYbuf[2] = z2c;
8073 raster = 0;
8074 }
8075
8076 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data(), Hoption.System);
8077
8078 Int_t nids = -1;
8079 TH1 * hid = nullptr;
8080 Color_t colormain = -1, colordark = -1;
8081 Bool_t drawShadowsInLego1 = kTRUE;
8082
8083 // LEGO3 is like LEGO1 except that the black lines around each lego are not drawn.
8084 if (Hoption.Lego == 13) {
8085 Hoption.Lego = 11;
8086 fLego->SetMesh(0);
8087 }
8088 // LEGO4 is like LEGO1 except no shadows are drawn.
8089 if (Hoption.Lego == 14) {
8090 Hoption.Lego = 11;
8091 drawShadowsInLego1 = kFALSE;
8092 }
8093
8094 // Initialize the levels on the Z axis
8095 Int_t ndiv = fH->GetContour();
8096 if (ndiv == 0 ) {
8097 ndiv = gStyle->GetNumberContours();
8098 fH->SetContour(ndiv);
8099 }
8100 Int_t ndivz = TMath::Abs(ndiv);
8101 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
8102
8103 // Initialize colors
8104 if (!fStack) {
8105 fLego->SetEdgeAtt(fH->GetLineColor(),fH->GetLineStyle(),fH->GetLineWidth(),0);
8106 } else {
8107 for (Int_t id=0;id<=fStack->GetSize();id++) {
8108 hid = (TH1*)fStack->At((id==0)?id:id-1);
8109 fLego->SetEdgeAtt(hid->GetLineColor(),hid->GetLineStyle(),hid->GetLineWidth(),id);
8110 }
8111 }
8112
8113 if (Hoption.Lego == 11) {
8114 nids = 1;
8115 if (fStack) nids = fStack->GetSize();
8116 hid = fH;
8117 for (Int_t id=0;id<=nids;id++) {
8118 if (id > 0 && fStack) hid = (TH1*)fStack->At(id-1);
8119 colormain = hid->GetFillColor();
8120 if (colormain == 1) colormain = 17; //avoid drawing with black
8121 if (drawShadowsInLego1) colordark = TColor::GetColorDark(colormain);
8122 else colordark = colormain;
8123 fLego->SetColorMain(colormain,id);
8124 fLego->SetColorDark(colordark,id);
8125 if (id <= 1) fLego->SetColorMain(colormain,-1); // Set Bottom color
8126 if (id == nids) fLego->SetColorMain(colormain,99); // Set Top color
8127 }
8128 }
8129
8130 // Now ready to draw the lego plot
8131 Int_t irep = 0;
8132
8133 TView *view = gPad ? gPad->GetView() : nullptr;
8134 if (!view) {
8135 Error("PaintLego", "no TView in current pad");
8136 return;
8137 }
8138
8139 Double_t thedeg = 90 - gPad->GetTheta();
8140 Double_t phideg = -90 - gPad->GetPhi();
8141 Double_t psideg = view->GetPsi();
8142 view->SetView(phideg, thedeg, psideg, irep);
8143
8144 fLego->SetLineColor(kBlack); // zgrid color for lego1 & lego2
8145 fLego->SetFillStyle(fH->GetFillStyle());
8146
8147 // Set color/style for back box
8148 fLego->SetFillStyle(gPad->GetFrameFillStyle());
8149 fLego->SetFillColor(gPad->GetFrameFillColor());
8150 fLego->TAttFill::Modify();
8151
8152 Int_t backcolor = gPad->GetFrameFillColor();
8153 if (Hoption.System != kCARTESIAN) backcolor = 0;
8154 view->PadRange(backcolor);
8155
8156 fLego->SetFillStyle(fH->GetFillStyle());
8157 fLego->SetFillColor(fH->GetFillColor());
8158 fLego->TAttFill::Modify();
8159
8160 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
8161
8162 if (raster) fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
8163 else fLego->InitMoveScreen(-1.1,1.1);
8164
8165 if (Hoption.Lego == 19) {
8167 if (Hoption.BackBox) fLego->BackBox(90);
8168 if (Hoption.FrontBox) fLego->FrontBox(90);
8169 if (!Hoption.Axis) { TGaxis axis; PaintLegoAxis(&axis, 90); }
8170 return;
8171 }
8172
8173 if (Hoption.Lego == 11 || Hoption.Lego == 12) {
8176 fLego->BackBox(90);
8177 }
8178 }
8179
8180 if (Hoption.Lego == 12) DefineColorLevels(ndivz);
8181
8182 fLego->SetLegoFunction(&TPainter3dAlgorithms::LegoFunction);
8184 if (Hoption.Lego == 11) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode3);
8185 if (Hoption.Lego == 12) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode2);
8186 if (Hoption.System == kPOLAR) {
8187 if (Hoption.Lego == 1) fLego->LegoPolar(1,nx,ny,"FB");
8188 if (Hoption.Lego == 11) fLego->LegoPolar(1,nx,ny,"BF");
8189 if (Hoption.Lego == 12) fLego->LegoPolar(1,nx,ny,"BF");
8190 } else if (Hoption.System == kCYLINDRICAL) {
8191 if (Hoption.Lego == 1) fLego->LegoCylindrical(1,nx,ny,"FB");
8192 if (Hoption.Lego == 11) fLego->LegoCylindrical(1,nx,ny,"BF");
8193 if (Hoption.Lego == 12) fLego->LegoCylindrical(1,nx,ny,"BF");
8194 } else if (Hoption.System == kSPHERICAL) {
8195 if (Hoption.Lego == 1) fLego->LegoSpherical(0,1,nx,ny,"FB");
8196 if (Hoption.Lego == 11) fLego->LegoSpherical(0,1,nx,ny,"BF");
8197 if (Hoption.Lego == 12) fLego->LegoSpherical(0,1,nx,ny,"BF");
8198 } else if (Hoption.System == kRAPIDITY) {
8199 if (Hoption.Lego == 1) fLego->LegoSpherical(1,1,nx,ny,"FB");
8200 if (Hoption.Lego == 11) fLego->LegoSpherical(1,1,nx,ny,"BF");
8201 if (Hoption.Lego == 12) fLego->LegoSpherical(1,1,nx,ny,"BF");
8202 } else {
8203 if (Hoption.Lego == 1) {
8205 fLego->LegoCartesian(90,nx,ny,"FB");}
8206 if (Hoption.Lego == 11) fLego->LegoCartesian(90,nx,ny,"BF");
8207 if (Hoption.Lego == 12) fLego->LegoCartesian(90,nx,ny,"BF");
8208 }
8209
8210 if (Hoption.Lego == 1 || Hoption.Lego == 11) {
8213 fLego->BackBox(90);
8214 }
8215 }
8216 if (Hoption.System == kCARTESIAN) {
8217 fLego->InitMoveScreen(-1.1,1.1);
8219 if (Hoption.FrontBox) fLego->FrontBox(90);
8220 }
8221 if (!Hoption.Axis && !Hoption.Same) {
8222 TGaxis axis;
8223 PaintLegoAxis(&axis, 90);
8224 }
8226 fLego.reset();
8227}
8228
8229////////////////////////////////////////////////////////////////////////////////
8230/// Draw the axis for legos and surface plots.
8231
8233{
8234
8235 static Double_t epsil = 0.001;
8236
8237 Double_t cosa, sina;
8238 Double_t bmin, bmax;
8239 Double_t r[24] /* was [3][8] */;
8240 Int_t ndivx, ndivy, ndivz, i;
8241 Double_t x1[3], x2[3], y1[3], y2[3], z1[3], z2[3], av[24] /* was [3][8] */;
8242 static char chopax[8], chopay[8], chopaz[8];
8243 Int_t ix1, ix2, iy1, iy2, iz1, iz2;
8244 Double_t rad;
8245
8246 TView *view = gPad ? gPad->GetView() : nullptr;
8247 if (!view) {
8248 Error("PaintLegoAxis", "no TView in current pad");
8249 return;
8250 }
8251
8252 // In polar coordinates, draw a short line going from the external circle
8253 // corresponding to r = 1 up to r = 1.1
8254 if (Hoption.System == kPOLAR) {
8255 r[0] = 1;
8256 r[1] = 0;
8257 r[2] = 0;
8258 view->WCtoNDC(r, x1);
8259 r[0] = 1.1;
8260 r[1] = 0;
8261 r[2] = 0;
8262 view->WCtoNDC(r, x2);
8263 gPad->PaintLine(x1[0],x1[1],x2[0],x2[1]);
8264 return;
8265 }
8266
8267 if (Hoption.System != kCARTESIAN) return;
8268
8269 rad = TMath::ATan(1.) * 4. /180.;
8270 cosa = TMath::Cos(ang*rad);
8271 sina = TMath::Sin(ang*rad);
8272
8273 view->AxisVertex(ang, av, ix1, ix2, iy1, iy2, iz1, iz2);
8274 for (i = 1; i <= 8; ++i) {
8275 r[i*3 - 3] = av[i*3 - 3] + av[i*3 - 2]*cosa;
8276 r[i*3 - 2] = av[i*3 - 2]*sina;
8277 r[i*3 - 1] = av[i*3 - 1];
8278 }
8279
8280 view->WCtoNDC(&r[ix1*3 - 3], x1);
8281 view->WCtoNDC(&r[ix2*3 - 3], x2);
8282 view->WCtoNDC(&r[iy1*3 - 3], y1);
8283 view->WCtoNDC(&r[iy2*3 - 3], y2);
8284 view->WCtoNDC(&r[iz1*3 - 3], z1);
8285 view->WCtoNDC(&r[iz2*3 - 3], z2);
8286
8287 view->SetAxisNDC(x1, x2, y1, y2, z1, z2);
8288
8289 Double_t *rmin = view->GetRmin();
8290 Double_t *rmax = view->GetRmax();
8291 if (!rmin || !rmax) return;
8292
8293 // Initialize the axis options
8294 if (x1[0] > x2[0]) strlcpy(chopax, "SDH=+",8);
8295 else strlcpy(chopax, "SDH=-",8);
8296 if (y1[0] > y2[0]) strlcpy(chopay, "SDH=+",8);
8297 else strlcpy(chopay, "SDH=-",8);
8298 if (z2[1] > z1[1]) strlcpy(chopaz, "SDH=+",8);
8299 else strlcpy(chopaz, "SDH=-",8);
8300
8301 // Option LOG is required ?
8302 if (Hoption.Logx) strlcat(chopax,"G",8);
8303 if (Hoption.Logy) strlcat(chopay,"G",8);
8304 if (Hoption.Logz) strlcat(chopaz,"G",8);
8305
8306 // Initialize the number of divisions. If the
8307 // number of divisions is negative, option 'N' is required.
8308 ndivx = fXaxis->GetNdivisions();
8309 ndivy = fYaxis->GetNdivisions();
8310 ndivz = fZaxis->GetNdivisions();
8311 if (ndivx < 0) {
8312 ndivx = TMath::Abs(ndivx);
8313 strlcat(chopax, "N",8);
8314 }
8315 if (ndivy < 0) {
8316 ndivy = TMath::Abs(ndivy);
8317 strlcat(chopay, "N",8);
8318 }
8319 if (ndivz < 0) {
8320 ndivz = TMath::Abs(ndivz);
8321 strlcat(chopaz, "N",8);
8322 }
8323
8324 // Set Axis attributes.
8325 // The variable SCALE rescales the VSIZ
8326 // in order to have the same label size for all angles.
8327
8328 axis->SetLineWidth(1);
8329
8330 // X axis drawing
8331 if (TMath::Abs(x1[0] - x2[0]) >= epsil || TMath::Abs(x1[1] - x2[1]) > epsil) {
8334 if (Hoption.Logx && !fH->InheritsFrom(TH3::Class())) {
8335 bmin = TMath::Power(10, rmin[0]);
8336 bmax = TMath::Power(10, rmax[0]);
8337 } else {
8338 bmin = rmin[0];
8339 bmax = rmax[0];
8340 }
8341 // Option time display is required ?
8342 if (fXaxis->GetTimeDisplay()) {
8343 strlcat(chopax,"t",8);
8344 if (strlen(fXaxis->GetTimeFormatOnly()) == 0) {
8345 axis->SetTimeFormat(fXaxis->ChooseTimeFormat(bmax-bmin));
8346 } else {
8348 }
8349 }
8350 axis->SetOption(chopax);
8351 axis->PaintAxis(x1[0], x1[1], x2[0], x2[1], bmin, bmax, ndivx, chopax);
8352 }
8353
8354 // Y axis drawing
8355 if (TMath::Abs(y1[0] - y2[0]) >= epsil || TMath::Abs(y1[1] - y2[1]) > epsil) {
8358 if (fYaxis->GetTitleOffset() == 0) axis->SetTitleOffset(1.5);
8359
8360 if (fH->GetDimension() < 2) {
8361 strlcpy(chopay, "V=+UN",8);
8362 ndivy = 0;
8363 }
8364 if (TMath::Abs(y1[0] - y2[0]) < epsil) {
8365 y2[0] = y1[0];
8366 }
8367 if (Hoption.Logy && !fH->InheritsFrom(TH3::Class())) {
8368 bmin = TMath::Power(10, rmin[1]);
8369 bmax = TMath::Power(10, rmax[1]);
8370 } else {
8371 bmin = rmin[1];
8372 bmax = rmax[1];
8373 }
8374 // Option time display is required ?
8375 if (fYaxis->GetTimeDisplay()) {
8376 strlcat(chopay,"t",8);
8377 if (strlen(fYaxis->GetTimeFormatOnly()) == 0) {
8378 axis->SetTimeFormat(fYaxis->ChooseTimeFormat(bmax-bmin));
8379 } else {
8381 }
8382 }
8383 axis->SetOption(chopay);
8384 axis->PaintAxis(y1[0], y1[1], y2[0], y2[1], bmin, bmax, ndivy, chopay);
8385 }
8386
8387 // Z axis drawing
8388 if (TMath::Abs(z1[0] - z2[0]) >= 100*epsil || TMath::Abs(z1[1] - z2[1]) > 100*epsil) {
8390 if (Hoption.Logz && !fH->InheritsFrom(TH3::Class())) {
8391 bmin = TMath::Power(10, rmin[2]);
8392 bmax = TMath::Power(10, rmax[2]);
8393 } else {
8394 bmin = rmin[2];
8395 bmax = rmax[2];
8396 }
8397 // Option time display is required ?
8398 if (fZaxis->GetTimeDisplay()) {
8399 strlcat(chopaz,"t",8);
8400 if (strlen(fZaxis->GetTimeFormatOnly()) == 0) {
8401 axis->SetTimeFormat(fZaxis->ChooseTimeFormat(bmax-bmin));
8402 } else {
8404 }
8405 }
8406 axis->SetOption(chopaz);
8407 TString ztit = fZaxis->GetTitle();
8408 if (ztit.Index(";")>0) {
8409 ztit.Remove(ztit.Index(";"),ztit.Length());
8410 axis->SetTitle(ztit.Data());
8411 }
8412 axis->PaintAxis(z1[0], z1[1], z2[0], z2[1], bmin, bmax, ndivz, chopaz);
8413 }
8414
8415 //fH->SetLineStyle(1); /// otherwise fEdgeStyle[i] gets overwritten!
8416}
8417
8418////////////////////////////////////////////////////////////////////////////////
8419/// [Paint the color palette on the right side of the pad.](\ref HP22)
8420
8422{
8423 TPaletteAxis *palette = (TPaletteAxis*)fFunctions->FindObject("palette");
8424 TView *view = gPad ? gPad->GetView() : nullptr;
8425 if (palette) {
8426 if (view) {
8427 if (!palette->TestBit(TPaletteAxis::kHasView)) {
8428 fFunctions->Remove(palette);
8429 delete palette; palette = nullptr;
8430 }
8431 } else {
8432 if (palette->TestBit(TPaletteAxis::kHasView)) {
8433 fFunctions->Remove(palette);
8434 delete palette; palette = nullptr;
8435 }
8436 }
8437 // make sure the histogram member of the palette is setup correctly. It may not be after a Clone()
8438 if (palette && !palette->GetHistogram()) palette->SetHistogram(fH);
8439 }
8440
8441 if (!palette) {
8442 Double_t xup = gPad->GetUxmax();
8443 Double_t x2 = gPad->PadtoX(gPad->GetX2());
8444 Double_t ymin = gPad->PadtoY(gPad->GetUymin());
8445 Double_t ymax = gPad->PadtoY(gPad->GetUymax());
8446 Double_t xr = 0.05*(gPad->GetX2() - gPad->GetX1());
8447 Double_t xmin = gPad->PadtoX(xup +0.1*xr);
8448 Double_t xmax = gPad->PadtoX(xup + xr);
8449 if (xmax > x2) xmax = gPad->PadtoX(gPad->GetX2()-0.01*xr);
8450 palette = new TPaletteAxis(xmin,ymin,xmax,ymax,fH);
8451 fFunctions->AddFirst(palette);
8452 palette->Paint();
8453 }
8454}
8455
8456////////////////////////////////////////////////////////////////////////////////
8457/// [Control function to draw a 2D histogram as a scatter plot.](\ref HP11)
8458
8460{
8461
8462 fH->TAttMarker::Modify();
8463
8464 Int_t k, marker;
8465 Double_t dz, z, xk,xstep, yk, ystep;
8466 Double_t scale = 1;
8467 Bool_t ltest = kFALSE;
8468 Double_t zmax = fH->GetMaximum();
8469 Double_t zmin = fH->GetMinimum();
8470 if (zmin == 0 && zmax == 0) return;
8471 if (zmin == zmax) {
8472 zmax += 0.1*TMath::Abs(zmax);
8473 zmin -= 0.1*TMath::Abs(zmin);
8474 }
8476 if (Hoption.Logz) {
8477 if (zmin > 0) zmin = TMath::Log10(zmin);
8478 else zmin = 0;
8479 if (zmax > 0) zmax = TMath::Log10(zmax);
8480 else zmax = 0;
8481 if (zmin == 0 && zmax == 0) return;
8482 dz = zmax - zmin;
8483 scale = 100/dz;
8484 if (ncells > 10000) scale /= 5;
8485 ltest = kTRUE;
8486 } else {
8487 dz = zmax - zmin;
8488 if (dz >= kNMAX || zmax < 1) {
8489 scale = (kNMAX-1)/dz;
8490 if (ncells > 10000) scale /= 5;
8491 ltest = kTRUE;
8492 }
8493 }
8494 if (fH->GetMinimumStored() == -1111) {
8495 Double_t yMARGIN = gStyle->GetHistTopMargin();
8496 if (Hoption.MinimumZero) {
8497 if (zmin >= 0) zmin = 0;
8498 else zmin -= yMARGIN*(zmax-zmin);
8499 } else {
8500 Double_t dzmin = yMARGIN*(zmax-zmin);
8501 if (zmin >= 0 && (zmin-dzmin <= 0)) zmin = 0;
8502 else zmin -= dzmin;
8503 }
8504 }
8505
8506 TString opt = option;
8507 opt.ToLower();
8508 if (opt.Contains("scat=")) {
8509 char optscat[100];
8510 strlcpy(optscat,opt.Data(),100);
8511 char *oscat = strstr(optscat,"scat=");
8512 char *blank = strstr(oscat," "); if (blank) *blank = 0;
8513 sscanf(oscat+5,"%lg",&scale);
8514 }
8515 // use an independent instance of a random generator
8516 // instead of gRandom to avoid conflicts and
8517 // to get same random numbers when drawing the same histogram
8518 TRandom2 random;
8519 marker=0;
8520 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
8521 yk = fYaxis->GetBinLowEdge(j);
8522 ystep = fYaxis->GetBinWidth(j);
8523 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
8524 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
8525 xk = fXaxis->GetBinLowEdge(i);
8526 xstep = fXaxis->GetBinWidth(i);
8527 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
8528 z = fH->GetBinContent(bin);
8529 if (z < zmin) z = zmin;
8530 if (z > zmax) z = zmax;
8531 if (Hoption.Logz) {
8532 if (z > 0) z = TMath::Log10(z) - zmin;
8533 } else {
8534 z -= zmin;
8535 }
8536 if (z <= 0) continue;
8537 k = Int_t(z*scale);
8538 if (ltest) k++;
8539 if (k > 0) {
8540 for (Int_t loop=0; loop<k; loop++) {
8541 if (k+marker >= kNMAX) {
8542 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
8543 marker=0;
8544 }
8545 fXbuf[marker] = (random.Rndm()*xstep) + xk;
8546 fYbuf[marker] = (random.Rndm()*ystep) + yk;
8547 if (Hoption.Logx) {
8548 if (fXbuf[marker] > 0) fXbuf[marker] = TMath::Log10(fXbuf[marker]);
8549 else break;
8550 }
8551 if (Hoption.Logy) {
8552 if (fYbuf[marker] > 0) fYbuf[marker] = TMath::Log10(fYbuf[marker]);
8553 else break;
8554 }
8555 if (fXbuf[marker] < gPad->GetUxmin()) break;
8556 if (fYbuf[marker] < gPad->GetUymin()) break;
8557 if (fXbuf[marker] > gPad->GetUxmax()) break;
8558 if (fYbuf[marker] > gPad->GetUymax()) break;
8559 marker++;
8560 }
8561 }
8562 }
8563 }
8564 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
8565
8567}
8568
8569////////////////////////////////////////////////////////////////////////////////
8570/// Static function to paint special objects like vectors and matrices.
8571/// This function is called via `gROOT->ProcessLine` to paint these objects
8572/// without having a direct dependency of the graphics or histogramming
8573/// system.
8574
8576{
8577
8578 if (!obj) return;
8581
8582 if (obj->InheritsFrom(TMatrixFBase::Class())) {
8583 // case TMatrixF
8584 TH2F *R__TMatrixFBase = new TH2F((TMatrixFBase &)*obj);
8585 R__TMatrixFBase->SetBit(kCanDelete);
8586 R__TMatrixFBase->Draw(option);
8587
8588 } else if (obj->InheritsFrom(TMatrixDBase::Class())) {
8589 // case TMatrixD
8590 TH2D *R__TMatrixDBase = new TH2D((TMatrixDBase &)*obj);
8591 R__TMatrixDBase->SetBit(kCanDelete);
8592 R__TMatrixDBase->Draw(option);
8593
8594 } else if (obj->InheritsFrom(TVectorF::Class())) {
8595 //case TVectorF
8596 TH1F *R__TVectorF = new TH1F((TVectorF &)*obj);
8597 R__TVectorF->SetBit(kCanDelete);
8598 R__TVectorF->Draw(option);
8599
8600 } else if (obj->InheritsFrom(TVectorD::Class())) {
8601 //case TVectorD
8602 TH1D *R__TVectorD = new TH1D((TVectorD &)*obj);
8603 R__TVectorD->SetBit(kCanDelete);
8604 R__TVectorD->Draw(option);
8605 }
8606
8607 TH1::AddDirectory(status);
8608}
8609
8610////////////////////////////////////////////////////////////////////////////////
8611/// [Draw the statistics box for 1D and profile histograms.](\ref HP07)
8612
8614{
8615 TString tt, tf;
8616 Int_t dofit;
8617 TPaveStats *stats = nullptr;
8618 TIter next(fFunctions);
8619 while (auto obj = next()) {
8620 if (obj->InheritsFrom(TPaveStats::Class())) {
8621 stats = (TPaveStats*)obj;
8622 break;
8623 }
8624 }
8625
8626 if (stats && dostat) {
8627 dofit = stats->GetOptFit();
8628 dostat = stats->GetOptStat();
8629 } else {
8630 dofit = gStyle->GetOptFit();
8631 }
8632 if (!dofit) fit = nullptr;
8633 if (dofit == 1) dofit = 111;
8634 if (dostat == 1) dostat = 1111;
8635 Int_t print_name = dostat%10;
8636 Int_t print_entries = (dostat/10)%10;
8637 Int_t print_mean = (dostat/100)%10;
8638 Int_t print_stddev = (dostat/1000)%10;
8639 Int_t print_under = (dostat/10000)%10;
8640 Int_t print_over = (dostat/100000)%10;
8641 Int_t print_integral= (dostat/1000000)%10;
8642 Int_t print_skew = (dostat/10000000)%10;
8643 Int_t print_kurt = (dostat/100000000)%10;
8644 Int_t nlines = print_name + print_entries + print_mean + print_stddev +
8645 print_under + print_over + print_integral +
8646 print_skew + print_kurt;
8647 Int_t print_fval = dofit%10;
8648 Int_t print_ferrors = (dofit/10)%10;
8649 Int_t print_fchi2 = (dofit/100)%10;
8650 Int_t print_fprob = (dofit/1000)%10;
8651 Int_t nlinesf = print_fval + print_fchi2 + print_fprob;
8652 if (fit) {
8653 if (print_fval < 2) nlinesf += fit->GetNumberFreeParameters();
8654 else nlinesf += fit->GetNpar();
8655 }
8656 if (fH->InheritsFrom(TProfile::Class())) nlinesf += print_mean + print_stddev;
8657
8658 // Pavetext with statistics
8659 Bool_t done = kFALSE;
8660 if (!dostat && !fit) {
8661 if (stats) { fFunctions->Remove(stats); delete stats;}
8662 return;
8663 }
8664 Double_t statw = gStyle->GetStatW();
8665 if (fit) statw = 1.8*gStyle->GetStatW();
8666 Double_t stath = (nlines+nlinesf)*gStyle->GetStatFontSize();
8667 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
8668 stath = 0.25*(nlines+nlinesf)*gStyle->GetStatH();
8669 }
8670 if (stats) {
8671 stats->Clear();
8672 done = kTRUE;
8673 } else {
8674 stats = new TPaveStats(
8675 gStyle->GetStatX()-statw,
8676 gStyle->GetStatY()-stath,
8677 gStyle->GetStatX(),
8678 gStyle->GetStatY(),"brNDC");
8679
8680 stats->SetParent(fH);
8681 stats->SetOptFit(dofit);
8682 stats->SetOptStat(dostat);
8683 stats->SetFillColor(gStyle->GetStatColor());
8684 stats->SetFillStyle(gStyle->GetStatStyle());
8686 stats->SetTextFont(gStyle->GetStatFont());
8687 if (gStyle->GetStatFont()%10 > 2)
8689 stats->SetFitFormat(gStyle->GetFitFormat());
8691 stats->SetName("stats");
8692
8694 stats->SetTextAlign(12);
8695 stats->SetBit(kCanDelete);
8696 stats->SetBit(kMustCleanup);
8697 }
8698 if (print_name) stats->AddText(fH->GetName());
8699 if (print_entries) {
8700 if (fH->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(fH->GetEntries()+0.5));
8701 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(fH->GetEntries()));
8702 stats->AddText(tt.Data());
8703 }
8704 if (print_mean) {
8705 if (print_mean == 1) {
8706 tf.Form("%s = %s%s",gStringMean.Data(),"%",stats->GetStatFormat());
8707 tt.Form(tf.Data(),fH->GetMean(1));
8708 } else {
8709 tf.Form("%s = %s%s #pm %s%s",gStringMean.Data(),"%",stats->GetStatFormat()
8710 ,"%",stats->GetStatFormat());
8711 tt.Form(tf.Data(),fH->GetMean(1),fH->GetMeanError(1));
8712 }
8713 stats->AddText(tt.Data());
8715 if (print_mean == 1) {
8716 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
8717 tt.Form(tf.Data(),fH->GetMean(2));
8718 } else {
8719 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
8720 ,"%",stats->GetStatFormat());
8721 tt.Form(tf.Data(),fH->GetMean(2),fH->GetMeanError(2));
8722 }
8723 stats->AddText(tt.Data());
8724 }
8725 }
8726 if (print_stddev) {
8727 if (print_stddev == 1) {
8728 tf.Form("%s = %s%s",gStringStdDev.Data(),"%",stats->GetStatFormat());
8729 tt.Form(tf.Data(),fH->GetStdDev(1));
8730 } else {
8731 tf.Form("%s = %s%s #pm %s%s",gStringStdDev.Data(),"%",stats->GetStatFormat()
8732 ,"%",stats->GetStatFormat());
8733 tt.Form(tf.Data(),fH->GetStdDev(1),fH->GetStdDevError(1));
8734 }
8735 stats->AddText(tt.Data());
8737 if (print_stddev == 1) {
8738 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
8739 tt.Form(tf.Data(),fH->GetStdDev(2));
8740 } else {
8741 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
8742 ,"%",stats->GetStatFormat());
8743 tt.Form(tf.Data(),fH->GetStdDev(2),fH->GetStdDevError(2));
8744 }
8745 stats->AddText(tt.Data());
8746 }
8747 }
8748 if (print_under) {
8749 tf.Form("%s = %s%s",gStringUnderflow.Data(),"%",stats->GetStatFormat());
8750 tt.Form(tf.Data(),fH->GetBinContent(0));
8751 stats->AddText(tt.Data());
8752 }
8753 if (print_over) {
8754 tf.Form("%s = %s%s",gStringOverflow.Data(),"%",stats->GetStatFormat());
8755 tt.Form(tf.Data(),fH->GetBinContent(fXaxis->GetNbins()+1));
8756 stats->AddText(tt.Data());
8757 }
8758 if (print_integral) {
8759 if (print_integral == 1) {
8760 tf.Form("%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
8761 tt.Form(tf.Data(),fH->Integral());
8762 } else {
8763 tf.Form("%s = %s%s",gStringIntegralBinWidth.Data(),"%",stats->GetStatFormat());
8764 tt.Form(tf.Data(),fH->Integral("width"));
8765 }
8766 stats->AddText(tt.Data());
8767 }
8768 if (print_skew) {
8769 if (print_skew == 1) {
8770 tf.Form("%s = %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat());
8771 tt.Form(tf.Data(),fH->GetSkewness(1));
8772 } else {
8773 tf.Form("%s = %s%s #pm %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat()
8774 ,"%",stats->GetStatFormat());
8775 tt.Form(tf.Data(),fH->GetSkewness(1),fH->GetSkewness(11));
8776 }
8777 stats->AddText(tt.Data());
8778 }
8779 if (print_kurt) {
8780 if (print_kurt == 1) {
8781 tf.Form("%s = %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat());
8782 tt.Form(tf.Data(),fH->GetKurtosis(1));
8783 } else {
8784 tf.Form("%s = %s%s #pm %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat()
8785 ,"%",stats->GetStatFormat());
8786 tt.Form(tf.Data(),fH->GetKurtosis(1),fH->GetKurtosis(11));
8787 }
8788 stats->AddText(tt.Data());
8789 }
8790
8791 // Draw Fit parameters
8792 if (fit) {
8793 Int_t ndf = fit->GetNDF();
8794 tf.Form("#chi^{2} / ndf = %s%s / %d","%",stats->GetFitFormat(),ndf);
8795 tt.Form(tf.Data(),fit->GetChisquare());
8796 if (print_fchi2) stats->AddText(tt.Data());
8797 if (print_fprob) {
8798 tf.Form("Prob = %s%s","%",stats->GetFitFormat());
8799 tt.Form(tf.Data(),TMath::Prob(fit->GetChisquare(),ndf));
8800 stats->AddText(tt.Data());
8801 }
8802 if (print_fval || print_ferrors) {
8803 Double_t parmin,parmax;
8804 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
8805 fit->GetParLimits(ipar,parmin,parmax);
8806 if (print_fval < 2 && parmin*parmax != 0 && parmin >= parmax) continue;
8807 if (print_ferrors) {
8808 tf.Form("%-8s = %s%s #pm %s ", fit->GetParName(ipar), "%",stats->GetFitFormat(),
8809 GetBestFormat(fit->GetParameter(ipar), fit->GetParError(ipar), stats->GetFitFormat()));
8810 tt.Form(tf.Data(),fit->GetParameter(ipar)
8811 ,fit->GetParError(ipar));
8812 } else {
8813 tf.Form("%-8s = %s%s ",fit->GetParName(ipar), "%",stats->GetFitFormat());
8814 tt.Form(tf.Data(),fit->GetParameter(ipar));
8815 }
8816 stats->AddText(tt.Data());
8817 }
8818 }
8819 }
8820
8821 if (!done) fFunctions->Add(stats);
8822 stats->Paint();
8823}
8824
8825////////////////////////////////////////////////////////////////////////////////
8826/// [Draw the statistics box for 2D histograms.](\ref HP07)
8827
8829{
8830
8831 if (fH->GetDimension() != 2) return;
8832 TH2 *h2 = (TH2*)fH;
8833
8834 TString tt, tf;
8835 Int_t dofit;
8836 TPaveStats *stats = nullptr;
8837 TIter next(fFunctions);
8838 while (auto obj = next()) {
8839 if (obj->InheritsFrom(TPaveStats::Class())) {
8840 stats = (TPaveStats*)obj;
8841 break;
8842 }
8843 }
8844 if (stats && dostat) {
8845 dofit = stats->GetOptFit();
8846 dostat = stats->GetOptStat();
8847 } else {
8848 dofit = gStyle->GetOptFit();
8849 }
8850 if (dostat == 1) dostat = 1111;
8851 Int_t print_name = dostat%10;
8852 Int_t print_entries = (dostat/10)%10;
8853 Int_t print_mean = (dostat/100)%10;
8854 Int_t print_stddev = (dostat/1000)%10;
8855 Int_t print_under = (dostat/10000)%10;
8856 Int_t print_over = (dostat/100000)%10;
8857 Int_t print_integral= (dostat/1000000)%10;
8858 Int_t print_skew = (dostat/10000000)%10;
8859 Int_t print_kurt = (dostat/100000000)%10;
8860 Int_t nlines = print_name + print_entries + 2*print_mean + 2*print_stddev + print_integral;
8861 if (print_under || print_over) nlines += 3;
8862
8863 // Pavetext with statistics
8864 if (!gStyle->GetOptFit()) fit = nullptr;
8865 Bool_t done = kFALSE;
8866 if (!dostat && !fit) {
8867 if (stats) { fFunctions->Remove(stats); delete stats;}
8868 return;
8869 }
8870 Double_t statw = gStyle->GetStatW();
8871 if (fit) statw = 1.8*gStyle->GetStatW();
8872 Double_t stath = nlines*gStyle->GetStatFontSize();
8873 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
8874 stath = 0.25*nlines*gStyle->GetStatH();
8875 }
8876 if (fit) stath += gStyle->GetStatH();
8877 if (stats) {
8878 stats->Clear();
8879 done = kTRUE;
8880 } else {
8881 stats = new TPaveStats(
8882 gStyle->GetStatX()-statw,
8883 gStyle->GetStatY()-stath,
8884 gStyle->GetStatX(),
8885 gStyle->GetStatY(),"brNDC");
8886
8887 stats->SetParent(fH);
8888 stats->SetOptFit(dofit);
8889 stats->SetOptStat(dostat);
8890 stats->SetFillColor(gStyle->GetStatColor());
8891 stats->SetFillStyle(gStyle->GetStatStyle());
8893 stats->SetName("stats");
8894
8896 stats->SetTextAlign(12);
8897 stats->SetTextFont(gStyle->GetStatFont());
8898 if (gStyle->GetStatFont()%10 > 2)
8900 stats->SetFitFormat(gStyle->GetFitFormat());
8902 stats->SetBit(kCanDelete);
8903 stats->SetBit(kMustCleanup);
8904 }
8905 if (print_name) stats->AddText(h2->GetName());
8906 if (print_entries) {
8907 if (h2->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(h2->GetEntries()+0.5));
8908 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(h2->GetEntries()));
8909 stats->AddText(tt.Data());
8910 }
8911 if (print_mean) {
8912 if (print_mean == 1) {
8913 tf.Form("%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
8914 tt.Form(tf.Data(),h2->GetMean(1));
8915 stats->AddText(tt.Data());
8916 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
8917 tt.Form(tf.Data(),h2->GetMean(2));
8918 stats->AddText(tt.Data());
8919 } else {
8920 tf.Form("%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
8921 ,"%",stats->GetStatFormat());
8922 tt.Form(tf.Data(),h2->GetMean(1),h2->GetMeanError(1));
8923 stats->AddText(tt.Data());
8924 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
8925 ,"%",stats->GetStatFormat());
8926 tt.Form(tf.Data(),h2->GetMean(2),h2->GetMeanError(2));
8927 stats->AddText(tt.Data());
8928 }
8929 }
8930 if (print_stddev) {
8931 if (print_stddev == 1) {
8932 tf.Form("%s = %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat());
8933 tt.Form(tf.Data(),h2->GetStdDev(1));
8934 stats->AddText(tt.Data());
8935 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
8936 tt.Form(tf.Data(),h2->GetStdDev(2));
8937 stats->AddText(tt.Data());
8938 } else {
8939 tf.Form("%s = %s%s #pm %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat()
8940 ,"%",stats->GetStatFormat());
8941 tt.Form(tf.Data(),h2->GetStdDev(1),h2->GetStdDevError(1));
8942 stats->AddText(tt.Data());
8943 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
8944 ,"%",stats->GetStatFormat());
8945 tt.Form(tf.Data(),h2->GetStdDev(2),h2->GetStdDevError(2));
8946 stats->AddText(tt.Data());
8947 }
8948 }
8949 if (print_integral) {
8950 tf.Form("%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
8951 tt.Form(tf.Data(),fH->Integral());
8952 stats->AddText(tt.Data());
8953 }
8954 if (print_skew) {
8955 if (print_skew == 1) {
8956 tf.Form("%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
8957 tt.Form(tf.Data(),h2->GetSkewness(1));
8958 stats->AddText(tt.Data());
8959 tf.Form("%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
8960 tt.Form(tf.Data(),h2->GetSkewness(2));
8961 stats->AddText(tt.Data());
8962 } else {
8963 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
8964 ,"%",stats->GetStatFormat());
8965 tt.Form(tf.Data(),h2->GetSkewness(1),h2->GetSkewness(11));
8966 stats->AddText(tt.Data());
8967 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
8968 ,"%",stats->GetStatFormat());
8969 tt.Form(tf.Data(),h2->GetSkewness(2),h2->GetSkewness(12));
8970 stats->AddText(tt.Data());
8971 }
8972 }
8973 if (print_kurt) {
8974 if (print_kurt == 1) {
8975 tf.Form("%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
8976 tt.Form(tf.Data(),h2->GetKurtosis(1));
8977 stats->AddText(tt.Data());
8978 tf.Form("%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
8979 tt.Form(tf.Data(),h2->GetKurtosis(2));
8980 stats->AddText(tt.Data());
8981 } else {
8982 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
8983 ,"%",stats->GetStatFormat());
8984 tt.Form(tf.Data(),h2->GetKurtosis(1),h2->GetKurtosis(11));
8985 stats->AddText(tt.Data());
8986 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
8987 ,"%",stats->GetStatFormat());
8988 tt.Form(tf.Data(),h2->GetKurtosis(2),h2->GetKurtosis(12));
8989 stats->AddText(tt.Data());
8990 }
8991 }
8992 if (print_under || print_over) {
8993 //get 3*3 under/overflows for 2d hist
8994 Double_t unov[9];
8995
8996 Int_t cellsX = h2->GetXaxis()->GetNbins() + 1;
8997 Int_t cellsY = h2->GetYaxis()->GetNbins() + 1;
8998 Int_t firstX = std::max(1, h2->GetXaxis()->GetFirst());
8999 Int_t firstY = std::max(1, h2->GetYaxis()->GetFirst());
9000 Int_t lastX = std::min(h2->GetXaxis()->GetLast(), h2->GetXaxis()->GetNbins());
9001 Int_t lastY = std::min(h2->GetYaxis()->GetLast(), h2->GetYaxis()->GetNbins());
9002
9003 unov[0] = h2->Integral( 0, firstX-1, lastY+1, cellsY );
9004 unov[1] = h2->Integral(firstX , lastX , lastY+1, cellsY );
9005 unov[2] = h2->Integral(lastX+1, cellsX , lastY+1, cellsY );
9006 unov[3] = h2->Integral( 0, firstX-1, firstY , lastY );
9007 unov[4] = h2->Integral(firstX , lastX , firstY , lastY );
9008 unov[5] = h2->Integral(lastX+1, cellsX , firstY , lastY );
9009 unov[6] = h2->Integral( 0, firstX-1, 0, firstY-1);
9010 unov[7] = h2->Integral(firstX, lastX, 0, firstY-1);
9011 unov[8] = h2->Integral(lastX+1, cellsX , 0, firstY-1);
9012
9013 tt.Form("%g|%g|%g\n", unov[0], unov[1], unov[2]);
9014 stats->AddText(tt.Data());
9015 tt.Form("%g|%g|%g\n", unov[3], unov[4], unov[5]);
9016 stats->AddText(tt.Data());
9017 tt.Form("%g|%g|%g\n", unov[6], unov[7], unov[8]);
9018 stats->AddText(tt.Data());
9019 }
9020
9021 // Draw Fit parameters
9022 if (fit) {
9023 Int_t ndf = fit->GetNDF();
9024 tt.Form("#chi^{2} / ndf = %6.4g / %d",fit->GetChisquare(),ndf);
9025 stats->AddText(tt.Data());
9026 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
9027 tt.Form("%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
9028 ,fit->GetParameter(ipar)
9029 ,fit->GetParError(ipar));
9030 stats->AddText(tt.Data());
9031 }
9032 }
9033
9034 if (!done) fFunctions->Add(stats);
9035 stats->Paint();
9036}
9037
9038////////////////////////////////////////////////////////////////////////////////
9039/// [Draw the statistics box for 3D histograms.](\ref HP07)
9040
9042{
9043
9044 if (fH->GetDimension() != 3) return;
9045 TH3 *h3 = (TH3*)fH;
9046
9047 TString tt, tf;
9048 Int_t dofit;
9049 TPaveStats *stats = nullptr;
9050 TIter next(fFunctions);
9051 while (auto obj = next()) {
9052 if (obj->InheritsFrom(TPaveStats::Class())) {
9053 stats = (TPaveStats*)obj;
9054 break;
9055 }
9056 }
9057 if (stats && dostat) {
9058 dofit = stats->GetOptFit();
9059 dostat = stats->GetOptStat();
9060 } else {
9061 dofit = gStyle->GetOptFit();
9062 }
9063 if (dostat == 1) dostat = 1111;
9064 Int_t print_name = dostat%10;
9065 Int_t print_entries = (dostat/10)%10;
9066 Int_t print_mean = (dostat/100)%10;
9067 Int_t print_stddev = (dostat/1000)%10;
9068 Int_t print_under = (dostat/10000)%10;
9069 Int_t print_over = (dostat/100000)%10;
9070 Int_t print_integral= (dostat/1000000)%10;
9071 Int_t print_skew = (dostat/10000000)%10;
9072 Int_t print_kurt = (dostat/100000000)%10;
9073 Int_t nlines = print_name + print_entries + 3*print_mean + 3*print_stddev + print_integral;
9074 if (print_under || print_over) nlines += 3;
9075
9076 // Pavetext with statistics
9077 if (!gStyle->GetOptFit()) fit = nullptr;
9078 Bool_t done = kFALSE;
9079 if (!dostat && !fit) {
9080 if (stats) { fFunctions->Remove(stats); delete stats;}
9081 return;
9082 }
9083 Double_t statw = gStyle->GetStatW();
9084 if (fit) statw = 1.8*gStyle->GetStatW();
9085 Double_t stath = nlines*gStyle->GetStatFontSize();
9086 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
9087 stath = 0.25*nlines*gStyle->GetStatH();
9088 }
9089 if (fit) stath += gStyle->GetStatH();
9090 if (stats) {
9091 stats->Clear();
9092 done = kTRUE;
9093 } else {
9094 stats = new TPaveStats(
9095 gStyle->GetStatX()-statw,
9096 gStyle->GetStatY()-stath,
9097 gStyle->GetStatX(),
9098 gStyle->GetStatY(),"brNDC");
9099
9100 stats->SetParent(fH);
9101 stats->SetOptFit(dofit);
9102 stats->SetOptStat(dostat);
9103 stats->SetFillColor(gStyle->GetStatColor());
9104 stats->SetFillStyle(gStyle->GetStatStyle());
9106 stats->SetName("stats");
9107
9109 stats->SetTextAlign(12);
9110 stats->SetTextFont(gStyle->GetStatFont());
9111 stats->SetFitFormat(gStyle->GetFitFormat());
9113 stats->SetBit(kCanDelete);
9114 stats->SetBit(kMustCleanup);
9115 }
9116 if (print_name) stats->AddText(h3->GetName());
9117 if (print_entries) {
9118 if (h3->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(h3->GetEntries()+0.5));
9119 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(h3->GetEntries()+0.5));
9120 stats->AddText(tt.Data());
9121 }
9122 if (print_mean) {
9123 if (print_mean == 1) {
9124 tf.Form("%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
9125 tt.Form(tf.Data(),h3->GetMean(1));
9126 stats->AddText(tt.Data());
9127 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
9128 tt.Form(tf.Data(),h3->GetMean(2));
9129 stats->AddText(tt.Data());
9130 tf.Form("%s = %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat());
9131 tt.Form(tf.Data(),h3->GetMean(3));
9132 stats->AddText(tt.Data());
9133 } else {
9134 tf.Form("%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
9135 ,"%",stats->GetStatFormat());
9136 tt.Form(tf.Data(),h3->GetMean(1),h3->GetMeanError(1));
9137 stats->AddText(tt.Data());
9138 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
9139 ,"%",stats->GetStatFormat());
9140 tt.Form(tf.Data(),h3->GetMean(2),h3->GetMeanError(2));
9141 stats->AddText(tt.Data());
9142 tf.Form("%s = %s%s #pm %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat()
9143 ,"%",stats->GetStatFormat());
9144 tt.Form(tf.Data(),h3->GetMean(3),h3->GetMeanError(3));
9145 stats->AddText(tt.Data());
9146 }
9147 }
9148 if (print_stddev) {
9149 if (print_stddev == 1) {
9150 tf.Form("%s = %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat());
9151 tt.Form(tf.Data(),h3->GetStdDev(1));
9152 stats->AddText(tt.Data());
9153 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
9154 tt.Form(tf.Data(),h3->GetStdDev(2));
9155 stats->AddText(tt.Data());
9156 tf.Form("%s = %s%s",gStringStdDevZ.Data(),"%",stats->GetStatFormat());
9157 tt.Form(tf.Data(),h3->GetStdDev(3));
9158 stats->AddText(tt.Data());
9159 } else {
9160 tf.Form("%s = %s%s #pm %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat()
9161 ,"%",stats->GetStatFormat());
9162 tt.Form(tf.Data(),h3->GetStdDev(1),h3->GetStdDevError(1));
9163 stats->AddText(tt.Data());
9164 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
9165 ,"%",stats->GetStatFormat());
9166 tt.Form(tf.Data(),h3->GetStdDev(2),h3->GetStdDevError(2));
9167 stats->AddText(tt.Data());
9168 tf.Form("%s = %s%s #pm %s%s",gStringStdDevZ.Data(),"%",stats->GetStatFormat()
9169 ,"%",stats->GetStatFormat());
9170 tt.Form(tf.Data(),h3->GetStdDev(3),h3->GetStdDevError(3));
9171 stats->AddText(tt.Data());
9172 }
9173 }
9174 if (print_integral) {
9175 tt.Form("%s = %6.4g",gStringIntegral.Data(),h3->Integral());
9176 stats->AddText(tt.Data());
9177 }
9178 if (print_skew) {
9179 if (print_skew == 1) {
9180 tf.Form("%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
9181 tt.Form(tf.Data(),h3->GetSkewness(1));
9182 stats->AddText(tt.Data());
9183 tf.Form("%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
9184 tt.Form(tf.Data(),h3->GetSkewness(2));
9185 stats->AddText(tt.Data());
9186 tf.Form("%s = %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat());
9187 tt.Form(tf.Data(),h3->GetSkewness(3));
9188 stats->AddText(tt.Data());
9189 } else {
9190 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
9191 ,"%",stats->GetStatFormat());
9192 tt.Form(tf.Data(),h3->GetSkewness(1),h3->GetSkewness(11));
9193 stats->AddText(tt.Data());
9194 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
9195 ,"%",stats->GetStatFormat());
9196 tt.Form(tf.Data(),h3->GetSkewness(2),h3->GetSkewness(12));
9197 stats->AddText(tt.Data());
9198 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat()
9199 ,"%",stats->GetStatFormat());
9200 tt.Form(tf.Data(),h3->GetSkewness(3),h3->GetSkewness(13));
9201 stats->AddText(tt.Data());
9202 }
9203 }
9204 if (print_kurt) {
9205 if (print_kurt == 1) {
9206 tf.Form("%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
9207 tt.Form(tf.Data(),h3->GetKurtosis(1));
9208 stats->AddText(tt.Data());
9209 tf.Form("%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
9210 tt.Form(tf.Data(),h3->GetKurtosis(2));
9211 stats->AddText(tt.Data());
9212 tf.Form("%s = %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat());
9213 tt.Form(tf.Data(),h3->GetKurtosis(3));
9214 stats->AddText(tt.Data());
9215 } else {
9216 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
9217 ,"%",stats->GetStatFormat());
9218 tt.Form(tf.Data(),h3->GetKurtosis(1),h3->GetKurtosis(11));
9219 stats->AddText(tt.Data());
9220 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
9221 ,"%",stats->GetStatFormat());
9222 tt.Form(tf.Data(),h3->GetKurtosis(2),h3->GetKurtosis(12));
9223 stats->AddText(tt.Data());
9224 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat()
9225 ,"%",stats->GetStatFormat());
9226 tt.Form(tf.Data(),h3->GetKurtosis(3),h3->GetKurtosis(13));
9227 stats->AddText(tt.Data());
9228 }
9229 }
9230 if (print_under || print_over) {
9231 // no underflow - overflow printing for a 3D histogram
9232 // one would need a 3D table
9233 }
9234
9235 // Draw Fit parameters
9236 if (fit) {
9237 Int_t ndf = fit->GetNDF();
9238 tt.Form("#chi^{2} / ndf = %6.4g / %d",fit->GetChisquare(),ndf);
9239 stats->AddText(tt.Data());
9240 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
9241 tt.Form("%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
9242 ,fit->GetParameter(ipar)
9243 ,fit->GetParError(ipar));
9244 stats->AddText(tt.Data());
9245 }
9246 }
9247
9248 if (!done) fFunctions->Add(stats);
9249 stats->Paint();
9250}
9251
9252////////////////////////////////////////////////////////////////////////////////
9253/// [Control function to draw a 2D histogram as a surface plot.](\ref HP18)
9254
9256{
9257
9258 const Double_t ydiff = 1;
9259 const Double_t yligh1 = 10;
9260 const Double_t qa = 0.15;
9261 const Double_t qd = 0.15;
9262 const Double_t qs = 0.8;
9263 Double_t fmin, fmax;
9264 Int_t raster = 0;
9265 Int_t irep = 0;
9266
9267 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
9270 Double_t zmin = Hparam.zmin;
9271 Double_t zmax = Hparam.zmax;
9272 Double_t xlab1 = Hparam.xmin;
9273 Double_t xlab2 = Hparam.xmax;
9274 Double_t ylab1 = Hparam.ymin;
9275 Double_t ylab2 = Hparam.ymax;
9276 Double_t dangle = 10*3.141592/180; //Delta angle for Rapidity option
9277 Double_t deltaz = TMath::Abs(zmin);
9278 if (deltaz == 0) deltaz = 1;
9279 if (zmin >= zmax) {
9280 zmin -= 0.5*deltaz;
9281 zmax += 0.5*deltaz;
9282 }
9283 Double_t z1c = zmin;
9284 Double_t z2c = zmin + (zmax-zmin)*(1+gStyle->GetHistTopMargin());
9285 // Compute the lego limits and instantiate a lego object
9286 fXbuf[0] = -1;
9287 fYbuf[0] = 1;
9288 fXbuf[1] = -1;
9289 fYbuf[1] = 1;
9290 if (Hoption.System >= kPOLAR && (Hoption.Surf == 1 || Hoption.Surf == 13)) raster = 1;
9291 if (Hoption.System == kPOLAR) {
9292 fXbuf[2] = z1c;
9293 fYbuf[2] = z2c;
9294 } else if (Hoption.System == kCYLINDRICAL) {
9295 if (Hoption.Logy) {
9296 if (ylab1 > 0) fXbuf[2] = TMath::Log10(ylab1);
9297 else fXbuf[2] = 0;
9298 if (ylab2 > 0) fYbuf[2] = TMath::Log10(ylab2);
9299 else fYbuf[2] = 0;
9300 } else {
9301 fXbuf[2] = ylab1;
9302 fYbuf[2] = ylab2;
9303 }
9304 z1c = 0; z2c = 1;
9305 } else if (Hoption.System == kSPHERICAL) {
9306 fXbuf[2] = -1;
9307 fYbuf[2] = 1;
9308 z1c = 0; z2c = 1;
9309 } else if (Hoption.System == kRAPIDITY) {
9310 fXbuf[2] = -1/TMath::Tan(dangle);
9311 fYbuf[2] = 1/TMath::Tan(dangle);
9312 } else {
9313 fXbuf[0] = xlab1;
9314 fYbuf[0] = xlab2;
9315 fXbuf[1] = ylab1;
9316 fYbuf[1] = ylab2;
9317 fXbuf[2] = z1c;
9318 fYbuf[2] = z2c;
9319 }
9320
9321 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data(), Hoption.System);
9322 fLego->SetEdgeAtt(fH->GetLineColor(),fH->GetLineStyle(),fH->GetLineWidth(),0);
9323 fLego->SetFillColor(fH->GetFillColor());
9324
9325 // Initialize the levels on the Z axis
9326 Int_t ndiv = fH->GetContour();
9327 if (ndiv == 0 ) {
9328 ndiv = gStyle->GetNumberContours();
9329 fH->SetContour(ndiv);
9330 }
9331 Int_t ndivz = TMath::Abs(ndiv);
9332 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
9333
9334 if (Hoption.Surf == 13 || Hoption.Surf == 15) fLego->SetMesh(3);
9335 if (Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) fLego->SetMesh(0);
9336
9337 // Close the surface in case of non cartesian coordinates.
9338
9339 if (Hoption.System != kCARTESIAN) {nx++; ny++;}
9340
9341 // Now ready to draw the surface plot
9342
9343 TView *view = gPad ? gPad->GetView() : nullptr;
9344 if (!view) {
9345 Error("PaintSurface", "no TView in current pad");
9346 return;
9347 }
9348
9349 Double_t thedeg = 90 - gPad->GetTheta();
9350 Double_t phideg = -90 - gPad->GetPhi();
9351 Double_t psideg = view->GetPsi();
9352 view->SetView(phideg, thedeg, psideg, irep);
9353
9354 // Set color/style for back box
9355 if (Hoption.Same) {
9356 fLego->SetFillStyle(0);
9357 fLego->SetFillColor(1);
9358 } else {
9359 fLego->SetFillStyle(gPad->GetFrameFillStyle());
9360 fLego->SetFillColor(gPad->GetFrameFillColor());
9361 }
9362 fLego->TAttFill::Modify();
9363
9364 Int_t backcolor = gPad->GetFrameFillColor();
9365 if (Hoption.System != kCARTESIAN) backcolor = 0;
9366 view->PadRange(backcolor);
9367
9368 fLego->SetFillStyle(fH->GetFillStyle());
9369 fLego->SetFillColor(fH->GetFillColor());
9370 fLego->TAttFill::Modify();
9371
9372 // Draw the filled contour on top
9373 Int_t icol1 = fH->GetFillColor();
9374
9375 Int_t hoption35 = Hoption.Surf;
9376 if (Hoption.Surf == 13 || Hoption.Surf == 15) {
9377 DefineColorLevels(ndivz);
9378 Hoption.Surf = 23;
9379 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9381 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"BF");
9382 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9383 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9384 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9385 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"BF");
9386 Hoption.Surf = hoption35;
9387 fLego->SetMesh(1);
9388 }
9389
9390 if (raster) fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
9391 else fLego->InitMoveScreen(-1.1,1.1);
9392
9393 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) {
9394 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9397 fLego->BackBox(90);
9398 }
9399 }
9400
9401 // Gouraud Shading surface
9402 if (Hoption.Surf == 14) {
9403 // Set light sources
9404 fLego->LightSource(0, ydiff, 0,0,0,irep);
9405 fLego->LightSource(1, yligh1 ,1,1,1,irep);
9406 fLego->SurfaceProperty(qa, qd, qs, 1, irep);
9407 fmin = ydiff*qa;
9408 fmax = fmin + (yligh1+0.1)*(qd+qs);
9409 Int_t nbcol = 28;
9410 icol1 = 201;
9411 Double_t dcol = 0.5/Double_t(nbcol);
9412 TColor *colref = gROOT->GetColor(fH->GetFillColor());
9413 if (!colref) return;
9414 Float_t r,g,b,hue,light,satur;
9415 colref->GetRGB(r,g,b);
9416 TColor::RGBtoHLS(r,g,b,hue,light,satur);
9417 TColor *acol;
9418 for (Int_t col=0;col<nbcol;col++) {
9419 acol = gROOT->GetColor(col+icol1);
9420 TColor::HLStoRGB(hue,.4+col*dcol,satur,r,g,b);
9421 if (acol) acol->SetRGB(r,g,b);
9422 }
9423 fLego->Spectrum(nbcol, fmin, fmax, icol1, 1, irep);
9424 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::GouraudFunction);
9426 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"BF");
9427 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9428 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9429 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9430 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"BF");
9431 } else if (Hoption.Surf == 15) {
9432 // The surface is not drawn in this case.
9433 } else {
9434 // Draw the surface
9435 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 16 || Hoption.Surf == 17) {
9436 DefineColorLevels(ndivz);
9437 } else {
9438 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9439 }
9440 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9441 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceRaster1);
9442 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode2);
9443 if (Hoption.System == kPOLAR) {
9444 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfacePolar(1,nx,ny,"FB");
9445 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfacePolar(1,nx,ny,"BF");
9446 } else if (Hoption.System == kCYLINDRICAL) {
9447 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceCylindrical(1,nx,ny,"FB");
9448 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9449 } else if (Hoption.System == kSPHERICAL) {
9450 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceSpherical(0,1,nx,ny,"FB");
9451 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9452 } else if (Hoption.System == kRAPIDITY) {
9453 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceSpherical(1,1,nx,ny,"FB");
9454 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9455 } else {
9456 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove1);
9457 if (Hoption.Surf == 16) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove3);
9458 if (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16) fLego->SurfaceCartesian(90,nx,ny,"FB");
9459 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCartesian(90,nx,ny,"BF");
9460 }
9461 }
9462
9463 // Paint the line contour on top for option SURF7
9464 if (Hoption.Surf == 17) {
9465 fLego->InitMoveScreen(-1.1,1.1);
9466 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9467 Hoption.Surf = 23;
9468 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9470 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"FB");
9471 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"FB");
9472 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"FB");
9473 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"FB");
9474 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"FB");
9475 }
9476
9477 if ((!Hoption.Same) &&
9478 (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16)) {
9481 fLego->BackBox(90);
9482 }
9483 }
9484 if (Hoption.System == kCARTESIAN) {
9485 fLego->InitMoveScreen(-1.1,1.1);
9487 if (Hoption.FrontBox) fLego->FrontBox(90);
9488 }
9489 if (!Hoption.Axis && !Hoption.Same) {
9490 TGaxis axis;
9491 PaintLegoAxis(&axis, 90);
9492 }
9493
9495
9496 fLego.reset();
9497}
9498
9499////////////////////////////////////////////////////////////////////////////////
9500/// Control function to draw a table using Delaunay triangles.
9501
9503{
9504
9505 TGraphDelaunay2D *dt = nullptr;
9506 TGraphDelaunay *dtOld = nullptr;
9507
9508 // Check if fH contains a TGraphDelaunay2D
9509 TList *hl = fH->GetListOfFunctions();
9510 dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
9511 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
9512 if (!dt && !dtOld) return;
9513
9514 // If needed, create a TGraph2DPainter
9515 if (!fGraph2DPainter)
9516 fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
9517
9518 // Define the 3D view
9519 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
9520 if (Hoption.Same) {
9521 TView *viewsame = gPad ? gPad->GetView() : nullptr;
9522 if (!viewsame) {
9523 Error("PaintTriangles", "no TView in current pad, do not use option SAME");
9524 return;
9525 }
9526 Double_t *rmin = viewsame->GetRmin();
9527 Double_t *rmax = viewsame->GetRmax();
9528 if (!rmin || !rmax) return;
9529 fXbuf[0] = rmin[0];
9530 fYbuf[0] = rmax[0];
9531 fXbuf[1] = rmin[1];
9532 fYbuf[1] = rmax[1];
9533 fXbuf[2] = rmin[2];
9534 fYbuf[2] = rmax[2];
9535 fH->SetMaximum(rmax[2]);
9536 fH->SetMinimum(rmin[2]);
9537 fH->GetXaxis()->SetRangeUser(rmin[0],rmax[0]);
9538 fH->GetYaxis()->SetRangeUser(rmin[1],rmax[1]);
9539 } else {
9540 fXbuf[0] = Hparam.xmin;
9541 fYbuf[0] = Hparam.xmax;
9542 fXbuf[1] = Hparam.ymin;
9543 fYbuf[1] = Hparam.ymax;
9544 fXbuf[2] = Hparam.zmin;
9545 fYbuf[2] = Hparam.zmax;
9546 }
9547
9548 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
9549 TView *view = gPad ? gPad->GetView() : nullptr;
9550 if (!view) {
9551 Error("PaintTriangles", "no TView in current pad");
9552 return;
9553 }
9554 Double_t thedeg = 90 - gPad->GetTheta();
9555 Double_t phideg = -90 - gPad->GetPhi();
9556 Double_t psideg = view->GetPsi();
9557 Int_t irep;
9558 view->SetView(phideg, thedeg, psideg, irep);
9559
9560 // Set color/style for back box
9561 fLego->SetFillStyle(gPad->GetFrameFillStyle());
9562 fLego->SetFillColor(gPad->GetFrameFillColor());
9563 fLego->TAttFill::Modify();
9564 Int_t backcolor = gPad->GetFrameFillColor();
9565 if (Hoption.System != kCARTESIAN) backcolor = 0;
9566 view->PadRange(backcolor);
9567 fLego->SetFillStyle(fH->GetFillStyle());
9568 fLego->SetFillColor(fH->GetFillColor());
9569 fLego->TAttFill::Modify();
9570
9571 // Paint the Back Box if needed
9572 if (Hoption.BackBox && !Hoption.Same) {
9573 fLego->InitMoveScreen(-1.1,1.1);
9574 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9576 fLego->BackBox(90);
9577 }
9578
9579 // Paint the triangles
9580 fGraph2DPainter->Paint(option);
9581
9582 // Paint the Front Box if needed
9583 if (Hoption.FrontBox) {
9584 fLego->InitMoveScreen(-1.1,1.1);
9586 fLego->FrontBox(90);
9587 }
9588
9589 // Paint the Axis if needed
9590 if (!Hoption.Axis && !Hoption.Same) {
9591 TGaxis axis;
9592 PaintLegoAxis(&axis, 90);
9593 }
9594
9596
9597 fLego.reset();
9598}
9599
9600////////////////////////////////////////////////////////////////////////////////
9601/// Define the color levels used to paint legos, surfaces etc..
9602
9604{
9605
9606 Int_t i, irep;
9607
9608 // Initialize the color levels
9609 if (ndivz >= 100) {
9610 Warning("PaintSurface", "too many color levels, %d >= 100, reset to 99", ndivz);
9611 ndivz = 99;
9612 }
9613 std::vector<Double_t> funlevel(ndivz+1);
9614 std::vector<Int_t> colorlevel(ndivz+1);
9615 Int_t theColor;
9616 Int_t ncolors = gStyle->GetNumberOfColors();
9617 for (i = 0; i < ndivz; ++i) {
9618 funlevel[i] = fH->GetContourLevelPad(i);
9619 theColor = Int_t((i+0.99)*Float_t(ncolors)/Float_t(ndivz));
9620 colorlevel[i] = gStyle->GetColorPalette(theColor);
9621 }
9622 colorlevel[ndivz] = gStyle->GetColorPalette(ncolors-1);
9623 fLego->ColorFunction(ndivz, funlevel.data(), colorlevel.data(), irep);
9624}
9625
9626////////////////////////////////////////////////////////////////////////////////
9627/// [Control function to draw 2D/3D histograms (tables).](\ref HP01c)
9628
9630{
9631
9632 // Fill Hparam structure with histo parameters
9633 if (!TableInit()) return;
9634
9635 // Draw histogram frame
9636 PaintFrame();
9637
9638 // If palette option not specified, delete a possible existing palette
9639 if (!Hoption.Zscale) {
9640 TObject *palette = fFunctions->FindObject("palette");
9641 if (palette) { fFunctions->Remove(palette); delete palette;}
9642 }
9643
9644 // Do not draw the histogram. Only the attached functions will be drawn.
9645 if (Hoption.Func == 2) {
9646 if (Hoption.Zscale) {
9647 Int_t ndiv = fH->GetContour();
9648 if (ndiv == 0 ) {
9649 ndiv = gStyle->GetNumberContours();
9650 fH->SetContour(ndiv);
9651 }
9652 PaintPalette();
9653 }
9654
9655 // Draw the histogram according to the option
9656 } else {
9657 if (fH->InheritsFrom(TH2Poly::Class()) && Hoption.Axis<=0) {
9658 if (Hoption.Fill) PaintTH2PolyBins("f");
9662 if (Hoption.Line) PaintTH2PolyBins("l");
9663 if (Hoption.Mark) PaintTH2PolyBins("P");
9664 } else if (fH->GetEntries() != 0 && Hoption.Axis<=0) {
9668 if (Hoption.Color) {
9671 }
9674 if (Hoption.Error >= 100) Paint2DErrors(option);
9676 }
9680 }
9681
9682 // Draw histogram title
9683 PaintTitle();
9684
9685 // Draw the axes
9686 if (!Hoption.Lego && !Hoption.Surf &&
9687 !Hoption.Tri && !(Hoption.Error >= 100)) PaintAxis(kFALSE);
9688
9689 TF1 *fit = nullptr;
9690 TIter next(fFunctions);
9691 while (auto obj = next()) {
9692 if (obj->InheritsFrom(TF1::Class())) {
9693 fit = (TF1*)obj;
9694 break;
9695 }
9696 }
9697 if ((Hoption.Same%10) != 1) {
9698 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
9699 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
9700 //ALWAYS executed on non-iOS platform.
9701 //On iOS, depends on mode.
9703 }
9704 }
9705 }
9706}
9707
9708////////////////////////////////////////////////////////////////////////////////
9709/// Control function to draw a TH2Poly bins' contours.
9710///
9711/// - option = "F" draw the bins as filled areas.
9712/// - option = "L" draw the bins as line.
9713/// - option = "P" draw the bins as markers.
9714
9716{
9717
9718 //Do not highlight the histogram, if its part was picked.
9719 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH) return;
9720
9721 TString opt = option;
9722 opt.ToLower();
9723 Bool_t line = kFALSE;
9724 Bool_t fill = kFALSE;
9725 Bool_t mark = kFALSE;
9726 if (opt.Contains("l")) line = kTRUE;
9727 if (opt.Contains("f")) fill = kTRUE;
9728 if (opt.Contains("p")) mark = kTRUE;
9729
9730 TH2PolyBin *b;
9731 Double_t z;
9732
9733 TIter next(((TH2Poly*)fH)->GetBins());
9734 TObject *obj, *poly;
9735
9736 while ((obj=next())) {
9737 b = (TH2PolyBin*)obj;
9738 z = b->GetContent();
9739 if (z==0 && Hoption.Zero) continue; // Do not draw empty bins in case of option "COL0 L"
9740 poly = b->GetPolygon();
9741
9742 // Paint the TGraph bins.
9743 if (poly->IsA() == TGraph::Class()) {
9744 TGraph *g = (TGraph*)poly;
9745 g->TAttLine::Modify();
9746 g->TAttMarker::Modify();
9747 g->TAttFill::Modify();
9748 if (line) {
9749 Int_t fs = g->GetFillStyle();
9750 Int_t db = gStyle->GetDrawBorder();
9751 g->SetFillStyle(0);
9753 g->Paint("F");
9754 gStyle->SetDrawBorder(db);
9755 g->SetFillStyle(fs);
9756 }
9757 if (fill) g->Paint("F");
9758 if (mark) g->Paint("P");
9759 }
9760
9761 // Paint the TMultiGraph bins.
9762 if (poly->IsA() == TMultiGraph::Class()) {
9763 TMultiGraph *mg = (TMultiGraph*)poly;
9764 TList *gl = mg->GetListOfGraphs();
9765 if (!gl) return;
9766 TGraph *g;
9767 TIter nextg(gl);
9768 while ((g = (TGraph*) nextg())) {
9769 g->TAttLine::Modify();
9770 g->TAttMarker::Modify();
9771 g->TAttFill::Modify();
9772 if (line) {
9773 Int_t fs = g->GetFillStyle();
9774 Int_t db = gStyle->GetDrawBorder();
9775 g->SetFillStyle(0);
9777 g->Paint("F");
9778 gStyle->SetDrawBorder(db);
9779 g->SetFillStyle(fs);
9780 }
9781 if (fill) g->Paint("F");
9782 if (mark) g->Paint("P");
9783 }
9784 }
9785 }
9786}
9787
9788////////////////////////////////////////////////////////////////////////////////
9789/// [Control function to draw a TH2Poly as a color plot.](\ref HP20a)
9790
9792{
9793
9794 //Do not highlight the histogram, if its part was picked.
9795 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
9796 return;
9797
9798 Int_t ncolors, color, theColor;
9799 Double_t z, zc;
9800 Double_t zmin = fH->GetMinimum();
9801 Double_t zmax = fH->GetMaximum();
9802 if (Hoption.Logz) {
9803 if (zmax > 0) {
9804 if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
9805 zmin = TMath::Log10(zmin);
9806 zmax = TMath::Log10(zmax);
9807 } else {
9808 return;
9809 }
9810 }
9811 Double_t dz = zmax - zmin;
9812
9813 // Initialize the levels on the Z axis
9814 ncolors = gStyle->GetNumberOfColors();
9815 Int_t ndiv = fH->GetContour();
9816 if (ndiv == 0 ) {
9817 ndiv = gStyle->GetNumberContours();
9818 fH->SetContour(ndiv);
9819 }
9820 Int_t ndivz = TMath::Abs(ndiv);
9821 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
9822 Double_t scale = ndivz/dz;
9823
9824 TIter next(((TH2Poly*)fH)->GetBins());
9825
9826 while (auto obj = next()) {
9827 TH2PolyBin *b = (TH2PolyBin*)obj;
9828 TObject *poly = b->GetPolygon();
9829
9830 z = b->GetContent();
9831 if (z==0 && Hoption.Zero) continue;
9832 if (Hoption.Logz) {
9833 if (z > 0) z = TMath::Log10(z);
9834 else z = zmin;
9835 }
9836 if (z < zmin) continue;
9837
9838 // Define the bin color.
9840 zc = fH->GetContourLevelPad(0);
9841 if (z < zc) continue;
9842 color = -1;
9843 for (Int_t k=0; k<ndiv; k++) {
9844 zc = fH->GetContourLevelPad(k);
9845 if (z < zc) {
9846 continue;
9847 } else {
9848 color++;
9849 }
9850 }
9851 } else {
9852 color = Int_t(0.01+(z-zmin)*scale);
9853 }
9854 theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
9855 if (theColor > ncolors-1) theColor = ncolors-1;
9856
9857 // Paint the TGraph bins.
9858 if (poly->IsA() == TGraph::Class()) {
9859 TGraph *g = (TGraph*)poly;
9860 g->SetFillColor(gStyle->GetColorPalette(theColor));
9861 g->TAttFill::Modify();
9862 g->Paint("F");
9863 }
9864
9865 // Paint the TMultiGraph bins.
9866 if (poly->IsA() == TMultiGraph::Class()) {
9867 TMultiGraph *mg = (TMultiGraph*)poly;
9868 TList *gl = mg->GetListOfGraphs();
9869 if (!gl) return;
9870 TGraph *g;
9871 TIter nextg(gl);
9872 while ((g = (TGraph*) nextg())) {
9873 g->SetFillColor(gStyle->GetColorPalette(theColor));
9874 g->TAttFill::Modify();
9875 g->Paint("F");
9876 }
9877 }
9878 }
9880}
9881
9882////////////////////////////////////////////////////////////////////////////////
9883/// [Control function to draw a TH2Poly as a scatter plot.](\ref HP20a)
9884
9886{
9887
9888 //Do not highlight the histogram, if its part was selected.
9889 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
9890 return;
9891
9892 Int_t k, loop, marker=0;
9893 Double_t z, xk,xstep, yk, ystep, xp, yp;
9894 Double_t scale = 1;
9895 Double_t zmin = fH->GetMinimum();
9896 Double_t zmax = fH->GetMaximum();
9897 if (Hoption.Logz) {
9898 if (zmax > 0) {
9899 if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
9900 zmin = TMath::Log10(zmin);
9901 zmax = TMath::Log10(zmax);
9902 } else {
9903 return;
9904 }
9905 }
9906 Double_t dz = zmax - zmin;
9907 scale = (kNMAX-1)/dz;
9908
9909
9910 // use an independent instance of a random generator
9911 // instead of gRandom to avoid conflicts and
9912 // to get same random numbers when drawing the same histogram
9913 TRandom2 random;
9914
9915 TH2PolyBin *b;
9916
9917 TIter next(((TH2Poly*)fH)->GetBins());
9918 TObject *obj, *poly;
9919
9920 Double_t maxarea = 0, a;
9921 while ((obj=next())) {
9922 b = (TH2PolyBin*)obj;
9923 a = b->GetArea();
9924 if (a>maxarea) maxarea = a;
9925 }
9926
9927 next.Reset();
9928
9929 while ((obj=next())) {
9930 b = (TH2PolyBin*)obj;
9931 poly = b->GetPolygon();
9932 z = b->GetContent();
9933 if (z < zmin) z = zmin;
9934 if (z > zmax) z = zmax;
9935 if (Hoption.Logz) {
9936 if (z > 0) z = TMath::Log10(z) - zmin;
9937 } else {
9938 z -= zmin;
9939 }
9940 k = Int_t((z*scale)*(b->GetArea()/maxarea));
9941 xk = b->GetXMin();
9942 yk = b->GetYMin();
9943 xstep = b->GetXMax()-xk;
9944 ystep = b->GetYMax()-yk;
9945
9946 // Paint the TGraph bins.
9947 if (poly->IsA() == TGraph::Class()) {
9948 TGraph *g = (TGraph*)poly;
9949 if (k <= 0 || z <= 0) continue;
9950 loop = 0;
9951 while (loop<k) {
9952 if (k+marker >= kNMAX) {
9953 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
9954 marker=0;
9955 }
9956 xp = (random.Rndm()*xstep) + xk;
9957 yp = (random.Rndm()*ystep) + yk;
9958 if (g->IsInside(xp,yp)) {
9959 fXbuf[marker] = xp;
9960 fYbuf[marker] = yp;
9961 marker++;
9962 loop++;
9963 }
9964 }
9965 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
9966 }
9967
9968 // Paint the TMultiGraph bins.
9969 if (poly->IsA() == TMultiGraph::Class()) {
9970 TMultiGraph *mg = (TMultiGraph*)poly;
9971 TList *gl = mg->GetListOfGraphs();
9972 if (!gl) return;
9973 if (k <= 0 || z <= 0) continue;
9974 loop = 0;
9975 while (loop<k) {
9976 if (k+marker >= kNMAX) {
9977 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
9978 marker=0;
9979 }
9980 xp = (random.Rndm()*xstep) + xk;
9981 yp = (random.Rndm()*ystep) + yk;
9982 if (mg->IsInside(xp,yp)) {
9983 fXbuf[marker] = xp;
9984 fYbuf[marker] = yp;
9985 marker++;
9986 loop++;
9987 }
9988 }
9989 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
9990 }
9991 }
9992 PaintTH2PolyBins("l");
9993}
9994
9995////////////////////////////////////////////////////////////////////////////////
9996/// [Control function to draw a TH2Poly as a text plot.](\ref HP20a)
9997
9999{
10000
10001 TLatex text;
10002 text.SetTextFont(gStyle->GetTextFont());
10003 text.SetTextColor(fH->GetMarkerColor());
10004 text.SetTextSize(0.02*fH->GetMarkerSize());
10005
10006 Double_t x, y, z, e, angle = 0;
10007 TString tt, tf;
10008 tf.Form("%s%s","%",gStyle->GetPaintTextFormat());
10009 if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
10010 Int_t opt = (Int_t)Hoption.Text/1000;
10011
10012 text.SetTextAlign(22);
10013 if (Hoption.Text == 1) angle = 0;
10014 text.SetTextAngle(angle);
10015 text.TAttText::Modify();
10016
10017 TH2PolyBin *b;
10018
10019 TIter next(((TH2Poly*)fH)->GetBins());
10020 TObject *obj, *p;
10021
10022 while ((obj=next())) {
10023 b = (TH2PolyBin*)obj;
10024 p = b->GetPolygon();
10025 x = (b->GetXMin()+b->GetXMax())/2;
10026 if (Hoption.Logx) {
10027 if (x > 0) x = TMath::Log10(x);
10028 else continue;
10029 }
10030 y = (b->GetYMin()+b->GetYMax())/2;
10031 if (Hoption.Logy) {
10032 if (y > 0) y = TMath::Log10(y);
10033 else continue;
10034 }
10035 z = b->GetContent();
10036 if (z < fH->GetMinimum() || (z == 0 && !Hoption.MinimumZero)) continue;
10037 if (opt==2) {
10038 e = fH->GetBinError(b->GetBinNumber());
10039 tf.Form("#splitline{%s%s}{#pm %s%s}",
10041 "%",gStyle->GetPaintTextFormat());
10042 tt.Form(tf.Data(),z,e);
10043 } else {
10044 tt.Form(tf.Data(),z);
10045 }
10046 if (opt==3) text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),p->GetName());
10047 else text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),tt.Data());
10048 }
10049
10050 PaintTH2PolyBins("l");
10051}
10052
10053////////////////////////////////////////////////////////////////////////////////
10054/// [Control function to draw a 1D/2D histograms with the bin values.](\ref HP15)
10055
10057{
10058
10059 TLatex text;
10060 text.SetTextFont(gStyle->GetTextFont());
10061 text.SetTextColor(fH->GetMarkerColor());
10062 text.SetTextSize(0.02*fH->GetMarkerSize());
10063
10064 Double_t x, y, z, e, angle = 0;
10065 TString tt, tf;
10066 tf.Form("%s%s","%",gStyle->GetPaintTextFormat());
10067 if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
10068
10069 // 1D histograms
10070 if (fH->GetDimension() == 1) {
10071 Bool_t getentries = kFALSE;
10072 Double_t yt;
10073 TProfile *hp = (TProfile*)fH;
10074 if (Hoption.Text>2000 && fH->InheritsFrom(TProfile::Class())) {
10075 Hoption.Text = Hoption.Text-2000;
10076 getentries = kTRUE;
10077 }
10078 if (Hoption.Text == 1) angle = 90;
10079 text.SetTextAlign(11);
10080 if (angle == 90) text.SetTextAlign(12);
10081 if (angle == 0) text.SetTextAlign(21);
10082 text.TAttText::Modify();
10083 Double_t dt = 0.02*(gPad->GetY2()-gPad->GetY1());
10084 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10085 if (Hoption.Bar) {
10086 x = fH->GetXaxis()->GetBinLowEdge(i)+
10087 fH->GetXaxis()->GetBinWidth(i)*
10088 (fH->GetBarOffset()+0.5*fH->GetBarWidth());
10089 } else {
10090 x = fH->GetXaxis()->GetBinCenter(i);
10091 }
10092 y = fH->GetBinContent(i);
10093 yt = y;
10094 if (Hoption.MinimumZero && y<0) y = 0;
10095 if (getentries) yt = hp->GetBinEntries(i);
10096 if (yt == 0.) continue;
10097 tt.Form(tf.Data(),yt);
10098 if (Hoption.Logx) {
10099 if (x > 0) x = TMath::Log10(x);
10100 else continue;
10101 }
10102 if (Hoption.Logy) {
10103 if (y > 0) y = TMath::Log10(y);
10104 else continue;
10105 }
10106 if (y >= gPad->GetY2()) continue;
10107 if (y <= gPad->GetY1()) continue;
10108 text.PaintLatex(x,y+0.2*dt,angle,0.02*fH->GetMarkerSize(),tt.Data());
10109 }
10110
10111 // 2D histograms
10112 } else {
10113 text.SetTextAlign(22);
10114 if (Hoption.Text == 1) angle = 0;
10115 text.SetTextAngle(angle);
10116 text.TAttText::Modify();
10117 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
10118 y = fYaxis->GetBinCenter(j);
10119 if (Hoption.Logy) {
10120 if (y > 0) y = TMath::Log10(y);
10121 else continue;
10122 }
10123 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10124 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
10125 x = fXaxis->GetBinCenter(i);
10126 if (Hoption.Logx) {
10127 if (x > 0) x = TMath::Log10(x);
10128 else continue;
10129 }
10130 if (!IsInside(x,y)) continue;
10131 z = fH->GetBinContent(bin);
10132 if (z < Hparam.zmin || (z == 0 && !Hoption.MinimumZero)) continue;
10133 if (Hoption.Text>2000) {
10134 e = fH->GetBinError(bin);
10135 tf.Form("#splitline{%s%s}{#pm %s%s}",
10137 "%",gStyle->GetPaintTextFormat());
10138 tt.Form(tf.Data(),z,e);
10139 } else {
10140 tt.Form(tf.Data(),z);
10141 }
10142 text.PaintLatex(x,y+fH->GetBarOffset()*fYaxis->GetBinWidth(j),
10143 angle,0.02*fH->GetMarkerSize(),tt.Data());
10144 }
10145 }
10146 }
10147}
10148
10149////////////////////////////////////////////////////////////////////////////////
10150/// [Control function to draw a 3D implicit functions.](\ref HP27)
10151
10153{
10154
10155 Int_t irep;
10156
10157 TAxis *xaxis = fH->GetXaxis();
10158 TAxis *yaxis = fH->GetYaxis();
10159 TAxis *zaxis = fH->GetZaxis();
10160
10161 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
10162 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
10163 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
10164 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
10165 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
10166 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
10167
10168 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
10169
10170 TView *view = gPad ? gPad->GetView() : nullptr;
10171 if (!view) {
10172 Error("PaintTF3", "no TView in current pad");
10173 return;
10174 }
10175 Double_t thedeg = 90 - gPad->GetTheta();
10176 Double_t phideg = -90 - gPad->GetPhi();
10177 Double_t psideg = view->GetPsi();
10178 view->SetView(phideg, thedeg, psideg, irep);
10179
10180 fLego->InitMoveScreen(-1.1,1.1);
10181
10182 if (Hoption.BackBox) {
10183 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
10185 fLego->BackBox(90);
10186 }
10187
10189
10190 fLego->ImplicitFunction(fCurrentF3, fXbuf.data(), fYbuf.data(), fH->GetNbinsX(),
10191 fH->GetNbinsY(),
10192 fH->GetNbinsZ(), "BF");
10193
10194 if (Hoption.FrontBox) {
10195 fLego->InitMoveScreen(-1.1,1.1);
10197 fLego->FrontBox(90);
10198 }
10199 if (!Hoption.Axis && !Hoption.Same) {
10200 TGaxis axis;
10201 PaintLegoAxis(&axis, 90);
10202 }
10203
10204 PaintTitle();
10205
10206 fLego.reset();
10207}
10208
10209/////////////////////////////////////////////////////////////new TGaxis///////////////////
10210/// Draw the histogram title
10211///
10212/// The title is drawn according to the title alignment returned by
10213/// `GetTitleAlign()`. It is a 2 digits integer): hv
10214///
10215/// where `h` is the horizontal alignment and `v` is the
10216/// vertical alignment.
10217///
10218/// - `h` can get the values 1 2 3 for left, center, and right
10219/// - `v` can get the values 1 2 3 for bottom, middle and top
10220///
10221/// for instance the default alignment is: 13 (left top)
10222
10224{
10225 // probably best place for calls PaintHighlightBin
10226 // calls after paint histo (1D or 2D) and before paint title and stats
10227 if (!gPad->GetView()) PaintHighlightBin();
10228
10229 if (Hoption.Same) return;
10230 if (fH->TestBit(TH1::kNoTitle)) return;
10231 Int_t nt = strlen(fH->GetTitle());
10232 TPaveText *title = nullptr;
10233 TObject *obj;
10234 TIter next(gPad->GetListOfPrimitives());
10235 while ((obj = next())) {
10236 if (!obj->InheritsFrom(TPaveText::Class())) continue;
10237 title = (TPaveText*)obj;
10238 if (strcmp(title->GetName(),"title")) {title = nullptr; continue;}
10239 break;
10240 }
10241 if (nt == 0 || gStyle->GetOptTitle() <= 0) {
10242 if (title) delete title;
10243 return;
10244 }
10245 Double_t ht = gStyle->GetTitleH();
10246 Double_t wt = gStyle->GetTitleW();
10247
10248 if (ht <= 0) {
10249 if (gStyle->GetTitleFont("")%10 == 3) {
10250 Double_t hw = TMath::Max((Double_t)gPad->XtoPixel(gPad->GetX2()),
10251 (Double_t)gPad->YtoPixel(gPad->GetY1()));
10252 ht = 1.1*(gStyle->GetTitleSize("")/hw);
10253 } else {
10254 ht = 1.1*gStyle->GetTitleFontSize();
10255 }
10256 }
10257 if (ht <= 0) ht = 0.05;
10258 if (wt <= 0) {
10259 TLatex l;
10260 l.SetTextSize(ht);
10261 l.SetTitle(fH->GetTitle());
10262 // adjustment in case the title has several lines (#splitline)
10263 ht = TMath::Max(ht, 1.2*l.GetYsize()/(gPad->GetY2() - gPad->GetY1()));
10264 Double_t wndc = l.GetXsize()/(gPad->GetX2() - gPad->GetX1());
10265 wt = TMath::Min(0.7, 0.02+wndc);
10266 }
10267 if (title) {
10268 TText *t0 = (TText*)title->GetLine(0);
10269 if (t0) {
10270 if (!strcmp(t0->GetTitle(),fH->GetTitle())) return;
10271 t0->SetTitle(fH->GetTitle());
10272 if (wt > 0) title->SetX2NDC(title->GetX1NDC()+wt);
10273 }
10274 return;
10275 }
10276
10277 Int_t talh = gStyle->GetTitleAlign()/10;
10278 if (talh < 1) talh = 1; else if (talh > 3) talh = 3;
10279 Int_t talv = gStyle->GetTitleAlign()%10;
10280 if (talv < 1) talv = 1; else if (talv > 3) talv = 3;
10282 xpos = gStyle->GetTitleX();
10283 ypos = gStyle->GetTitleY();
10284 if (talh == 2) xpos = xpos-wt/2.;
10285 if (talh == 3) xpos = xpos-wt;
10286 if (talv == 2) ypos = ypos+ht/2.;
10287 if (talv == 1) ypos = ypos+ht;
10288
10289 TPaveText *ptitle = new TPaveText(xpos, ypos-ht, xpos+wt, ypos,"blNDC");
10290
10291 // box with the histogram title
10293 ptitle->SetFillStyle(gStyle->GetTitleStyle());
10294 ptitle->SetName("title");
10297 ptitle->SetTextFont(gStyle->GetTitleFont(""));
10298 if (gStyle->GetTitleFont("")%10 > 2)
10300 ptitle->AddText(fH->GetTitle());
10301 ptitle->SetBit(kCanDelete);
10302 ptitle->Draw();
10303 ptitle->Paint("blNDC");
10304
10305 if(!gPad->IsEditable()) delete ptitle;
10306}
10307
10308////////////////////////////////////////////////////////////////////////////////
10309/// Process message `mess`.
10310
10311void THistPainter::ProcessMessage(const char *mess, const TObject *obj)
10312{
10313 if (!strcmp(mess,"SetF3")) {
10314 fCurrentF3 = (TF3 *)obj;
10315 }
10316}
10317
10318////////////////////////////////////////////////////////////////////////////////
10319/// Static function.
10320///
10321/// Convert Right Ascension, Declination to X,Y using an AITOFF projection.
10322/// This procedure can be used to create an all-sky map in Galactic
10323/// coordinates with an equal-area Aitoff projection. Output map
10324/// coordinates are zero longitude centered.
10325/// Also called Hammer-Aitoff projection (first presented by Ernst von Hammer in 1892)
10326///
10327/// source: GMT
10328///
10329/// code from Ernst-Jan Buis
10330
10332{
10333
10334 Double_t x, y;
10335
10336 Double_t alpha2 = (l/2)*TMath::DegToRad();
10337 Double_t delta = b*TMath::DegToRad();
10338 Double_t r2 = TMath::Sqrt(2.);
10339 Double_t f = 2*r2/TMath::Pi();
10340 Double_t cdec = TMath::Cos(delta);
10341 Double_t denom = TMath::Sqrt(1. + cdec*TMath::Cos(alpha2));
10342 x = cdec*TMath::Sin(alpha2)*2.*r2/denom;
10343 y = TMath::Sin(delta)*r2/denom;
10344 x *= TMath::RadToDeg()/f;
10345 y *= TMath::RadToDeg()/f;
10346 // x *= -1.; // for a skymap swap left<->right
10347 Al = x;
10348 Ab = y;
10349
10350 return 0;
10351}
10352
10353////////////////////////////////////////////////////////////////////////////////
10354/// Static function
10355///
10356/// Probably the most famous of the various map projections, the Mercator projection
10357/// takes its name from Mercator who presented it in 1569. It is a cylindrical, conformal projection
10358/// with no distortion along the equator.
10359/// The Mercator projection has been used extensively for world maps in which the distortion towards
10360/// the polar regions grows rather large, thus incorrectly giving the impression that, for example,
10361/// Greenland is larger than South America. In reality, the latter is about eight times the size of
10362/// Greenland. Also, the Former Soviet Union looks much bigger than Africa or South America. One may wonder
10363/// whether this illusion has had any influence on U.S. foreign policy.' (Source: GMT)
10364/// code from Ernst-Jan Buis
10365
10367{
10368
10369 Al = l;
10371 Ab = TMath::Log(aid);
10372 return 0;
10373}
10374
10375////////////////////////////////////////////////////////////////////////////////
10376/// Static function code for sinusoidal projection
10377/// from Ernst-Jan Buis
10378/// Source https://en.wikipedia.org/wiki/Sinusoidal_projection
10379
10381{
10382
10383 Al = l*cos(b*TMath::DegToRad());
10384 Ab = b;
10385 return 0;
10386}
10387
10388////////////////////////////////////////////////////////////////////////////////
10389/// Static function code for parabolic projection
10390/// from Ernst-Jan Buis
10391
10393{
10394
10395 Al = l*(2.*TMath::Cos(2*b*TMath::DegToRad()/3) - 1);
10396 Ab = 180*TMath::Sin(b*TMath::DegToRad()/3);
10397 return 0;
10398}
10399
10400////////////////////////////////////////////////////////////////////////////////
10401/// Static function.
10402///
10403/// Convert Right Ascension, Declination to X,Y using an MOLLWEIDE projection.
10404/// This procedure can be used to create an all-sky map in Galactic
10405/// coordinates with an equal-area Mollweide projection. Output map
10406/// coordinates are zero longitude centered.
10407/// It is also known as the Babinet projection, homalographic projection, homolographic projection, and elliptical projection.
10408/// Source: https://en.wikipedia.org/wiki/Mollweide_projection
10409///
10410/// code from Marco Meyer-Conde
10411
10413{
10414
10415 Double_t theta0 = b * TMath::DegToRad(), theta = theta0;
10416
10417 for (int i = 0; i < 100; i++) {
10418 Double_t num = 2 * theta + TMath::Sin(2 * theta) - TMath::Pi() * TMath::Sin(theta0);
10419 Double_t den = 4 * TMath::Power(TMath::Cos(theta), 2);
10420
10421 if (den < 1e-20) {
10422 theta = theta0;
10423 break;
10424 }
10425
10426 theta -= num / den;
10427
10428 if (TMath::Abs(num / den) < 1e-4) break;
10429 }
10430
10431 Al = l * TMath::Cos(theta);
10432 Ab = 90 * TMath::Sin(theta);
10433
10434 return 0;
10435}
10436
10437////////////////////////////////////////////////////////////////////////////////
10438/// Recompute the histogram range following graphics operations.
10439
10441{
10442
10443 if (Hoption.Same) return;
10444
10445 // Compute x,y range
10447 xmax = Hparam.xmax,
10448 ymin = Hparam.ymin,
10449 ymax = Hparam.ymax,
10450 xscale = 1;
10451
10452 std::function<Int_t(Double_t,Double_t,Double_t&,Double_t&)> func;
10453
10454 if (Hoption.Proj == 1) {
10455 func = ProjectAitoff2xy;
10456 xscale = 0.9999;
10457 } else if (Hoption.Proj == 2) {
10458 if (Hparam.ymin <= -90 || Hparam.ymax >= 90) {
10459 Warning("Mercator Projection", "Latitude out of range %f or %f", Hparam.ymin, Hparam.ymax);
10460 Hoption.Proj = 0;
10461 } else {
10464 }
10465 } else if (Hoption.Proj == 3) {
10466 func = ProjectSinusoidal2xy;
10467 } else if (Hoption.Proj == 4) {
10468 func = ProjectParabolic2xy;
10469 } else if (Hoption.Proj == 5) {
10470 func = ProjectMollweide2xy;
10471 }
10472
10473 if (func) {
10474 Double_t xmin_aid, ymin_aid, xmax_aid, ymax_aid;
10475
10476 func(Hparam.xmin, Hparam.ymin, xmin_aid, ymin_aid);
10477 func(Hparam.xmin, Hparam.ymax, xmin, ymax_aid);
10478 func(Hparam.xmax, Hparam.ymax, xmax_aid, ymax);
10479 func(Hparam.xmax, Hparam.ymin, xmax, ymin);
10480
10481 if (xmin > xmin_aid) xmin = xmin_aid;
10482 if (ymin > ymin_aid) ymin = ymin_aid;
10483 if (xmax < xmax_aid) xmax = xmax_aid;
10484 if (ymax < ymax_aid) ymax = ymax_aid;
10485 if (Hparam.ymin < 0 && Hparam.ymax > 0) {
10486 // there is an 'equator', check its range in the plot..
10487 func(Hparam.xmin*xscale, 0, xmin_aid, ymin_aid);
10488 func(Hparam.xmax*xscale, 0, xmax_aid, ymin_aid);
10489 if (xmin > xmin_aid) xmin = xmin_aid;
10490 if (xmax < xmax_aid) xmax = xmax_aid;
10491 }
10492 if (Hparam.xmin < 0 && Hparam.xmax > 0) {
10493 func(0, Hparam.ymin, xmin_aid, ymin_aid);
10494 func(0, Hparam.ymax, xmax_aid, ymax_aid);
10495 if (ymin > ymin_aid) ymin = ymin_aid;
10496 if (ymax < ymax_aid) ymax = ymax_aid;
10497 }
10498 }
10499
10500 Hparam.xmin = xmin;
10501 Hparam.xmax = xmax;
10502 Hparam.ymin = ymin;
10503 Hparam.ymax = ymax;
10504
10505 Double_t dx = xmax-xmin;
10506 Double_t dy = ymax-ymin;
10507 Double_t dxr = dx/(1 - gPad->GetLeftMargin() - gPad->GetRightMargin());
10508 Double_t dyr = dy/(1 - gPad->GetBottomMargin() - gPad->GetTopMargin());
10509
10510 // Range() could change the size of the pad pixmap and therefore should
10511 // be called before the other paint routines
10512 gPad->Range(xmin - dxr*gPad->GetLeftMargin(),
10513 ymin - dyr*gPad->GetBottomMargin(),
10514 xmax + dxr*gPad->GetRightMargin(),
10515 ymax + dyr*gPad->GetTopMargin());
10516 gPad->RangeAxis(xmin, ymin, xmax, ymax);
10517}
10518
10519////////////////////////////////////////////////////////////////////////////////
10520/// Set current histogram to `h`
10521
10523{
10524
10525 if (h == nullptr) return;
10526 fH = h;
10527 fXaxis = h->GetXaxis();
10528 fYaxis = h->GetYaxis();
10529 fZaxis = h->GetZaxis();
10531}
10532
10533////////////////////////////////////////////////////////////////////////////////
10534/// Initialize various options to draw 2D histograms.
10535
10537{
10538
10539 static const char *where = "TableInit";
10540
10541 Int_t first, last;
10542 Double_t yMARGIN= gStyle->GetHistTopMargin();
10543 Double_t zmin, zmax;
10544 Int_t maximum = 0;
10545 Int_t minimum = 0;
10546 if (fH->GetMaximumStored() != -1111) maximum = 1;
10547 if (fH->GetMinimumStored() != -1111) minimum = 1;
10548
10549 // ----------------- Compute X axis parameters
10550 first = fXaxis->GetFirst();
10551 last = fXaxis->GetLast();
10552 Hparam.xlast = last;
10553 Hparam.xfirst = first;
10558
10559 // if log scale in X, replace xmin,max by the log
10560 if (Hoption.Logx) {
10561 // find the first edge of a bin that is > 0
10562 if (Hparam.xlowedge <=0 ) {
10565 }
10566 if (Hparam.xmin <=0 || Hparam.xmax <=0) {
10567 Error(where, "cannot set X axis to log scale");
10568 return 0;
10569 }
10571 if (Hparam.xfirst < first) Hparam.xfirst = first;
10573 if (Hparam.xlast > last) Hparam.xlast = last;
10576 }
10577
10578 // ----------------- Compute Y axis parameters
10579 first = fYaxis->GetFirst();
10580 last = fYaxis->GetLast();
10581 Hparam.ylast = last;
10582 Hparam.yfirst = first;
10585 if (!Hparam.ybinsize) Hparam.ybinsize = 1;
10588
10589 // if log scale in Y, replace ymin,max by the log
10590 if (Hoption.Logy) {
10591 if (Hparam.ylowedge <=0 ) {
10594 }
10595 if (Hparam.ymin <=0 || Hparam.ymax <=0) {
10596 Error(where, "cannot set Y axis to log scale");
10597 return 0;
10598 }
10600 if (Hparam.yfirst < first) Hparam.yfirst = first;
10602 if (Hparam.ylast > last) Hparam.ylast = last;
10605 }
10606
10607
10608 // ----------------- Compute Z axis parameters
10609 Double_t bigp = TMath::Power(10,32);
10610 zmax = -bigp;
10611 zmin = bigp;
10612 Double_t c1, e1;
10613 Double_t allchan = 0;
10614 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
10615 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10616 c1 = fH->GetBinContent(i,j);
10617 zmax = TMath::Max(zmax,c1);
10618 if (Hoption.Error) {
10619 e1 = fH->GetBinError(i,j);
10620 zmax = TMath::Max(zmax,c1+e1);
10621 }
10622 zmin = TMath::Min(zmin,c1);
10623 allchan += c1;
10624 }
10625 }
10626
10627 // Take into account maximum , minimum
10628
10629 if (maximum) zmax = fH->GetMaximumStored();
10630 if (minimum) zmin = fH->GetMinimumStored();
10631 if (Hoption.Logz && zmax < 0) {
10632 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10633 return 0;
10634 } else if (Hoption.Logz && zmin>=0 && zmax==0) { // empty histogram in log scale
10635 zmin = 0.01;
10636 zmax = 10.;
10637 }
10638 if (zmin >= zmax) {
10639 if (Hoption.Logz) {
10640 if (zmax > 0) zmin = 0.001*zmax;
10641 else {
10642 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10643 return 0;
10644 }
10645 }
10646 }
10647
10648 // take into account normalization factor
10649 Hparam.allchan = allchan;
10650 Double_t factor = allchan;
10651 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
10652 if (allchan) factor /= allchan;
10653 if (factor == 0) factor = 1;
10654 Hparam.factor = factor;
10655 zmax = factor*zmax;
10656 zmin = factor*zmin;
10657 c1 = zmax;
10658 if (TMath::Abs(zmin) > TMath::Abs(c1)) c1 = zmin;
10659
10660 // For log scales, histogram coordinates are log10(ymin) and
10661 // log10(ymax). Final adjustment (if not option "Same")
10662 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
10663 // Maximum and Minimum are not defined.
10664 if (Hoption.Logz) {
10665 if (zmin <= 0) {
10666 zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
10667 fH->SetMinimum(zmin);
10668 }
10669 zmin = TMath::Log10(zmin);
10670 if (!minimum) zmin += TMath::Log10(0.5);
10671 zmax = TMath::Log10(zmax);
10672 if (!maximum) zmax += TMath::Log10(2*(0.9/0.95));
10673 goto LZMIN;
10674 }
10675
10676 // final adjustment of YMAXI for linear scale (if not option "Same"):
10677 // decrease histogram height to MAX% of allowed height if HMAXIM
10678 // has not been called.
10679 // MAX% is the value in percent which has been set in HPLSET
10680 // (default is 90%).
10681 if (!maximum) {
10682 zmax += yMARGIN*(zmax-zmin);
10683 }
10684
10685 // final adjustment of ymin for linear scale.
10686 // if minimum is not set , then ymin is set to zero if >0
10687 // or to ymin - yMARGIN if <0.
10688 if (!minimum) {
10689 if (Hoption.MinimumZero) {
10690 if (zmin >= 0) zmin = 0;
10691 else zmin -= yMARGIN*(zmax-zmin);
10692 } else {
10693 Double_t dzmin = yMARGIN*(zmax-zmin);
10694 if (zmin >= 0 && (zmin-dzmin <= 0)) zmin = 0;
10695 else zmin -= dzmin;
10696 }
10697 }
10698
10699LZMIN:
10700 Hparam.zmin = zmin;
10701 Hparam.zmax = zmax;
10702
10703 // Set bar offset and width
10706
10707 return 1;
10708}
10709
10710////////////////////////////////////////////////////////////////////////////////
10711/// This function returns the best format to print the error value (e)
10712/// knowing the parameter value (v) and the format (f) used to print it.
10713
10715{
10716
10717 static TString ef;
10718 TString tf, tv;
10719
10720 // print v with the format f in tv.
10721 tf.Form("%s%s","%",f);
10722 tv.Form(tf.Data(),v);
10723
10724 // Analyse tv.
10725 int ie = tv.Index("e");
10726 int iE = tv.Index("E");
10727 int id = tv.Index(".");
10728
10729 // v has been printed with the exponent notation.
10730 // There is 2 cases, the exponent is positive or negative
10731 if (ie >= 0 || iE >= 0) {
10732 if (tv.Index("+") >= 0) {
10733 if (e < 1) {
10734 ef.Form("%s.1f","%");
10735 } else {
10736 if (ie >= 0) {
10737 ef.Form("%s.%de","%",ie-id-1);
10738 } else {
10739 ef.Form("%s.%dE","%",iE-id-1);
10740 }
10741 }
10742 } else {
10743 if (ie >= 0) {
10744 ef.Form("%s.%de","%",ie-id-1);
10745 } else {
10746 ef.Form("%s.%dE","%",iE-id-1);
10747 }
10748 }
10749
10750 // There is not '.' in tv. e will be printed with one decimal digit.
10751 } else if (id < 0) {
10752 ef.Form("%s.1f","%");
10753
10754 // There is a '.' in tv and no exponent notation. e's decimal part will
10755 // have the same number of digits as v's one.
10756 } else {
10757 ef.Form("%s.%df","%",tv.Length()-id-1);
10758 }
10759
10760 return ef.Data();
10761}
10762
10763////////////////////////////////////////////////////////////////////////////////
10764/// Set projection.
10765
10767{
10768 if (fShowProjection2) {
10769 auto name2 = TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2);
10770 auto c2 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name2.Data()));
10771 if (c2) c2->Close();
10772 fShowProjection2 = 0;
10773 }
10774 if (fShowProjection) {
10775 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10776 auto c1 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name1.Data()));
10777 if (c1) c1->Close();
10778 fShowProjection = 0;
10779 }
10780
10781 if (nbins <= 0) return;
10782
10783 TString opt = option;
10784 opt.ToLower();
10785 Int_t projection = 0;
10786 if (opt.Contains("x")) projection = 1;
10787 if (opt.Contains("y")) projection = 2;
10788 if (opt.Contains("z")) projection = 3;
10789 if (opt.Contains("xy")) projection = 4;
10790 if (opt.Contains("yx")) projection = 5;
10791 if (opt.Contains("xz")) projection = 6;
10792 if (opt.Contains("zx")) projection = 7;
10793 if (opt.Contains("yz")) projection = 8;
10794 if (opt.Contains("zy")) projection = 9;
10795 if (projection < 4) fShowOption = option+1;
10796 else fShowOption = option+2;
10797 fShowProjection = projection+100*nbins;
10798 fShowProjection2 = 0;
10799 gROOT->MakeDefCanvas();
10800 gPad->SetName(TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection).Data());
10801 gPad->SetGrid();
10802}
10803
10805{
10806 if (fShowProjection2) {
10807 auto name2 = TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2);
10808 auto c2 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name2.Data()));
10809 if (c2) c2->Close();
10810 fShowProjection2 = 0;
10811 }
10812 if (fShowProjection) {
10813 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10814 auto c1 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name1.Data()));
10815 if (c1) c1->Close();
10816 fShowProjection = 0;
10817 }
10818
10819 if ((nbinsX <= 0) || (nbinsY <= 0)) return;
10820
10821
10822 TString opt = option;
10823 opt.ToLower();
10824 Int_t projection = 0;
10825 if (opt.Contains("x")) projection = 1;
10826 if (opt.Contains("y")) projection = 2;
10827 if (opt.Contains("z")) projection = 3;
10828 if (opt.Contains("xy")) projection = 4;
10829 if (opt.Contains("yx")) projection = 5;
10830 if (opt.Contains("xz")) projection = 6;
10831 if (opt.Contains("zx")) projection = 7;
10832 if (opt.Contains("yz")) projection = 8;
10833 if (opt.Contains("zy")) projection = 9;
10834 if (projection < 4) fShowOption = option+1;
10835 else fShowOption = option+2;
10836 fShowProjection = projection+100*nbinsY;
10837 fShowProjection2 = projection+100*nbinsX;
10838 gROOT->MakeDefCanvas();
10839 gPad->SetName(TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection).Data());
10840 gPad->SetGrid();
10841 gROOT->MakeDefCanvas();
10842 gPad->SetName(TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2).Data());
10843 gPad->SetGrid();
10844}
10845
10846
10847////////////////////////////////////////////////////////////////////////////////
10848/// Show projection onto X.
10849
10851{
10852
10853 Int_t nbins = (Int_t)fShowProjection/100;
10854 gPad->SetDoubleBuffer(0); // turn off double buffer mode
10855 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
10856
10857 // Erase old position and draw a line at current position
10858 static int pyold1 = 0;
10859 static int pyold2 = 0;
10860 float uxmin = gPad->GetUxmin();
10861 float uxmax = gPad->GetUxmax();
10862 int pxmin = gPad->XtoAbsPixel(uxmin);
10863 int pxmax = gPad->XtoAbsPixel(uxmax);
10864 Float_t upy = gPad->AbsPixeltoY(py);
10865 Float_t y = gPad->PadtoY(upy);
10866 Int_t biny1 = fH->GetYaxis()->FindBin(y);
10867 Int_t biny2 = TMath::Min(biny1+nbins-1, fH->GetYaxis()->GetNbins());
10868 Int_t py1 = gPad->YtoAbsPixel(fH->GetYaxis()->GetBinLowEdge(biny1));
10869 Int_t py2 = gPad->YtoAbsPixel(fH->GetYaxis()->GetBinUpEdge(biny2));
10870
10871 if (pyold1 || pyold2) gVirtualX->DrawBox(pxmin,pyold1,pxmax,pyold2,TVirtualX::kFilled);
10872 gVirtualX->DrawBox(pxmin,py1,pxmax,py2,TVirtualX::kFilled);
10873 pyold1 = py1;
10874 pyold2 = py2;
10875
10876 // Create or set the new canvas proj x
10877 TVirtualPad::TContext ctxt(true);
10878 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10879 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(name1.Data());
10880 if (c) {
10881 c->Clear();
10882 } else {
10883 fShowProjection = 0;
10884 fShowProjection2 = 0;
10885 pyold1 = 0;
10886 pyold2 = 0;
10887 return;
10888 }
10889 c->cd();
10890 c->SetLogy(ctxt.GetSaved()->GetLogz());
10891 c->SetLogx(ctxt.GetSaved()->GetLogx());
10892
10893 // Draw slice corresponding to mouse position
10894 TString prjName = TString::Format("slice_px_of_%s",fH->GetName());
10895 TH1D *hp = ((TH2*)fH)->ProjectionX(prjName, biny1, biny2);
10896 if (hp) {
10897 hp->SetFillColor(38);
10898 // apply a patch from Oliver Freyermuth to set the title in the projection
10899 // using the range of the projected Y values
10900 if (biny1 == biny2) {
10901 Double_t valueFrom = fH->GetYaxis()->GetBinLowEdge(biny1);
10902 Double_t valueTo = fH->GetYaxis()->GetBinUpEdge(biny1);
10903 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
10904 Int_t valuePrecision = -TMath::Nint(TMath::Log10(valueTo-valueFrom))+1;
10905 if (fH->GetYaxis()->GetLabels() != nullptr) {
10906 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf] %s", biny1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetYaxis()->GetBinLabel(biny1)));
10907 } else {
10908 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf]", biny1, valuePrecision, valueFrom, valuePrecision, valueTo));
10909 }
10910 } else {
10911 Double_t valueFrom = fH->GetYaxis()->GetBinLowEdge(biny1);
10912 Double_t valueTo = fH->GetYaxis()->GetBinUpEdge(biny2);
10913 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
10914 // biny1 is used here to get equal precision no matter how large the binrange is,
10915 // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
10916 Int_t valuePrecision = -TMath::Nint(TMath::Log10(fH->GetYaxis()->GetBinUpEdge(biny1)-valueFrom))+1;
10917 if (fH->GetYaxis()->GetLabels() != nullptr) {
10918 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)));
10919 } else {
10920 hp->SetTitle(TString::Format("ProjectionX of biny=[%d,%d] [y=%.*lf..%.*lf]", biny1, biny2, valuePrecision, valueFrom, valuePrecision, valueTo));
10921 }
10922 }
10923 hp->SetXTitle(fH->GetXaxis()->GetTitle());
10924 hp->SetYTitle(((TH2*)fH)->GetZaxis()->GetTitle() ? ((TH2*)fH)->GetZaxis()->GetTitle() : "Number of Entries");
10925 hp->Draw();
10926 c->Update();
10927 }
10928}
10929
10930////////////////////////////////////////////////////////////////////////////////
10931/// Show projection onto Y.
10932
10934{
10935
10936 Int_t nbins = (Int_t)fShowProjection/100;
10937 if (fShowProjection2)
10938 nbins = (Int_t)fShowProjection2/100;
10939 gPad->SetDoubleBuffer(0); // turn off double buffer mode
10940 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
10941
10942 // Erase old position and draw a line at current position
10943 static int pxold1 = 0;
10944 static int pxold2 = 0;
10945 float uymin = gPad->GetUymin();
10946 float uymax = gPad->GetUymax();
10947 int pymin = gPad->YtoAbsPixel(uymin);
10948 int pymax = gPad->YtoAbsPixel(uymax);
10949 Float_t upx = gPad->AbsPixeltoX(px);
10950 Float_t x = gPad->PadtoX(upx);
10951 Int_t binx1 = fH->GetXaxis()->FindBin(x);
10952 Int_t binx2 = TMath::Min(binx1+nbins-1, fH->GetXaxis()->GetNbins());
10953 Int_t px1 = gPad->XtoAbsPixel(fH->GetXaxis()->GetBinLowEdge(binx1));
10954 Int_t px2 = gPad->XtoAbsPixel(fH->GetXaxis()->GetBinUpEdge(binx2));
10955
10956 if (pxold1 || pxold2) gVirtualX->DrawBox(pxold1,pymin,pxold2,pymax,TVirtualX::kFilled);
10957 gVirtualX->DrawBox(px1,pymin,px2,pymax,TVirtualX::kFilled);
10958 pxold1 = px1;
10959 pxold2 = px2;
10960
10961 // Create or set the new canvas proj y
10962 TVirtualPad::TContext ctxt(true);
10963
10964 TString name2 = fShowProjection2 ? TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2)
10965 : TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10966
10967 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(name2.Data());
10968 if (c) {
10969 c->Clear();
10970 } else {
10971 fShowProjection = 0;
10972 fShowProjection2 = 0;
10973 pxold1 = 0;
10974 pxold2 = 0;
10975 return;
10976 }
10977 c->cd();
10978 c->SetLogy(ctxt.GetSaved()->GetLogz());
10979 c->SetLogx(ctxt.GetSaved()->GetLogy());
10980
10981 // Draw slice corresponding to mouse position
10982 TString prjName = TString::Format("slice_py_of_%s",fH->GetName());
10983 TH1D *hp = ((TH2*)fH)->ProjectionY(prjName, binx1, binx2);
10984 if (hp) {
10985 hp->SetFillColor(38);
10986 // apply a patch from Oliver Freyermuth to set the title in the projection
10987 // using the range of the projected X values
10988 if (binx1 == binx2) {
10989 Double_t valueFrom = fH->GetXaxis()->GetBinLowEdge(binx1);
10990 Double_t valueTo = fH->GetXaxis()->GetBinUpEdge(binx1);
10991 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
10992 Int_t valuePrecision = -TMath::Nint(TMath::Log10(valueTo-valueFrom))+1;
10993 if (fH->GetXaxis()->GetLabels() != nullptr) {
10994 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf] [%s]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetXaxis()->GetBinLabel(binx1)));
10995 } else {
10996 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo));
10997 }
10998 } else {
10999 Double_t valueFrom = fH->GetXaxis()->GetBinLowEdge(binx1);
11000 Double_t valueTo = fH->GetXaxis()->GetBinUpEdge(binx2);
11001 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11002 // binx1 is used here to get equal precision no matter how large the binrange is,
11003 // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
11004 Int_t valuePrecision = -TMath::Nint(TMath::Log10(fH->GetXaxis()->GetBinUpEdge(binx1)-valueFrom))+1;
11005 if (fH->GetXaxis()->GetLabels() != nullptr) {
11006 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)));
11007 } else {
11008 hp->SetTitle(TString::Format("ProjectionY of binx=[%d,%d] [x=%.*lf..%.*lf]", binx1, binx2, valuePrecision, valueFrom, valuePrecision, valueTo));
11009 }
11010 }
11011 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11012 hp->SetYTitle(((TH2*)fH)->GetZaxis()->GetTitle() ? ((TH2*)fH)->GetZaxis()->GetTitle() : "Number of Entries");
11013 hp->Draw(fShowProjection2 ? "hbar" : "");
11014 c->Update();
11015 }
11016}
11017
11018////////////////////////////////////////////////////////////////////////////////
11019/// Show projection (specified by `fShowProjection`) of a `TH3`.
11020/// The drawing option for the projection is in `fShowOption`.
11021///
11022/// First implementation; R.Brun
11023///
11024/// Full implementation: Tim Tran (timtran@jlab.org) April 2006
11025
11027{
11028
11029 Int_t nbins=(Int_t)fShowProjection/100; //decode nbins
11030 if (fH->GetDimension() < 3) {
11031 if (fShowProjection2 % 100 == 1) {
11032 ShowProjectionY(px, py);
11033 }
11034 if (fShowProjection % 100 == 1) {
11035 ShowProjectionX(px, py);
11036 return;
11037 }
11038 if (fShowProjection % 100 == 2) {
11039 ShowProjectionY(px, py);
11040 return;
11041 }
11042 }
11043
11044 gPad->SetDoubleBuffer(0); // turn off double buffer mode
11045 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
11046
11047 // Erase old position and draw a line at current position
11048 TView *view = gPad->GetView();
11049 if (!view) return;
11050 TH3 *h3 = (TH3*)fH;
11051 TAxis *xaxis = h3->GetXaxis();
11052 TAxis *yaxis = h3->GetYaxis();
11053 TAxis *zaxis = h3->GetZaxis();
11054 Double_t u[3],xx[3];
11055
11056 static TPoint line1[2];//store end points of a line, initialised 0 by default
11057 static TPoint line2[2];// second line when slice thickness > 1 bin thickness
11058 static TPoint line3[2];
11059 static TPoint line4[2];
11060 static TPoint endface1[5];
11061 static TPoint endface2[5];
11062 static TPoint rect1[5];//store vertices of the polyline (rectangle), initialsed 0 by default
11063 static TPoint rect2[5];// second rectangle when slice thickness > 1 bin thickness
11064
11065 Double_t uxmin = gPad->GetUxmin();
11066 Double_t uxmax = gPad->GetUxmax();
11067 Double_t uymin = gPad->GetUymin();
11068 Double_t uymax = gPad->GetUymax();
11069
11070 int pxmin = gPad->XtoAbsPixel(uxmin);
11071 int pxmax = gPad->XtoAbsPixel(uxmax);
11072 if (pxmin==pxmax) return;
11073 int pymin = gPad->YtoAbsPixel(uymin);
11074 int pymax = gPad->YtoAbsPixel(uymax);
11075 if (pymin==pymax) return;
11076 Double_t cx = (pxmax-pxmin)/(uxmax-uxmin);
11077 Double_t cy = (pymax-pymin)/(uymax-uymin);
11078 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(TString::Format("c_%zx_projection_%d",
11079 (size_t)fH, fShowProjection).Data());
11080 if (!c) {
11081 fShowProjection = 0;
11082 return;
11083 }
11084
11085 TVirtualPad::TContext ctxt(true);
11086
11087 switch ((Int_t)fShowProjection%100) {
11088 case 1:
11089 // "x"
11090 {
11091 Int_t firstY = yaxis->GetFirst();
11092 Int_t lastY = yaxis->GetLast();
11093 Int_t biny = firstY + Int_t((lastY-firstY)*(px-pxmin)/(pxmax-pxmin));
11094 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11095 yaxis->SetRange(biny,biny2);
11096 Int_t firstZ = zaxis->GetFirst();
11097 Int_t lastZ = zaxis->GetLast();
11098 Int_t binz = firstZ + Int_t((lastZ-firstZ)*(py-pymin)/(pymax-pymin));
11099 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11100 zaxis->SetRange(binz,binz2);
11101 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11102 if (nbins>1 && line1[0].GetX()) {
11103 gVirtualX->DrawPolyLine(2,line2);
11104 gVirtualX->DrawPolyLine(2,line3);
11105 gVirtualX->DrawPolyLine(2,line4);
11106 gVirtualX->DrawPolyLine(5,endface1);
11107 gVirtualX->DrawPolyLine(5,endface2);
11108 }
11109 xx[0] = xaxis->GetXmin();
11110 xx[2] = zaxis->GetBinCenter(binz);
11111 xx[1] = yaxis->GetBinCenter(biny);
11112 view->WCtoNDC(xx,u);
11113 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11114 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11115 xx[0] = xaxis->GetXmax();
11116 view->WCtoNDC(xx,u);
11117 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11118 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11119 gVirtualX->DrawPolyLine(2,line1);
11120 if (nbins>1) {
11121 xx[0] = xaxis->GetXmin();
11122 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11123 xx[1] = yaxis->GetBinCenter(biny);
11124 view->WCtoNDC(xx,u);
11125 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11126 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11127 xx[0] = xaxis->GetXmax();
11128 view->WCtoNDC(xx,u);
11129 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11130 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11131
11132 xx[0] = xaxis->GetXmin();
11133 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11134 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11135 view->WCtoNDC(xx,u);
11136 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11137 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11138 xx[0] = xaxis->GetXmax();
11139 view->WCtoNDC(xx,u);
11140 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11141 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11142
11143 xx[0] = xaxis->GetXmin();
11144 xx[2] = zaxis->GetBinCenter(binz);
11145 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11146 view->WCtoNDC(xx,u);
11147 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11148 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11149 xx[0] = xaxis->GetXmax();
11150 view->WCtoNDC(xx,u);
11151 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11152 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11153
11154 endface1[0].SetX(line1[0].GetX());
11155 endface1[0].SetY(line1[0].GetY());
11156 endface1[1].SetX(line2[0].GetX());
11157 endface1[1].SetY(line2[0].GetY());
11158 endface1[2].SetX(line3[0].GetX());
11159 endface1[2].SetY(line3[0].GetY());
11160 endface1[3].SetX(line4[0].GetX());
11161 endface1[3].SetY(line4[0].GetY());
11162 endface1[4].SetX(line1[0].GetX());
11163 endface1[4].SetY(line1[0].GetY());
11164
11165 endface2[0].SetX(line1[1].GetX());
11166 endface2[0].SetY(line1[1].GetY());
11167 endface2[1].SetX(line2[1].GetX());
11168 endface2[1].SetY(line2[1].GetY());
11169 endface2[2].SetX(line3[1].GetX());
11170 endface2[2].SetY(line3[1].GetY());
11171 endface2[3].SetX(line4[1].GetX());
11172 endface2[3].SetY(line4[1].GetY());
11173 endface2[4].SetX(line1[1].GetX());
11174 endface2[4].SetY(line1[1].GetY());
11175
11176 gVirtualX->DrawPolyLine(2,line2);
11177 gVirtualX->DrawPolyLine(2,line3);
11178 gVirtualX->DrawPolyLine(2,line4);
11179 gVirtualX->DrawPolyLine(5,endface1);
11180 gVirtualX->DrawPolyLine(5,endface2);
11181 }
11182 c->Clear();
11183 c->cd();
11184 TH1 *hp = h3->Project3D("x");
11185 yaxis->SetRange(firstY,lastY);
11186 zaxis->SetRange(firstZ,lastZ);
11187 if (hp) {
11188 hp->SetFillColor(38);
11189 if (nbins == 1)
11190 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny),
11191 binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
11192 else {
11193 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),
11194 binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
11195 }
11196 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11197 hp->SetYTitle("Number of Entries");
11198 hp->Draw(fShowOption.Data());
11199 }
11200 }
11201 break;
11202
11203 case 2:
11204 // "y"
11205 {
11206 Int_t firstX = xaxis->GetFirst();
11207 Int_t lastX = xaxis->GetLast();
11208 Int_t binx = firstX + Int_t((lastX-firstX)*(px-pxmin)/(pxmax-pxmin));
11209 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11210 xaxis->SetRange(binx,binx2);
11211 Int_t firstZ = zaxis->GetFirst();
11212 Int_t lastZ = zaxis->GetLast();
11213 Int_t binz = firstZ + Int_t((lastZ-firstZ)*(py-pymin)/(pymax-pymin));
11214 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11215 zaxis->SetRange(binz,binz2);
11216 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11217 if (nbins>1 && line1[0].GetX()) {
11218 gVirtualX->DrawPolyLine(2,line2);
11219 gVirtualX->DrawPolyLine(2,line3);
11220 gVirtualX->DrawPolyLine(2,line4);
11221 gVirtualX->DrawPolyLine(5,endface1);
11222 gVirtualX->DrawPolyLine(5,endface2);
11223 }
11224 xx[0]=xaxis->GetBinCenter(binx);
11225 xx[2] = zaxis->GetBinCenter(binz);
11226 xx[1] = yaxis->GetXmin();
11227 view->WCtoNDC(xx,u);
11228 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11229 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11230 xx[1] = yaxis->GetXmax();
11231 view->WCtoNDC(xx,u);
11232 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11233 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11234 gVirtualX->DrawPolyLine(2,line1);
11235 if (nbins>1) {
11236 xx[1] = yaxis->GetXmin();
11237 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11238 xx[0] = xaxis->GetBinCenter(binx);
11239 view->WCtoNDC(xx,u);
11240 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11241 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11242 xx[1] = yaxis->GetXmax();
11243 view->WCtoNDC(xx,u);
11244 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11245 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11246
11247 xx[1] = yaxis->GetXmin();
11248 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11249 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11250 view->WCtoNDC(xx,u);
11251 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11252 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11253 xx[1] = yaxis->GetXmax();
11254 view->WCtoNDC(xx,u);
11255 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11256 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11257
11258 xx[1] = yaxis->GetXmin();
11259 xx[2] = zaxis->GetBinCenter(binz);
11260 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11261 view->WCtoNDC(xx,u);
11262 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11263 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11264 xx[1] = yaxis->GetXmax();
11265 view->WCtoNDC(xx,u);
11266 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11267 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11268
11269 endface1[0].SetX(line1[0].GetX());
11270 endface1[0].SetY(line1[0].GetY());
11271 endface1[1].SetX(line2[0].GetX());
11272 endface1[1].SetY(line2[0].GetY());
11273 endface1[2].SetX(line3[0].GetX());
11274 endface1[2].SetY(line3[0].GetY());
11275 endface1[3].SetX(line4[0].GetX());
11276 endface1[3].SetY(line4[0].GetY());
11277 endface1[4].SetX(line1[0].GetX());
11278 endface1[4].SetY(line1[0].GetY());
11279
11280 endface2[0].SetX(line1[1].GetX());
11281 endface2[0].SetY(line1[1].GetY());
11282 endface2[1].SetX(line2[1].GetX());
11283 endface2[1].SetY(line2[1].GetY());
11284 endface2[2].SetX(line3[1].GetX());
11285 endface2[2].SetY(line3[1].GetY());
11286 endface2[3].SetX(line4[1].GetX());
11287 endface2[3].SetY(line4[1].GetY());
11288 endface2[4].SetX(line1[1].GetX());
11289 endface2[4].SetY(line1[1].GetY());
11290
11291 gVirtualX->DrawPolyLine(2,line2);
11292 gVirtualX->DrawPolyLine(2,line3);
11293 gVirtualX->DrawPolyLine(2,line4);
11294 gVirtualX->DrawPolyLine(5,endface1);
11295 gVirtualX->DrawPolyLine(5,endface2);
11296 }
11297 c->Clear();
11298 c->cd();
11299 TH1 *hp = h3->Project3D("y");
11300 xaxis->SetRange(firstX,lastX);
11301 zaxis->SetRange(firstZ,lastZ);
11302 if (hp) {
11303 hp->SetFillColor(38);
11304 if (nbins == 1)
11305 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
11306 binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
11307 else
11308 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),
11309 binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
11310 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11311 hp->SetYTitle("Number of Entries");
11312 hp->Draw(fShowOption.Data());
11313 }
11314 }
11315 break;
11316
11317 case 3:
11318 // "z"
11319 {
11320 Int_t firstX = xaxis->GetFirst();
11321 Int_t lastX = xaxis->GetLast();
11322 Int_t binx = firstX + Int_t((lastX-firstX)*(px-pxmin)/(pxmax-pxmin));
11323 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11324 xaxis->SetRange(binx,binx2);
11325 Int_t firstY = yaxis->GetFirst();
11326 Int_t lastY = yaxis->GetLast();
11327 Int_t biny = firstY + Int_t((lastY-firstY)*(py-pymin)/(pymax-pymin));
11328 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11329 yaxis->SetRange(biny,biny2);
11330 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11331 if (nbins>1 && line1[0].GetX()) {
11332 gVirtualX->DrawPolyLine(2,line2);
11333 gVirtualX->DrawPolyLine(2,line3);
11334 gVirtualX->DrawPolyLine(2,line4);
11335 gVirtualX->DrawPolyLine(5,endface1);
11336 gVirtualX->DrawPolyLine(5,endface2);
11337 }
11338 xx[0] = xaxis->GetBinCenter(binx);
11339 xx[1] = yaxis->GetBinCenter(biny);
11340 xx[2] = zaxis->GetXmin();
11341 view->WCtoNDC(xx,u);
11342 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11343 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11344 xx[2] = zaxis->GetXmax();
11345 view->WCtoNDC(xx,u);
11346 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11347 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11348 gVirtualX->DrawPolyLine(2,line1);
11349 if (nbins>1) {
11350 xx[2] = zaxis->GetXmin();
11351 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11352 xx[0] = xaxis->GetBinCenter(binx);
11353 view->WCtoNDC(xx,u);
11354 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11355 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11356 xx[2] = zaxis->GetXmax();
11357 view->WCtoNDC(xx,u);
11358 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11359 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11360
11361 xx[2] = zaxis->GetXmin();
11362 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11363 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11364 view->WCtoNDC(xx,u);
11365 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11366 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11367 xx[2] = zaxis->GetXmax();
11368 view->WCtoNDC(xx,u);
11369 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11370 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11371
11372 xx[2] = zaxis->GetXmin();
11373 xx[1] = yaxis->GetBinCenter(biny);
11374 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11375 view->WCtoNDC(xx,u);
11376 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11377 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11378 xx[2] = zaxis->GetXmax();
11379 view->WCtoNDC(xx,u);
11380 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11381 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11382
11383 endface1[0].SetX(line1[0].GetX());
11384 endface1[0].SetY(line1[0].GetY());
11385 endface1[1].SetX(line2[0].GetX());
11386 endface1[1].SetY(line2[0].GetY());
11387 endface1[2].SetX(line3[0].GetX());
11388 endface1[2].SetY(line3[0].GetY());
11389 endface1[3].SetX(line4[0].GetX());
11390 endface1[3].SetY(line4[0].GetY());
11391 endface1[4].SetX(line1[0].GetX());
11392 endface1[4].SetY(line1[0].GetY());
11393
11394 endface2[0].SetX(line1[1].GetX());
11395 endface2[0].SetY(line1[1].GetY());
11396 endface2[1].SetX(line2[1].GetX());
11397 endface2[1].SetY(line2[1].GetY());
11398 endface2[2].SetX(line3[1].GetX());
11399 endface2[2].SetY(line3[1].GetY());
11400 endface2[3].SetX(line4[1].GetX());
11401 endface2[3].SetY(line4[1].GetY());
11402 endface2[4].SetX(line1[1].GetX());
11403 endface2[4].SetY(line1[1].GetY());
11404
11405 gVirtualX->DrawPolyLine(2,line2);
11406 gVirtualX->DrawPolyLine(2,line3);
11407 gVirtualX->DrawPolyLine(2,line4);
11408 gVirtualX->DrawPolyLine(5,endface1);
11409 gVirtualX->DrawPolyLine(5,endface2);
11410 }
11411 c->Clear();
11412 c->cd();
11413 TH1 *hp = h3->Project3D("z");
11414 xaxis->SetRange(firstX,lastX);
11415 yaxis->SetRange(firstY,lastY);
11416 if (hp) {
11417 hp->SetFillColor(38);
11418 if (nbins == 1)
11419 hp->SetTitle(TString::Format("ProjectionZ of binx=%d [x=%.1f..%.1f] biny=%d [y=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
11420 biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny)));
11421 else
11422 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),
11423 biny, biny2, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny2) ) );
11424 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11425 hp->SetYTitle("Number of Entries");
11426 hp->Draw(fShowOption.Data());
11427 }
11428 }
11429 break;
11430
11431 case 4:
11432 // "xy"
11433 {
11434 Int_t first = zaxis->GetFirst();
11435 Int_t last = zaxis->GetLast();
11436 Int_t binz = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11437 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11438 zaxis->SetRange(binz,binz2);
11439 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11440 if (nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11441 xx[0] = xaxis->GetXmin();
11442 xx[1] = yaxis->GetXmax();
11443 xx[2] = zaxis->GetBinCenter(binz);
11444 view->WCtoNDC(xx,u);
11445 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11446 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11447 rect1[4].SetX(rect1[0].GetX());
11448 rect1[4].SetY(rect1[0].GetY());
11449 xx[0] = xaxis->GetXmax();
11450 view->WCtoNDC(xx,u);
11451 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11452 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11453 xx[1] = yaxis->GetXmin();
11454 view->WCtoNDC(xx,u);
11455 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11456 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11457 xx[0] = xaxis->GetXmin();
11458 view->WCtoNDC(xx,u);
11459 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11460 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11461 gVirtualX->DrawPolyLine(5,rect1);
11462 if (nbins>1) {
11463 xx[0] = xaxis->GetXmin();
11464 xx[1] = yaxis->GetXmax();
11465 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11466 view->WCtoNDC(xx,u);
11467 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11468 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11469 rect2[4].SetX(rect2[0].GetX());
11470 rect2[4].SetY(rect2[0].GetY());
11471 xx[0] = xaxis->GetXmax();
11472 view->WCtoNDC(xx,u);
11473 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11474 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11475 xx[1] = yaxis->GetXmin();
11476 view->WCtoNDC(xx,u);
11477 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11478 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11479 xx[0] = xaxis->GetXmin();
11480 view->WCtoNDC(xx,u);
11481 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11482 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11483 gVirtualX->DrawPolyLine(5,rect2);
11484 }
11485
11486 c->Clear();
11487 c->cd();
11488 TH2 *hp = (TH2*)h3->Project3D("xy");
11489 zaxis->SetRange(first,last);
11490 if (hp) {
11491 hp->SetFillColor(38);
11492 if (nbins==1)hp->SetTitle(TString::Format("ProjectionXY of binz=%d [z=%.1f..%.f]", binz,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz)));
11493 else hp->SetTitle(TString::Format("ProjectionXY, binz=[%d,%d] [z=%.1f..%.1f]", binz,binz2,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz2)));
11494 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11495 hp->SetYTitle(fH->GetXaxis()->GetTitle());
11496 hp->SetZTitle("Number of Entries");
11497 hp->Draw(fShowOption.Data());
11498 }
11499 }
11500 break;
11501
11502 case 5:
11503 // "yx"
11504 {
11505 Int_t first = zaxis->GetFirst();
11506 Int_t last = zaxis->GetLast();
11507 Int_t binz = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11508 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11509 zaxis->SetRange(binz,binz2);
11510 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11511 if (nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11512 xx[0] = xaxis->GetXmin();
11513 xx[1] = yaxis->GetXmax();
11514 xx[2] = zaxis->GetBinCenter(binz);
11515 view->WCtoNDC(xx,u);
11516 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11517 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11518 rect1[4].SetX(rect1[0].GetX());
11519 rect1[4].SetY(rect1[0].GetY());
11520 xx[0] = xaxis->GetXmax();
11521 view->WCtoNDC(xx,u);
11522 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11523 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11524 xx[1] = yaxis->GetXmin();
11525 view->WCtoNDC(xx,u);
11526 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11527 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11528 xx[0] = xaxis->GetXmin();
11529 view->WCtoNDC(xx,u);
11530 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11531 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11532 gVirtualX->DrawPolyLine(5,rect1);
11533 if (nbins>1) {
11534 xx[0] = xaxis->GetXmin();
11535 xx[1] = yaxis->GetXmax();
11536 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11537 view->WCtoNDC(xx,u);
11538 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11539 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11540 rect2[4].SetX(rect2[0].GetX());
11541 rect2[4].SetY(rect2[0].GetY());
11542 xx[0] = xaxis->GetXmax();
11543 view->WCtoNDC(xx,u);
11544 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11545 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11546 xx[1] = yaxis->GetXmin();
11547 view->WCtoNDC(xx,u);
11548 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11549 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11550 xx[0] = xaxis->GetXmin();
11551 view->WCtoNDC(xx,u);
11552 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11553 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11554 gVirtualX->DrawPolyLine(5,rect2);
11555 }
11556 c->Clear();
11557 c->cd();
11558 TH2 *hp = (TH2*)h3->Project3D("yx");
11559 zaxis->SetRange(first,last);
11560 if (hp) {
11561 hp->SetFillColor(38);
11562 if (nbins==1)hp->SetTitle(TString::Format("ProjectionYX of binz=%d [z=%.1f..%.f]", binz,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz)));
11563 else hp->SetTitle(TString::Format("ProjectionYX, binz=[%d,%d] [z=%.1f..%.1f]", binz,binz2,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz2)));
11564 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11565 hp->SetYTitle(fH->GetYaxis()->GetTitle());
11566 hp->SetZTitle("Number of Entries");
11567 hp->Draw(fShowOption.Data());
11568 }
11569 }
11570 break;
11571
11572 case 6:
11573 // "xz"
11574 {
11575 Int_t first = yaxis->GetFirst();
11576 Int_t last = yaxis->GetLast();
11577 Int_t biny = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11578 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11579 yaxis->SetRange(biny,biny2);
11580 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11581 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11582 xx[0] = xaxis->GetXmin();
11583 xx[2] = zaxis->GetXmax();
11584 xx[1] = yaxis->GetBinCenter(biny);
11585 view->WCtoNDC(xx,u);
11586 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11587 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11588 rect1[4].SetX(rect1[0].GetX());
11589 rect1[4].SetY(rect1[0].GetY());
11590 xx[0] = xaxis->GetXmax();
11591 view->WCtoNDC(xx,u);
11592 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11593 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11594 xx[2] = zaxis->GetXmin();
11595 view->WCtoNDC(xx,u);
11596 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11597 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11598 xx[0] = xaxis->GetXmin();
11599 view->WCtoNDC(xx,u);
11600 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11601 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11602 gVirtualX->DrawPolyLine(5,rect1);
11603 if (nbins>1) {
11604 xx[0] = xaxis->GetXmin();
11605 xx[2] = zaxis->GetXmax();
11606 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11607 view->WCtoNDC(xx,u);
11608 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11609 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11610 rect2[4].SetX(rect2[0].GetX());
11611 rect2[4].SetY(rect2[0].GetY());
11612 xx[0] = xaxis->GetXmax();
11613 view->WCtoNDC(xx,u);
11614 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11615 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11616 xx[2] = zaxis->GetXmin();
11617 view->WCtoNDC(xx,u);
11618 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11619 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11620 xx[0] = xaxis->GetXmin();
11621 view->WCtoNDC(xx,u);
11622 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11623 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11624 gVirtualX->DrawPolyLine(5,rect2);
11625 }
11626 c->Clear();
11627 c->cd();
11628 TH2 *hp = (TH2*)h3->Project3D("xz");
11629 yaxis->SetRange(first,last);
11630 if (hp) {
11631 hp->SetFillColor(38);
11632 if (nbins==1)hp->SetTitle(TString::Format("ProjectionXZ of biny=%d [y=%.1f..%.f]", biny,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny)));
11633 else hp->SetTitle(TString::Format("ProjectionXZ, biny=[%d,%d] [y=%.1f..%.1f]", biny,biny2,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny2)));
11634 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11635 hp->SetYTitle(fH->GetXaxis()->GetTitle());
11636 hp->SetZTitle("Number of Entries");
11637 hp->Draw(fShowOption.Data());
11638 }
11639 }
11640 break;
11641
11642 case 7:
11643 // "zx"
11644 {
11645 Int_t first = yaxis->GetFirst();
11646 Int_t last = yaxis->GetLast();
11647 Int_t biny = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11648 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11649 yaxis->SetRange(biny,biny2);
11650 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11651 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11652 xx[0] = xaxis->GetXmin();
11653 xx[2] = zaxis->GetXmax();
11654 xx[1] = yaxis->GetBinCenter(biny);
11655 view->WCtoNDC(xx,u);
11656 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11657 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11658 rect1[4].SetX(rect1[0].GetX());
11659 rect1[4].SetY(rect1[0].GetY());
11660 xx[0] = xaxis->GetXmax();
11661 view->WCtoNDC(xx,u);
11662 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11663 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11664 xx[2] = zaxis->GetXmin();
11665 view->WCtoNDC(xx,u);
11666 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11667 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11668 xx[0] = xaxis->GetXmin();
11669 view->WCtoNDC(xx,u);
11670 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11671 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11672 gVirtualX->DrawPolyLine(5,rect1);
11673 if (nbins>1) {
11674 xx[0] = xaxis->GetXmin();
11675 xx[2] = zaxis->GetXmax();
11676 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11677 view->WCtoNDC(xx,u);
11678 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11679 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11680 rect2[4].SetX(rect2[0].GetX());
11681 rect2[4].SetY(rect2[0].GetY());
11682 xx[0] = xaxis->GetXmax();
11683 view->WCtoNDC(xx,u);
11684 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11685 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11686 xx[2] = zaxis->GetXmin();
11687 view->WCtoNDC(xx,u);
11688 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11689 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11690 xx[0] = xaxis->GetXmin();
11691 view->WCtoNDC(xx,u);
11692 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11693 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11694 gVirtualX->DrawPolyLine(5,rect2);
11695 }
11696 c->Clear();
11697 c->cd();
11698 TH2 *hp = (TH2*)h3->Project3D("zx");
11699 yaxis->SetRange(first,last);
11700 if (hp) {
11701 hp->SetFillColor(38);
11702 if (nbins==1)hp->SetTitle(TString::Format("ProjectionZX of biny=%d [y=%.1f..%.f]", biny,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny)));
11703 else hp->SetTitle(TString::Format("ProjectionZX, biny=[%d,%d] [y=%.1f..%.1f]", biny,biny2,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny2)));
11704 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11705 hp->SetYTitle(fH->GetZaxis()->GetTitle());
11706 hp->SetZTitle("Number of Entries");
11707 hp->Draw(fShowOption.Data());
11708 }
11709 }
11710 break;
11711
11712 case 8:
11713 // "yz"
11714 {
11715 Int_t first = xaxis->GetFirst();
11716 Int_t last = xaxis->GetLast();
11717 Int_t binx = first + Int_t((last-first)*(px-pxmin)/(pxmax-pxmin));
11718 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11719 xaxis->SetRange(binx,binx2);
11720 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11721 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11722 xx[2] = zaxis->GetXmin();
11723 xx[1] = yaxis->GetXmax();
11724 xx[0] = xaxis->GetBinCenter(binx);
11725 view->WCtoNDC(xx,u);
11726 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11727 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11728 rect1[4].SetX(rect1[0].GetX());
11729 rect1[4].SetY(rect1[0].GetY());
11730 xx[2] = zaxis->GetXmax();
11731 view->WCtoNDC(xx,u);
11732 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11733 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11734 xx[1] = yaxis->GetXmin();
11735 view->WCtoNDC(xx,u);
11736 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11737 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11738 xx[2] = zaxis->GetXmin();
11739 view->WCtoNDC(xx,u);
11740 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11741 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11742 gVirtualX->DrawPolyLine(5,rect1);
11743 if (nbins>1) {
11744 xx[2] = zaxis->GetXmin();
11745 xx[1] = yaxis->GetXmax();
11746 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11747 view->WCtoNDC(xx,u);
11748 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11749 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11750 rect2[4].SetX(rect2[0].GetX());
11751 rect2[4].SetY(rect2[0].GetY());
11752 xx[2] = zaxis->GetXmax();
11753 view->WCtoNDC(xx,u);
11754 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11755 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11756 xx[1] = yaxis->GetXmin();
11757 view->WCtoNDC(xx,u);
11758 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11759 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11760 xx[2] = zaxis->GetXmin();
11761 view->WCtoNDC(xx,u);
11762 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11763 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11764 gVirtualX->DrawPolyLine(5,rect2);
11765 }
11766 c->Clear();
11767 c->cd();
11768 TH2 *hp = (TH2*)h3->Project3D("yz");
11769 xaxis->SetRange(first,last);
11770 if (hp) {
11771 hp->SetFillColor(38);
11772 if (nbins==1)hp->SetTitle(TString::Format("ProjectionYZ of binx=%d [x=%.1f..%.f]", binx,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx)));
11773 else hp->SetTitle(TString::Format("ProjectionYZ, binx=[%d,%d] [x=%.1f..%.1f]", binx,binx2,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx2)));
11774 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11775 hp->SetYTitle(fH->GetYaxis()->GetTitle());
11776 hp->SetZTitle("Number of Entries");
11777 hp->Draw(fShowOption.Data());
11778 }
11779 }
11780 break;
11781
11782 case 9:
11783 // "zy"
11784 {
11785 Int_t first = xaxis->GetFirst();
11786 Int_t last = xaxis->GetLast();
11787 Int_t binx = first + Int_t((last-first)*(px-pxmin)/(pxmax-pxmin));
11788 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11789 xaxis->SetRange(binx,binx2);
11790 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11791 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11792 xx[2] = zaxis->GetXmin();
11793 xx[1] = yaxis->GetXmax();
11794 xx[0] = xaxis->GetBinCenter(binx);
11795 view->WCtoNDC(xx,u);
11796 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11797 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11798 rect1[4].SetX(rect1[0].GetX());
11799 rect1[4].SetY(rect1[0].GetY());
11800 xx[2] = zaxis->GetXmax();
11801 view->WCtoNDC(xx,u);
11802 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11803 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11804 xx[1] = yaxis->GetXmin();
11805 view->WCtoNDC(xx,u);
11806 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11807 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11808 xx[2] = zaxis->GetXmin();
11809 view->WCtoNDC(xx,u);
11810 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11811 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11812 gVirtualX->DrawPolyLine(5,rect1);
11813 if (nbins>1) {
11814 xx[2] = zaxis->GetXmin();
11815 xx[1] = yaxis->GetXmax();
11816 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11817 view->WCtoNDC(xx,u);
11818 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11819 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11820 rect2[4].SetX(rect2[0].GetX());
11821 rect2[4].SetY(rect2[0].GetY());
11822 xx[2] = zaxis->GetXmax();
11823 view->WCtoNDC(xx,u);
11824 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11825 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11826 xx[1] = yaxis->GetXmin();
11827 view->WCtoNDC(xx,u);
11828 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11829 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11830 xx[2] = zaxis->GetXmin();
11831 view->WCtoNDC(xx,u);
11832 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11833 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11834 gVirtualX->DrawPolyLine(5,rect2);
11835 }
11836 c->Clear();
11837 c->cd();
11838 TH2 *hp = (TH2*)h3->Project3D("zy");
11839 xaxis->SetRange(first,last);
11840 if (hp) {
11841 hp->SetFillColor(38);
11842 if (nbins==1)hp->SetTitle(TString::Format("ProjectionZY of binx=%d [x=%.1f..%.f]", binx,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx)));
11843 else hp->SetTitle(TString::Format("ProjectionZY, binx=[%d,%d] [x=%.1f..%.1f]", binx,binx2,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx2)));
11844 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11845 hp->SetYTitle(fH->GetZaxis()->GetTitle());
11846 hp->SetZTitle("Number of Entries");
11847 hp->Draw(fShowOption.Data());
11848 }
11849 }
11850 break;
11851 }
11852 c->Update();
11853}
@ 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:31
virtual Bool_t GetTimeDisplay() const
Definition TAxis.h:131
Bool_t IsAlphanumeric() const
Definition TAxis.h:88
const char * GetTitle() const override
Returns title of object.
Definition TAxis.h:135
virtual Double_t GetBinCenter(Int_t bin) const
Return center of bin.
Definition TAxis.cxx:478
Bool_t CanExtend() const
Definition TAxis.h:86
const TArrayD * GetXbins() const
Definition TAxis.h:136
Double_t GetXmax() const
Definition TAxis.h:140
const char * GetBinLabel(Int_t bin) const
Return label for bin.
Definition TAxis.cxx:440
virtual Int_t FindBin(Double_t x)
Find bin number corresponding to abscissa x.
Definition TAxis.cxx:293
virtual Double_t GetBinLowEdge(Int_t bin) const
Return low edge of bin.
Definition TAxis.cxx:518
virtual Int_t FindFixBin(Double_t x) const
Find bin number corresponding to abscissa x.
Definition TAxis.cxx:419
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:132
Int_t GetLast() const
Return last bin on the axis i.e.
Definition TAxis.cxx:469
virtual const char * GetTimeFormatOnly() const
Return only the time format from the string fTimeFormat.
Definition TAxis.cxx:600
Double_t GetXmin() const
Definition TAxis.h:139
Int_t GetNbins() const
Definition TAxis.h:125
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:1086
virtual const char * GetTimeFormat() const
Definition TAxis.h:132
virtual void SetRange(Int_t first=0, Int_t last=0)
Set the viewing range for the axis using bin numbers.
Definition TAxis.cxx:1057
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width.
Definition TAxis.cxx:542
virtual Double_t GetBinUpEdge(Int_t bin) const
Return up edge of bin.
Definition TAxis.cxx:528
Int_t GetFirst() const
Return first bin on the axis i.e.
Definition TAxis.cxx:458
THashList * GetLabels() const
Definition TAxis.h:121
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:1850
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:1920
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:2087
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:2130
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:52
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
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:27
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