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
247\anchor HP01b
248#### Options supported for 1D histograms
249
250| Option | Description |
251|----------|-------------------------------------------------------------------|
252| " " | Default. |
253| "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.|
254| "][" | When this option is selected the first and last vertical lines of the histogram are not drawn.|
255| "B" | Bar chart option.|
256| "BAR" | Like option "B", but bars can be drawn with a 3D effect.|
257| "HBAR" | Like option "BAR", but bars are drawn horizontally.|
258| "C" | Draw a smooth Curve through the histogram bins.|
259| "E0" | Draw error bars. Markers are drawn for bins with 0 contents. Combined with E1 or E2 it avoids error bars clipping|
260| "E1" | Draw error bars with perpendicular lines at the edges.|
261| "E2" | Draw error bars with rectangles.|
262| "E3" | Draw a fill area through the end points of the vertical error bars.|
263| "E4" | Draw a smoothed filled area through the end points of the error bars.|
264| "E5" | Like E3 but ignore the bins with 0 contents.|
265| "E6" | Like E4 but ignore the bins with 0 contents.|
266| "X0" | When used with one of the "E" option, it suppress the error bar along X as `gStyle->SetErrorX(0)` would do.|
267| "L" | Draw a line through the bin contents.|
268| "P" | Draw current marker at each bin except empty bins.|
269| "P*" | Draw a star marker at each bin except empty bins.|
270| "P0" | Draw current marker at each bin including empty bins.|
271| "PIE" | Draw histogram as a Pie Chart.|
272| "*H" | Draw histogram with a * at each bin.|
273| "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.|
274
275
276
277\anchor HP01c
278#### Options supported for 2D histograms
279
280| Option | Description |
281|--------------|------------------------------------------------------------------|
282| " " | Default (color plot).|
283| "ARR" | Arrow mode. Shows gradient between adjacent cells.|
284| "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. |
285| "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.|
286| "COL" | A box is drawn for each cell with a color scale varying with contents. All the none empty bins (bins with content and error equal to 0) are painted. Empty bins are not painted unless some bins have a negative content because in that case the null bins might be not empty. `TProfile2D` histograms are handled differently because, for this type of 2D histograms, it is possible to know if an empty bin has been filled or not. So even if all the bins' contents are positive some empty bins might be painted. And vice versa, if some bins have a negative content some empty bins might be not painted (default).|
287| "COL1" | Same as "COL" but in case of histogram with negative content the empty bins are not drawn.
288| "COLZ" | Same as "COL". In addition the color palette is also drawn.|
289| "COL2" | Alternative rendering algorithm to "COL". Can significantly improve rendering performance for large, non-sparse 2-D histograms.|
290| "COLZ2" | Same as "COL2". In addition the color palette is also drawn.|
291| "Z CJUST" | In combination with colored options "COL","CONT0" etc: Justify labels in the color palette at color boundaries. For more details see `TPaletteAxis`|
292| "CANDLE" | Draw a candle plot along X axis.|
293| "CANDLEX" | Same as "CANDLE".|
294| "CANDLEY" | Draw a candle plot along Y axis.|
295| "CANDLEXn" | Draw a candle plot along X axis. Different candle-styles with n from 1 to 6.|
296| "CANDLEYn" | Draw a candle plot along Y axis. Different candle-styles with n from 1 to 6.|
297| "VIOLIN" | Draw a violin plot along X axis.|
298| "VIOLINX" | Same as "VIOLIN".|
299| "VIOLINY" | Draw a violin plot along Y axis.|
300| "VIOLINXn" | Draw a violin plot along X axis. Different violin-styles with n being 1 or 2.|
301| "VIOLINYn" | Draw a violin plot along Y axis. Different violin-styles with n being 1 or 2.|
302| "CONT" | Draw a contour plot (same as CONT0).|
303| "CONT0" | Draw a contour plot using surface colors to distinguish contours.|
304| "CONT1" | Draw a contour plot using line styles to distinguish contours.|
305| "CONT2" | Draw a contour plot using the same line style for all contours.|
306| "CONT3" | Draw a contour plot using fill area colors.|
307| "CONT4" | Draw a contour plot using surface colors (SURF option at theta = 0).|
308| "LIST" | Generate a list of TGraph objects for each contour.|
309| "SAME0" | Same as "SAME" but do not use the z-axis range of the first plot. |
310| "SAMES0" | Same as "SAMES" but do not use the z-axis range of the first plot. |
311| "CYL" | Use Cylindrical coordinates. The X coordinate is mapped on the angle and the Y coordinate on the cylinder length.|
312| "POL" | Use Polar coordinates. The visible X range mapped on the angle and the visible Y coordinate on the radius.|
313| "POLF" | Fixed Polar coordinates. The histogram X coordinate mapped on the angle and the Y coordinate on the radius.|
314| "POLN" | Natural Polar coordinates. The X coordinate directly represent angle in radian and the Y coordinate is the radius.|
315| "SPH" | Use Spherical coordinates. The X coordinate is mapped on the latitude and the Y coordinate on the longitude.|
316| "PSR" | Use PseudoRapidity/Phi coordinates. The X coordinate is mapped on Phi.|
317| "SURF" | Draw a surface plot with hidden line removal.|
318| "SURF1" | Draw a surface plot with hidden surface removal.|
319| "SURF2" | Draw a surface plot using colors to show the cell contents.|
320| "SURF3" | Same as SURF with in addition a contour view drawn on the top.|
321| "SURF4" | Draw a surface using Gouraud shading.|
322| "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.|
323| "AITOFF" | Draw a contour via an AITOFF projection.|
324| "MERCATOR" | Draw a contour via an Mercator projection.|
325| "SINUSOIDAL" | Draw a contour via an Sinusoidal projection.|
326| "PARABOLIC" | Draw a contour via an Parabolic projection.|
327| "MOLLWEIDE" | Draw a contour via an Mollweide projection.|
328| "LEGO9" | Draw the 3D axis only. Mainly needed for internal use |
329| "FB" | With LEGO or SURFACE, suppress the Front-Box.|
330| "BB" | With LEGO or SURFACE, suppress the Back-Box.|
331| "A" | With LEGO or SURFACE, suppress the axis.|
332| "SCAT" | Draw a scatter-plot (legacy draw option).|
333| "[cutg]" | Draw only the sub-range selected by the TCutG named "cutg".|
334
335
336
337\anchor HP01d
338#### Options supported for 3D histograms
339
340| Option | Description |
341|----------|-------------------------------------------------------------------|
342| " " | Default (color plot).|
343| "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)`.|
344| "BOX" | Draw a for each cell with volume proportional to the content's absolute value. An hidden line removal algorithm is used|
345| "BOX1" | Same as BOX but an hidden surface removal algorithm is used|
346| "BOX2" | The boxes' colors are picked in the current palette according to the bins' contents|
347| "BOX2Z" | Same as "BOX2". In addition the color palette is also drawn.|
348| "BOX3" | Same as BOX1, but the border lines of each lego-bar are not drawn.|
349| "LEGO" | Same as `BOX`.|
350
351\anchor HP01e
352#### Options supported for histograms' stacks (`THStack`)
353
354| Option | Description |
355|------------|-----------------------------------------------------------------|
356| " " | Default, the histograms are drawn on top of each other (as lego plots for 2D histograms).|
357| "NOSTACK" | Histograms in the stack are all paint in the same pad as if the option `SAME` had been specified.|
358| "NOSTACKB" | Histograms are drawn next to each other as bar charts.|
359| "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.|
360| "PADSn" | Like PADS but the current pad/canvas is subdivided into a `n` columns, automatically calculating the number of rows.|
361| "PFC" | Palette Fill Color: stack's fill color is taken in the current palette. |
362| "PLC" | Palette Line Color: stack's line color is taken in the current palette. |
363| "PMC" | Palette Marker Color: stack's marker color is taken in the current palette. |
364
365
366
367\anchor HP02
368### Setting the Style
369
370
371Histograms use the current style (`gStyle`). When one changes the current
372style and would like to propagate the changes to the histogram,
373`TH1::UseCurrentStyle` should be called. Call `UseCurrentStyle` on
374each histogram is needed.
375
376To force all the histogram to use the current style use:
377
378 gROOT->ForceStyle();
379
380All the histograms read after this call will use the current style.
381
382
383\anchor HP03
384### Setting line, fill, marker, and text attributes
385
386
387The histogram classes inherit from the attribute classes:
388`TAttLine`, `TAttFill` and `TAttMarker`.
389See the description of these classes for the list of options.
390
391
392\anchor HP04
393### Setting Tick marks on the histogram axis
394
395
396The `TPad::SetTicks` method specifies the type of tick marks on the axis.
397If ` tx = gPad->GetTickx()` and `ty = gPad->GetTicky()` then:
398
399 tx = 1; tick marks on top side are drawn (inside)
400 tx = 2; tick marks and labels on top side are drawn
401 ty = 1; tick marks on right side are drawn (inside)
402 ty = 2; tick marks and labels on right side are drawn
403
404By default only the left Y axis and X bottom axis are drawn
405(`tx = ty = 0`)
406
407`TPad::SetTicks(tx,ty)` allows to set these options.
408See also The `TAxis` functions to set specific axis attributes.
409
410In case multiple color filled histograms are drawn on the same pad, the fill
411area may hide the axis tick marks. One can force a redraw of the axis over all
412the histograms by calling:
413
414 gPad->RedrawAxis();
415
416
417\anchor HP05
418### Giving titles to the X, Y and Z axis
419
420
421 h->GetXaxis()->SetTitle("X axis title");
422 h->GetYaxis()->SetTitle("Y axis title");
423
424The histogram title and the axis titles can be any `TLatex` string.
425The titles are part of the persistent histogram.
426
427
428\anchor HP060
429### The option "SAME"
430
431
432By default, when an histogram is drawn, the current pad is cleared before
433drawing. In order to keep the previous drawing and draw on top of it the
434option `SAME` should be use. The histogram drawn with the option
435`SAME` uses the coordinates system available in the current pad.
436
437This option can be used alone or combined with any valid drawing option but
438some combinations must be use with care.
439
440\anchor HP060a
441#### Limitations
442
443- It does not work when combined with the `LEGO` and `SURF` options unless the
444 histogram plotted with the option `SAME` has exactly the same
445 ranges on the X, Y and Z axis as the currently drawn histogram. To superimpose
446 lego plots [histograms' stacks](\ref HP26) should be used.
447
448
449\anchor HP061
450### Colors automatically picked in palette
451
452\since **ROOT version 6.09/01**
453
454When several histograms are painted in the same canvas thanks to the option "SAME"
455or via a `THStack` it might be useful to have an easy and automatic way to choose
456their color. The simplest way is to pick colors in the current active color
457palette. Palette coloring for histogram is activated thanks to the options `PFC`
458(Palette Fill Color), `PLC` (Palette Line Color) and `PMC` (Palette Marker Color).
459When one of these options is given to `TH1::Draw` the histogram get its color
460from the current color palette defined by `gStyle->SetPalette(...)`. The color
461is determined according to the number of objects having palette coloring in
462the current pad.
463
464Begin_Macro(source)
465../../../tutorials/hist/hist005_TH1_palettecolor.C
466End_Macro
467
468Begin_Macro(source)
469../../../tutorials/hist/hist027_THStack_palette_color.C
470End_Macro
471
472Begin_Macro(source)
473../../../tutorials/hist/hist025_THStack_2d_palette_color.C
474End_Macro
475
476\anchor HP06
477### Superimposing two histograms with different scales in the same pad
478
479
480The following example creates two histograms, the second histogram is the bins
481integral of the first one. It shows a procedure to draw the two histograms in
482the same pad and it draws the scale of the second histogram using a new vertical
483axis on the right side. See also the tutorial `transpad.C` for a variant
484of this example.
485
486Begin_Macro(source)
487{
488 auto c1 = new TCanvas("c1","c1",600,400);
489 // create/fill draw h1
490 gStyle->SetOptStat(kFALSE);
491 auto h1 = new TH1F("h1","Superimposing two histograms with different scales",100,-3,3);
492 Int_t i;
493 for (i=0;i<10000;i++) h1->Fill(gRandom->Gaus(0,1));
494 h1->Draw();
495 c1->Update();
496
497 // create hint1 filled with the bins integral of h1
498 auto hint1 = new TH1F("hint1","h1 bins integral",100,-3,3);
499 float sum = 0.f;
500 for (i=1;i<=100;i++) {
501 sum += h1->GetBinContent(i);
502 hint1->SetBinContent(i,sum);
503 }
504
505 // scale hint1 to the pad coordinates
506 float rightmax = 1.1*hint1->GetMaximum();
507 float scale = gPad->GetUymax()/rightmax;
508 hint1->SetLineColor(kRed);
509 hint1->Scale(scale);
510 hint1->Draw("same");
511
512 // draw an axis on the right side
513 auto axis = new TGaxis(gPad->GetUxmax(),gPad->GetUymin(),
514 gPad->GetUxmax(), gPad->GetUymax(),0,rightmax,510,"+L");
515 axis->SetLineColor(kRed);
516 axis->SetTextColor(kRed);
517 axis->Draw();
518}
519End_Macro
520
521
522\anchor HP07
523### Statistics Display
524
525
526The type of information shown in the histogram statistics box can be selected
527with:
528
529 gStyle->SetOptStat(mode);
530
531The `mode` has up to nine digits that can be set to on (1 or 2), off (0).
532
533 mode = ksiourmen (default = 000001111)
534 k = 1; kurtosis printed
535 k = 2; kurtosis and kurtosis error printed
536 s = 1; skewness printed
537 s = 2; skewness and skewness error printed
538 i = 1; integral of bins printed
539 i = 2; integral of bins with option "width" printed
540 o = 1; number of overflows printed
541 u = 1; number of underflows printed
542 r = 1; standard deviation printed
543 r = 2; standard deviation and standard deviation error printed
544 m = 1; mean value printed
545 m = 2; mean and mean error values printed
546 e = 1; number of entries printed
547 n = 1; name of histogram is printed
548
549For example:
550
551 gStyle->SetOptStat(11);
552
553displays only the name of histogram and the number of entries, whereas:
554
555 gStyle->SetOptStat(1101);
556
557displays the name of histogram, mean value and standard deviation.
558
559<b>WARNING 1:</b> never do:
560
561 gStyle->SetOptStat(0001111);
562
563but instead do:
564
565 gStyle->SetOptStat(1111);
566
567because `0001111` will be taken as an octal number!
568
569<b>WARNING 2:</b> for backward compatibility with older versions
570
571 gStyle->SetOptStat(1);
572
573is taken as:
574
575 gStyle->SetOptStat(1111)
576
577To print only the name of the histogram do:
578
579 gStyle->SetOptStat(1000000001);
580
581<b>NOTE</b> that in case of 2D histograms, when selecting only underflow
582(10000) or overflow (100000), the statistics box will show all combinations
583of underflow/overflows and not just one single number.
584
585The parameter mode can be any combination of the letters `kKsSiIourRmMen`
586
587 k : kurtosis printed
588 K : kurtosis and kurtosis error printed
589 s : skewness printed
590 S : skewness and skewness error printed
591 i : integral of bins printed
592 I : integral of bins with option "width" printed
593 o : number of overflows printed
594 u : number of underflows printed
595 r : standard deviation printed
596 R : standard deviation and standard deviation error printed
597 m : mean value printed
598 M : mean value mean error values printed
599 e : number of entries printed
600 n : name of histogram is printed
601
602For example, to print only name of histogram and number of entries do:
603
604 gStyle->SetOptStat("ne");
605
606To print only the name of the histogram do:
607
608 gStyle->SetOptStat("n");
609
610The default value is:
611
612 gStyle->SetOptStat("nemr");
613
614When a histogram is painted, a `TPaveStats` object is created and added
615to the list of functions of the histogram. If a `TPaveStats` object
616already exists in the histogram list of functions, the existing object is just
617updated with the current histogram parameters.
618
619Once a histogram is painted, the statistics box can be accessed using
620`h->FindObject("stats")`. In the command line it is enough to do:
621
622 Root > h->Draw()
623 Root > TPaveStats *st = (TPaveStats*)h->FindObject("stats")
624
625because after `h->Draw()` the histogram is automatically painted. But
626in a script file the painting should be forced using `gPad->Update()`
627in order to make sure the statistics box is created:
628
629 h->Draw();
630 gPad->Update();
631 TPaveStats *st = (TPaveStats*)h->FindObject("stats");
632
633Without `gPad->Update()` the line `h->FindObject("stats")` returns a null pointer.
634
635When a histogram is drawn with the option `SAME`, the statistics box
636is not drawn. To force the statistics box drawing with the option
637`SAME`, the option `SAMES` must be used.
638If the new statistics box hides the previous statistics box, one can change
639its position with these lines (`h` being the pointer to the histogram):
640
641 Root > TPaveStats *st = (TPaveStats*)h->FindObject("stats")
642 Root > st->SetX1NDC(newx1); //new x start position
643 Root > st->SetX2NDC(newx2); //new x end position
644
645To change the type of information for an histogram with an existing
646`TPaveStats` one should do:
647
648 st->SetOptStat(mode);
649
650Where `mode` has the same meaning than when calling `gStyle->SetOptStat(mode)`
651(see above).
652
653One can delete the statistics box for a histogram `TH1* h` with:
654
655 h->SetStats(0)
656
657and activate it again with:
658
659 h->SetStats(1).
660
661Labels used in the statistics box ("Mean", "Std Dev", ...) can be changed from
662`$ROOTSYS/etc/system.rootrc` or `.rootrc` (look for the string `Hist.Stats.`).
663
664
665\anchor HP08
666### Fit Statistics
667
668
669The type of information about fit parameters printed in the histogram statistics
670box can be selected via the parameter mode. The parameter mode can be
671`= pcev` (default `= 0111`)
672
673 p = 1; print Probability
674 c = 1; print Chisquare/Number of degrees of freedom
675 e = 1; print errors (if e=1, v must be 1)
676 v = 1; print name/values of parameters
677
678Example:
679
680 gStyle->SetOptFit(1011);
681
682print fit probability, parameter names/values and errors.
683
6841. When `v = 1` is specified, only the non-fixed parameters are shown.
6852. When `v = 2` all parameters are shown.
686
687Note: `gStyle->SetOptFit(1)` means "default value", so it is equivalent
688to `gStyle->SetOptFit(111)`
689
690
691\anchor HP09
692### The error bars options
693
694
695| Option | Description |
696|----------|-------------------------------------------------------------------|
697| "E" | Default. Shows only the error bars, not a marker.|
698| "E1" | Small lines are drawn at the end of the error bars.|
699| "E2" | Error rectangles are drawn.|
700| "E3" | A filled area is drawn through the end points of the vertical error bars.|
701| "E4" | A smoothed filled area is drawn through the end points of the vertical error bars.|
702| "E0" | Draw error bars. Markers are drawn for bins with 0 contents. Combined with E1 or E2 it avoids error bars clipping|
703| "E5" | Like E3 but ignore the bins with 0 contents.|
704| "E6" | Like E4 but ignore the bins with 0 contents.|
705| "X0" | When used with one of the "E" option, it suppress the error bar along X as `gStyle->SetErrorX(0)` would do.|
706
707Begin_Macro(source)
708{
709 auto c1 = new TCanvas("c1","c1",600,400);
710 auto he = new TH1F("he","Distribution drawn with error bars (option E1) ",100,-3,3);
711 for (int i=0; i<10000; i++) he->Fill(gRandom->Gaus(0,1));
712 gStyle->SetEndErrorSize(3);
713 gStyle->SetErrorX(1.);
714 he->SetMarkerStyle(20);
715 he->Draw("E1");
716}
717End_Macro
718
719The options "E3" and "E4" draw an error band through the end points of the
720vertical error bars. With "E4" the error band is smoothed. Because of the
721smoothing algorithm used some artefacts may appear at the end of the band
722like in the following example. In such cases "E3" should be used instead
723of "E4".
724
725Begin_Macro(source)
726{
727 auto ce4 = new TCanvas("ce4","ce4",600,400);
728 ce4->Divide(2,1);
729 auto he4 = new TH1F("he4","Distribution drawn with option E4",100,-3,3);
730 Int_t i;
731 for (i=0;i<10000;i++) he4->Fill(gRandom->Gaus(0,1));
732 he4->SetFillColor(kRed);
733 he4->GetXaxis()->SetRange(40,48);
734 ce4->cd(1);
735 he4->Draw("E4");
736 ce4->cd(2);
737 auto he3 = (TH1F*)he4->DrawClone("E3");
738 he3->SetTitle("Distribution drawn option E3");
739}
740End_Macro
741
7422D histograms can be drawn with error bars as shown is the following example:
743
744Begin_Macro(source)
745{
746 auto c2e = new TCanvas("c2e","c2e",600,400);
747 auto h2e = new TH2F("h2e","TH2 drawn with option E",40,-4,4,40,-20,20);
748 float px, py;
749 for (Int_t i = 0; i < 25000; i++) {
750 gRandom->Rannor(px,py);
751 h2e->Fill(px,5*py);
752 }
753 h2e->Draw("E");
754}
755End_Macro
756
757
758\anchor HP100
759### The bar chart option
760
761
762The option "B" allows to draw simple vertical bar charts.
763The bar width is controlled with `TH1::SetBarWidth()`,
764and the bar offset within the bin, with `TH1::SetBarOffset()`.
765These two settings are useful to draw several histograms on the
766same plot as shown in the following example:
767
768Begin_Macro(source)
769{
770 int i;
771 const Int_t nx = 8;
772 string os_X[nx] = {"8","32","128","512","2048","8192","32768","131072"};
773 float d_35_0[nx] = {0.75, -3.30, -0.92, 0.10, 0.08, -1.69, -1.29, -2.37};
774 float d_35_1[nx] = {1.01, -3.02, -0.65, 0.37, 0.34, -1.42, -1.02, -2.10};
775
776 auto cb = new TCanvas("cb","cb",600,400);
777 cb->SetGrid();
778
779 gStyle->SetHistMinimumZero();
780
781 auto h1b = new TH1F("h1b","Option B example",nx,0,nx);
782 h1b->SetFillColor(4);
783 h1b->SetBarWidth(0.4);
784 h1b->SetBarOffset(0.1);
785 h1b->SetStats(0);
786 h1b->SetMinimum(-5);
787 h1b->SetMaximum(5);
788
789 for (i=1; i<=nx; i++) {
790 h1b->SetBinContent(i, d_35_0[i-1]);
791 h1b->GetXaxis()->SetBinLabel(i,os_X[i-1].c_str());
792 }
793
794 h1b->Draw("b");
795
796 auto h2b = new TH1F("h2b","h2b",nx,0,nx);
797 h2b->SetFillColor(38);
798 h2b->SetBarWidth(0.4);
799 h2b->SetBarOffset(0.5);
800 h2b->SetStats(0);
801 for (i=1;i<=nx;i++) h2b->SetBinContent(i, d_35_1[i-1]);
802
803 h2b->Draw("b same");
804}
805End_Macro
806
807
808\anchor HP10
809### The "BAR" and "HBAR" options
810
811
812When the option `bar` or `hbar` is specified, a bar chart is drawn. A vertical
813bar-chart is drawn with the options `bar`, `bar0`, `bar1`, `bar2`, `bar3`, `bar4`.
814An horizontal bar-chart is drawn with the options `hbar`, `hbar0`, `hbar1`,
815`hbar2`, `hbar3`, `hbar4` (hist006_TH1_bar_charts.C).
816
817- The bar is filled with the histogram fill color.
818- The left side of the bar is drawn with a light fill color.
819- The right side of the bar is drawn with a dark fill color.
820- The percentage of the bar drawn with either the light or dark color is:
821 - 0% for option "(h)bar" or "(h)bar0"
822 - 10% for option "(h)bar1"
823 - 20% for option "(h)bar2"
824 - 30% for option "(h)bar3"
825 - 40% for option "(h)bar4"
826
827When an histogram has errors the option ["HIST"](\ref OPTHIST) together with the `(h)bar` option.
828
829Begin_Macro(source)
830../../../tutorials/hist/hist006_TH1_bar_charts.C
831End_Macro
832
833To control the bar width (default is the bin width) `TH1::SetBarWidth()`
834should be used.
835
836To control the bar offset (default is 0) `TH1::SetBarOffset()` should
837be used.
838
839These two parameters are useful when several histograms are plotted using
840the option `SAME`. They allow to plot the histograms next to each other.
841
842
843\anchor HP11
844### The SCATter plot option (legacy draw option)
845
846\attention
847Use of option `SCAT` has been deprecated. It was the default drawing option for 2D and
8483D histograms. The new default option is `COL` (heat-map).
849
850
851For each cell (i,j) a number of points proportional to the cell content is
852drawn. A maximum of `kNMAX` points per cell is drawn. If the maximum is above
853`kNMAX` contents are normalized to `kNMAX` (`kNMAX=2000`).
854If option is of the form `scat=ff`, (eg `scat=1.8`,
855`scat=1e-3`), then `ff` is used as a scale factor to compute the
856number of dots. `scat=1` is the default.
857
858By default the scatter plot is painted with a "dot marker" which not scalable
859(see the `TAttMarker` documentation). To change the marker size, a scalable marker
860type should be used. For instance a circle (marker style 20).
861
862Begin_Macro(source)
863{
864 auto c1 = new TCanvas("c1","c1",600,400);
865 auto hscat = new TH2F("hscat","Option SCATter example (default for 2D histograms) ",40,-4,4,40,-20,20);
866 float px, py;
867 for (Int_t i = 0; i < 25000; i++) {
868 gRandom->Rannor(px,py);
869 hscat->Fill(px,5*py);
870 hscat->Fill(3+0.5*px,2*py-10.);
871 }
872 hscat->Draw("scat=0.5"); // This a legacy draw option. Please consider using TScatter
873}
874End_Macro
875
876
877\anchor HP12
878### The ARRow option
879
880
881Shows gradient between adjacent cells. For each cell (i,j) an arrow is drawn
882The orientation of the arrow follows the cell gradient.
883
884Begin_Macro(source)
885{
886 auto c1 = new TCanvas("c1","c1",600,400);
887 auto harr = new TH2F("harr","Option ARRow example",20,-4,4,20,-20,20);
888 harr->SetLineColor(kRed);
889 float px, py;
890 for (Int_t i = 0; i < 25000; i++) {
891 gRandom->Rannor(px,py);
892 harr->Fill(px,5*py);
893 harr->Fill(3+0.5*px,2*py-10.,0.1);
894 }
895 harr->Draw("ARR");
896}
897End_Macro
898
899\since **ROOT version 6.17/01**
900
901The option `ARR` can be combined with the option `COL` or `COLZ`.
902
903Begin_Macro(source)
904{
905 auto c1 = new TCanvas("c1","c1",600,400);
906 auto harr = new TH2F("harr","Option ARR + COLZ example",20,-4,4,20,-20,20);
907 harr->SetStats(0);
908 float px, py;
909 for (Int_t i = 0; i < 25000; i++) {
910 gRandom->Rannor(px,py);
911 harr->Fill(px,5*py);
912 harr->Fill(3+0.5*px,2*py-10.,0.1);
913 }
914 harr->Draw("ARR COLZ");
915}
916End_Macro
917
918
919\anchor HP13
920### The BOX option
921
922
923For each cell (i,j) a box is drawn. The size (surface) of the box is
924proportional to the absolute value of the cell content.
925The cells with a negative content are drawn with a `X` on top of the box.
926
927Begin_Macro(source)
928{
929 auto c1 = new TCanvas("c1","c1",600,400);
930 auto hbox = new TH2F("hbox","Option BOX example",3,0,3,3,0,3);
931 hbox->SetFillColor(42);
932 hbox->Fill(0.5, 0.5, 1.);
933 hbox->Fill(0.5, 1.5, 4.);
934 hbox->Fill(0.5, 2.5, 3.);
935 hbox->Fill(1.5, 0.5, 2.);
936 hbox->Fill(1.5, 1.5, 12.);
937 hbox->Fill(1.5, 2.5, -6.);
938 hbox->Fill(2.5, 0.5, -4.);
939 hbox->Fill(2.5, 1.5, 6.);
940 hbox->Fill(2.5, 2.5, 0.5);
941 hbox->Draw("BOX");
942}
943End_Macro
944
945With option `BOX1` a button is drawn for each cell with surface
946proportional to content's absolute value. A sunken button is drawn for
947negative values a raised one for positive.
948
949Begin_Macro(source)
950{
951 auto c1 = new TCanvas("c1","c1",600,400);
952 auto hbox1 = new TH2F("hbox1","Option BOX1 example",3,0,3,3,0,3);
953 hbox1->SetFillColor(42);
954 hbox1->Fill(0.5, 0.5, 1.);
955 hbox1->Fill(0.5, 1.5, 4.);
956 hbox1->Fill(0.5, 2.5, 3.);
957 hbox1->Fill(1.5, 0.5, 2.);
958 hbox1->Fill(1.5, 1.5, 12.);
959 hbox1->Fill(1.5, 2.5, -6.);
960 hbox1->Fill(2.5, 0.5, -4.);
961 hbox1->Fill(2.5, 1.5, 6.);
962 hbox1->Fill(2.5, 2.5, 0.5);
963 hbox1->Draw("BOX1");
964}
965End_Macro
966
967When the option `SAME` (or "SAMES") is used with the option `BOX`,
968the boxes' sizes are computed taking the previous plots into account. The range
969along the Z axis is imposed by the first plot (the one without option
970`SAME`); therefore the order in which the plots are done is relevant.
971
972Begin_Macro(source)
973{
974 auto c1 = new TCanvas("c1","c1",600,400);
975 auto hb1 = new TH2F("hb1","Example of BOX plots with option SAME ",40,-3,3,40,-3,3);
976 auto hb2 = new TH2F("hb2","hb2",40,-3,3,40,-3,3);
977 auto hb3 = new TH2F("hb3","hb3",40,-3,3,40,-3,3);
978 auto hb4 = new TH2F("hb4","hb4",40,-3,3,40,-3,3);
979 for (Int_t i=0;i<1000;i++) {
980 double x,y;
981 gRandom->Rannor(x,y);
982 if (x>0 && y>0) hb1->Fill(x,y,4);
983 if (x<0 && y<0) hb2->Fill(x,y,3);
984 if (x>0 && y<0) hb3->Fill(x,y,2);
985 if (x<0 && y>0) hb4->Fill(x,y,1);
986 }
987 hb1->SetFillColor(1);
988 hb2->SetFillColor(2);
989 hb3->SetFillColor(3);
990 hb4->SetFillColor(4);
991 hb1->Draw("box");
992 hb2->Draw("box same");
993 hb3->Draw("box same");
994 hb4->Draw("box same");
995}
996End_Macro
997
998\since **ROOT version 6.17/01:**
999
1000Sometimes the change of the range of the Z axis is unwanted, in which case, one
1001can use `SAME0` (or `SAMES0`) option to opt out of this change.
1002
1003Begin_Macro(source)
1004{
1005 auto h2 = new TH2F("h2"," ",10,0,10,10,20,30);
1006 auto hf = (TH2F*)h2->Clone("hf");
1007 h2->SetBit(TH1::kNoStats);
1008 hf->SetBit(TH1::kNoStats);
1009 h2->Fill(5,22);
1010 h2->Fill(5,23);
1011 h2->Fill(6,22);
1012 h2->Fill(6,23);
1013 hf->Fill(6,23);
1014 hf->Fill(6,23);
1015 hf->Fill(6,23);
1016 hf->Fill(6,23);
1017 hf->Fill(5,23);
1018
1019 auto hf_copy1 = hf->Clone("hf_copy1");
1020 TLatex lt;
1021
1022 auto cx = new TCanvas(); cx->Divide(2,1);
1023
1024 cx->cd(1);
1025 h2->Draw("box");
1026 hf->Draw("text colz same");
1027 lt.DrawLatexNDC(0.3,0.5,"SAME");
1028
1029 cx->cd(2);
1030 h2->Draw("box");
1031 hf_copy1->Draw("text colz same0");
1032 lt.DrawLatexNDC(0.3,0.5,"SAME0");
1033}
1034End_Macro
1035
1036
1037\anchor HP14
1038### The COLor option (default for 2D histograms)
1039
1040The magnitude of individual cell (i,j) is represented as a color picked in the current color palette.
1041This data visualization technique is often called a heat map (or heat-map).
1042
1043The color table used is defined in the current style.
1044
1045If the histogram's minimum and maximum are the same (flat histogram), the
1046mapping on colors is not possible, therefore nothing is painted. To paint a
1047flat histogram it is enough to set the histogram minimum
1048(`TH1::SetMinimum()`) different from the bins' content.
1049
1050The default number of color levels used to paint the cells is 20.
1051It can be changed with `TH1::SetContour()` or
1052`TStyle::SetNumberContours()`. The higher this number is, the smoother
1053is the color change between cells.
1054
1055The color palette in TStyle can be modified via `gStyle->SetPalette()`.
1056
1057All the non-empty bins are painted. Empty bins (bins with content and error equal to 0) are
1058not painted unless some bins have a negative content because in that case the null bins
1059might be not empty.
1060
1061`TProfile2D` histograms are handled differently because, for this type of 2D
1062histograms, it is possible to know if an empty bin has been filled or not. So even
1063if all the bins' contents are positive some empty bins might be painted. And vice versa,
1064if some bins have a negative content some empty bins might be not painted.
1065
1066Combined with the option `COL`, the option `Z` allows to
1067display the color palette defined by `gStyle->SetPalette()`.
1068
1069In the following example, the histogram has only positive bins; the empty
1070bins (containing 0) are not drawn.
1071
1072Begin_Macro(source)
1073{
1074 auto c1 = new TCanvas("c1","c1",600,400);
1075 auto hcol1 = new TH2F("hcol1","Option COLor example ",40,-4,4,40,-20,20);
1076 float px, py;
1077 for (Int_t i = 0; i < 25000; i++) {
1078 gRandom->Rannor(px,py);
1079 hcol1->Fill(px,5*py);
1080 }
1081 hcol1->Draw("COLZ");
1082}
1083End_Macro
1084
1085In the first plot of following example, the histogram has some negative bins;
1086the empty bins (containing 0) are drawn. In some cases one wants to not draw
1087empty bins (containing 0) of histograms having a negative minimum. The option
1088`1`, used to produce the second plot in the following picture, allows to do that.
1089
1090Begin_Macro(source)
1091{
1092 auto c1 = new TCanvas("c1","c1",600,600);
1093 c1->Divide(1,2);
1094 auto hcol23 = new TH2F("hcol23","Option COLZ example ",40,-4,4,40,-20,20);
1095 auto hcol24 = new TH2F("hcol24","Option COLZ1 example ",40,-4,4,40,-20,20);
1096 float px, py;
1097 for (Int_t i = 0; i < 25000; i++) {
1098 gRandom->Rannor(px,py);
1099 hcol23->Fill(px,5*py);
1100 hcol24->Fill(px,5*py);
1101 }
1102 hcol23->Fill(0.,0.,-200.);
1103 hcol24->Fill(0.,0.,-200.);
1104 c1->cd(1); hcol23->Draw("COLZ");
1105 c1->cd(2); hcol24->Draw("COLZ1");
1106}
1107End_Macro
1108
1109When the maximum of the histogram is set to a smaller value than the real maximum,
1110 the bins having a content between the new maximum and the real maximum are
1111painted with the color corresponding to the new maximum.
1112
1113When the minimum of the histogram is set to a greater value than the real minimum,
1114 the bins having a value between the real minimum and the new minimum are not drawn
1115 unless the option `0` is set.
1116In other words, option `COLZ0` forces the painting of bins with content < set minimum with
1117 a color corresponding to the set minimum. In contrast, option `COLZ` would not draw values
1118 smaller than the specified minimum. Note that both `COLZ` and `COLZ0` still do not draw
1119 empty bins, ie bins with `content == error == 0`, if the set min is not negative.
1120(Note that option `COLZ0` for TH2Poly has a different behavior than for TH2.)
1121
1122The following example illustrates the option `0` combined with the option `COL`.
1123
1124Begin_Macro(source)
1125{
1126 auto c1 = new TCanvas("c1","c1",600,600);
1127 c1->Divide(1,2);
1128 auto hcol21 = new TH2F("hcol21","Option COLZ",40,-4,4,40,-20,20);
1129 auto hcol22 = new TH2F("hcol22","Option COLZ0",40,-4,4,40,-20,20);
1130 float px, py;
1131 for (Int_t i = 0; i < 25000; i++) {
1132 gRandom->Rannor(px,py);
1133 hcol21->Fill(px,5*py);
1134 hcol22->Fill(px,5*py);
1135 }
1136 hcol21->SetBit(TH1::kNoStats);
1137 hcol22->SetBit(TH1::kNoStats);
1138 c1->cd(1); hcol21->Draw("COLZ");
1139 c1->cd(2); hcol22->Draw("COLZ0");
1140 hcol21->SetMaximum(100);
1141 hcol21->SetMinimum(40);
1142 hcol22->SetMaximum(100);
1143 hcol22->SetMinimum(40);
1144}
1145End_Macro
1146
1147Note that the behavior of `COLZ` is not symmetric: it does not draw values below the specified minimum,
1148but does draw values above the specified maximum by clipping them to the maximum color. In contrast, `COLZ0`
1149clips color on both lower and upper sides. Both `COLZ0` and `COLZ` exclude drawing empty bins (`content == error == 0`),
1150if the set minimum is not negative.
1151
1152\since **ROOT version 6.09/01:**
1153
1154When the option SAME (or "SAMES") is used with the option COL, the boxes' color
1155are computed taking the previous plots into account. The range along the Z axis
1156is imposed by the first plot (the one without option SAME); therefore the order
1157in which the plots are done is relevant. Same as [in the `BOX` option](\ref HP13), one can use
1158`SAME0` (or `SAMES0`) to opt out of this imposition.
1159
1160Begin_Macro(source)
1161{
1162 auto c = new TCanvas("c","Example of col plots with option SAME",200,10,700,500);
1163 auto h1 = new TH2F("h1","h1",40,-3,3,40,-3,3);
1164 auto h2 = new TH2F("h2","h2",40,-3,3,40,-3,3);
1165 auto h3 = new TH2F("h3","h3",40,-3,3,40,-3,3);
1166 auto h4 = new TH2F("h4","h4",40,-3,3,40,-3,3);
1167 h1->SetBit(TH1::kNoStats);
1168 for (Int_t i=0;i<5000;i++) {
1169 double x,y;
1170 gRandom->Rannor(x,y);
1171 if(x>0 && y>0) h1->Fill(x,y,4);
1172 if(x<0 && y<0) h2->Fill(x,y,3);
1173 if(x>0 && y<0) h3->Fill(x,y,2);
1174 if(x<0 && y>0) h4->Fill(x,y,1);
1175 }
1176 h1->Draw("colz");
1177 h2->Draw("col same");
1178 h3->Draw("col same");
1179 h4->Draw("col same");
1180}
1181End_Macro
1182
1183The option `COL` can be combined with the option `POL`:
1184
1185Begin_Macro(source)
1186{
1187 auto c1 = new TCanvas("c1","c1",600,400);
1188 auto hcol1 = new TH2F("hcol1","Option COLor combined with POL",40,-4,4,40,-4,4);
1189 float px, py;
1190 for (Int_t i = 0; i < 25000; i++) {
1191 gRandom->Rannor(px,py);
1192 hcol1->Fill(px,py);
1193 }
1194 hcol1->Draw("COLZPOL");
1195}
1196End_Macro
1197
1198\since **ROOT version 6.07/03:**
1199
1200A second rendering technique is also available with the COL2 and COLZ2 options.
1201
1202These options provide potential performance improvements compared to the standard
1203COL option. The performance comparison of the COL2 to the COL option depends on
1204the histogram and the size of the rendering region in the current pad. In general,
1205a small (approx. less than 100 bins per axis), sparsely populated TH2 will render
1206faster with the COL option.
1207
1208However, for larger histograms (approx. more than 100 bins per axis)
1209that are not sparse, the COL2 option will provide up to 20 times performance improvements.
1210For example, a 1000x1000 bin TH2 that is not sparse will render an order of magnitude
1211faster with the COL2 option.
1212
1213The COL2 option will also scale its performance based on the size of the
1214pixmap the histogram image is being rendered into. It also is much better optimized for
1215sessions where the user is forwarding X11 windows through an `ssh` connection.
1216
1217For the most part, the COL2 and COLZ2 options are a drop in replacement to the COL
1218and COLZ options. There is one major difference and that concerns the treatment of
1219bins with zero content. The COL2 and COLZ2 options color these bins the color of zero.
1220
1221COL2 option renders the histogram as a bitmap. Therefore it cannot be saved in vector
1222graphics file format like PostScript or PDF (an empty image will be generated). It can
1223be saved only in bitmap files like PNG format for instance.
1224
1225
1226\anchor HP140
1227### The CANDLE and VIOLIN options
1228
1229The mechanism behind Candle plots and Violin plots is very similar. Because of this they are
1230implemented in the same class TCandle. The keywords CANDLE or VIOLIN will initiate the drawing of
1231the corresponding plots. Followed by the keyword the user can select a plot direction (X or V for
1232vertical projections, or Y or H for horizontal projections) and/or predefined definitions
1233(1-6 for candles, 1-2 for violins). The order doesn't matter. Default is X and 1.
1234
1235Instead of using the predefined representations, the candle and violin parameters can be
1236changed individually. In that case the option have the following form:
1237
1238 CANDLEX(<option-string>)
1239 CANDLEY(<option-string>)
1240 VIOLINX(<option-string>)
1241 VIOLINY(<option-string>).
1242
1243All zeros at the beginning of `option-string` can be omitted.
1244
1245`option-string` consists eight values, defined as follow:
1246
1247 "CANDLEX(zhpawMmb)"
1248
1249Where:
1250
1251 - `b = 0`; no box drawn
1252 - `b = 1`; the box is drawn. As the candle-plot is also called a box-plot it
1253 makes sense in the very most cases to always draw the box
1254 - `b = 2`; draw a filled box with border
1255
1256 - `m = 0`; no median drawn
1257 - `m = 1`; median is drawn as a line
1258 - `m = 2`; median is drawn with errors (notches)
1259 - `m = 3`; median is drawn as a circle
1260
1261 - `M = 0`; no mean drawn
1262 - `M = 1`; mean is drawn as a dashed line
1263 - `M = 3`; mean is drawn as a circle
1264
1265 - `w = 0`; no whisker drawn
1266 - `w = 1`; whisker is drawn to end of distribution.
1267 - `w = 2`; whisker is drawn to max 1.5*iqr
1268
1269 - `a = 0`; no anchor drawn
1270 - `a = 1`; the anchors are drawn
1271
1272 - `p = 0`; no points drawn
1273 - `p = 1`; only outliers are drawn
1274 - `p = 2`; all datapoints are drawn
1275 - `p = 3`: all datapoints are drawn scattered
1276
1277 - `h = 0`; no histogram is drawn
1278 - `h = 1`; histogram at the left or bottom side is drawn
1279 - `h = 2`; histogram at the right or top side is drawn
1280 - `h = 3`; histogram at left and right or top and bottom (violin-style) is drawn
1281
1282 - `z = 0`; no zero indicator line is drawn
1283 - `z = 1`; zero indicator line is drawn.
1284
1285As one can see all individual options for both candle and violin plots can be accessed by this
1286mechanism. In deed the keywords CANDLE(<option-string>) and VIOLIN(<option-string>) have the same
1287meaning. So you can parametrise an option-string for a candle plot and use the keywords VIOLIN and
1288vice versa, if you wish.
1289
1290Using a logarithmic x- or y-axis is possible for candle and violin charts.
1291
1292\since **ROOT version 6.11/01**
1293
1294a logarithmic z-axis is possible, too but will only affect violin charts of course.
1295
1296\anchor HP140a
1297#### The CANDLE option
1298
1299<a href="http://en.wikipedia.org/wiki/Box_plot">A Candle plot</a> (also known as
1300a "box plot" or "whisker plot") was invented in 1977 by John Tukey. It is a convenient
1301way to describe graphically a data distribution (D) with only five numbers:
1302
1303 1. The minimum value of the distribution D (bottom or left whisker).
1304 2. The lower quartile (Q1): 25% of the data points in D are less than Q1 (bottom of the box).
1305 3. The median (M): 50% of the data points in D are less than M.
1306 4. The upper quartile (Q3): 75% of the data points in D are less than Q3 (top of the box).
1307 5. The maximum value of the distribution D (top or right whisker).
1308
1309In this implementation a TH2 is considered as a collection of TH1 along
1310X (option `CANDLE` or `CANDLEX`) or Y (option `CANDLEY`).
1311Each TH1 is represented as one candle.
1312
1313Begin_Macro(source)
1314../../../tutorials/hist/hist052_Graphics_candle_plot_whiskers.C
1315End_Macro
1316
1317The candle reduces the information coming from a whole distribution into few values.
1318Independently from the number of entries or the significance of the underlying distribution
1319a candle will always look like a candle. So candle plots should be used carefully in
1320particular with unknown distributions. The definition of a candle is based on
1321__unbinned data__. Here, candles are created from binned data. Because of this, the
1322deviation is connected to the bin width used. The calculation of the quantiles
1323normally done on unbinned data also. Because data are binned, this will
1324only work the best possible way within the resolution of one bin
1325
1326Because of all these facts one should take care that:
1327
1328 - there are enough points per candle
1329 - the bin width is small enough (more bins will increase the maximum
1330 available resolution of the quantiles although there will be some
1331 bins with no entries)
1332 - never make a candle-plot if the underlying distribution is double-distributed
1333 - only create candles of distributions that are more-or-less gaussian (the
1334 MPV should be not too far away from the mean).
1335
1336#### What a candle is made of
1337
1338\since **ROOT version 6.07/05**
1339
1340##### The box
1341The box displays the position of the inter-quantile-range of the underlying
1342distribution. The box contains 25% of the distribution below the median
1343and 25% of the distribution above the median. If the underlying distribution is large
1344enough and gaussian shaped the end-points of the box represent \f$ 0.6745\times\sigma \f$
1345(Where \f$ \sigma \f$ is the standard deviation of the gaussian). The width and
1346the position of the box can be modified by SetBarWidth() and SetBarOffset().
1347The +-25% quantiles are calculated by the GetQuantiles() methods.
1348
1349\since **ROOT version 6.11/01**
1350
1351Using the static function TCandle::SetBoxRange(double) the box definition will be
1352overwritten. E.g. using a box range of 0.68 will redefine the area of the lower box edge
1353to the upper box edge in order to cover 68% of the distribution illustrated by that candle.
1354The static function will affect all candle-charts in the running program.
1355Default is 0.5.
1356
1357Using the static function TCandle::SetScaledCandle(bool) the width of the box (and the
1358whole candle) can be influenced. Deactivated, the width is constant (to be set by
1359SetBarWidth() ). Activated, the width of the boxes will be scaled to each other based on the
1360amount of data in the corresponding candle, the maximum width can be influenced by
1361SetBarWidth(). The static function will affect all candle-charts in the running program.
1362Default is false. Scaling between multiple candle-charts (using "same" or THStack) is not
1363supported, yet
1364
1365##### The Median
1366For a sorted list of numbers, the median is the value in the middle of the list.
1367E.g. if a sorted list is made of five numbers "1,2,3,6,7" 3 will be the median
1368because it is in the middle of the list. If the number of entries is even the
1369average of the two values in the middle will be used. As histograms are binned
1370data, the situation is a bit more complex. The following example shows this:
1371
1372~~~ {.cpp}
1373void quantiles() {
1374 auto h = new TH1I("h","h",10,0,10);
1375 //h->Fill(3);
1376 //h->Fill(3);
1377 h->Fill(4);
1378 h->Draw();
1379 double p = 0.;
1380 double q = 0.;
1381 h->GetQuantiles(1,&q,&p);
1382
1383 cout << "Median is: " << q << std::endl;
1384}
1385~~~
1386
1387Here the bin-width is 1.0. If the two Fill(3) are commented out, as there are currently,
1388the example will return a calculated median of 4.5, because that's the bin center
1389of the bin in which the value 4.0 has been dropped. If the two Fill(3) are not
1390commented out, it will return 3.75, because the algorithm tries to evenly distribute
1391the individual values of a bin with bin content > 0. It means the sorted list
1392would be "3.25, 3.75, 4.5".
1393
1394The consequence is a median of 3.75. This shows how important it is to use a
1395small enough bin-width when using candle-plots on binned data.
1396If the distribution is large enough and gaussian shaped the median will be exactly
1397equal to the mean.
1398The median can be shown as a line or as a circle or not shown at all.
1399
1400In order to show the significance of the median notched candle plots apply a "notch" or
1401narrowing of the box around the median. The significance is defined by
1402\f$ 1.57\times\frac{iqr}{N} \f$ and will be represented as the size of the notch
1403(where iqr is the size of the box and N is the number of entries of the whole
1404distribution). Candle plots like these are usually called "notched candle plots".
1405
1406In case the significance of the median is greater that the size of the box, the
1407box will have an unnatural shape. Usually it means the chart has not enough data,
1408or that representing this uncertainty is not useful
1409
1410##### The Mean
1411The mean can be drawn as a dashed line or as a circle or not drawn at all.
1412The mean is the arithmetic average of the values in the distribution.
1413It is calculated using GetMean(). Because histograms are
1414binned data, the mean value can differ from a calculation on the raw-data.
1415If the distribution is large enough and gaussian shaped the mean will be
1416exactly the median.
1417
1418##### The Whiskers
1419The whiskers represent the part of the distribution not covered by the box.
1420The upper 25% and the lower 25% of the distribution are located within the whiskers.
1421Two representations are available.
1422
1423 - A simple one (using w=1) defining the lower whisker from the lowest data value
1424 to the bottom of the box, and the upper whisker from the top of the box to the
1425 highest data value. In this representation the whisker-lines are dashed.
1426 - A more complex one having a further restriction. The whiskers are still connected
1427 to the box but their length cannot exceed \f$ 1.5\times iqr \f$. So it might
1428 be that the outermost part of the underlying distribution will not be covered
1429 by the whiskers. Usually these missing parts will be represented by the outliers
1430 (see points). Of course the upper and the lower whisker may differ in length.
1431 In this representation the whiskers are drawn as solid lines.
1432
1433\since **ROOT version 6.11/01**
1434
1435Using the static function TCandle::SetWhiskerRange(double) the whisker definition w=1
1436will be overwritten. E.g. using a whisker-range of 0.95 and w=1 will redefine the area of
1437the lower whisker to the upper whisker in order to cover 95% of the distribution inside
1438that candle. The static function will affect all candle-charts in the running program.
1439Default is 1.
1440
1441If the distribution is large enough and gaussian shaped, the maximum length of
1442the whisker will be located at \f$ \pm 2.698 \sigma \f$ (when using the
14431.5*iqr-definition (w=2), where \f$ \sigma \f$ is the standard deviation
1444(see picture above). In that case 99.3% of the total distribution will be covered
1445by the box and the whiskers, whereas 0.7% are represented by the outliers.
1446
1447##### The Anchors
1448The anchors have no special meaning in terms of statistical calculation. They mark
1449the end of the whiskers and they have the width of the box. Both representation
1450with and without anchors are common.
1451
1452##### The Points
1453Depending on the configuration the points can have different meanings:
1454 - If p=1 the points represent the outliers. If they are shown, it means
1455 some parts of the underlying distribution are not covered by the whiskers.
1456 This can only occur when the whiskers are set to option w=2. Here the whiskers
1457 can have a maximum length of \f$ 1.5 \times iqr \f$. So any points outside the
1458 whiskers will be drawn as outliers. The outliers will be represented by crosses.
1459 - If p=2 all points in the distribution will be painted as crosses. This is
1460 useful for small datasets only (up to 10 or 20 points per candle).
1461 The outliers are shown along the candle. Because the underlying distribution
1462 is binned, is frequently occurs that a bin contains more than one value.
1463 Because of this the points will be randomly scattered within their bin along
1464 the candle axis. If the bin content for a bin is exactly 1 (usually
1465 this happens for the outliers) if will be drawn in the middle of the bin along
1466 the candle axis. As the maximum number of points per candle is limited by kNMax/2
1467 on very large datasets scaling will be performed automatically. In that case one
1468 would loose all outliers because they have usually a bin content of 1 (and a
1469 bin content between 0 and 1 after the scaling). Because of this all bin contents
1470 between 0 and 1 - after the scaling - will be forced to be 1.
1471 - As the drawing of all values on large datasets can lead to big amounts of crosses,
1472 one can show all values as a scatter plot instead by choosing p=3. The points will be
1473 drawn as dots and will be scattered within the width of the candle. The color
1474 of the points will be the color of the candle-chart.
1475
1476##### Other Options
1477Is is possible to combine all options of candle and violin plots with each other. E.g. a box-plot
1478with a histogram.
1479
1480#### How to use the candle-plots drawing option
1481
1482There are six predefined candle-plot representations:
1483
1484 - "CANDLEX1": Standard candle (whiskers cover the whole distribution)
1485 - "CANDLEX2": Standard candle with better whisker definition + outliers.
1486 It is a good compromise
1487 - "CANDLEX3": Like candle2 but with a mean as a circle.
1488 It is easier to distinguish mean and median
1489 - "CANDLEX4": Like candle3 but showing the uncertainty of the median as well
1490 (notched candle plots).
1491 For bigger datasets per candle
1492 - "CANDLEX5": Like candle2 but showing all data points.
1493 For very small datasets
1494 - "CANDLEX6": Like candle2 but showing all datapoints scattered.
1495 For huge datasets
1496
1497
1498The following picture shows how the six predefined representations look.
1499
1500Begin_Macro
1501{
1502 auto c1 = new TCanvas("c1","c1",700,800);
1503 c1->Divide(2,3);
1504 gStyle->SetOptStat(kFALSE);
1505
1506 auto hcandle = new TH2F("hcandle"," ",10,-4,4,40,-20,20);
1507 float px, py;
1508 for (Int_t i = 0; i < 15000; i++) {
1509 gRandom->Rannor(px,py);
1510 hcandle->Fill(px,5*py);
1511 }
1512 hcandle->SetMarkerSize(0.5);
1513
1514 TH2F *h2;
1515 for (Int_t i=1; i<7; i++) {
1516 c1->cd(i);
1517 h2 = (TH2F*)hcandle->DrawClone(Form("CANDLE%d",i));
1518 h2->SetTitle(Form("CANDLE%d",i));
1519 }
1520}
1521End_Macro
1522
1523
1524#### Example 1
1525Box and improved whisker, no mean, no median, no anchor no outliers
1526
1527 h1->Draw("CANDLEX(2001)");
1528
1529#### Example 2
1530A Candle-definition like "CANDLEX2" (New standard candle with better whisker definition + outliers)
1531
1532 h1->Draw("CANDLEX(112111)");
1533
1534#### Example 3
1535The following example shows how several candle plots can be super-imposed using
1536the option SAME. Note that the bar-width and bar-offset are active on candle plots.
1537Also the color, the line width, the size of the points and so on can be changed by the
1538standard attribute setting methods such as SetLineColor() SetLineWidth().
1539
1540Begin_Macro(source)
1541../../../tutorials/hist/hist049_Graphics_candle_plot.C
1542End_Macro
1543
1544\anchor HP140b
1545#### The VIOLIN option
1546
1547<a href="http://en.wikipedia.org/wiki/Violin_plot">A violin plot</a> is a candle plot
1548that also encodes the pdf information at each point.
1549
1550
1551Quartiles and mean are also represented at each point, with a marker
1552and two lines.
1553
1554In this implementation a TH2 is considered as a collection of TH1 along
1555X (option `VIOLIN` or `VIOLINX`) or Y (option `VIOLINY`).
1556
1557#### What a violin is made of
1558
1559\since **ROOT version 6.09/02**
1560
1561##### The histogram
1562The histogram is typically drawn to both directions with respect to the middle-line of the
1563corresponding bin. This can be achieved by using h=3. It is possible to draw a histogram only to
1564one side (h=1, or h=2).
1565The maximum number of bins in the histogram is limited to 500, if the number of bins in the used
1566histogram is higher it will be rebinned automatically. The maximum height of the histogram can
1567be modified by using SetBarWidth() and the position can be changed with SetBarOffset().
1568A solid fill style is recommended.
1569
1570\since **ROOT version 6.11/01**
1571
1572Using the static function TCandle::SetScaledViolin(bool) the height of the histogram or the
1573violin can be influenced. Activated, the height of the bins of the individual violins will be
1574scaled with respect to each other, the maximum height can be influenced by SetBarWidth().
1575Deactivated, the height of the bin with the maximum content of each individual violin is
1576set to a constant value using SetBarWidth(). The static function will affect all violin-charts
1577in the running program. Default is true. Scaling between multiple violin-charts
1578(using "same" or THStack) is not supported, yet.
1579
1580##### The zero indicator line
1581Typical for violin charts is a line in the background over the whole histogram indicating
1582the bins with zero entries. The zero indicator line can be activated with z=1. The line color
1583will always be the same as the fill-color of the histogram.
1584
1585##### The Mean
1586The Mean is illustrated with the same mechanism as used for candle plots. Usually a circle is used.
1587
1588##### Whiskers
1589The whiskers are illustrated by the same mechanism as used for candle plots. There is only one
1590difference. When using the simple whisker definition (w=1) and the zero indicator line (z=1), then
1591the whiskers will be forced to be solid (usually hashed)
1592
1593##### Points
1594The points are illustrated by the same mechanism as used for candle plots. E.g. VIOLIN2 uses
1595better whisker definition (w=2) and outliers (p=1).
1596
1597##### Other options
1598It is possible to combine all options of candle or violin plots with each other. E.g. a violin plot
1599including a box-plot.
1600
1601#### How to use the violin-plots drawing option
1602
1603There are two predefined violin-plot representations:
1604 - "VIOLINX1": Standard violin (histogram, mean, whisker over full distribution,
1605 zero indicator line)
1606 - "VIOLINX2": Line VIOLINX1 both with better whisker definition + outliers.
1607
1608A solid fill style is recommended for this plot (as opposed to a hollow or
1609hashed style).
1610
1611Begin_Macro(source)
1612{
1613 auto c1 = new TCanvas("c1","c1",600,400);
1614 Int_t nx(6), ny(40);
1615 double xmin(0.0), xmax(+6.0), ymin(0.0), ymax(+4.0);
1616 auto hviolin = new TH2F("hviolin", "Option VIOLIN example", nx, xmin, xmax, ny, ymin, ymax);
1617 TF1 f1("f1", "gaus", +0,0 +4.0);
1618 double x,y;
1619 for (Int_t iBin=1; iBin<hviolin->GetNbinsX(); ++iBin) {
1620 double xc = hviolin->GetXaxis()->GetBinCenter(iBin);
1621 f1.SetParameters(1, 2.0+TMath::Sin(1.0+xc), 0.2+0.1*(xc-xmin)/xmax);
1622 for(Int_t i=0; i<10000; ++i){
1623 x = xc;
1624 y = f1.GetRandom();
1625 hviolin->Fill(x, y);
1626 }
1627 }
1628 hviolin->SetFillColor(kGray);
1629 hviolin->SetMarkerStyle(20);
1630 hviolin->SetMarkerSize(0.5);
1631 hviolin->Draw("VIOLIN");
1632 c1->Update();
1633}
1634End_Macro
1635
1636The next example illustrates a time development of a certain value:
1637
1638Begin_Macro(source)
1639../../../tutorials/hist/hist047_Graphics_candle_decay.C
1640End_Macro
1641
1642
1643\anchor HP15
1644### The TEXT and TEXTnn Option
1645
1646
1647For each bin the content is printed. The text attributes are:
1648
1649- text font = current TStyle font (`gStyle->SetTextFont()`).
1650- text size = 0.02*padheight*markersize (if `h` is the histogram drawn
1651 with the option `TEXT` the marker size can be changed with
1652 `h->SetMarkerSize(markersize)`).
1653- text color = marker color.
1654
1655By default the format `g` is used. This format can be redefined
1656by calling `gStyle->SetPaintTextFormat()`.
1657
1658It is also possible to use `TEXTnn` in order to draw the text with
1659the angle `nn` (`0 < nn <= 90`).
1660
1661For 2D histograms the text is plotted in the center of each non empty cells.
1662It is possible to plot empty cells by calling `gStyle->SetHistMinimumZero()`
1663or providing MIN0 draw option. For 1D histogram the text is plotted at a y
1664position equal to the bin content.
1665
1666For 2D histograms when the option "E" (errors) is combined with the option
1667text ("TEXTE"), the error for each bin is also printed.
1668
1669Begin_Macro(source)
1670{
1671 auto c01 = new TCanvas("c01","c01",700,400);
1672 c01->Divide(2,1);
1673 auto htext1 = new TH1F("htext1","Option TEXT on 1D histograms ",10,-4,4);
1674 auto htext2 = new TH2F("htext2","Option TEXT on 2D histograms ",10,-4,4,10,-20,20);
1675 float px, py;
1676 for (Int_t i = 0; i < 25000; i++) {
1677 gRandom->Rannor(px,py);
1678 htext1->Fill(px,0.1);
1679 htext2->Fill(px,5*py,0.1);
1680 }
1681 gStyle->SetPaintTextFormat("4.1f m");
1682 htext2->SetMarkerSize(1.8);
1683 c01->cd(1);
1684 htext2->Draw("TEXT45");
1685 c01->cd(2);
1686 htext1->Draw();
1687 htext1->Draw("HIST TEXT0 SAME");
1688}
1689End_Macro
1690
1691\since **ROOT version 6.07/07:**
1692
1693In case several histograms are drawn on top ot each other (using option `SAME`),
1694the text can be shifted using `SetBarOffset()`. It specifies an offset for the
1695text position in each cell, in percentage of the bin width.
1696
1697Begin_Macro(source)
1698{
1699 auto c03 = new TCanvas("c03","c03",700,400);
1700 gStyle->SetOptStat(0);
1701 auto htext3 = new TH2F("htext3","Several 2D histograms drawn with option TEXT",10,-4,4,10,-20,20);
1702 auto htext4 = new TH2F("htext4","htext4",10,-4,4,10,-20,20);
1703 auto htext5 = new TH2F("htext5","htext5",10,-4,4,10,-20,20);
1704 float px, py;
1705 for (Int_t i = 0; i < 25000; i++) {
1706 gRandom->Rannor(px,py);
1707 htext3->Fill(4*px,20*py,0.1);
1708 htext4->Fill(4*px,20*py,0.5);
1709 htext5->Fill(4*px,20*py,1.0);
1710 }
1711 htext4->SetMarkerSize(1.8);
1712 htext5->SetMarkerSize(1.8);
1713 htext5->SetMarkerColor(kRed);
1714 htext4->SetBarOffset(0.2);
1715 htext5->SetBarOffset(-0.2);
1716 htext3->Draw("COL");
1717 htext4->Draw("TEXT SAME");
1718 htext5->Draw("TEXT SAME");
1719}
1720End_Macro
1721
1722In the case of profile histograms it is possible to print the number
1723of entries instead of the bin content. It is enough to combine the
1724option "E" (for entries) with the option "TEXT".
1725
1726Begin_Macro(source)
1727{
1728 auto c02 = new TCanvas("c02","c02",700,400);
1729 c02->Divide(2,1);
1730 gStyle->SetPaintTextFormat("g");
1731
1732 auto profile = new TProfile("profile","profile",10,0,10);
1733 profile->SetMarkerSize(2.2);
1734 profile->Fill(0.5,1);
1735 profile->Fill(1.5,2);
1736 profile->Fill(2.5,3);
1737 profile->Fill(3.5,4);
1738 profile->Fill(4.5,5);
1739 profile->Fill(5.5,5);
1740 profile->Fill(6.5,4);
1741 profile->Fill(7.5,3);
1742 profile->Fill(8.5,2);
1743 profile->Fill(9.5,1);
1744 c02->cd(1); profile->Draw("HIST TEXT0");
1745 c02->cd(2); profile->Draw("HIST TEXT0E");
1746}
1747End_Macro
1748
1749\anchor HP16
1750### The CONTour options
1751
1752
1753The following contour options are supported:
1754
1755| Option | Description |
1756|----------|-----------------------------------------------------------------------------|
1757| "CONT" | Draw a contour plot (same as CONT0). |
1758| "CONT0" | Draw a contour plot using surface colors to distinguish contours. |
1759| "CONT1" | Draw a contour plot using the line colors to distinguish contours. |
1760| "CONT2" | Draw a contour plot using the line styles (1 to 5) to distinguish contours. |
1761| "CONT3" | Draw a contour plot using the same line style for all contours. |
1762| "CONT4" | Draw a contour plot using surface colors (`SURF` option at theta = 0). |
1763
1764
1765The following example shows a 2D histogram plotted with the option
1766`CONTZ`. The option `CONT` draws a contour plot using surface
1767colors to distinguish contours. Combined with the option `CONT` (or
1768`CONT0`), the option `Z` allows to display the color palette
1769defined by `gStyle->SetPalette()`.
1770
1771Begin_Macro(source)
1772{
1773 auto c1 = new TCanvas("c1","c1",600,400);
1774 auto hcontz = new TH2F("hcontz","Option CONTZ example ",40,-4,4,40,-20,20);
1775 float px, py;
1776 for (Int_t i = 0; i < 25000; i++) {
1777 gRandom->Rannor(px,py);
1778 hcontz->Fill(px-1,5*py);
1779 hcontz->Fill(2+0.5*px,2*py-10.,0.1);
1780 }
1781 hcontz->Draw("CONTZ");
1782}
1783End_Macro
1784
1785The following example shows a 2D histogram plotted with the option
1786`CONT1Z`. The option `CONT1` draws a contour plot using the
1787line colors to distinguish contours. Combined with the option `CONT1`,
1788the option `Z` allows to display the color palette defined by
1789`gStyle->SetPalette()`.
1790
1791Begin_Macro(source)
1792{
1793 auto c1 = new TCanvas("c1","c1",600,400);
1794 auto hcont1 = new TH2F("hcont1","Option CONT1Z example ",40,-4,4,40,-20,20);
1795 float px, py;
1796 for (Int_t i = 0; i < 25000; i++) {
1797 gRandom->Rannor(px,py);
1798 hcont1->Fill(px-1,5*py);
1799 hcont1->Fill(2+0.5*px,2*py-10.,0.1);
1800 }
1801 hcont1->Draw("CONT1Z");
1802}
1803End_Macro
1804
1805The following example shows a 2D histogram plotted with the option
1806`CONT2`. The option `CONT2` draws a contour plot using the
1807line styles (1 to 5) to distinguish contours.
1808
1809Begin_Macro(source)
1810{
1811 auto c1 = new TCanvas("c1","c1",600,400);
1812 auto hcont2 = new TH2F("hcont2","Option CONT2 example ",40,-4,4,40,-20,20);
1813 float px, py;
1814 for (Int_t i = 0; i < 25000; i++) {
1815 gRandom->Rannor(px,py);
1816 hcont2->Fill(px-1,5*py);
1817 hcont2->Fill(2+0.5*px,2*py-10.,0.1);
1818 }
1819 hcont2->Draw("CONT2");
1820}
1821End_Macro
1822
1823The following example shows a 2D histogram plotted with the option
1824`CONT3`. The option `CONT3` draws contour plot using the same line style for
1825all contours.
1826
1827Begin_Macro(source)
1828{
1829 auto c1 = new TCanvas("c1","c1",600,400);
1830 auto hcont3 = new TH2F("hcont3","Option CONT3 example ",40,-4,4,40,-20,20);
1831 float px, py;
1832 for (Int_t i = 0; i < 25000; i++) {
1833 gRandom->Rannor(px,py);
1834 hcont3->Fill(px-1,5*py);
1835 hcont3->Fill(2+0.5*px,2*py-10.,0.1);
1836 }
1837 hcont3->SetLineStyle(kDotted);
1838 hcont3->Draw("CONT3");
1839}
1840End_Macro
1841
1842The following example shows a 2D histogram plotted with the option
1843`CONT4`. The option `CONT4` draws a contour plot using surface
1844colors to distinguish contours (`SURF` option at theta = 0). Combined
1845with the option `CONT` (or `CONT0`), the option `Z`
1846allows to display the color palette defined by `gStyle->SetPalette()`.
1847
1848Begin_Macro(source)
1849{
1850 auto c1 = new TCanvas("c1","c1",600,400);
1851 auto hcont4 = new TH2F("hcont4","Option CONT4Z example ",40,-4,4,40,-20,20);
1852 float px, py;
1853 for (Int_t i = 0; i < 25000; i++) {
1854 gRandom->Rannor(px,py);
1855 hcont4->Fill(px-1,5*py);
1856 hcont4->Fill(2+0.5*px,2*py-10.,0.1);
1857 }
1858 hcont4->Draw("CONT4Z");
1859}
1860End_Macro
1861
1862The default number of contour levels is 20 equidistant levels and can be changed
1863with `TH1::SetContour()` or `TStyle::SetNumberContours()`.
1864
1865\anchor HP16a
1866#### The LIST option
1867
1868When option `LIST` is specified together with option
1869`CONT`, the points used to draw the contours are saved in
1870`TGraph` objects:
1871
1872 h->Draw("CONT LIST");
1873 gPad->Update();
1874
1875The contour are saved in `TGraph` objects once the pad is painted.
1876Therefore to use this functionality in a macro, `gPad->Update()`
1877should be performed after the histogram drawing. Once the list is
1878built, the contours are accessible in the following way:
1879
1880 TObjArray *contours = (TObjArray*)gROOT->GetListOfSpecials()->FindObject("contours");
1881 Int_t ncontours = contours->GetSize();
1882 TList *list = (TList*)contours->At(i);
1883
1884Where `i` is a contour number, and list contains a list of
1885`TGraph` objects.
1886For one given contour, more than one disjoint polyline may be generated.
1887The number of TGraphs per contour is given by:
1888
1889 list->GetSize();
1890
1891To access the first graph in the list one should do:
1892
1893 TGraph *gr1 = (TGraph*)list->First();
1894
1895
1896The following example (hist102_TH2_contour_list.C) shows how to use this functionality.
1897
1898Begin_Macro(source)
1899../../../tutorials/hist/hist102_TH2_contour_list.C
1900End_Macro
1901
1902\anchor HP16b
1903#### The AITOFF, MERCATOR, SINUSOIDAL and PARABOLIC options
1904
1905The following options select the `CONT4` option and are useful for
1906sky maps or exposure maps (earth.C).
1907
1908| Option | Description |
1909|--------------|---------------------------------------------------------------|
1910| "AITOFF" | Draw a contour via an AITOFF projection.|
1911| "MERCATOR" | Draw a contour via an Mercator projection.|
1912| "SINUSOIDAL" | Draw a contour via an Sinusoidal projection.|
1913| "PARABOLIC" | Draw a contour via an Parabolic projection.|
1914
1915Begin_Macro(source)
1916../../../tutorials/visualisation/graphics/earth.C
1917End_Macro
1918
1919
1920\anchor HP17
1921### The LEGO options
1922
1923
1924In a lego plot the cell contents are drawn as 3-d boxes. The height of each box
1925is proportional to the cell content. The lego aspect is control with the
1926following options:
1927
1928| Option | Description |
1929|----------|-------------------------------------------------------------------|
1930| "LEGO" | Draw a lego plot using the hidden lines removal technique.|
1931| "LEGO1" | Draw a lego plot using the hidden surface removal technique.|
1932| "LEGO2" | Draw a lego plot using colors to show the cell contents.|
1933| "LEGO3" | Draw a lego plot with hidden surface removal, like LEGO1 but the border lines of each lego-bar are not drawn.|
1934| "LEGO4" | Draw a lego plot with hidden surface removal, like LEGO1 but without the shadow effect on each lego-bar.|
1935| "0" | When used with any LEGO option, the empty bins are not drawn.|
1936
1937
1938See the limitations with [the option "SAME"](\ref HP060a).
1939
1940Line attributes can be used in lego plots to change the edges' style.
1941
1942The following example shows a 2D histogram plotted with the option
1943`LEGO`. The option `LEGO` draws a lego plot using the hidden
1944lines removal technique.
1945
1946Begin_Macro(source)
1947{
1948 auto c2 = new TCanvas("c2","c2",600,400);
1949 auto hlego = new TH2F("hlego","Option LEGO example ",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 hlego->Fill(px-1,5*py);
1954 hlego->Fill(2+0.5*px,2*py-10.,0.1);
1955 }
1956 hlego->Draw("LEGO");
1957}
1958End_Macro
1959
1960The following example shows a 2D histogram plotted with the option
1961`LEGO1`. The option `LEGO1` draws a lego plot using the
1962hidden surface removal technique. Combined with any `LEGOn` option, the
1963option `0` allows to not drawn the empty bins.
1964
1965Begin_Macro(source)
1966{
1967 auto c2 = new TCanvas("c2","c2",600,400);
1968 auto hlego1 = new TH2F("hlego1","Option LEGO1 example (with option 0) ",40,-4,4,40,-20,20);
1969 float px, py;
1970 for (Int_t i = 0; i < 25000; i++) {
1971 gRandom->Rannor(px,py);
1972 hlego1->Fill(px-1,5*py);
1973 hlego1->Fill(2+0.5*px,2*py-10.,0.1);
1974 }
1975 hlego1->SetFillColor(kYellow);
1976 hlego1->Draw("LEGO1 0");
1977}
1978End_Macro
1979
1980The following example shows a 2D histogram plotted with the option
1981`LEGO3`. Like the option `LEGO1`, the option `LEGO3`
1982draws a lego plot using the hidden surface removal technique but doesn't draw
1983the border lines of each individual lego-bar. This is very useful for histograms
1984having many bins. With such histograms the option `LEGO1` gives a black
1985image because of the border lines. This option also works with stacked legos.
1986
1987Begin_Macro(source)
1988{
1989 auto c2 = new TCanvas("c2","c2",600,400);
1990 auto hlego3 = new TH2F("hlego3","Option LEGO3 example",40,-4,4,40,-20,20);
1991 float px, py;
1992 for (Int_t i = 0; i < 25000; i++) {
1993 gRandom->Rannor(px,py);
1994 hlego3->Fill(px-1,5*py);
1995 hlego3->Fill(2+0.5*px,2*py-10.,0.1);
1996 }
1997 hlego3->SetFillColor(kRed);
1998 hlego3->Draw("LEGO3");
1999}
2000End_Macro
2001
2002The following example shows a 2D histogram plotted with the option
2003`LEGO2`. The option `LEGO2` draws a lego plot using colors to
2004show the cell contents. Combined with the option `LEGO2`, the option
2005`Z` allows to display the color palette defined by
2006`gStyle->SetPalette()`.
2007
2008Begin_Macro(source)
2009{
2010 auto c2 = new TCanvas("c2","c2",600,400);
2011 auto hlego2 = new TH2F("hlego2","Option LEGO2Z example ",40,-4,4,40,-20,20);
2012 float px, py;
2013 for (Int_t i = 0; i < 25000; i++) {
2014 gRandom->Rannor(px,py);
2015 hlego2->Fill(px-1,5*py);
2016 hlego2->Fill(2+0.5*px,2*py-10.,0.1);
2017 }
2018 hlego2->Draw("LEGO2Z");
2019}
2020End_Macro
2021
2022
2023
2024\anchor HP18
2025### The "SURFace" options
2026
2027
2028In a surface plot, cell contents are represented as a mesh.
2029The height of the mesh is proportional to the cell content.
2030
2031| Option | Description |
2032|----------|-------------------------------------------------------------------|
2033| "SURF" | Draw a surface plot using the hidden line removal technique.|
2034| "SURF1" | Draw a surface plot using the hidden surface removal technique.|
2035| "SURF2" | Draw a surface plot using colors to show the cell contents.|
2036| "SURF3" | Same as `SURF` with an additional filled contour plot on top.|
2037| "SURF4" | Draw a surface using the Gouraud shading technique.|
2038| "SURF5" | Used with one of the options CYL, PSR and CYL this option allows to draw a filled contour plot.|
2039| "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.|
2040| "SURF7" | Same as `SURF2` with an additional line contour plot on top.|
2041
2042
2043
2044See the limitations with [the option "SAME"](\ref HP060a).
2045
2046The following example shows a 2D histogram plotted with the option
2047`SURF`. The option `SURF` draws a lego plot using the hidden
2048lines removal technique.
2049
2050Begin_Macro(source)
2051{
2052 auto c2 = new TCanvas("c2","c2",600,400);
2053 auto hsurf = new TH2F("hsurf","Option SURF example ",30,-4,4,30,-20,20);
2054 float px, py;
2055 for (Int_t i = 0; i < 25000; i++) {
2056 gRandom->Rannor(px,py);
2057 hsurf->Fill(px-1,5*py);
2058 hsurf->Fill(2+0.5*px,2*py-10.,0.1);
2059 }
2060 hsurf->Draw("SURF");
2061}
2062End_Macro
2063
2064The following example shows a 2D histogram plotted with the option
2065`SURF1`. The option `SURF1` draws a surface plot using the
2066hidden surface removal technique. Combined with the option `SURF1`,
2067the option `Z` allows to display the color palette defined by
2068`gStyle->SetPalette()`.
2069
2070Begin_Macro(source)
2071{
2072 auto c2 = new TCanvas("c2","c2",600,400);
2073 auto hsurf1 = new TH2F("hsurf1","Option SURF1 example ",30,-4,4,30,-20,20);
2074 float px, py;
2075 for (Int_t i = 0; i < 25000; i++) {
2076 gRandom->Rannor(px,py);
2077 hsurf1->Fill(px-1,5*py);
2078 hsurf1->Fill(2+0.5*px,2*py-10.,0.1);
2079 }
2080 hsurf1->Draw("SURF1");
2081}
2082End_Macro
2083
2084The following example shows a 2D histogram plotted with the option
2085`SURF2`. The option `SURF2` draws a surface plot using colors
2086to show the cell contents. Combined with the option `SURF2`, the option
2087`Z` allows to display the color palette defined by
2088`gStyle->SetPalette()`.
2089
2090Begin_Macro(source)
2091{
2092 auto c2 = new TCanvas("c2","c2",600,400);
2093 auto hsurf2 = new TH2F("hsurf2","Option SURF2 example ",30,-4,4,30,-20,20);
2094 float px, py;
2095 for (Int_t i = 0; i < 25000; i++) {
2096 gRandom->Rannor(px,py);
2097 hsurf2->Fill(px-1,5*py);
2098 hsurf2->Fill(2+0.5*px,2*py-10.,0.1);
2099 }
2100 hsurf2->Draw("SURF2");
2101}
2102End_Macro
2103
2104The following example shows a 2D histogram plotted with the option
2105`SURF3`. The option `SURF3` draws a surface plot using the
2106hidden line removal technique with, in addition, a filled contour view drawn on the
2107top. Combined with the option `SURF3`, the option `Z` allows
2108to display the color palette defined by `gStyle->SetPalette()`.
2109
2110Begin_Macro(source)
2111{
2112 auto c2 = new TCanvas("c2","c2",600,400);
2113 auto hsurf3 = new TH2F("hsurf3","Option SURF3 example ",30,-4,4,30,-20,20);
2114 float px, py;
2115 for (Int_t i = 0; i < 25000; i++) {
2116 gRandom->Rannor(px,py);
2117 hsurf3->Fill(px-1,5*py);
2118 hsurf3->Fill(2+0.5*px,2*py-10.,0.1);
2119 }
2120 hsurf3->Draw("SURF3");
2121}
2122End_Macro
2123
2124The following example shows a 2D histogram plotted with the option
2125`SURF4`. The option `SURF4` draws a surface using the Gouraud
2126shading technique.
2127
2128Begin_Macro(source)
2129{
2130 auto c2 = new TCanvas("c2","c2",600,400);
2131 auto hsurf4 = new TH2F("hsurf4","Option SURF4 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 hsurf4->Fill(px-1,5*py);
2136 hsurf4->Fill(2+0.5*px,2*py-10.,0.1);
2137 }
2138 hsurf4->SetFillColor(kOrange);
2139 hsurf4->Draw("SURF4");
2140}
2141End_Macro
2142
2143The following example shows a 2D histogram plotted with the option
2144`SURF5 CYL`. Combined with the option `SURF5`, the option
2145`Z` allows to display the color palette defined by `gStyle->SetPalette()`.
2146
2147Begin_Macro(source)
2148{
2149 auto c2 = new TCanvas("c2","c2",600,400);
2150 auto hsurf5 = new TH2F("hsurf4","Option SURF5 example ",30,-4,4,30,-20,20);
2151 float px, py;
2152 for (Int_t i = 0; i < 25000; i++) {
2153 gRandom->Rannor(px,py);
2154 hsurf5->Fill(px-1,5*py);
2155 hsurf5->Fill(2+0.5*px,2*py-10.,0.1);
2156 }
2157 hsurf5->Draw("SURF5 CYL");
2158}
2159End_Macro
2160
2161The following example shows a 2D histogram plotted with the option
2162`SURF7`. The option `SURF7` draws a surface plot using the
2163hidden surfaces removal technique with, in addition, a line contour view drawn on the
2164top. Combined with the option `SURF7`, the option `Z` allows
2165to display the color palette defined by `gStyle->SetPalette()`.
2166
2167Begin_Macro(source)
2168{
2169 auto c2 = new TCanvas("c2","c2",600,400);
2170 auto hsurf7 = new TH2F("hsurf3","Option SURF7 example ",30,-4,4,30,-20,20);
2171 float px, py;
2172 for (Int_t i = 0; i < 25000; i++) {
2173 gRandom->Rannor(px,py);
2174 hsurf7->Fill(px-1,5*py);
2175 hsurf7->Fill(2+0.5*px,2*py-10.,0.1);
2176 }
2177 hsurf7->Draw("SURF7");
2178}
2179End_Macro
2180
2181As shown in the following example, when a contour plot is painted on top of a
2182surface plot using the option `SAME`, the contours appear in 3D on the
2183surface.
2184
2185Begin_Macro(source)
2186{
2187 auto c20=new TCanvas("c20","c20",600,400);
2188 int NBins = 50;
2189 double d = 2;
2190 auto hsc = new TH2F("hsc", "Surface and contour with option SAME ", NBins, -d, d, NBins, -d, d);
2191 for (int bx = 1; bx <= NBins; ++bx) {
2192 for (int by = 1; by <= NBins; ++by) {
2193 double x = hsc->GetXaxis()->GetBinCenter(bx);
2194 double y = hsc->GetYaxis()->GetBinCenter(by);
2195 hsc->SetBinContent(bx, by, exp(-x*x)*exp(-y*y));
2196 }
2197 }
2198 hsc->Draw("surf2");
2199 hsc->Draw("CONT1 SAME");
2200}
2201End_Macro
2202
2203
2204\anchor HP19
2205### Cylindrical, Polar, Spherical and PseudoRapidity/Phi options
2206
2207
2208Legos and surfaces plots are represented by default in Cartesian coordinates.
2209Combined with any `LEGOn` or `SURFn` options the following
2210options allow to draw a lego or a surface in other coordinates systems.
2211
2212| Option | Description |
2213|----------|-------------------------------------------------------------------|
2214| "CYL" | Use Cylindrical coordinates. The X coordinate is mapped on the angle and the Y coordinate on the cylinder length.|
2215| "POL" | Use Polar coordinates. The X coordinate is mapped on the angle and the Y coordinate on the radius.|
2216| "SPH" | Use Spherical coordinates. The X coordinate is mapped on the latitude and the Y coordinate on the longitude.|
2217| "PSR" | Use PseudoRapidity/Phi coordinates. The X coordinate is mapped on Phi.|
2218
2219
2220
2221<b>WARNING:</b> Axis are not drawn with these options.
2222
2223The following example shows the same histogram as a lego plot is the four
2224different coordinates systems.
2225
2226Begin_Macro(source)
2227{
2228 auto c3 = new TCanvas("c3","c3",600,400);
2229 c3->Divide(2,2);
2230 auto hlcc = new TH2F("hlcc","Cylindrical coordinates",20,-4,4,20,-20,20);
2231 float px, py;
2232 for (Int_t i = 0; i < 25000; i++) {
2233 gRandom->Rannor(px,py);
2234 hlcc->Fill(px-1,5*py);
2235 hlcc->Fill(2+0.5*px,2*py-10.,0.1);
2236 }
2237 hlcc->SetFillColor(kYellow);
2238 c3->cd(1); hlcc->Draw("LEGO1 CYL");
2239 c3->cd(2); auto hlpc = (TH2F*) hlcc->DrawClone("LEGO1 POL");
2240 hlpc->SetTitle("Polar coordinates");
2241 c3->cd(3); auto hlsc = (TH2F*) hlcc->DrawClone("LEGO1 SPH");
2242 hlsc->SetTitle("Spherical coordinates");
2243 c3->cd(4); auto hlprpc = (TH2F*) hlcc->DrawClone("LEGO1 PSR");
2244 hlprpc->SetTitle("PseudoRapidity/Phi coordinates");
2245}
2246End_Macro
2247
2248The following example shows the same histogram as a surface plot is the four different coordinates systems.
2249
2250Begin_Macro(source)
2251{
2252 auto c4 = new TCanvas("c4","c4",600,400);
2253 c4->Divide(2,2);
2254 auto hscc = new TH2F("hscc","Cylindrical coordinates",20,-4,4,20,-20,20);
2255 float px, py;
2256 for (Int_t i = 0; i < 25000; i++) {
2257 gRandom->Rannor(px,py);
2258 hscc->Fill(px-1,5*py);
2259 hscc->Fill(2+0.5*px,2*py-10.,0.1);
2260 }
2261 c4->cd(1); hscc->Draw("SURF1 CYL");
2262 c4->cd(2); auto hspc = (TH2F*) hscc->DrawClone("SURF1 POL");
2263 hspc->SetTitle("Polar coordinates");
2264 c4->cd(3); auto hssc = (TH2F*) hscc->DrawClone("SURF1 SPH");
2265 hssc->SetTitle("Spherical coordinates");
2266 c4->cd(4); auto hsprpc = (TH2F*) hscc->DrawClone("SURF1 PSR");
2267 hsprpc->SetTitle("PseudoRapidity/Phi coordinates");
2268}
2269End_Macro
2270
2271
2272\anchor HP20
2273### Base line for bar-charts and lego plots
2274
2275
2276By default the base line used to draw the boxes for bar-charts and lego plots is
2277the histogram minimum. It is possible to force this base line to be 0, using MIN0 draw
2278option or with the command:
2279
2280 gStyle->SetHistMinimumZero();
2281
2282Begin_Macro(source)
2283{
2284 auto c5 = new TCanvas("c5","c5",700,400);
2285 c5->Divide(2,1);
2286 auto hz1 = new TH1F("hz1","Bar-chart drawn from 0",20,-3,3);
2287 auto hz2 = new TH2F("hz2","Lego plot drawn from 0",20,-3,3,20,-3,3);
2288 Int_t i;
2289 double x,y;
2290 hz1->SetFillColor(kBlue);
2291 hz2->SetFillColor(kBlue);
2292 for (i=0;i<10000;i++) {
2293 x = gRandom->Gaus(0,1);
2294 y = gRandom->Gaus(0,1);
2295 if (x>0) {
2296 hz1->Fill(x,1);
2297 hz2->Fill(x,y,1);
2298 } else {
2299 hz1->Fill(x,-1);
2300 hz2->Fill(x,y,-2);
2301 }
2302 }
2303 c5->cd(1); hz1->Draw("bar2 min0");
2304 c5->cd(2); hz2->Draw("lego1 min0");
2305}
2306End_Macro
2307
2308This option also works for horizontal plots. The example given in the section
2309["The bar chart option"](\ref HP100) appears as follow:
2310
2311Begin_Macro(source)
2312{
2313 int i;
2314 const Int_t nx = 8;
2315 string os_X[nx] = {"8","32","128","512","2048","8192","32768","131072"};
2316 float d_35_0[nx] = {0.75, -3.30, -0.92, 0.10, 0.08, -1.69, -1.29, -2.37};
2317 float d_35_1[nx] = {1.01, -3.02, -0.65, 0.37, 0.34, -1.42, -1.02, -2.10};
2318
2319 auto cbh = new TCanvas("cbh","cbh",400,600);
2320 cbh->SetGrid();
2321
2322 auto h1bh = new TH1F("h1bh","Option HBAR centered on 0",nx,0,nx);
2323 h1bh->SetFillColor(4);
2324 h1bh->SetBarWidth(0.4);
2325 h1bh->SetBarOffset(0.1);
2326 h1bh->SetStats(0);
2327 h1bh->SetMinimum(-5);
2328 h1bh->SetMaximum(5);
2329
2330 for (i=1; i<=nx; i++) {
2331 h1bh->Fill(os_X[i-1].c_str(), d_35_0[i-1]);
2332 h1bh->GetXaxis()->SetBinLabel(i,os_X[i-1].c_str());
2333 }
2334
2335 h1bh->Draw("hbar min0");
2336
2337 auto h2bh = new TH1F("h2bh","h2bh",nx,0,nx);
2338 h2bh->SetFillColor(38);
2339 h2bh->SetBarWidth(0.4);
2340 h2bh->SetBarOffset(0.5);
2341 h2bh->SetStats(0);
2342 for (i=1;i<=nx;i++) h2bh->Fill(os_X[i-1].c_str(), d_35_1[i-1]);
2343
2344 h2bh->Draw("hbar min0 same");
2345}
2346End_Macro
2347
2348
2349\anchor HP20a
2350### TH2Poly Drawing
2351
2352
2353The following options are supported:
2354
2355| Option | Description |
2356|----------|-------------------------------------------------------------------|
2357| "SCAT" | Draw a scatter plot (legacy draw option).|
2358| "COL" | Draw a color plot. All the bins are painted even the empty bins (default).|
2359| "COLZ" | Same as "COL". In addition the color palette is also drawn.|
2360| "0" | When used with any COL options, the empty bins are not drawn.|
2361| "TEXT" | Draw bin contents as text (format set via `gStyle->SetPaintTextFormat`).|
2362| "TEXTN" | Draw bin names as text.|
2363| "TEXTnn" | Draw bin contents as text at angle nn (0 < nn <= 90).|
2364| "L" | Draw the bins boundaries as lines. The lines attributes are the TGraphs ones.|
2365| "P" | Draw the bins boundaries as markers. The markers attributes are the TGraphs ones.|
2366| "F" | Draw the bins boundaries as filled polygons. The filled polygons attributes are the TGraphs ones.|
2367
2368
2369
2370`TH2Poly` can be drawn as a color plot (option COL). `TH2Poly` bins can have any
2371shapes. The bins are defined as graphs. The following macro is a very simple
2372example showing how to book a TH2Poly and draw it.
2373
2374Begin_Macro(source)
2375{
2376 auto ch2p1 = new TCanvas("ch2p1","ch2p1",600,400);
2377 auto h2p = new TH2Poly();
2378 h2p->SetName("h2poly_name");
2379 h2p->SetTitle("h2poly_title");
2380 double px1[] = {0, 5, 6};
2381 double py1[] = {0, 0, 5};
2382 double px2[] = {0, -1, -1, 0};
2383 double py2[] = {0, 0, -1, 3};
2384 double px3[] = {4, 3, 0, 1, 2.4};
2385 double py3[] = {4, 3.7, 1, 3.7, 2.5};
2386 h2p->AddBin(3, px1, py1);
2387 h2p->AddBin(4, px2, py2);
2388 h2p->AddBin(5, px3, py3);
2389 h2p->Fill(0.1, 0.01, 3);
2390 h2p->Fill(-0.5, -0.5, 7);
2391 h2p->Fill(-0.7, -0.5, 1);
2392 h2p->Fill(1, 3, 1.5);
2393 double fx[] = {0.1, -0.5, -0.7, 1};
2394 double fy[] = {0.01, -0.5, -0.5, 3};
2395 double fw[] = {3, 1, 1, 1.5};
2396 h2p->FillN(4, fx, fy, fw);
2397 h2p->Draw("col");
2398}
2399End_Macro
2400
2401Rectangular bins are a frequent case. The special version of
2402the `AddBin` method allows to define them more easily like
2403shown in the following example (hist037_TH2Poly_boxes.C).
2404
2405Begin_Macro(source)
2406../../../tutorials/hist/hist037_TH2Poly_boxes.C
2407End_Macro
2408
2409One `TH2Poly` bin can be a list of polygons. Such bins are defined
2410by calling `AddBin` with a `TMultiGraph`. The following example
2411shows a such case:
2412
2413Begin_Macro(source)
2414{
2415 auto ch2p2 = new TCanvas("ch2p2","ch2p2",600,400);
2416
2417 Int_t i, bin;
2418 const Int_t nx = 48;
2419 const char *states [nx] = {
2420 "alabama", "arizona", "arkansas", "california",
2421 "colorado", "connecticut", "delaware", "florida",
2422 "georgia", "idaho", "illinois", "indiana",
2423 "iowa", "kansas", "kentucky", "louisiana",
2424 "maine", "maryland", "massachusetts", "michigan",
2425 "minnesota", "mississippi", "missouri", "montana",
2426 "nebraska", "nevada", "new_hampshire", "new_jersey",
2427 "new_mexico", "new_york", "north_carolina", "north_dakota",
2428 "ohio", "oklahoma", "oregon", "pennsylvania",
2429 "rhode_island", "south_carolina", "south_dakota", "tennessee",
2430 "texas", "utah", "vermont", "virginia",
2431 "washington", "west_virginia", "wisconsin", "wyoming"
2432 };
2433 Double_t pop[nx] = {
2434 4708708, 6595778, 2889450, 36961664, 5024748, 3518288, 885122, 18537969,
2435 9829211, 1545801, 12910409, 6423113, 3007856, 2818747, 4314113, 4492076,
2436 1318301, 5699478, 6593587, 9969727, 5266214, 2951996, 5987580, 974989,
2437 1796619, 2643085, 1324575, 8707739, 2009671, 19541453, 9380884, 646844,
2438 11542645, 3687050, 3825657, 12604767, 1053209, 4561242, 812383, 6296254,
2439 24782302, 2784572, 621760, 7882590, 6664195, 1819777, 5654774, 544270
2440 };
2441
2442 Double_t lon1 = -130;
2443 Double_t lon2 = -65;
2444 Double_t lat1 = 24;
2445 Double_t lat2 = 50;
2446 auto p = new TH2Poly("USA","USA Population",lon1,lon2,lat1,lat2);
2447
2448 TFile::SetCacheFileDir(".");
2449 auto f = TFile::Open("http://root.cern/files/usa.root", "CACHEREAD");
2450
2451 TMultiGraph *mg;
2452 TKey *key;
2453 TIter nextkey(gDirectory->GetListOfKeys());
2454 while ((key = (TKey*)nextkey())) {
2455 TObject *obj = key->ReadObj();
2456 if (obj->InheritsFrom("TMultiGraph")) {
2457 mg = (TMultiGraph*)obj;
2458 bin = p->AddBin(mg);
2459 }
2460 }
2461
2462 for (i=0; i<nx; i++) p->Fill(states[i], pop[i]);
2463
2464 gStyle->SetOptStat(11);
2465 p->Draw("COLZ L");
2466}
2467End_Macro
2468
2469`TH2Poly` histograms can also be plotted using the GL interface using
2470the option "GLLEGO".
2471
2472\since **ROOT version 6.09/01**
2473
2474In some cases it can be useful to not draw the empty bins. the option "0"
2475combined with the option "COL" and "COLZ" allows to do that.
2476
2477Begin_Macro(source)
2478{
2479 auto chc = new TCanvas("chc","chc",600,400);
2480
2481 auto hc = new TH2Poly();
2482 hc->Honeycomb(0,0,.1,25,25);
2483 hc->SetName("hc");
2484 hc->SetTitle("Option COLZ 0");
2485 TRandom ran;
2486 for (int i = 0; i<300; i++) hc->Fill(ran.Gaus(2.,1), ran.Gaus(2.,1));
2487 hc->Draw("colz 0");
2488}
2489End_Macro
2490
2491\anchor HP21
2492### The SPEC option
2493
2494
2495This option allows to use the `TSpectrum2Painter` tools. See the full
2496documentation in `TSpectrum2Painter::PaintSpectrum`.
2497
2498
2499\anchor HP22
2500### Option "Z" : Adding the color palette on the right side of the pad
2501
2502
2503When this option is specified, a color palette with an axis indicating the value
2504of the corresponding color is drawn on the right side of the picture. In case,
2505not enough space is left, one can increase the size of the right margin by
2506calling `TPad::SetRightMargin()`. The attributes used to display the
2507palette axis values are taken from the Z axis of the object. For example, to
2508set the labels size on the palette axis do:
2509
2510 hist->GetZaxis()->SetLabelSize().
2511
2512<b>WARNING:</b> The palette axis is always drawn vertically.
2513
2514
2515\anchor HP23
2516### Setting the color palette
2517
2518
2519To change the color palette `TStyle::SetPalette` should be used, eg:
2520
2521 gStyle->SetPalette(ncolors,colors);
2522
2523For example the option `COL` draws a 2D histogram with cells
2524represented by a box filled with a color index which is a function
2525of the cell content.
2526If the cell content is N, the color index used will be the color number
2527in `colors[N]`, etc. If the maximum cell content is greater than
2528`ncolors`, all cell contents are scaled to `ncolors`.
2529
2530If ` ncolors <= 0`, a default palette (see below) of 50 colors is
2531defined. This palette is recommended for pads, labels ...
2532
2533`if ncolors == 1 && colors == 0`, then a Pretty Palette with a
2534Spectrum Violet->Red is created with 50 colors. That's the default rain bow
2535palette.
2536
2537Other pre-defined palettes with 255 colors are available when `colors == 0`.
2538The following value of `ncolors` give access to:
2539
2540
2541 if ncolors = 51 and colors=0, a Deep Sea palette is used.
2542 if ncolors = 52 and colors=0, a Grey Scale palette is used.
2543 if ncolors = 53 and colors=0, a Dark Body Radiator palette is used.
2544 if ncolors = 54 and colors=0, a two-color hue palette palette is used.(dark blue through neutral gray to bright
2545yellow) if ncolors = 55 and colors=0, a Rain Bow palette is used. if ncolors = 56 and colors=0, an inverted Dark Body
2546Radiator palette is used.
2547
2548
2549If `ncolors > 0 && colors == 0`, the default palette is used with a maximum of ncolors.
2550
2551The default palette defines:
2552
2553- index 0 to 9 : shades of grey
2554- index 10 to 19 : shades of brown
2555- index 20 to 29 : shades of blue
2556- index 30 to 39 : shades of red
2557- index 40 to 49 : basic colors
2558
2559The color numbers specified in the palette can be viewed by selecting
2560the item `colors` in the `VIEW` menu of the canvas tool bar.
2561The red, green, and blue components of a color can be changed thanks to
2562`TColor::SetRGB()`.
2563
2564\since **ROOT version 6.19/01**
2565
2566As default labels and ticks are drawn by `TGAxis` at equidistant (lin or log)
2567points as controlled by SetNdivisions.
2568If option "CJUST" is given labels and ticks are justified at the
2569color boundaries defined by the contour levels.
2570For more details see `TPaletteAxis`
2571
2572\anchor HP24
2573### Drawing a sub-range of a 2D histogram; the [cutg] option
2574
2575
2576Using a `TCutG` object, it is possible to draw a sub-range of a 2D
2577histogram. One must create a graphical cut (mouse or C++) and specify the name
2578of the cut between `[]` in the `Draw()` option.
2579For example (fit2a.C), with a `TCutG` named `cutg`, one can call:
2580
2581 myhist->Draw("surf1 [cutg]");
2582
2583To invert the cut, it is enough to put a `-` in front of its name:
2584
2585 myhist->Draw("surf1 [-cutg]");
2586
2587It is possible to apply several cuts (`,` means logical AND):
2588
2589 myhist->Draw("surf1 [cutg1,cutg2]");
2590
2591Begin_Macro(source)
2592../../../tutorials/fit/fit2a.C
2593End_Macro
2594
2595\anchor HP25
2596### Drawing options for 3D histograms
2597
2598
2599| Option | Description |
2600|----------|-------------------------------------------------------------------|
2601| "SCAT" | Draw a scatter plot (legacy draw option).|
2602| "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)`|
2603| "BOX" | Draw a for each cell with volume proportional to the content's absolute value. An hidden line removal algorithm is used|
2604| "BOX1" | Same as BOX but an hidden surface removal algorithm is used|
2605| "BOX2" | Same as "COL". The boxes' colors are picked in the current palette according to the bins' contents (default)|
2606| "BOX2Z" | Same as "BOX2". In addition the color palette is also drawn.|
2607| "BOX3" | Same as BOX1, but the border lines of each lego-bar are not drawn.|
2608
2609Note that instead of `BOX` one can also use `LEGO`.
2610
2611By default, 3D histograms are drawn as a colored box plots.
2612
2613The following example shows a 3D histogram plotted as a scatter plot.
2614
2615Begin_Macro(source)
2616{
2617 auto c06 = new TCanvas("c06","c06",600,400);
2618 gStyle->SetOptStat(kFALSE);
2619 auto h3scat = new TH3F("h3scat","Option SCAT",15,-2,2,15,-2,2,15,0,4);
2620 double x, y, z;
2621 for (Int_t i=0;i<10000;i++) {
2622 gRandom->Rannor(x, y);
2623 z = x*x + y*y;
2624 h3scat->Fill(x,y,z);
2625 }
2626 h3scat->Draw("SCAT"); // This a legacy draw option
2627}
2628End_Macro
2629
2630The following example shows a 3D histogram plotted with the option `BOX`.
2631
2632Begin_Macro(source)
2633{
2634 auto c16 = new TCanvas("c16","c16",600,400);
2635 gStyle->SetOptStat(kFALSE);
2636 auto h3box = new TH3F("h3box","Option BOX",15,-2,2,15,-2,2,15,0,4);
2637 double x, y, z;
2638 for (Int_t i=0;i<10000;i++) {
2639 gRandom->Rannor(x, y);
2640 z = x*x + y*y;
2641 h3box->Fill(x,y,z);
2642 }
2643 h3box->Draw("BOX");
2644}
2645End_Macro
2646
2647The following example shows a 3D histogram plotted with the option `BOX1`.
2648
2649Begin_Macro(source)
2650{
2651 auto c36 = new TCanvas("c36","c36",600,400);
2652 gStyle->SetOptStat(kFALSE);
2653 auto h3box = new TH3F("h3box","Option BOX1",10,-2.,2.,10,-2.,2.,10,-0.5,2.);
2654 double x, y, z;
2655 for (Int_t i=0;i<10000;i++) {
2656 gRandom->Rannor(x, y);
2657 z = abs(sin(x)/x + cos(y)*y);
2658 h3box->Fill(x,y,z);
2659 }
2660 h3box->SetFillColor(9);
2661 h3box->Draw("BOX1");
2662}
2663End_Macro
2664
2665The following example shows a 3D histogram plotted with the option `BOX2`.
2666
2667Begin_Macro(source)
2668{
2669 auto c56 = new TCanvas("c56","c56",600,400);
2670 gStyle->SetOptStat(kFALSE);
2671 auto h3box = new TH3F("h3box","Option BOX2 (default)",10,-2.,2.,10,-2.,2.,10,-0.5,2.);
2672 double x, y, z;
2673 for (Int_t i=0;i<10000;i++) {
2674 gRandom->Rannor(x, y);
2675 z = abs(sin(x)/x + cos(y)*y);
2676 h3box->Fill(x,y,z);
2677 }
2678 h3box->Draw("BOX2 Z");
2679}
2680End_Macro
2681
2682The following example shows a 3D histogram plotted with the option `BOX3`.
2683
2684Begin_Macro(source)
2685{
2686 auto c46 = new TCanvas("c46","c46",600,400);
2687 c46->SetFillColor(38);
2688 gStyle->SetOptStat(kFALSE);
2689 auto h3box = new TH3F("h3box","Option BOX3",15,-2,2,15,-2,2,15,0,4);
2690 double x, y, z;
2691 for (Int_t i=0;i<10000;i++) {
2692 gRandom->Rannor(x, y);
2693 z = x*x + y*y;
2694 h3box->Fill(x,y,z);
2695 }
2696 h3box->Draw("BOX3");
2697}
2698End_Macro
2699
2700For all the `BOX` options each bin is drawn as a 3D box with a volume proportional
2701to the absolute value of the bin content. The bins with a negative content are
2702drawn with a X on each face of the box as shown in the following example:
2703
2704Begin_Macro(source)
2705{
2706 auto c = new TCanvas("c","c",600,400);
2707 gStyle->SetOptStat(kFALSE);
2708 auto h3box = new TH3F("h3box","Option BOX1 with negative bins",3, 0., 4., 3, 0.,4., 3, 0., 4.);
2709 h3box->Fill(0., 2., 2., 10.);
2710 h3box->Fill(2., 2., 2., 5.);
2711 h3box->Fill(2., 2., .5, 2.);
2712 h3box->Fill(2., 2., 3., -1.);
2713 h3box->Fill(3., 2., 2., -10.);
2714 h3box->SetFillColor(8);
2715 h3box->Draw("box1");
2716}
2717End_Macro
2718
2719The following example shows a 3D histogram plotted with the option `ISO`.
2720
2721Begin_Macro(source)
2722{
2723 auto c26 = new TCanvas("c26","c26",600,400);
2724 gStyle->SetOptStat(kFALSE);
2725 auto h3iso = new TH3F("h3iso","Option ISO",15,-2,2,15,-2,2,15,0,4);
2726 double x, y, z;
2727 for (Int_t i=0;i<10000;i++) {
2728 gRandom->Rannor(x, y);
2729 z = x*x + y*y;
2730 h3iso->Fill(x,y,z);
2731 }
2732 h3iso->SetFillColor(kCyan);
2733 h3iso->Draw("ISO");
2734}
2735End_Macro
2736
2737
2738\anchor HP26
2739### Drawing option for histograms' stacks
2740
2741
2742Stacks of histograms are managed with the `THStack`. A `THStack`
2743is a collection of `TH1` (or derived) objects. For painting only the
2744`THStack` containing `TH1` only or
2745`THStack` containing `TH2` only will be considered.
2746
2747By default, histograms are shown stacked:
2748
27491. The first histogram is paint.
27502. The sum of the first and second, etc...
2751
2752If the option `NOSTACK` is specified, the histograms are all paint in
2753the same pad as if the option `SAME` had been specified. This allows to
2754compute X and Y scales common to all the histograms, like
2755`TMultiGraph` does for graphs.
2756
2757If the option `PADS` is specified, the current pad/canvas is subdivided into
2758a number of pads equal to the number of histograms and each histogram is paint
2759into a separate pad. With `PADSn`, the current pad/canvas is subdivided into
2760`n` columns, automatically calculating the number of rows.
2761
2762The following example shows various types of stacks (hist023_THStack_simple.C).
2763
2764Begin_Macro(source)
2765../../../tutorials/hist/hist023_THStack_simple.C
2766End_Macro
2767
2768The option `nostackb` allows to draw the histograms next to each
2769other as bar charts:
2770
2771Begin_Macro(source)
2772{
2773 auto cst0 = new TCanvas("cst0","cst0",600,400);
2774 auto hs = new THStack("hs","Stacked 1D histograms: option #font[82]{\"nostackb\"}");
2775
2776 auto h1 = new TH1F("h1","h1",10,-4,4);
2777 h1->FillRandom("gaus",20000);
2778 h1->SetFillColor(kRed);
2779 hs->Add(h1);
2780
2781 auto h2 = new TH1F("h2","h2",10,-4,4);
2782 h2->FillRandom("gaus",15000);
2783 h2->SetFillColor(kBlue);
2784 hs->Add(h2);
2785
2786 auto h3 = new TH1F("h3","h3",10,-4,4);
2787 h3->FillRandom("gaus",10000);
2788 h3->SetFillColor(kGreen);
2789 hs->Add(h3);
2790
2791 hs->Draw("nostackb");
2792 hs->GetXaxis()->SetNdivisions(-10);
2793 cst0->SetGridx();
2794}
2795End_Macro
2796
2797If at least one of the histograms in the stack has errors, the whole stack is
2798visualized by default with error bars. To visualize it without errors the
2799option `HIST` should be used.
2800
2801Begin_Macro(source)
2802{
2803 auto cst1 = new TCanvas("cst1","cst1",700,400);
2804 cst1->Divide(2,1);
2805
2806 auto hst11 = new TH1F("hst11", "", 20, -10, 10);
2807 hst11->Sumw2();
2808 hst11->FillRandom("gaus", 1000);
2809 hst11->SetFillColor(kViolet);
2810 hst11->SetLineColor(kViolet);
2811
2812 auto hst12 = new TH1F("hst12", "", 20, -10, 10);
2813 hst12->FillRandom("gaus", 500);
2814 hst12->SetFillColor(kBlue);
2815 hst12->SetLineColor(kBlue);
2816
2817 THStack st1("st1", "st1");
2818 st1.Add(hst11);
2819 st1.Add(hst12);
2820
2821 cst1->cd(1); st1.Draw();
2822 cst1->cd(2); st1.Draw("hist");
2823}
2824End_Macro
2825
2826\anchor HP27
2827### Drawing of 3D implicit functions
2828
2829
28303D implicit functions (`TF3`) can be drawn as iso-surfaces.
2831The implicit function f(x,y,z) = 0 is drawn in cartesian coordinates.
2832In the following example the options "FB" and "BB" suppress the
2833"Front Box" and "Back Box" around the plot.
2834
2835Begin_Macro(source)
2836{
2837 auto c2 = new TCanvas("c2","c2",600,400);
2838 auto f3 = new TF3("f3","sin(x*x+y*y+z*z-36)",-2,2,-2,2,-2,2);
2839 f3->SetClippingBoxOn(0,0,0);
2840 f3->SetFillColor(30);
2841 f3->SetLineColor(15);
2842 f3->Draw("FBBB");
2843}
2844End_Macro
2845
2846
2847\anchor HP28
2848### Associated functions drawing
2849
2850
2851An associated function is created by `TH1::Fit`. More than on fitted
2852function can be associated with one histogram (see `TH1::Fit`).
2853
2854A `TF1` object `f1` can be added to the list of associated
2855functions of an histogram `h` without calling `TH1::Fit`
2856simply doing:
2857
2858 h->GetListOfFunctions()->Add(f1);
2859
2860or
2861
2862 h->GetListOfFunctions()->Add(f1,someoption);
2863
2864To retrieve a function by name from this list, do:
2865
2866 TF1 *f1 = (TF1*)h->GetListOfFunctions()->FindObject(name);
2867
2868or
2869
2870 TF1 *f1 = h->GetFunction(name);
2871
2872Associated functions are automatically painted when an histogram is drawn.
2873To avoid the painting of the associated functions the option `HIST`
2874should be added to the list of the options used to paint the histogram.
2875
2876
2877\anchor HP29
2878### Drawing using OpenGL
2879
2880
2881The class `TGLHistPainter` allows to paint data set using the OpenGL 3D
2882graphics library. The plotting options start with `GL` keyword.
2883In addition, in order to inform canvases that OpenGL should be used to render
28843D representations, the following option should be set:
2885
2886 gStyle->SetCanvasPreferGL(true);
2887
2888
2889\anchor HP29a
2890#### General information: plot types and supported options
2891
2892The following types of plots are provided:
2893
2894For lego plots the supported options are:
2895
2896| Option | Description |
2897|----------|-------------------------------------------------------------------|
2898| "GLLEGO" | Draw a lego plot. It works also for `TH2Poly`.|
2899| "GLLEGO2"| Bins with color levels.|
2900| "GLLEGO3"| Cylindrical bars.|
2901
2902
2903
2904Lego painter in cartesian supports logarithmic scales for X, Y, Z.
2905In polar only Z axis can be logarithmic, in cylindrical only Y.
2906
2907For surface plots (`TF2` and `TH2`) the supported options are:
2908
2909| Option | Description |
2910|-----------|------------------------------------------------------------------|
2911| "GLSURF" | Draw a surface.|
2912| "GLSURF1" | Surface with color levels|
2913| "GLSURF2" | The same as "GLSURF1" but without polygon outlines.|
2914| "GLSURF3" | Color level projection on top of plot (works only in cartesian coordinate system).|
2915| "GLSURF4" | Same as "GLSURF" but without polygon outlines.|
2916
2917
2918
2919The surface painting in cartesian coordinates supports logarithmic scales along
2920X, Y, Z axis. In polar coordinates only the Z axis can be logarithmic,
2921in cylindrical coordinates only the Y axis.
2922
2923Additional options to SURF and LEGO - Coordinate systems:
2924
2925| Option | Description |
2926|----------|-------------------------------------------------------------------|
2927| " " | Default, cartesian coordinates system.|
2928| "POL" | Polar coordinates system.|
2929| "CYL" | Cylindrical coordinates system.|
2930| "SPH" | Spherical coordinates system.|
2931
2932
2933
2934\anchor HP290
2935#### TH3 as color boxes
2936
2937The supported option is:
2938
2939| Option | Description |
2940|----------|-------------------------------------------------------------------|
2941| "GLCOL" | H3 is drawn using semi-transparent colored boxes. See glvox1.C .|
2942
2943
2944
2945\anchor HP29b
2946#### TH3 as boxes (spheres)
2947
2948The supported options are:
2949
2950| Option | Description |
2951|----------|-------------------------------------------------------------------|
2952| "GLBOX" | TH3 as a set of boxes, size of box is proportional to bin content.|
2953| "GLBOX1" | The same as "glbox", but spheres are drawn instead of boxes.|
2954
2955
2956
2957\anchor HP29c
2958#### TH3 as iso-surface(s)
2959
2960The supported option is:
2961
2962| Option | Description |
2963|----------|-------------------------------------------------------------------|
2964| "GLISO" | TH3 is drawn using iso-surfaces.|
2965
2966
2967
2968\anchor HP29d
2969#### TF3 (implicit function)
2970
2971The supported option is:
2972
2973| Option | Description |
2974|----------|-------------------------------------------------------------------|
2975| "GL" | Draw a TF3.|
2976
2977
2978
2979\anchor HP29e
2980#### Parametric surfaces
2981
2982glparametric.C shows how to create parametric equations and visualize the surface.
2983
2984\anchor HP29f
2985#### Interaction with the plots
2986
2987All the interactions are implemented via standard methods
2988`DistancetoPrimitive()` and `ExecuteEvent()`. That's why all the
2989interactions with the OpenGL plots are possible only when the mouse cursor is
2990in the plot's area (the plot's area is the part of a the pad occupied by
2991gl-produced picture). If the mouse cursor is not above gl-picture, the standard
2992pad interaction is performed.
2993
2994\anchor HP29g
2995#### Selectable parts
2996
2997Different parts of the plot can be selected:
2998
2999- xoz, yoz, xoy back planes: When such a plane selected, it's highlighted in green
3000 if the dynamic slicing by this plane is supported, and it's highlighted in red,
3001 if the dynamic slicing is not supported.
3002- The plot itself:
3003 On surfaces, the selected surface is outlined in red. (TF3 and
3004 ISO are not outlined). On lego plots, the selected bin is
3005 highlighted. The bin number and content are displayed in pad's
3006 status bar. In box plots, the box or sphere is highlighted and
3007 the bin info is displayed in pad's status bar.
3008
3009
3010\anchor HP29h
3011#### Rotation and zooming
3012
3013
3014- Rotation:
3015 When the plot is selected, it can be rotated by pressing and
3016 holding the left mouse button and move the cursor.
3017- Zoom/Unzoom:
3018 Mouse wheel or 'j', 'J', 'k', 'K' keys.
3019
3020
3021\anchor HP29i
3022#### Panning
3023
3024The selected plot can be moved in a pad's area by pressing and
3025holding the left mouse button and the shift key.
3026
3027\anchor HP29j
3028#### Box cut
3029
3030Surface, iso, box, TF3 and parametric painters support box cut by
3031pressing the 'c' or 'C' key when the mouse cursor is in a plot's
3032area. That will display a transparent box, cutting away part of the
3033surface (or boxes) in order to show internal part of plot. This box
3034can be moved inside the plot's area (the full size of the box is
3035equal to the plot's surrounding box) by selecting one of the box
3036cut axes and pressing the left mouse button to move it.
3037
3038\anchor HP29k
3039#### Plot specific interactions (dynamic slicing etc.)
3040
3041Currently, all gl-plots support some form of slicing. When back plane
3042is selected (and if it's highlighted in green) you can press and hold
3043left mouse button and shift key and move this back plane inside
3044plot's area, creating the slice. During this "slicing" plot becomes
3045semi-transparent. To remove all slices (and projected curves for
3046surfaces) double click with left mouse button in a plot's area.
3047
3048\anchor HP29l
3049#### Surface with option "GLSURF"
3050
3051The surface profile is displayed on the slicing plane.
3052The profile projection is drawn on the back plane
3053by pressing `'p'` or `'P'` key.
3054
3055\anchor HP29m
3056#### TF3
3057
3058The contour plot is drawn on the slicing plane. For TF3 the color
3059scheme can be changed by pressing 's' or 'S'.
3060
3061\anchor HP29n
3062#### Box
3063
3064The contour plot corresponding to slice plane position is drawn in real time.
3065
3066\anchor HP29o
3067#### Iso
3068
3069Slicing is similar to "GLBOX" option.
3070
3071\anchor HP29p
3072#### Parametric plot
3073
3074No slicing. Additional keys: 's' or 'S' to change color scheme -
3075about 20 color schemes supported ('s' for "scheme"); 'l' or 'L' to
3076increase number of polygons ('l' for "level" of details), 'w' or 'W'
3077to show outlines ('w' for "wireframe").
3078
3079\anchor HP30
3080#### Highlight mode for histogram
3081
3082\since **ROOT version 6.15/01**
3083
3084\image html hlHisto3_top.gif "Highlight mode"
3085
3086Highlight mode is implemented for `TH1` (and for `TGraph`) class. When
3087highlight mode is on, mouse movement over the bin will be represented
3088graphically. Bin will be highlighted as "bin box" (presented by box
3089object). Moreover, any highlight (change of bin) emits signal
3090`TCanvas::Highlighted()` which allows the user to react and call their own
3091function. For a better understanding see also the tutorial `hist043` to `hist046`
3092located in `$ROOTSYS/tutorials/hist/`.
3093
3094Highlight mode is switched on/off by `TH1::SetHighlight()` function
3095or interactively from `TH1` context menu. `TH1::IsHighlight()` to verify
3096whether the highlight mode enabled or disabled, default it is disabled.
3097
3098~~~ {.cpp}
3099 root [0] .x $ROOTSYS/tutorials/hsimple.C
3100 root [1] hpx->SetHighlight(kTRUE) // or interactively from TH1 context menu
3101 root [2] hpx->IsHighlight()
3102 (bool) true
3103~~~
3104
3105\image html hlsimple_nofun.gif "Highlight mode for histogram"
3106
3107\anchor HP30a
3108#### Highlight mode and user function
3109
3110The user can use (connect) `TCanvas::Highlighted()` signal, which is always
3111emitted if there is a highlight bin and call user function via signal
3112and slot communication mechanism. `TCanvas::Highlighted()` is similar
3113`TCanvas::Picked()`
3114
3115- when selected object (histogram as a whole) is different from previous
3116then emit `Picked()` signal
3117- when selected (highlighted) bin from histogram is different from previous
3118then emit `Highlighted()` signal
3119
3120Any user function (or functions) has to be defined
3121`UserFunction(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)`.
3122In example (see below) has name `PrintInfo()`. All parameters of user
3123function are taken from
3124
3125 void TCanvas::Highlighted(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)
3126
3127- `pad` is pointer to pad with highlighted histogram
3128- `obj` is pointer to highlighted histogram
3129- `x` is highlighted x bin for 1D histogram
3130- `y` is highlighted y bin for 2D histogram (for 1D histogram not in use)
3131
3132Example how to create a connection from any `TCanvas` object to a user
3133`UserFunction()` slot (see also `TQObject::Connect()` for additional info)
3134
3135 TQObject::Connect("TCanvas", "Highlighted(TVirtualPad*,TObject*,Int_t,Int_t)",
3136 0, 0, "UserFunction(TVirtualPad*,TObject*,Int_t,Int_t)");
3137
3138or use non-static "simplified" function
3139`TCanvas::HighlightConnect(const char *slot)`
3140
3141 c1->HighlightConnect("UserFunction(TVirtualPad*,TObject*,Int_t,Int_t)");
3142
3143NOTE the signal and slot string must have a form
3144"(TVirtualPad*,TObject*,Int_t,Int_t)"
3145
3146 root [0] .x $ROOTSYS/tutorials/hsimple.C
3147 root [1] hpx->SetHighlight(kTRUE)
3148 root [2] .x hlprint.C
3149
3150file `hlprint.C`
3151~~~ {.cpp}
3152void PrintInfo(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)
3153{
3154 auto h = (TH1F *)obj;
3155 if (!h->IsHighlight()) // after highlight disabled
3156 h->SetTitle("highlight disable");
3157 else
3158 h->SetTitle(TString::Format("bin[%03d] (%5.2f) content %g", x,
3159 h->GetBinCenter(x), h->GetBinContent(x)));
3160 pad->Update();
3161}
3162
3163void hlprint()
3164{
3165 if (!gPad) return;
3166 gPad->GetCanvas()->HighlightConnect("PrintInfo(TVirtualPad*,TObject*,Int_t,Int_t)");
3167}
3168~~~
3169
3170\image html hlsimple.gif "Highlight mode and simple user function"
3171
3172For more complex demo please see for example tree200_temperature.C file.
3173
3174*/
3175
3177
3180
3181const Int_t kNMAX = 2000;
3182
3183const Int_t kMAXCONTOUR = 104;
3185
3186static std::unique_ptr<TBox> gXHighlightBox, gYHighlightBox; // highlight X and Y box
3187
3209
3210
3211////////////////////////////////////////////////////////////////////////////////
3212/// Default constructor.
3213
3215{
3216 fH = nullptr;
3217 fXaxis = nullptr;
3218 fYaxis = nullptr;
3219 fZaxis = nullptr;
3220 fFunctions = nullptr;
3221 fNcuts = 0;
3222 fStack = nullptr;
3223 fShowProjection = 0;
3224 fShowProjection2 = 0;
3225 fShowOption = "";
3226 for (int i=0; i<kMaxCuts; i++) {
3227 fCuts[i] = nullptr;
3228 fCutsOpt[i] = 0;
3229 }
3230 fXHighlightBin = -1;
3231 fYHighlightBin = -1;
3232 fCurrentF3 = nullptr;
3233
3234 gStringEntries = gEnv->GetValue("Hist.Stats.Entries", "Entries");
3235 gStringMean = gEnv->GetValue("Hist.Stats.Mean", "Mean");
3236 gStringMeanX = gEnv->GetValue("Hist.Stats.MeanX", "Mean x");
3237 gStringMeanY = gEnv->GetValue("Hist.Stats.MeanY", "Mean y");
3238 gStringMeanZ = gEnv->GetValue("Hist.Stats.MeanZ", "Mean z");
3239 gStringStdDev = gEnv->GetValue("Hist.Stats.StdDev", "Std Dev");
3240 gStringStdDevX = gEnv->GetValue("Hist.Stats.StdDevX", "Std Dev x");
3241 gStringStdDevY = gEnv->GetValue("Hist.Stats.StdDevY", "Std Dev y");
3242 gStringStdDevZ = gEnv->GetValue("Hist.Stats.StdDevZ", "Std Dev z");
3243 gStringUnderflow = gEnv->GetValue("Hist.Stats.Underflow", "Underflow");
3244 gStringOverflow = gEnv->GetValue("Hist.Stats.Overflow", "Overflow");
3245 gStringIntegral = gEnv->GetValue("Hist.Stats.Integral", "Integral");
3246 gStringIntegralBinWidth = gEnv->GetValue("Hist.Stats.IntegralBinWidth", "Integral(w)");
3247 gStringSkewness = gEnv->GetValue("Hist.Stats.Skewness", "Skewness");
3248 gStringSkewnessX = gEnv->GetValue("Hist.Stats.SkewnessX", "Skewness x");
3249 gStringSkewnessY = gEnv->GetValue("Hist.Stats.SkewnessY", "Skewness y");
3250 gStringSkewnessZ = gEnv->GetValue("Hist.Stats.SkewnessZ", "Skewness z");
3251 gStringKurtosis = gEnv->GetValue("Hist.Stats.Kurtosis", "Kurtosis");
3252 gStringKurtosisX = gEnv->GetValue("Hist.Stats.KurtosisX", "Kurtosis x");
3253 gStringKurtosisY = gEnv->GetValue("Hist.Stats.KurtosisY", "Kurtosis y");
3254 gStringKurtosisZ = gEnv->GetValue("Hist.Stats.KurtosisZ", "Kurtosis z");
3255}
3256
3257////////////////////////////////////////////////////////////////////////////////
3258/// destructor.
3259
3263
3264////////////////////////////////////////////////////////////////////////////////
3265/// Compute the distance from the point px,py to a line.
3266///
3267/// Compute the closest distance of approach from point px,py to elements of
3268/// an histogram. The distance is computed in pixels units.
3269///
3270/// Algorithm: Currently, this simple model computes the distance from the mouse
3271/// to the histogram contour only.
3272
3274{
3275
3276 Double_t defaultLabelSize = 0.04; // See TAttAxis.h for source of this value
3277
3278 const Int_t big = 9999;
3279 const Int_t kMaxDiff = 7;
3280
3281 if (fPie)
3282 return fPie->DistancetoPrimitive(px, py);
3283
3284 Double_t x = gPad->AbsPixeltoX(px);
3285 Double_t x1 = gPad->AbsPixeltoX(px+1);
3286
3287 Int_t puxmin = gPad->XtoAbsPixel(gPad->GetUxmin());
3288 Int_t puymin = gPad->YtoAbsPixel(gPad->GetUymin());
3289 Int_t puxmax = gPad->XtoAbsPixel(gPad->GetUxmax());
3290 Int_t puymax = gPad->YtoAbsPixel(gPad->GetUymax());
3291 Int_t curdist = big;
3293 Bool_t dsame;
3294 TObject *PadPointer = gPad->GetPadPointer();
3295 if (!PadPointer) return 0;
3296 TString doption = PadPointer->GetDrawOption();
3297 Double_t factor = 1;
3298 if (fH->GetNormFactor() != 0) {
3299 factor = fH->GetNormFactor()/fH->GetSumOfWeights();
3300 }
3301 // return if point is not in the histogram area
3302
3303 // If a 3D view exists, check distance to axis
3304 TView *view = gPad->GetView();
3305 Int_t d1,d2,d3;
3306 if (view && Hoption.Contour != 14) {
3307 Double_t ratio;
3308 d3 = view->GetDistancetoAxis(3, px, py, ratio);
3309 if (d3 <= kMaxDiff) {gPad->SetSelected(fZaxis); return 0;}
3310 d1 = view->GetDistancetoAxis(1, px, py, ratio);
3311 if (d1 <= kMaxDiff) {gPad->SetSelected(fXaxis); return 0;}
3312 d2 = view->GetDistancetoAxis(2, px, py, ratio);
3313 if (d2 <= kMaxDiff) {gPad->SetSelected(fYaxis); return 0;}
3314 if ( px > puxmin && px < puxmax && py > puymax && py < puymin) curdist = 1;
3315 goto FUNCTIONS;
3316 }
3317 // check if point is close to an axis
3318 doption.ToLower();
3319 dsame = kFALSE;
3320 if (doption.Contains("same")) dsame = kTRUE;
3321
3323 if (doption.Contains("y+")) {
3325 if (px <= xyaxis+dyaxis && px >= xyaxis && py >puymax && py < puymin) {
3326 if (!dsame) {
3327 if (gPad->IsVertical()) gPad->SetSelected(fYaxis);
3328 else gPad->SetSelected(fXaxis);
3329 return 0;
3330 }
3331 }
3332 } else {
3334 if (px >= xyaxis-dyaxis && px <= xyaxis && py >puymax && py < puymin) {
3335 if (!dsame) {
3336 if (gPad->IsVertical()) gPad->SetSelected(fYaxis);
3337 else gPad->SetSelected(fXaxis);
3338 return 0;
3339 }
3340 }
3341 }
3342
3344 if (doption.Contains("x+")) {
3346 if (py >= yxaxis-dxaxis && py <= yxaxis && px <puxmax && px > puxmin) {
3347 if (!dsame) {
3348 if (gPad->IsVertical()) gPad->SetSelected(fXaxis);
3349 else gPad->SetSelected(fYaxis);
3350 return 0;
3351 }
3352 }
3353 } else {
3355 if (yxaxis < puymin) yxaxis = puymin;
3357 if (!dsame) {
3358 if (gPad->IsVertical()) gPad->SetSelected(fXaxis);
3359 else gPad->SetSelected(fYaxis);
3360 return 0;
3361 }
3362 }
3363 }
3364
3365 if (fH->IsHighlight()) { // only if highlight is enable
3366 if ((px > puxmin) && (py < puymin) && (px < puxmax) && (py > puymax))
3367 HighlightBin(px, py);
3368 }
3369
3370 // if object is 2D or 3D return this object
3371 if (fH->GetDimension() == 2) {
3372 if (fH->InheritsFrom(TH2Poly::Class())) {
3373 TH2Poly *th2 = (TH2Poly*)fH;
3375 gPad->GetRangeAxis(xmin, ymin, xmax, ymax);
3376 Double_t pxu = gPad->AbsPixeltoX(px);
3377 Double_t pyu = gPad->AbsPixeltoY(py);
3378 if ((pxu>xmax) || (pxu < xmin) || (pyu>ymax) || (pyu < ymin)) {
3379 curdist = big;
3380 goto FUNCTIONS;
3381 } else {
3382 Int_t bin = th2->FindBin(pxu, pyu);
3383 if (bin>0) curdist = 1;
3384 else curdist = big;
3385 goto FUNCTIONS;
3386 }
3387 }
3388 Int_t delta2 = 5; //Give a margin of delta2 pixels to be in the 2-d area
3389 if ( px > puxmin + delta2
3390 && px < puxmax - delta2
3391 && py > puymax + delta2
3392 && py < puymin - delta2) {curdist =1; goto FUNCTIONS;}
3393 }
3394
3395 // point is inside histogram area. Find channel number
3396 if (gPad->IsVertical()) {
3397 Int_t bin = fXaxis->FindFixBin(gPad->PadtoX(x));
3398 Int_t binsup = fXaxis->FindFixBin(gPad->PadtoX(x1));
3399 Double_t binval = factor*fH->GetBinContent(bin);
3400 Int_t pybin = gPad->YtoAbsPixel(gPad->YtoPad(binval));
3401 if (binval == 0 && pybin < puymin) pybin = 10000;
3402 // special case if more than one bin for the pixel
3403 if (binsup-bin>1) {
3407 for (Int_t ibin=bin+1; ibin<binsup; ibin++) {
3411 }
3412 Int_t pybinmin = gPad->YtoAbsPixel(gPad->YtoPad(binvalmax));
3413 Int_t pybinmax = gPad->YtoAbsPixel(gPad->YtoPad(binvalmin));
3415 }
3416 if (bin != binsup) { // Mouse on bin border
3418 Int_t pybinsub = gPad->YtoAbsPixel(gPad->YtoPad(binsupval));
3419 if (py <= TMath::Max(pybinsub,pybin) && py >= TMath::Min(pybinsub,pybin) && pybin != 10000) return 0;
3420 }
3421 if (TMath::Abs(py - pybin) <= kMaxDiff) return TMath::Abs(py - pybin);
3422 } else {
3423 Double_t y = gPad->AbsPixeltoY(py);
3424 Double_t y1 = gPad->AbsPixeltoY(py+1);
3425 Int_t bin = fXaxis->FindFixBin(gPad->PadtoY(y));
3426 Int_t binsup = fXaxis->FindFixBin(gPad->PadtoY(y1));
3427 Double_t binval = factor*fH->GetBinContent(bin);
3428 Int_t pxbin = gPad->XtoAbsPixel(gPad->XtoPad(binval));
3429 if (binval == 0 && pxbin > puxmin) pxbin = 10000;
3430 // special case if more than one bin for the pixel
3431 if (binsup-bin>1) {
3435 for (Int_t ibin=bin+1; ibin<binsup; ibin++) {
3439 }
3440 Int_t pxbinmin = gPad->XtoAbsPixel(gPad->XtoPad(binvalmax));
3441 Int_t pxbinmax = gPad->XtoAbsPixel(gPad->XtoPad(binvalmin));
3443 }
3444 if (TMath::Abs(px - pxbin) <= kMaxDiff) return TMath::Abs(px - pxbin);
3445 }
3446 // Loop on the list of associated functions and user objects
3447FUNCTIONS:
3448 TObject *f;
3449 TIter next(fFunctions);
3450 while ((f = (TObject*) next())) {
3451 Int_t dist;
3452 if (f->InheritsFrom(TF1::Class())) dist = f->DistancetoPrimitive(-px,py);
3453 else dist = f->DistancetoPrimitive(px,py);
3454 if (dist < kMaxDiff) {gPad->SetSelected(f); return dist;}
3455 }
3456 return curdist;
3457}
3458
3459////////////////////////////////////////////////////////////////////////////////
3460/// Display a panel with all histogram drawing options.
3461
3463{
3464
3465 gCurrentHist = fH;
3466 if (!gPad) {
3467 Error("DrawPanel", "need to draw histogram first");
3468 return;
3469 }
3471 editor->Show();
3472 gROOT->ProcessLine(TString::Format("((TCanvas*)0x%zx)->Selected((TVirtualPad*)0x%zx,(TObject*)0x%zx,1)",
3473 (size_t)gPad->GetCanvas(), (size_t)gPad, (size_t)fH).Data());
3474}
3475
3476////////////////////////////////////////////////////////////////////////////////
3477/// Execute the actions corresponding to `event`.
3478///
3479/// This function is called when a histogram is clicked with the locator at
3480/// the pixel position px,py.
3481
3483{
3484
3485 if (!gPad) return;
3486
3487 static Int_t bin, px1, py1, px2, py2, pyold;
3488 static std::unique_ptr<TBox> zoombox;
3490
3491 Int_t bin1, bin2;
3492 Double_t xlow, xup, ylow, binval, x, baroffset, barwidth, binwidth;
3493 Bool_t opaque = gPad->OpaqueMoving();
3494
3495 if (!gPad->IsEditable()) return;
3496
3497 if (fPie) {
3498 fPie->ExecuteEvent(event, px, py);
3499 return;
3500 }
3501 // come here if we have a lego/surface in the pad
3502 TView *view = gPad->GetView();
3503
3504 if (!fShowProjection && view && !view->TestBit(kCannotRotate)) {
3505 view->ExecuteRotateView(event, px, py);
3506 return;
3507 }
3508
3509 TAxis *xaxis = fH->GetXaxis();
3510 TAxis *yaxis = fH->GetYaxis();
3511 Int_t dimension = fH->GetDimension();
3512
3513 // In case of option SAME the axis must be the ones of the first drawn histogram
3514 TString IsSame = fH->GetDrawOption();
3515 IsSame.ToLower();
3516 if (IsSame.Index("same")>=0) {
3517 TH1 *h1;
3518 TIter next(gPad->GetListOfPrimitives());
3519 while ((h1 = (TH1 *)next())) {
3520 if (!h1->InheritsFrom(TH1::Class())) continue;
3521 xaxis = h1->GetXaxis();
3522 yaxis = h1->GetYaxis();
3523 break;
3524 }
3525 }
3526
3527 Double_t factor = 1;
3528 if (fH->GetNormFactor() != 0) {
3529 factor = fH->GetNormFactor()/fH->GetSumOfWeights();
3530 }
3531
3532 switch (event) {
3533
3534 case kButton1Down:
3535
3536 if (!opaque) gVirtualX->SetLineColor(-1);
3537 fH->TAttLine::Modify();
3538
3539 if (opaque && dimension ==2) {
3540 zbx1 = gPad->AbsPixeltoX(px);
3541 zbx2 = gPad->AbsPixeltoX(px);
3542 zby1 = gPad->AbsPixeltoY(py);
3543 zby2 = gPad->AbsPixeltoY(py);
3544 px1 = px;
3545 py1 = py;
3546 if (gPad->GetLogx()) {
3547 zbx1 = TMath::Power(10,zbx1);
3548 zbx2 = TMath::Power(10,zbx2);
3549 }
3550 if (gPad->GetLogy()) {
3551 zby1 = TMath::Power(10,zby1);
3552 zby2 = TMath::Power(10,zby2);
3553 }
3554 if (zoombox) Error("ExecuteEvent", "Last zoom box was not deleted");
3555 zoombox = std::make_unique<TBox>(zbx1, zby1, zbx2, zby2);
3556 Int_t ci = TColor::GetColor("#7d7dff");
3557 TColor *zoomcolor = gROOT->GetColor(ci);
3558 if (!TCanvas::SupportAlpha() || !zoomcolor) zoombox->SetFillStyle(3002);
3559 else zoomcolor->SetAlpha(0.5);
3560 zoombox->SetFillColor(ci);
3561 zoombox->Draw();
3562 gPad->Modified();
3563 gPad->Update();
3564 }
3565 // No break !!!
3566
3567 case kMouseMotion:
3568
3569 if (fShowProjection) {ShowProjection3(px,py); break;}
3570
3571 gPad->SetCursor(kPointer);
3572 if (dimension ==1) {
3573 if (Hoption.Bar) {
3574 baroffset = fH->GetBarOffset();
3575 barwidth = fH->GetBarWidth();
3576 } else {
3577 baroffset = 0;
3578 barwidth = 1;
3579 }
3580 x = gPad->AbsPixeltoX(px);
3581 bin = fXaxis->FindFixBin(gPad->PadtoX(x));
3583 xlow = gPad->XtoPad(fXaxis->GetBinLowEdge(bin) + baroffset*binwidth);
3584 xup = gPad->XtoPad(xlow + barwidth*binwidth);
3585 ylow = gPad->GetUymin();
3586 px1 = gPad->XtoAbsPixel(xlow);
3587 px2 = gPad->XtoAbsPixel(xup);
3588 py1 = gPad->YtoAbsPixel(ylow);
3589 py2 = py;
3590 pyold = py;
3591 if (gROOT->GetEditHistograms()) gPad->SetCursor(kArrowVer);
3592 }
3593
3594 break;
3595
3596 case kButton1Motion:
3597
3598 if (dimension ==1) {
3599 if (gROOT->GetEditHistograms()) {
3600 if (!opaque) {
3601 gVirtualX->DrawBox(px1, py1, px2, py2,TVirtualX::kHollow); // Draw the old box
3602 py2 += py - pyold;
3603 gVirtualX->DrawBox(px1, py1, px2, py2,TVirtualX::kHollow); // Draw the new box
3604 pyold = py;
3605 } else {
3606 py2 += py - pyold;
3607 pyold = py;
3608 binval = gPad->PadtoY(gPad->AbsPixeltoY(py2))/factor;
3610 gPad->Modified(kTRUE);
3611 }
3612 }
3613 }
3614
3615 if (opaque && dimension ==2) {
3616 if (TMath::Abs(px1-px)>5 && TMath::Abs(py1-py)>5) {
3617 zbx2 = gPad->AbsPixeltoX(px);
3618 zby2 = gPad->AbsPixeltoY(py);
3619 if (gPad->GetLogx()) zbx2 = TMath::Power(10,zbx2);
3620 if (gPad->GetLogy()) zby2 = TMath::Power(10,zby2);
3621 if (zoombox) {
3622 zoombox->SetX2(zbx2);
3623 zoombox->SetY2(zby2);
3624 }
3625 gPad->Modified();
3626 gPad->Update();
3627 }
3628 }
3629
3630 break;
3631
3632 case kWheelUp:
3633
3634 if (dimension ==2) {
3635 bin1 = xaxis->GetFirst()+1;
3636 bin2 = xaxis->GetLast()-1;
3637 bin1 = TMath::Max(bin1, 1);
3638 bin2 = TMath::Min(bin2, xaxis->GetNbins());
3639 if (bin2>bin1) xaxis->SetRange(bin1,bin2);
3640 bin1 = yaxis->GetFirst()+1;
3641 bin2 = yaxis->GetLast()-1;
3642 bin1 = TMath::Max(bin1, 1);
3643 bin2 = TMath::Min(bin2, yaxis->GetNbins());
3644 if (bin2>bin1) yaxis->SetRange(bin1,bin2);
3645 }
3646 gPad->Modified();
3647 gPad->Update();
3648
3649 break;
3650
3651 case kWheelDown:
3652
3653 if (dimension == 2) {
3654 bin1 = xaxis->GetFirst()-1;
3655 bin2 = xaxis->GetLast()+1;
3656 bin1 = TMath::Max(bin1, 1);
3657 bin2 = TMath::Min(bin2, xaxis->GetNbins());
3658 const bool resetXaxisRange = bin1 == 1 && xaxis->GetFirst() == 1 && bin2 == xaxis->GetNbins() && xaxis->GetLast() == xaxis->GetNbins();
3659 if (bin2>bin1) xaxis->SetRange(bin1,bin2);
3660 if (resetXaxisRange) xaxis->ResetBit(TAxis::kAxisRange);
3661 bin1 = yaxis->GetFirst()-1;
3662 bin2 = yaxis->GetLast()+1;
3663 bin1 = TMath::Max(bin1, 1);
3664 bin2 = TMath::Min(bin2, yaxis->GetNbins());
3665 const bool resetYaxisRange = bin1 == 1 && yaxis->GetFirst() == 1 && bin2 == yaxis->GetNbins() && yaxis->GetLast() == yaxis->GetNbins();
3666 if (bin2>bin1) yaxis->SetRange(bin1,bin2);
3667 if (resetYaxisRange) yaxis->ResetBit(TAxis::kAxisRange);
3668 }
3669 gPad->Modified();
3670 gPad->Update();
3671
3672 break;
3673
3674 case kButton1Up:
3675 if (dimension ==1) {
3676 if (gROOT->GetEditHistograms()) {
3677 binval = gPad->PadtoY(gPad->AbsPixeltoY(py2))/factor;
3679 PaintInit(); // recalculate Hparam structure and recalculate range
3680 }
3681
3682 // might resize pad pixmap so should be called before any paint routine
3684 }
3685 if (opaque && dimension ==2) {
3686 if (zoombox) {
3687 Double_t x1 = TMath::Min(zoombox->GetX1(), zoombox->GetX2());
3688 Double_t x2 = TMath::Max(zoombox->GetX1(), zoombox->GetX2());
3689 Double_t y1 = TMath::Min(zoombox->GetY1(), zoombox->GetY2());
3690 Double_t y2 = TMath::Max(zoombox->GetY1(), zoombox->GetY2());
3691 x1 = TMath::Max(x1,xaxis->GetXmin());
3692 x2 = TMath::Min(x2,xaxis->GetXmax());
3693 y1 = TMath::Max(y1,yaxis->GetXmin());
3694 y2 = TMath::Min(y2,yaxis->GetXmax());
3695 if (x1<x2 && y1<y2) {
3696 xaxis->SetRangeUser(x1, x2);
3697 yaxis->SetRangeUser(y1, y2);
3698 }
3699 zoombox.reset();
3700 }
3701 }
3702 gPad->Modified(kTRUE);
3703 if (opaque) gVirtualX->SetLineColor(-1);
3704
3705 break;
3706
3707 case kButton1Locate:
3708
3709 ExecuteEvent(kButton1Down, px, py);
3710
3711 while (true) {
3712 px = py = 0;
3713 event = gVirtualX->RequestLocator(1, 1, px, py);
3714
3716
3717 if (event != -1) { // button is released
3718 ExecuteEvent(kButton1Up, px, py);
3719 return;
3720 }
3721 }
3722 }
3723}
3724
3725////////////////////////////////////////////////////////////////////////////////
3726/// Get a contour (as a list of TGraphs) using the Delaunay triangulation.
3727
3729{
3730 // Check if fH contains a TGraphDelaunay2D
3732 TGraphDelaunay2D *dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
3733 // try with the old painter
3734 TGraphDelaunay *dtOld = nullptr;
3735 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
3736
3737 if (!dt && !dtOld) return nullptr;
3738
3739 gCurrentHist = fH;
3740
3741 if (!fGraph2DPainter)
3742 ((THistPainter*)this)->fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
3743
3744 return fGraph2DPainter->GetContourList(contour);
3745}
3746
3747////////////////////////////////////////////////////////////////////////////////
3748/// Display the histogram info (bin number, contents, integral up to bin
3749/// corresponding to cursor position px,py.
3750
3752{
3753
3754 if (!gPad) return (char*)"";
3755
3756 Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
3757 Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
3758 Double_t x1 = gPad->PadtoX(gPad->AbsPixeltoX(px+1));
3760 drawOption.ToLower();
3763 if (fH->GetDimension() == 2) {
3764 if (gPad->GetView() || drawOption.Index("cont") >= 0) {
3765 uxmin=gPad->GetUxmin();
3766 uxmax=gPad->GetUxmax();
3769 x = xmin +(xmax-xmin)*(x-uxmin)/(uxmax-uxmin);
3770 uymin=gPad->GetUymin();
3771 uymax=gPad->GetUymax();
3774 y = ymin +(ymax-ymin)*(y-uymin)/(uymax-uymin);
3775 }
3776 }
3778 if (gPad->IsVertical()) {
3779 binx = fXaxis->FindFixBin(x);
3780 if (drawOption.Index("same") >= 0) {
3781 TH1 *h1;
3782 TIter next(gPad->GetListOfPrimitives());
3783 while ((h1 = (TH1 *)next())) {
3784 if (!h1->InheritsFrom(TH1::Class())) continue;
3785 binmin = h1->GetXaxis()->GetFirst();
3786 break;
3787 }
3788 } else {
3789 binmin = fXaxis->GetFirst();
3790 }
3792 // special case if more than 1 bin in x per pixel
3793 if (binx1-binx>1 && fH->GetDimension() == 1) {
3796 for (Int_t ibin=binx+1; ibin<binx1; ibin++) {
3800 binnear=ibin;
3801 }
3802 }
3803 binx = binnear;
3804 }
3805 } else {
3806 x1 = gPad->PadtoY(gPad->AbsPixeltoY(py+1));
3807 binx = fXaxis->FindFixBin(y);
3808 if (drawOption.Index("same") >= 0) {
3809 TH1 *h1;
3810 TIter next(gPad->GetListOfPrimitives());
3811 while ((h1 = (TH1 *)next())) {
3812 if (!h1->InheritsFrom(TH1::Class())) continue;
3813 binmin = h1->GetXaxis()->GetFirst();
3814 break;
3815 }
3816 } else {
3817 binmin = fXaxis->GetFirst();
3818 }
3820 // special case if more than 1 bin in x per pixel
3821 if (binx1-binx>1 && fH->GetDimension() == 1) {
3824 for (Int_t ibin=binx+1; ibin<binx1; ibin++) {
3828 binnear=ibin;
3829 }
3830 }
3831 binx = binnear;
3832 }
3833 }
3834 if (fH->GetDimension() == 1) {
3836 TProfile *tp = (TProfile*)fH;
3837 fObjectInfo.Form("(x=%g, y=%g, binx=%d, binc=%g, bine=%g, binn=%d)",
3839 (Int_t) tp->GetBinEntries(binx));
3840 }
3841 else {
3842 Double_t integ = 0;
3843 for (Int_t bin=binmin;bin<=binx;bin++) {integ += fH->GetBinContent(bin);}
3844 fObjectInfo.Form("(x=%g, y=%g, binx=%d, binc=%g, Sum=%g)",
3846 }
3847 } else if (fH->GetDimension() == 2) {
3848 if (fH->InheritsFrom(TH2Poly::Class())) {
3849 TH2Poly *th2 = (TH2Poly*)fH;
3850 biny = th2->FindBin(x,y);
3851 fObjectInfo.Form("%s (x=%g, y=%g, bin=%d, binc=%g)",
3852 th2->GetBinTitle(biny),x,y,biny,th2->GetBinContent(biny));
3853 }
3854 else if (fH->InheritsFrom(TProfile2D::Class())) {
3856 biny = fYaxis->FindFixBin(y);
3857 Int_t bin = fH->GetBin(binx,biny);
3858 fObjectInfo.Form("(x=%g, y=%g, binx=%d, biny=%d, binc=%g, bine=%g, binn=%d)",
3859 x, y, binx, biny, fH->GetBinContent(bin),
3860 fH->GetBinError(bin), (Int_t) tp->GetBinEntries(bin));
3861 } else {
3862 biny = fYaxis->FindFixBin(y);
3863 fObjectInfo.Form("(x=%g, y=%g, binx=%d, biny=%d, binc=%g bine=%g)",
3866 }
3867 } else {
3868 // 3d case: retrieving the x,y,z bin is not yet implemented
3869 // print just the x,y info
3870 fObjectInfo.Form("(x=%g, y=%g)",x,y);
3871 }
3872
3873 return (char *)fObjectInfo.Data();
3874}
3875
3876////////////////////////////////////////////////////////////////////////////////
3877/// Set highlight (enable/disable) mode for fH
3878
3880{
3881 if (fH->IsHighlight()) return;
3882
3883 fXHighlightBin = -1;
3884 fYHighlightBin = -1;
3885 // delete previous highlight box
3886 if (gXHighlightBox) gXHighlightBox.reset();
3887 if (gYHighlightBox) gYHighlightBox.reset();
3888 // emit Highlighted() signal (user can check on disabled)
3889 if (gPad->GetCanvas()) gPad->GetCanvas()->Highlighted(gPad, fH, fXHighlightBin, fYHighlightBin);
3890}
3891
3892////////////////////////////////////////////////////////////////////////////////
3893/// Check on highlight bin
3894
3896{
3897 // call from DistancetoPrimitive (only if highlight is enable)
3898
3899 Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
3900 Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
3903 if (!gPad->IsVertical()) binx = fXaxis->FindFixBin(y);
3904
3906 if (binx != fXHighlightBin) {
3908 changedBin = kTRUE;
3909 } else if (fH->GetDimension() == 1) return;
3910 if (biny != fYHighlightBin) {
3912 changedBin = kTRUE;
3913 }
3914 if (!changedBin) return;
3915
3916 // Info("HighlightBin", "histo: %p '%s'\txbin: %d, ybin: %d",
3917 // (void *)fH, fH->GetName(), fXHighlightBin, fYHighlightBin);
3918
3919 // paint highlight bin as box (recursive calls PaintHighlightBin)
3920 gPad->Modified(kTRUE);
3921 gPad->Update();
3922
3923 // emit Highlighted() signal
3924 if (gPad->GetCanvas()) gPad->GetCanvas()->Highlighted(gPad, fH, fXHighlightBin, fYHighlightBin);
3925}
3926
3927////////////////////////////////////////////////////////////////////////////////
3928/// Paint highlight bin as TBox object
3929
3931{
3932 // call from PaintTitle
3933
3934 if (!fH->IsHighlight()) return;
3935
3936 Double_t uxmin = gPad->GetUxmin();
3937 Double_t uxmax = gPad->GetUxmax();
3938 Double_t uymin = gPad->GetUymin();
3939 Double_t uymax = gPad->GetUymax();
3940 if (gPad->GetLogx()) {
3941 uxmin = TMath::Power(10.0, uxmin);
3942 uxmax = TMath::Power(10.0, uxmax);
3943 }
3944 if (gPad->GetLogy()) {
3945 uymin = TMath::Power(10.0, uymin);
3946 uymax = TMath::Power(10.0, uymax);
3947 }
3948
3949 // testing specific possibility (after zoom, draw with "same", log, etc.)
3951 if (gPad->IsVertical()) {
3953 if ((hcenter < uxmin) || (hcenter > uxmax)) return;
3954 } else {
3956 if ((hcenter < uymin) || (hcenter > uymax)) return;
3957 }
3958 if (fH->GetDimension() == 2) {
3960 if ((hcenter < uymin) || (hcenter > uymax)) return;
3961 }
3962
3963 // paint X highlight bin (for 1D or 2D)
3965 if (gPad->IsVertical()) {
3968 hby1 = uymin;
3969 hby2 = uymax;
3970 } else {
3971 hbx1 = uxmin;
3972 hbx2 = uxmax;
3975 }
3976
3977 if (!gXHighlightBox) {
3978 gXHighlightBox = std::make_unique<TBox>(hbx1, hby1, hbx2, hby2);
3979 gXHighlightBox->SetBit(kCannotPick);
3980 gXHighlightBox->SetFillColor(TColor::GetColor("#9797ff"));
3981 if (!TCanvas::SupportAlpha()) gXHighlightBox->SetFillStyle(3001);
3982 else gROOT->GetColor(gXHighlightBox->GetFillColor())->SetAlpha(0.5);
3983 }
3984 gXHighlightBox->SetX1(hbx1);
3985 gXHighlightBox->SetX2(hbx2);
3986 gXHighlightBox->SetY1(hby1);
3987 gXHighlightBox->SetY2(hby2);
3988 gXHighlightBox->Paint();
3989
3990 // Info("PaintHighlightBin", "histo: %p '%s'\txbin: %d, ybin: %d",
3991 // (void *)fH, fH->GetName(), fXHighlightBin, fYHighlightBin);
3992
3993 // paint Y highlight bin (only for 2D)
3994 if (fH->GetDimension() != 2) return;
3995 hbx1 = uxmin;
3996 hbx2 = uxmax;
3999
4000 if (!gYHighlightBox) {
4001 gYHighlightBox = std::make_unique<TBox>(hbx1, hby1, hbx2, hby2);
4002 gYHighlightBox->SetBit(kCannotPick);
4003 gYHighlightBox->SetFillColor(gXHighlightBox->GetFillColor());
4004 gYHighlightBox->SetFillStyle(gXHighlightBox->GetFillStyle());
4005 }
4006 gYHighlightBox->SetX1(hbx1);
4007 gYHighlightBox->SetX2(hbx2);
4008 gYHighlightBox->SetY1(hby1);
4009 gYHighlightBox->SetY2(hby2);
4010 gYHighlightBox->Paint();
4011}
4012
4013////////////////////////////////////////////////////////////////////////////////
4014/// Return `kTRUE` if the cell `ix`, `iy` is inside one of the graphical cuts.
4015
4017{
4018
4019 for (Int_t i=0;i<fNcuts;i++) {
4022 if (fCutsOpt[i] > 0) {
4023 if (!fCuts[i]->IsInside(x,y)) return kFALSE;
4024 } else {
4025 if (fCuts[i]->IsInside(x,y)) return kFALSE;
4026 }
4027 }
4028 return kTRUE;
4029}
4030
4031////////////////////////////////////////////////////////////////////////////////
4032/// Return `kTRUE` if the point `x`, `y` is inside one of the graphical cuts.
4033
4035{
4036
4037 for (Int_t i=0;i<fNcuts;i++) {
4038 if (fCutsOpt[i] > 0) {
4039 if (!fCuts[i]->IsInside(x,y)) return kFALSE;
4040 } else {
4041 if (fCuts[i]->IsInside(x,y)) return kFALSE;
4042 }
4043 }
4044 return kTRUE;
4045}
4046
4047////////////////////////////////////////////////////////////////////////////////
4048/// Decode string `choptin` and fill Hoption structure.
4049
4051{
4052
4053 char *l;
4054 char chopt[128];
4056 strlcpy(chopt,choptin,128);
4059
4067 Hoption.Candle = 0;
4068 Hoption.Polar = 0;
4069
4070 // special 2D options
4071 Hoption.List = 0;
4072 Hoption.Zscale = 0;
4073 Hoption.FrontBox = 1;
4074 Hoption.BackBox = 1;
4076
4077 Hoption.Zero = 0;
4078
4080
4081 //check for graphical cuts
4082 MakeCuts(chopt);
4083
4084 for (Int_t i=0;i<nch;i++) chopt[i] = toupper(chopt[i]);
4085 if (hdim > 1) Hoption.Color = 1; // Default drawing option for 2D and 3D histograms
4086 if (!nch) Hoption.Hist = 1;
4087 if (fFunctions->First()) Hoption.Func = 1;
4088 if (fH->GetSumw2N() && hdim == 1) Hoption.Error = 2;
4089
4090 char *l1 = strstr(chopt,"PFC"); // Automatic Fill Color
4091 char *l2 = strstr(chopt,"PLC"); // Automatic Line Color
4092 char *l3 = strstr(chopt,"PMC"); // Automatic Marker Color
4093 if (l1 || l2 || l3) {
4094 Int_t i = gPad->NextPaletteColor();
4095 if (l1) {memcpy(l1," ",3); fH->SetFillColor(i);}
4096 if (l2) {memcpy(l2," ",3); fH->SetLineColor(i);}
4097 if (l3) {memcpy(l3," ",3); fH->SetMarkerColor(i);}
4098 Hoption.Hist = 1; // Make sure something is drawn in case there is no drawing option specified.
4099 }
4100
4101 l = strstr(chopt,"MIN0");
4102 if (l) {
4103 Hoption.MinimumZero = 1;
4104 memcpy(l," ",4);
4105 }
4106
4107 l = strstr(chopt,"SPEC");
4108 if (l) {
4109 Hoption.Color = 0;
4110 memcpy(l," ",4);
4111 Int_t bs=0;
4112 l = strstr(chopt,"BF(");
4113 if (l) {
4114 if (sscanf(&l[3],"%d",&bs) > 0) {
4115 Int_t i=0;
4116 while (l[i]!=')') {
4117 l[i] = ' ';
4118 i++;
4119 }
4120 l[i] = ' ';
4121 }
4122 }
4123 Hoption.Spec = TMath::Max(1600,bs);
4124 return 1;
4125 }
4126
4127 l = strstr(chopt,"GL");
4128 if (l) {
4129 memcpy(l," ",2);
4130 }
4131 l = strstr(chopt,"X+");
4132 if (l) {
4133 Hoption.AxisPos = 10;
4134 memcpy(l," ",2);
4135 }
4136 l = strstr(chopt,"Y+");
4137 if (l) {
4138 Hoption.AxisPos += 1;
4139 memcpy(l," ",2);
4140 }
4141 if ((Hoption.AxisPos == 10 || Hoption.AxisPos == 1) && (nch == 2)) Hoption.Hist = 1;
4142 if (Hoption.AxisPos == 11 && nch == 4) Hoption.Hist = 1;
4143
4144 l = strstr(chopt,"SAMES");
4145 if (l) {
4146 if (nch == 5) Hoption.Hist = 1;
4147 Hoption.Same = 2;
4148 memcpy(l," ",5);
4149 if (l[5] == '0') { Hoption.Same += 10; l[5] = ' '; }
4150 }
4151 l = strstr(chopt,"SAME");
4152 if (l) {
4153 if (nch == 4) Hoption.Hist = 1;
4154 Hoption.Same = 1;
4155 memcpy(l," ",4);
4156 if (l[4] == '0') { Hoption.Same += 10; l[4] = ' '; }
4157 }
4158
4159 l = strstr(chopt,"SCAT");
4160 if (l) {
4161 Warning("MakeChopt","option SCAT is deprecated.");
4162 Hoption.Scat = 1;
4163 memcpy(l," ",4);
4164 Hoption.Color = 0;
4165 }
4166
4167 l = strstr(chopt,"PIE");
4168 if (l) {
4169 Hoption.Pie = 1;
4170 memcpy(l," ",3);
4171 }
4172
4173
4174 l = strstr(chopt,"CANDLE");
4175 if (l) {
4177 Hoption.Candle = candle.ParseOption(l);
4178 Hoption.Color = 0;
4179 }
4180
4181 l = strstr(chopt,"VIOLIN");
4182 if (l) {
4184 Hoption.Candle = candle.ParseOption(l);
4185 Hoption.Color = 0;
4186 }
4187
4188 l = strstr(chopt,"LEGO");
4189 if (l) {
4190 Hoption.Color = 0;
4191 Hoption.Lego = 1; memcpy(l," ",4);
4192 if (l[4] == '1') { Hoption.Lego = 11; l[4] = ' '; }
4193 if (l[4] == '2') { Hoption.Lego = 12; l[4] = ' '; }
4194 if (l[4] == '3') { Hoption.Lego = 13; l[4] = ' '; }
4195 if (l[4] == '4') { Hoption.Lego = 14; l[4] = ' '; }
4196 if (l[4] == '9') { Hoption.Lego = 19; l[4] = ' '; }
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 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4200 }
4201
4202 l = strstr(chopt,"SURF");
4203 if (l) {
4204 Hoption.Color = 0;
4205 Hoption.Surf = 1; memcpy(l," ",4);
4206 if (l[4] == '1') { Hoption.Surf = 11; l[4] = ' '; }
4207 if (l[4] == '2') { Hoption.Surf = 12; l[4] = ' '; }
4208 if (l[4] == '3') { Hoption.Surf = 13; l[4] = ' '; }
4209 if (l[4] == '4') { Hoption.Surf = 14; l[4] = ' '; }
4210 if (l[4] == '5') { Hoption.Surf = 15; l[4] = ' '; }
4211 if (l[4] == '6') { Hoption.Surf = 16; l[4] = ' '; }
4212 if (l[4] == '7') { Hoption.Surf = 17; l[4] = ' '; }
4213 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4214 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4215 }
4216
4217 l = strstr(chopt,"TF3");
4218 if (l) {
4219 memcpy(l," ",3);
4220 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4221 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4222 }
4223
4224 l = strstr(chopt,"ISO");
4225 if (l) {
4226 memcpy(l," ",3);
4227 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4228 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4229 Hoption.Color = 0;
4230 }
4231
4232 l = strstr(chopt,"LIST"); if (l) { Hoption.List = 1; memcpy(l," ",4);}
4233
4234 l = strstr(chopt,"CONT");
4235 if (l) {
4236 memcpy(l," ",4);
4237 if (hdim>1) {
4238 Hoption.Color = 0;
4239 Hoption.Contour = 1;
4240 if (l[4] == '1') { Hoption.Contour = 11; l[4] = ' '; }
4241 if (l[4] == '2') { Hoption.Contour = 12; l[4] = ' '; }
4242 if (l[4] == '3') { Hoption.Contour = 13; l[4] = ' '; }
4243 if (l[4] == '4') { Hoption.Contour = 14; l[4] = ' '; }
4244 if (l[4] == '5') { Hoption.Contour = 15; l[4] = ' '; }
4245 } else {
4246 Hoption.Hist = 1;
4247 }
4248 }
4249 l = strstr(chopt,"HBAR");
4250 if (l) {
4251 Hoption.Hist = 0;
4252 Hoption.Bar = 20; memcpy(l," ",4);
4253 if (l[4] == '1') { Hoption.Bar = 21; l[4] = ' '; }
4254 if (l[4] == '2') { Hoption.Bar = 22; l[4] = ' '; }
4255 if (l[4] == '3') { Hoption.Bar = 23; l[4] = ' '; }
4256 if (l[4] == '4') { Hoption.Bar = 24; l[4] = ' '; }
4257 }
4258 l = strstr(chopt,"BAR");
4259 if (l) {
4260 Hoption.Hist = 0;
4261 Hoption.Bar = 10; memcpy(l," ",3);
4262 if (l[3] == '1') { Hoption.Bar = 11; l[3] = ' '; }
4263 if (l[3] == '2') { Hoption.Bar = 12; l[3] = ' '; }
4264 if (l[3] == '3') { Hoption.Bar = 13; l[3] = ' '; }
4265 if (l[3] == '4') { Hoption.Bar = 14; l[3] = ' '; }
4266 }
4267
4268 l = strstr(chopt,"ARR" );
4269 if (l) {
4270 memcpy(l," ", 3);
4271 if (hdim>1) {
4272 Hoption.Arrow = 1;
4273 Hoption.Color = 0;
4274 l = strstr(chopt,"COL"); if (l) { Hoption.Arrow = 2; memcpy(l," ",3); }
4275 l = strstr(chopt,"Z"); if (l) { Hoption.Zscale = 1; memcpy(l," ",1); }
4276 } else {
4277 Hoption.Hist = 1;
4278 }
4279 }
4280 l = strstr(chopt,"BOX" );
4281 if (l) {
4282 memcpy(l," ", 3);
4283 if (hdim>1) {
4284 Hoption.Color = 0;
4285 Hoption.Box = 1;
4286 if (l[3] == '1') { Hoption.Box = 11; l[3] = ' '; }
4287 if (l[3] == '2') { Hoption.Box = 12; l[3] = ' '; }
4288 if (l[3] == '3') { Hoption.Box = 13; l[3] = ' '; }
4289 } else {
4290 Hoption.Hist = 1;
4291 }
4292 }
4293 l = strstr(chopt,"TEXT");
4294 if (l) {
4295 Int_t angle;
4296 if (sscanf(&l[4],"%d",&angle) > 0) {
4297 if (angle < 0) angle=0;
4298 if (angle > 90) angle=90;
4299 Hoption.Text = 1000+angle;
4300 } else {
4301 Hoption.Text = 1;
4302 }
4303 memcpy(l," ", 4);
4304 l = strstr(chopt,"N");
4305 if (l && fH->InheritsFrom(TH2Poly::Class())) Hoption.Text = 3000 + (Hoption.Text != 1 ? Hoption.Text : 0);
4306 Hoption.Color = 0;
4307 }
4308 l = strstr(chopt,"COLZ");
4309 if (l) {
4310 memcpy(l," ",4);
4311 if (hdim > 1) {
4313 Hoption.Color = 1;
4314 Hoption.Zscale = 1;
4315 if (l[4] == '2') { Hoption.Color = 3; l[4] = ' '; }
4316 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4317 l = strstr(chopt,"1"); if (l) { Hoption.Color = 2; memcpy(l," ",1); }
4318 } else {
4319 Hoption.Hist = 1;
4320 }
4321 }
4322 l = strstr(chopt,"COL" );
4323 if (l) {
4324 memcpy(l," ", 3);
4325 if (hdim > 1) {
4327 Hoption.Color = 1;
4328 if (l[3] == '2') { Hoption.Color = 3; l[3] = ' '; }
4329 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4330 l = strstr(chopt,"1"); if (l) { Hoption.Color = 2; memcpy(l," ",1); }
4331 } else {
4332 Hoption.Hist = 1;
4333 }
4334 }
4335 l = strstr(chopt,"FUNC"); if (l) { Hoption.Func = 2; memcpy(l," ",4); Hoption.Hist = 0; }
4336 l = strstr(chopt,"HIST"); if (l) { Hoption.Hist = 2; memcpy(l," ",4); Hoption.Func = 0; Hoption.Error = 0;}
4337 l = strstr(chopt,"AXIS"); if (l) { Hoption.Axis = 1; memcpy(l," ",4); }
4338 l = strstr(chopt,"AXIG"); if (l) { Hoption.Axis = 2; memcpy(l," ",4); }
4339 l = strstr(chopt,"SCAT"); if (l) { Hoption.Scat = 1; memcpy(l," ",4); }
4340 l = strstr(chopt,"POLN"); if (l) { Hoption.System = kPOLAR; Hoption.Polar = 3; memcpy(l," ",4); }
4341 l = strstr(chopt,"POLF"); if (l) { Hoption.System = kPOLAR; Hoption.Polar = 2; memcpy(l," ",4); }
4342 l = strstr(chopt,"POL"); if (l) { Hoption.System = kPOLAR; Hoption.Polar = 1; memcpy(l," ",3); }
4343 l = strstr(chopt,"CYL"); if (l) { Hoption.System = kCYLINDRICAL; memcpy(l," ",3); }
4344 l = strstr(chopt,"SPH"); if (l) { Hoption.System = kSPHERICAL; memcpy(l," ",3); }
4345 l = strstr(chopt,"PSR"); if (l) { Hoption.System = kRAPIDITY; memcpy(l," ",3); }
4346
4347 l = strstr(chopt,"TRI");
4348 if (l) {
4349 if (!explicitColor) Hoption.Color = 0;
4350 Hoption.Tri = 1; memcpy(l," ",3);
4351 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4352 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4353 l = strstr(chopt,"ERR"); if (l) memcpy(l," ",3);
4354 }
4355
4356 l = strstr(chopt,"AITOFF");
4357 if (l) {
4358 Hoption.Proj = 1; memcpy(l," ",6); //Aitoff projection
4359 }
4360 l = strstr(chopt,"MERCATOR");
4361 if (l) {
4362 Hoption.Proj = 2; memcpy(l," ",8); //Mercator projection
4363 }
4364 l = strstr(chopt,"SINUSOIDAL");
4365 if (l) {
4366 Hoption.Proj = 3; memcpy(l," ",10); //Sinusoidal projection
4367 }
4368 l = strstr(chopt,"PARABOLIC");
4369 if (l) {
4370 Hoption.Proj = 4; memcpy(l," ",9); //Parabolic projection
4371 }
4372 l = strstr(chopt,"MOLLWEIDE");
4373 if (l) {
4374 Hoption.Proj = 5; memcpy(l," ",9); //Mollweide projection
4375 }
4376 if (Hoption.Proj > 0) {
4377 if (!explicitColor) Hoption.Color = 0;
4378 Hoption.Contour = 14;
4379 }
4380
4381 if (strstr(chopt,"A")) Hoption.Axis = -1;
4382 if (strstr(chopt,"B")) Hoption.Bar = 1;
4383 if (strstr(chopt,"C") && !strstr(chopt,"CJUST")) { Hoption.Curve =1; Hoption.Hist = -1;}
4384 if (strstr(chopt,"F")) Hoption.Fill =1;
4385 if (strstr(chopt,"][")) {Hoption.Off =1; Hoption.Hist =1;}
4386 if (strstr(chopt,"F2")) Hoption.Fill =2;
4387 if (strstr(chopt,"L")) { Hoption.Line =1; Hoption.Hist = -1;}
4388 if (strstr(chopt,"P")) { Hoption.Mark =1; Hoption.Hist = -1;}
4389 if (strstr(chopt,"Z")) Hoption.Zscale =1;
4390 if (strstr(chopt,"*")) Hoption.Star =1;
4391 if (strstr(chopt,"H")) Hoption.Hist =2;
4392 if (strstr(chopt,"P0")) Hoption.Mark =10;
4393
4394 if (fH->InheritsFrom(TH2Poly::Class())) {
4396 }
4397
4398 if (strstr(chopt,"E")) {
4399 if (hdim == 1) {
4400 Hoption.Error = 1;
4401 if (strstr(chopt,"E1")) Hoption.Error = 11;
4402 if (strstr(chopt,"E2")) Hoption.Error = 12;
4403 if (strstr(chopt,"E3")) Hoption.Error = 13;
4404 if (strstr(chopt,"E4")) Hoption.Error = 14;
4405 if (strstr(chopt,"E5")) Hoption.Error = 15;
4406 if (strstr(chopt,"E6")) Hoption.Error = 16;
4407 if (strstr(chopt,"E0")) Hoption.Error += 40;
4408 if (strstr(chopt,"X0")) {
4409 if (Hoption.Error == 1) Hoption.Error += 20;
4410 Hoption.Error += 10;
4411 }
4413 Hoption.Text += 2000;
4414 Hoption.Error = 0;
4415 }
4416 } else {
4417 if (Hoption.Error == 0) {
4418 Hoption.Error = 100;
4419 if (!explicitColor) Hoption.Color = 0;
4420 }
4421 if (Hoption.Text) {
4422 Hoption.Text += 2000;
4423 Hoption.Error = 0;
4424 }
4425 }
4426 }
4427
4428 if (Hoption.Surf == 15) {
4430 Hoption.Surf = 13;
4431 Warning("MakeChopt","option SURF5 is not supported in Cartesian and Polar modes");
4432 }
4433 }
4434
4435 // Copy options from current style
4436 Hoption.Logx = gPad->GetLogx();
4437 Hoption.Logy = gPad->GetLogy();
4438 Hoption.Logz = gPad->GetLogz();
4439
4440 // Check options incompatibilities
4441 if (Hoption.Bar == 1) Hoption.Hist = -1;
4442 return 1;
4443}
4444
4445////////////////////////////////////////////////////////////////////////////////
4446/// Decode string `choptin` and fill Graphical cuts structure.
4447
4449{
4450
4451 fNcuts = 0;
4452 char *left = (char*)strchr(choptin,'[');
4453 if (!left) return 0;
4454 char *right = (char*)strchr(choptin,']');
4455 if (!right) return 0;
4456 Int_t nch = right-left;
4457 if (nch < 2) return 0;
4458 char *cuts = left+1;
4459 *right = 0;
4460 char *comma, *minus;
4461 Int_t i;
4462 while (true) {
4463 comma = strchr(cuts,',');
4464 if (comma) *comma = 0;
4465 minus = strchr(cuts,'-');
4466 if (minus) cuts = minus+1;
4467 while (*cuts == ' ') cuts++;
4468 Int_t nc = strlen(cuts);
4469 while (cuts[nc-1] == ' ') {cuts[nc-1] = 0; nc--;}
4470 TIter next(gROOT->GetListOfSpecials());
4471 TCutG *cut=nullptr;
4472 TObject *obj;
4473 while ((obj = next())) {
4474 if (!obj->InheritsFrom(TCutG::Class())) continue;
4475 if (strcmp(obj->GetName(),cuts)) continue;
4476 cut = (TCutG*)obj;
4477 break;
4478 }
4479 if (cut) {
4480 fCuts[fNcuts] = cut;
4481 fCutsOpt[fNcuts] = 1;
4482 if (minus) fCutsOpt[fNcuts] = -1;
4483 fNcuts++;
4484 }
4485 if (!comma) break;
4486 cuts = comma+1;
4487 }
4488 for (i=0;i<=nch;i++) left[i] = ' ';
4489 return fNcuts;
4490}
4491
4492////////////////////////////////////////////////////////////////////////////////
4493/// [Control routine to paint any kind of histograms](\ref HP00)
4494
4496{
4497
4498 if (fH->GetBuffer()) fH->BufferEmpty(-1);
4499
4500 //For iOS: put the histogram on the top of stack of pickable objects.
4502
4503 gPad->SetVertical(kTRUE);
4504
4506 gCurrentHist = fH;
4507 TH1 *hsave = fH;
4509
4510 if (!MakeChopt(option)) return; //check options and fill Hoption structure
4511
4512 // Paint using TSpectrum2Painter
4513 if (Hoption.Spec) {
4514 if (!TableInit()) return;
4515 if (!TClass::GetClass("TSpectrum2Painter")) gSystem->Load("libSpectrumPainter");
4516 gROOT->ProcessLineFast(TString::Format("TSpectrum2Painter::PaintSpectrum((TH2F*)0x%zx,\"%s\",%d)",
4517 (size_t)fH, option, Hoption.Spec).Data());
4518 return;
4519 }
4520
4521 // Deflate the labels in case of alphanumeric labels
4525
4526 if (Hoption.Pie) {
4527 if (fH->GetDimension() == 1) {
4528 if (!fPie)
4529 fPie = std::make_unique<TPie>(fH);
4530 fPie->Paint(option);
4531 } else {
4532 Error("Paint", "Option PIE is for 1D histograms only");
4533 }
4534 return;
4535 } else {
4536 fPie.reset();
4537 }
4538
4539 fXbuf.resize(kNMAX);
4540 fYbuf.resize(kNMAX);
4541 if (fH->GetDimension() > 2) {
4542 PaintH3(option);
4544 if (Hoption.Func) {
4549 Hoption = hoptsave;
4550 Hparam = hparsave;
4551 }
4553 fXbuf.clear();
4554 fYbuf.clear();
4555 return;
4556 }
4557 TView *view = gPad->GetView();
4558 if (view) {
4559 if (!Hoption.Lego && !Hoption.Surf && !Hoption.Tri) {
4560 delete view;
4561 gPad->SetView(nullptr);
4562 }
4563 }
4564 if (fH->GetDimension() > 1 || Hoption.Lego || Hoption.Surf) {
4565 // In case of 1D histogram, Z axis becomes Y axis.
4566 Int_t logysav=0, logzsav=0;
4567 if (fH->GetDimension() == 1) {
4570 Hoption.Logz = 0;
4571 if (Hoption.Logy) {
4572 Hoption.Logz = 1;
4573 Hoption.Logy = 0;
4574 }
4575 }
4577 if (Hoption.Func) {
4582 Hoption = hoptsave;
4583 Hparam = hparsave;
4584 }
4587 fXbuf.clear();
4588 fYbuf.clear();
4589 if (fH->GetDimension() == 1) {
4592 }
4593 return;
4594 }
4595
4596 if (Hoption.Bar >= 20) {
4598 fXbuf.clear();
4599 fYbuf.clear();
4600 return;
4601 }
4602
4603 gPad->RangeAxisChanged(); //emit RangeAxisChanged() signal to sync axes
4604 // fill Hparam structure with histo parameters
4605 if (!PaintInit()) {
4606 fXbuf.clear();
4607 fYbuf.clear();
4608 return;
4609 }
4610
4611 // Picture surround (if new page) and page number (if requested).
4612 // Histogram surround (if not option "Same").
4613 PaintFrame();
4614
4615 // Paint histogram axis only
4616 Bool_t gridx = gPad->GetGridx();
4617 Bool_t gridy = gPad->GetGridy();
4618 if (Hoption.Axis > 0) {
4619 if (Hoption.Axis > 1) PaintAxis(kTRUE); //axis with grid
4620 else {
4621 if (gridx) gPad->SetGridx(0);
4622 if (gridy) gPad->SetGridy(0);
4624 if (gridx) gPad->SetGridx(1);
4625 if (gridy) gPad->SetGridy(1);
4626 }
4627 if ((Hoption.Same%10) ==1) Hoption.Same += 1;
4628 goto paintstat;
4629 }
4630 if (gridx || gridy) PaintAxis(kTRUE); // Draw the grid only
4631
4632 // test for options BAR or HBAR
4633 if (Hoption.Bar >= 10) {
4635 }
4636
4637 // do not draw histogram if error bars required
4638 if (!Hoption.Error) {
4639 if (Hoption.Hist && Hoption.Bar<10) PaintHist(option);
4640 }
4641
4642 // test for error bars or option E
4643 if (Hoption.Error) {
4645 if (Hoption.Hist == 2) PaintHist(option);
4646 }
4647
4649
4650 // test for associated function
4651 if (Hoption.Func) {
4656 Hoption = hoptsave;
4657 Hparam = hparsave;
4658 }
4659
4660 if (gridx) gPad->SetGridx(0);
4661 if (gridy) gPad->SetGridy(0);
4663 if (gridx) gPad->SetGridx(1);
4664 if (gridy) gPad->SetGridy(1);
4665
4666 PaintTitle(); // Draw histogram title
4667
4668 // Draw box with histogram statistics and/or fit parameters
4669paintstat:
4670 if ((Hoption.Same%10) != 1 && !fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
4671 TIter next(fFunctions);
4672 TObject *obj = nullptr;
4673 while ((obj = next())) {
4674 if (obj->InheritsFrom(TF1::Class())) break;
4675 obj = nullptr;
4676 }
4677
4678 //Stat is painted twice (first, it will be in canvas' list of primitives),
4679 //second, it will be here, this is not required on iOS.
4680 //Condition is ALWAYS true on a platform different from iOS.
4681 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode())
4682 PaintStat(gStyle->GetOptStat(),(TF1*)obj);
4683 }
4686 fXbuf.clear();
4687 fYbuf.clear();
4688}
4689
4690////////////////////////////////////////////////////////////////////////////////
4691/// [Control function to draw a table as an arrow plot](\ref HP12)
4692
4694{
4696 Double_t dx, dy, x1, x2, y1, y2, xc, yc, dxn, dyn;
4699 Double_t xrg = gPad->GetUxmin();
4700 Double_t yrg = gPad->GetUymin();
4701 Double_t xln = gPad->GetUxmax() - xrg;
4702 Double_t yln = gPad->GetUymax() - yrg;
4703 Double_t cx = (xln/Double_t(ncx))/2.;
4704 Double_t cy = (yln/Double_t(ncy))/2.;
4705 Double_t dn = 1.E-30;
4706
4707 auto arrow = new TArrow();
4708 arrow->SetAngle(30);
4709 arrow->SetFillStyle(1001);
4710 arrow->SetFillColor(fH->GetLineColor());
4711 arrow->SetLineColor(fH->GetLineColor());
4712 arrow->SetLineWidth(fH->GetLineWidth());
4713
4714 // Initialize the levels on the Z axis
4715 Int_t ncolors=0, ndivz=0;
4716 Double_t scale=0.;
4717 if (Hoption.Arrow>1) {
4719 Int_t ndiv = fH->GetContour();
4720 if (ndiv == 0 ) {
4721 ndiv = gStyle->GetNumberContours();
4722 fH->SetContour(ndiv);
4723 }
4724 ndivz = TMath::Abs(ndiv);
4725 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
4727 }
4728
4729 for (Int_t id=1;id<=2;id++) {
4730 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
4733 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
4734 xk = fXaxis->GetBinLowEdge(i);
4735 xstep = fXaxis->GetBinWidth(i);
4736 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
4737 if (i == Hparam.xfirst) {
4738 dx = fH->GetBinContent(i+1, j) - fH->GetBinContent(i, j);
4739 } else if (i == Hparam.xlast) {
4740 dx = fH->GetBinContent(i, j) - fH->GetBinContent(i-1, j);
4741 } else {
4742 dx = 0.5*(fH->GetBinContent(i+1, j) - fH->GetBinContent(i-1, j));
4743 }
4744 if (j == Hparam.yfirst) {
4745 dy = fH->GetBinContent(i, j+1) - fH->GetBinContent(i, j);
4746 } else if (j == Hparam.ylast) {
4747 dy = fH->GetBinContent(i, j) - fH->GetBinContent(i, j-1);
4748 } else {
4749 dy = 0.5*(fH->GetBinContent(i, j+1) - fH->GetBinContent(i, j-1));
4750 }
4751 if (id == 1) {
4754 } else if (id == 2) {
4755 xc = xrg + xln*(Double_t(i - Hparam.xfirst+1)-0.5)/Double_t(ncx);
4756 dxn = cx*dx/dn;
4757 x1 = xc - dxn;
4758 x2 = xc + dxn;
4759 yc = yrg + yln*(Double_t(j - Hparam.yfirst+1)-0.5)/Double_t(ncy);
4760 dyn = cy*dy/dn;
4761 y1 = yc - dyn;
4762 y2 = yc + dyn;
4763 if (Hoption.Arrow>1) {
4764 int color = Int_t(0.01+(fH->GetBinContent(i, j)-fH->GetMinimum())*scale);
4765 Int_t theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
4766 if (theColor > ncolors-1) theColor = ncolors-1;
4767 arrow->SetFillColor(gStyle->GetColorPalette(theColor));
4768 arrow->SetLineColor(gStyle->GetColorPalette(theColor));
4769 }
4770 if (TMath::Abs(x2-x1) > 0. || TMath::Abs(y2-y1) > 0.) {
4771 arrow->PaintArrow(x1, y1, x2, y2, 0.015, "|>");
4772 } else {
4773 arrow->PaintArrow(x1, y1, x2, y2, 0.005, "|>");
4774 }
4775 }
4776 }
4777 }
4778 }
4779
4781}
4782
4783////////////////////////////////////////////////////////////////////////////////
4784/// Draw axis (2D case) of an histogram.
4785///
4786/// If `drawGridOnly` is `TRUE`, only the grid is painted (if needed). This allows
4787/// to draw the grid and the axis separately. In `THistPainter::Paint` this
4788/// feature is used to make sure that the grid is drawn in the background and
4789/// the axis tick marks in the foreground of the pad.
4790
4792{
4793
4794 //On iOS, grid should not be pickable and can not be highlighted.
4795 //Condition is never true on a platform different from iOS.
4796 if (drawGridOnly && (gPad->PadInHighlightMode() || gPad->PadInSelectionMode()))
4797 return;
4798
4799 if (Hoption.Axis == -1) return;
4800 if (Hoption.Same && Hoption.Axis <= 0) return;
4801
4802 // Repainting alphanumeric labels axis on a plot done with
4803 // the option HBAR (horizontal) needs some adjustments.
4804 TAxis *xaxis = nullptr;
4805 TAxis *yaxis = nullptr;
4806 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4807 if (fXaxis->GetLabels() || fYaxis->GetLabels()) { // One axis has alphanumeric labels
4808 TIter next(gPad->GetListOfPrimitives());
4809 TObject *obj;
4810 // Check if the first TH1 of THStack in the pad is drawn with the option HBAR
4811 while ((obj = next())) {
4812 if (!obj->InheritsFrom(TH1::Class()) &&
4813 !obj->InheritsFrom(THStack::Class())) continue;
4814 TString opt = obj->GetDrawOption();
4815 opt.ToLower();
4816 // if drawn with HBAR, the axis should be inverted and the pad set to horizontal
4817 if (strstr(opt,"hbar")) {
4818 gPad->SetVertical(kFALSE);
4819 xaxis = fXaxis;
4820 yaxis = fYaxis;
4821 if (!strcmp(xaxis->GetName(),"xaxis")) {
4822 fXaxis = yaxis;
4823 fYaxis = xaxis;
4824 }
4825 }
4826 break;
4827 }
4828 }
4829 }
4830
4831 static char chopt[10] = "";
4832 Double_t gridl = 0;
4833 Int_t ndiv, ndivx, ndivy, nx1, nx2, ndivsave;
4834 Int_t useHparam = 0;
4838
4839 Double_t axmin = gPad->GetUxmin();
4840 Double_t axmax = gPad->GetUxmax();
4841 Double_t aymin = gPad->GetUymin();
4842 Double_t aymax = gPad->GetUymax();
4843 char *cw = nullptr;
4844 TGaxis axis;
4845
4846 // In case of option 'cont4' or in case of option 'same' over a 'cont4 plot'
4847 // Hparam must be use for the axis limits.
4848 if (Hoption.Contour == 14) useHparam = 1;
4849 if (Hoption.Same) {
4850 TObject *obj;
4851 TIter next(gPad->GetListOfPrimitives());
4852 while ((obj=next())) {
4853 if (strstr(obj->GetDrawOption(),"cont4")) {
4854 useHparam = 1;
4855 break;
4856 }
4857 }
4858 }
4859
4860 // Paint X axis
4861
4862 //To make X-axis selectable on iOS device.
4863 if (gPad->PadInSelectionMode())
4864 gPad->PushSelectableObject(fXaxis);
4865
4866 //This condition is ALWAYS true, unless it works on iOS (can be false on iOS).
4867 if (gPad->PadInSelectionMode() || !gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && gPad->GetSelected() == fXaxis)) {
4869 if (ndivx > 1000) {
4870 nx2 = ndivx/100;
4871 nx1 = TMath::Max(1, ndivx%100);
4872 ndivx = 100*nx2 + Int_t(Float_t(nx1)*gPad->GetAbsWNDC());
4873 }
4874 axis.SetTextAngle(0);
4876
4877 chopt[0] = 0;
4878 strlcat(chopt, "SDH",10);
4879 if (ndivx < 0) strlcat(chopt, "N",10);
4880 if (gPad->GetGridx()) {
4881 gridl = (aymax-aymin)/(gPad->GetY2() - gPad->GetY1());
4882 strlcat(chopt, "W",10);
4883 }
4884
4885 // Define X-Axis limits
4886 if (Hoption.Logx) {
4887 strlcat(chopt, "G",10);
4888 ndiv = TMath::Abs(ndivx);
4889 if (useHparam) {
4892 } else {
4893 umin = TMath::Power(10,axmin);
4894 umax = TMath::Power(10,axmax);
4895 }
4896 } else {
4897 ndiv = TMath::Abs(ndivx);
4898 if (useHparam) {
4899 umin = Hparam.xmin;
4900 umax = Hparam.xmax;
4901 } else {
4902 umin = axmin;
4903 umax = axmax;
4904 }
4905 }
4906
4907 // Display axis as time
4908 if (fXaxis->GetTimeDisplay()) {
4909 strlcat(chopt,"t",10);
4910 if (strlen(fXaxis->GetTimeFormatOnly()) == 0) {
4912 }
4913 }
4914
4915 // The main X axis can be on the bottom or on the top of the pad
4917 if (xAxisPos == 1) {
4918 // Main X axis top
4919 xAxisYPos1 = aymax;
4920 xAxisYPos2 = aymin;
4921 } else {
4922 // Main X axis bottom
4923 xAxisYPos1 = aymin;
4924 xAxisYPos2 = aymax;
4925 }
4926
4927 // Paint the main X axis (always)
4928 uminsave = umin;
4929 umaxsave = umax;
4930 ndivsave = ndiv;
4931 axis.SetOption(chopt);
4932 if (xAxisPos) {
4933 strlcat(chopt, "-",10);
4934 gridl = -gridl;
4935 }
4936 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4937 axis.SetLabelSize(0.);
4938 axis.SetTitle("");
4939 }
4942 umin, umax, ndiv, chopt, gridl, drawGridOnly);
4943
4944 // Paint additional X axis (if needed)
4945 // On iOS, this additional X axis is neither pickable, nor highlighted.
4946 // Additional checks PadInSelectionMode etc. does not effect non-iOS platform.
4947 if (gPad->GetTickx() && !gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
4948 if (xAxisPos) {
4949 cw=strstr(chopt,"-");
4950 *cw='z';
4951 } else {
4952 strlcat(chopt, "-",10);
4953 }
4954 if (gPad->GetTickx() < 2) strlcat(chopt, "U",10);
4955 if ((cw=strstr(chopt,"W"))) *cw='z';
4956 axis.SetTitle("");
4960 }
4961 }//End of "if pad in selection mode etc".
4962
4963 // Paint Y axis
4964 //On iOS, Y axis must pushed into the stack of selectable objects.
4965 if (gPad->PadInSelectionMode())
4966 gPad->PushSelectableObject(fYaxis);
4967
4968 //This conditions is ALWAYS true on a platform, different from iOS (on iOS can be true, can be false).
4969 if (gPad->PadInSelectionMode() || !gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && gPad->GetSelected() == fYaxis)) {
4972
4973 chopt[0] = 0;
4974 strlcat(chopt, "SDH",10);
4975 if (ndivy < 0) strlcat(chopt, "N",10);
4976 if (gPad->GetGridy()) {
4977 gridl = (axmax-axmin)/(gPad->GetX2() - gPad->GetX1());
4978 strlcat(chopt, "W",10);
4979 }
4980
4981 // Define Y-Axis limits
4982 if (Hoption.Logy) {
4983 strlcat(chopt, "G",10);
4984 ndiv = TMath::Abs(ndivy);
4985 if (useHparam) {
4988 } else {
4989 umin = TMath::Power(10,aymin);
4990 umax = TMath::Power(10,aymax);
4991 }
4992 } else {
4993 ndiv = TMath::Abs(ndivy);
4994 if (useHparam) {
4995 umin = Hparam.ymin;
4996 umax = Hparam.ymax;
4997 } else {
4998 umin = aymin;
4999 umax = aymax;
5000 }
5001 }
5002
5003 // Display axis as time
5004 if (fYaxis->GetTimeDisplay()) {
5005 strlcat(chopt,"t",10);
5006 if (strlen(fYaxis->GetTimeFormatOnly()) == 0) {
5008 }
5009 }
5010
5011 // The main Y axis can be on the left or on the right of the pad
5013 if (yAxisPos == 1) {
5014 // Main Y axis left
5015 yAxisXPos1 = axmax;
5016 yAxisXPos2 = axmin;
5017 } else {
5018 // Main Y axis right
5019 yAxisXPos1 = axmin;
5020 yAxisXPos2 = axmax;
5021 }
5022
5023 // Paint the main Y axis (always)
5024 uminsave = umin;
5025 umaxsave = umax;
5026 ndivsave = ndiv;
5027 axis.SetOption(chopt);
5028 if (yAxisPos) {
5029 strlcat(chopt, "+L",10);
5030 gridl = -gridl;
5031 }
5032 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
5033 axis.SetLabelSize(0.);
5034 axis.SetTitle("");
5035 }
5038 umin, umax, ndiv, chopt, gridl, drawGridOnly);
5039
5040 // Paint the additional Y axis (if needed)
5041 // Additional checks for pad mode are required on iOS: this "second" axis is
5042 // neither pickable, nor highlighted. Additional checks have no effect on non-iOS platform.
5043 if (gPad->GetTicky() && !gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
5044 if (gPad->GetTicky() < 2) {
5045 strlcat(chopt, "U",10);
5047 } else {
5048 strlcat(chopt, "+L",10);
5049 }
5050 if ((cw=strstr(chopt,"W"))) *cw='z';
5051 axis.SetTitle("");
5055 }
5056 }//End of "if pad is in selection mode etc."
5057
5058 // Reset the axis if they have been inverted in case of option HBAR
5059 if (xaxis) {
5060 fXaxis = xaxis;
5061 fYaxis = yaxis;
5062 }
5063}
5064
5065////////////////////////////////////////////////////////////////////////////////
5066/// [Draw a bar-chart in a normal pad.](\ref HP10)
5067
5069{
5070
5071 Int_t bar = Hoption.Bar - 10;
5075 TBox box;
5077 if (hcolor == gPad->GetFrameFillColor()) ++hcolor;
5079 box.SetFillColor(hcolor);
5080 box.SetFillStyle(hstyle);
5081 box.SetLineStyle(fH->GetLineStyle());
5082 box.SetLineColor(fH->GetLineColor());
5083 box.SetLineWidth(fH->GetLineWidth());
5084 for (Int_t bin=fXaxis->GetFirst();bin<=fXaxis->GetLast();bin++) {
5085 y = fH->GetBinContent(bin);
5086 xmin = gPad->XtoPad(fXaxis->GetBinLowEdge(bin));
5087 xmax = gPad->XtoPad(fXaxis->GetBinUpEdge(bin));
5088 ymin = gPad->GetUymin();
5089 ymax = gPad->YtoPad(y);
5090 if (ymax < gPad->GetUymin()) continue;
5091 if (ymax > gPad->GetUymax()) ymax = gPad->GetUymax();
5092 if (ymin < gPad->GetUymin()) ymin = gPad->GetUymin();
5093 if (Hoption.MinimumZero && ymin < 0)
5094 ymin=TMath::Min(0.,gPad->GetUymax());
5095 w = (xmax-xmin)*width;
5096 xmin += offset*(xmax-xmin);
5097 xmax = xmin + w;
5098 if (bar < 1) {
5099 box.PaintBox(xmin,ymin,xmax,ymax);
5100 } else {
5101 umin = xmin + bar*(xmax-xmin)/10.;
5102 umax = xmax - bar*(xmax-xmin)/10.;
5103 box.SetFillColor(TColor::GetColorBright(hcolor)); //bright
5104 box.PaintBox(xmin,ymin,umin,ymax);
5105 box.SetFillColor(hcolor);
5106 box.PaintBox(umin,ymin,umax,ymax);
5107 box.SetFillColor(TColor::GetColorDark(hcolor)); //dark
5108 box.PaintBox(umax,ymin,xmax,ymax);
5109 }
5110 }
5111}
5112
5113////////////////////////////////////////////////////////////////////////////////
5114/// [Draw a bar char in a rotated pad (X vertical, Y horizontal)](\ref HP10)
5115
5117{
5118
5119 gPad->SetVertical(kFALSE);
5120
5121 PaintInitH();
5122
5123 TAxis *xaxis = fXaxis;
5124 TAxis *yaxis = fYaxis;
5125 if (!strcmp(xaxis->GetName(),"xaxis")) {
5126 fXaxis = yaxis;
5127 fYaxis = xaxis;
5128 }
5129
5130 PaintFrame();
5132
5133 Int_t bar = Hoption.Bar - 20;
5137 TBox box;
5139 if (hcolor == gPad->GetFrameFillColor()) ++hcolor;
5141 box.SetFillColor(hcolor);
5142 box.SetFillStyle(hstyle);
5143 box.SetLineStyle(fH->GetLineStyle());
5144 box.SetLineColor(fH->GetLineColor());
5145 box.SetLineWidth(fH->GetLineWidth());
5146 for (Int_t bin=fYaxis->GetFirst();bin<=fYaxis->GetLast();bin++) {
5147 ymin = gPad->YtoPad(fYaxis->GetBinLowEdge(bin));
5148 ymax = gPad->YtoPad(fYaxis->GetBinUpEdge(bin));
5149 xmin = gPad->GetUxmin();
5150 xmax = gPad->XtoPad(fH->GetBinContent(bin));
5151 if (xmax < gPad->GetUxmin()) continue;
5152 if (xmax > gPad->GetUxmax()) xmax = gPad->GetUxmax();
5153 if (xmin < gPad->GetUxmin()) xmin = gPad->GetUxmin();
5154 if (Hoption.MinimumZero && xmin < 0)
5155 xmin=TMath::Min(0.,gPad->GetUxmax());
5156 w = (ymax-ymin)*width;
5157 ymin += offset*(ymax-ymin);
5158 ymax = ymin + w;
5159 if (bar < 1) {
5160 box.PaintBox(xmin,ymin,xmax,ymax);
5161 } else {
5162 umin = ymin + bar*(ymax-ymin)/10.;
5163 umax = ymax - bar*(ymax-ymin)/10.;
5164 box.SetFillColor(TColor::GetColorDark(hcolor)); //dark
5165 box.PaintBox(xmin,ymin,xmax,umin);
5166 box.SetFillColor(hcolor);
5167 box.PaintBox(xmin,umin,xmax,umax);
5168 box.SetFillColor(TColor::GetColorBright(hcolor)); //bright
5169 box.PaintBox(xmin,umax,xmax,ymax);
5170 }
5171 }
5172
5173 PaintTitle();
5174
5175 // Draw box with histogram statistics and/or fit parameters
5176 if ((Hoption.Same%10) != 1 && !fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
5177 TIter next(fFunctions);
5178 TObject *obj = nullptr;
5179 while ((obj = next())) {
5180 if (obj->InheritsFrom(TF1::Class())) break;
5181 obj = nullptr;
5182 }
5183 PaintStat(gStyle->GetOptStat(),(TF1*)obj);
5184 }
5185
5186 fXaxis = xaxis;
5187 fYaxis = yaxis;
5188}
5189
5190////////////////////////////////////////////////////////////////////////////////
5191/// [Control function to draw a 2D histogram as a box plot](\ref HP13)
5192
5194{
5195
5198 if (fH->GetFillColor() == 0) fH->SetFillStyle(0);
5199 if (Hoption.Box == 11) fH->SetFillStyle(1001);
5200 fH->TAttLine::Modify();
5201 fH->TAttFill::Modify();
5202
5203 Double_t z, xk,xstep, yk, ystep, xcent, ycent, xlow, xup, ylow, yup;
5204 Double_t ux1 = gPad->PixeltoX(1);
5205 Double_t ux0 = gPad->PixeltoX(0);
5206 Double_t uy1 = gPad->PixeltoY(1);
5207 Double_t uy0 = gPad->PixeltoY(0);
5208 Double_t dxmin = 0.51*(gPad->PadtoX(ux1)-gPad->PadtoX(ux0));
5209 Double_t dymin = 0.51*(gPad->PadtoY(uy0)-gPad->PadtoY(uy1));
5210
5211 Double_t zmin = TMath::Max(fH->GetMinimum(),0.);
5214 Double_t zminlin = zmin, zmaxlin = zmax;
5215
5216 // In case of option SAME, zmin and zmax values are taken from the
5217 // first plotted 2D histogram.
5218 if (Hoption.Same > 0 && Hoption.Same < 10) {
5219 TH2 *h2;
5220 TIter next(gPad->GetListOfPrimitives());
5221 while ((h2 = (TH2 *)next())) {
5222 if (!h2->InheritsFrom(TH2::Class())) continue;
5223 zmin = TMath::Max(h2->GetMinimum(), 0.);
5224 zmax = TMath::Max(TMath::Abs(h2->GetMaximum()),
5225 TMath::Abs(h2->GetMinimum()));
5226 zminlin = zmin;
5227 zmaxlin = zmax;
5228 if (Hoption.Logz) {
5229 if (zmin <= 0) {
5230 zmin = TMath::Log10(zmax*0.001);
5231 } else {
5232 zmin = TMath::Log10(zmin);
5233 }
5234 zmax = TMath::Log10(zmax);
5235 }
5236 break;
5237 }
5238 } else {
5239 if (Hoption.Logz) {
5240 if (zmin > 0) {
5241 zmin = TMath::Log10(zmin);
5242 zmax = TMath::Log10(zmax);
5243 } else {
5244 return;
5245 }
5246 }
5247 }
5248
5249 Double_t zratio, dz = zmax - zmin;
5251 if (fH->GetMinimum()<0) kZminNeg = kTRUE;
5253
5254 // Define the dark and light colors the "button style" boxes.
5255 Color_t color = fH->GetFillColor();
5256 Color_t light=0, dark=0;
5257 if (Hoption.Box == 11) {
5259 dark = TColor::GetColorDark(color);
5260 }
5261
5262 // Loop over all the bins and draw the boxes
5263 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
5266 ycent = 0.5*ystep;
5267 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
5268 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
5269 xk = fXaxis->GetBinLowEdge(i);
5270 xstep = fXaxis->GetBinWidth(i);
5271 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
5272 xcent = 0.5*xstep;
5274 kZNeg = kFALSE;
5275
5276 if (TMath::Abs(z) < zminlin) continue; // Can be the case with ...
5277 if (TMath::Abs(z) > zmaxlin) z = zmaxlin; // ... option Same
5278 if (kZminNeg && z==0) continue; // Do not draw empty bins if case of histo with negative bins.
5279
5280 if (z < 0) {
5281 if (Hoption.Logz) continue;
5282 z = -z;
5283 kZNeg = kTRUE;
5284 }
5285 if (Hoption.Logz) {
5286 if (z != 0) z = TMath::Log10(z);
5287 else z = zmin;
5288 }
5289
5290 if (dz == 0) continue;
5291 zratio = TMath::Sqrt((z-zmin)/dz);
5292 if (zratio == 0) continue;
5293
5294 xup = xcent*zratio + xk + xcent;
5295 xlow = 2*(xk + xcent) - xup;
5296 if (xup-xlow < dxmin) xup = xlow+dxmin;
5297 if (Hoption.Logx) {
5298 if (xup > 0) xup = TMath::Log10(xup);
5299 else continue;
5300 if (xlow > 0) xlow = TMath::Log10(xlow);
5301 else continue;
5302 }
5303
5304 yup = ycent*zratio + yk + ycent;
5305 ylow = 2*(yk + ycent) - yup;
5306 if (yup-ylow < dymin) yup = ylow+dymin;
5307 if (Hoption.Logy) {
5308 if (yup > 0) yup = TMath::Log10(yup);
5309 else continue;
5310 if (ylow > 0) ylow = TMath::Log10(ylow);
5311 else continue;
5312 }
5313
5314 xlow = TMath::Max(xlow, gPad->GetUxmin());
5315 ylow = TMath::Max(ylow, gPad->GetUymin());
5316 xup = TMath::Min(xup , gPad->GetUxmax());
5317 yup = TMath::Min(yup , gPad->GetUymax());
5318
5319 if (xlow >= xup) continue;
5320 if (ylow >= yup) continue;
5321
5322 if (Hoption.Box == 1) {
5323 fH->SetFillColor(color);
5324 fH->TAttFill::Modify();
5325 gPad->PaintBox(xlow, ylow, xup, yup);
5326 if (kZNeg) {
5327 gPad->PaintLine(xlow, ylow, xup, yup);
5328 gPad->PaintLine(xlow, yup, xup, ylow);
5329 }
5330 } else if (Hoption.Box == 11) {
5331 // Draw the center of the box
5332 fH->SetFillColor(color);
5333 fH->TAttFill::Modify();
5334 gPad->PaintBox(xlow, ylow, xup, yup);
5335
5336 // Draw top&left part of the box
5337 Double_t x[7], y[7];
5338 Double_t bwidth = 0.1;
5339 x[0] = xlow; y[0] = ylow;
5340 x[1] = xlow + bwidth*(xup-xlow); y[1] = ylow + bwidth*(yup-ylow);
5341 x[2] = x[1]; y[2] = yup - bwidth*(yup-ylow);
5342 x[3] = xup - bwidth*(xup-xlow); y[3] = y[2];
5343 x[4] = xup; y[4] = yup;
5344 x[5] = xlow; y[5] = yup;
5345 x[6] = xlow; y[6] = ylow;
5346 if (kZNeg) fH->SetFillColor(dark);
5347 else fH->SetFillColor(light);
5348 fH->TAttFill::Modify();
5349 gPad->PaintFillArea(7, x, y);
5350
5351 // Draw bottom&right part of the box
5352 x[0] = xlow; y[0] = ylow;
5353 x[1] = xlow + bwidth*(xup-xlow); y[1] = ylow + bwidth*(yup-ylow);
5354 x[2] = xup - bwidth*(xup-xlow); y[2] = y[1];
5355 x[3] = x[2]; y[3] = yup - bwidth*(yup-ylow);
5356 x[4] = xup; y[4] = yup;
5357 x[5] = xup; y[5] = ylow;
5358 x[6] = xlow; y[6] = ylow;
5359 if (kZNeg) fH->SetFillColor(light);
5360 else fH->SetFillColor(dark);
5361 fH->TAttFill::Modify();
5362 gPad->PaintFillArea(7, x, y);
5363 }
5364 }
5365 }
5366
5370 fH->TAttFill::Modify();
5371}
5372
5373
5374
5375////////////////////////////////////////////////////////////////////////////////
5376/// [Control function to draw a 2D histogram as a candle (box) plot or violin plot](\ref HP14)
5377
5379{
5380 TH1D *hproj = nullptr;
5381 TH2D *h2 = (TH2D*)fH;
5382
5385 myCandle.SetMarkerColor(fH->GetLineColor());
5386 myCandle.SetLineColor(fH->GetLineColor());
5387 myCandle.SetLineWidth(fH->GetLineWidth());
5388 myCandle.SetFillColor(fH->GetFillColor());
5389 myCandle.SetFillStyle(fH->GetFillStyle());
5390 myCandle.SetMarkerSize(fH->GetMarkerSize());
5391 myCandle.SetMarkerStyle(fH->GetMarkerStyle());
5393
5394 Bool_t swapXY = myCandle.IsHorizontal();
5395 const Double_t standardCandleWidth = 0.66;
5396 const Double_t standardHistoWidth = 0.8;
5397
5398 double allMaxContent = 0, allMaxIntegral = 0;
5399 if (myCandle.IsViolinScaled())
5401
5402 if (!swapXY) { // Vertical candle
5403 //Determining the slice with the maximum integral - if necessary
5404 if (myCandle.IsCandleScaled())
5405 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast; i++) {
5406 hproj = h2->ProjectionY("_px", i, i);
5407 if (hproj->Integral() > allMaxIntegral) allMaxIntegral = hproj->Integral();
5408 }
5409 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast; i++) {
5411 Double_t binWidth = fXaxis->GetBinWidth(i);
5412 hproj = h2->ProjectionY("_px", i, i);
5413 if (hproj->GetEntries() != 0) {
5415 Double_t offset = fH->GetBarOffset()*binWidth;
5416 double myMaxContent = hproj->GetBinContent(hproj->GetMaximumBin());
5417 double myIntegral = hproj->Integral();
5419 if (candleWidth > 0.999 && candleWidth < 1.001) {
5422 }
5423 if (Hoption.Logz && myMaxContent > 0) {
5425 if (myCandle.IsViolinScaled() && myMaxContent > 0 && allMaxContent > 0)
5427 } else if (myCandle.IsViolinScaled() && (allMaxContent > 0))
5429 if (myCandle.IsCandleScaled() && (allMaxIntegral > 0))
5431
5432 myCandle.SetAxisPosition(binPosX+binWidth/2. + offset);
5433 myCandle.SetCandleWidth(candleWidth*binWidth);
5434 myCandle.SetHistoWidth(histoWidth*binWidth);
5435 myCandle.SetHistogram(hproj);
5436 myCandle.Paint();
5437 }
5438 }
5439 } else { // Horizontal candle
5440 //Determining the slice with the maximum integral - if necessary
5441 if (myCandle.IsCandleScaled())
5442 for (Int_t i=Hparam.yfirst; i<=Hparam.ylast; i++) {
5443 hproj = h2->ProjectionX("_py", i, i);
5444 if (hproj->Integral() > allMaxIntegral) allMaxIntegral = hproj->Integral();
5445 }
5446 for (Int_t i=Hparam.yfirst; i<=Hparam.ylast; i++) {
5448 Double_t binWidth = fYaxis->GetBinWidth(i);
5449 hproj = h2->ProjectionX("_py", i, i);
5450 if (hproj->GetEntries() != 0) {
5452 Double_t offset = fH->GetBarOffset()*binWidth;
5453 double myMaxContent = hproj->GetBinContent(hproj->GetMaximumBin());
5454 double myIntegral = hproj->Integral();
5456 if (candleWidth > 0.999 && candleWidth < 1.001) {
5459 }
5460 if (Hoption.Logz && myMaxContent > 0) {
5462 if (myCandle.IsViolinScaled() && myMaxContent > 0 && allMaxContent > 0)
5464 } else if (myCandle.IsViolinScaled() && (allMaxContent > 0))
5466 if (myCandle.IsCandleScaled() && (allMaxIntegral > 0))
5468
5469 myCandle.SetAxisPosition(binPosY+binWidth/2. + offset);
5470 myCandle.SetCandleWidth(candleWidth*binWidth);
5471 myCandle.SetHistoWidth(histoWidth*binWidth);
5472 myCandle.SetHistogram(hproj);
5473 myCandle.Paint();
5474 }
5475 }
5476 }
5477 delete hproj;
5478}
5479
5480
5481
5482////////////////////////////////////////////////////////////////////////////////
5483/// Returns the rendering regions for an axis to use in the COL2 option
5484///
5485/// The algorithm analyses the size of the axis compared to the size of
5486/// the rendering region. It figures out the boundaries to use for each color
5487/// of the rendering region. Only one axis is computed here.
5488///
5489/// This allows for a single computation of the boundaries before iterating
5490/// through all of the bins.
5491///
5492/// \param pAxis the axis to consider
5493/// \param nPixels the number of pixels to render axis into
5494/// \param isLog whether the axis is log scale
5495
5496std::vector<THistRenderingRegion>
5498{
5499 std::vector<THistRenderingRegion> regions;
5500
5501 enum STRATEGY { Bins, Pixels } strategy;
5502
5503 Int_t nBins = (pAxis->GetLast() - pAxis->GetFirst() + 1);
5504
5505 if (nBins >= nPixels) {
5506 // more bins than pixels... we should loop over pixels and sample
5507 strategy = Pixels;
5508 } else {
5509 // fewer bins than pixels... we should loop over bins
5510 strategy = Bins;
5511 }
5512
5513 if (isLog) {
5514
5515 Double_t xMin = pAxis->GetBinLowEdge(pAxis->GetFirst());
5516 Int_t binOffset=0;
5517 while (xMin <= 0 && ((pAxis->GetFirst()+binOffset) != pAxis->GetLast()) ) {
5518 binOffset++;
5519 xMin = pAxis->GetBinLowEdge(pAxis->GetFirst()+binOffset);
5520 }
5521 if (xMin <= 0) {
5522 // this should cause an error if we have
5523 return regions;
5524 }
5525 Double_t xMax = pAxis->GetBinUpEdge(pAxis->GetLast());
5526
5527 if (strategy == Bins) {
5528 // logarithmic plot. we find the pixel for the bin
5529 // pixel = eta * log10(V) - alpha
5530 // where eta = nPixels/(log10(Vmax)-log10(Vmin))
5531 // and alpha = nPixels*log10(Vmin)/(log10(Vmax)-log10(Vmin))
5532 // and V is axis value
5534 Double_t offset = -1.0 * eta * TMath::Log10(xMin);
5535
5536 for (Int_t bin=pAxis->GetFirst()+binOffset; bin<=pAxis->GetLast(); bin++) {
5537
5538 // linear plot. we simply need to find the appropriate bin
5539 // for the
5540 Double_t xLowValue = pAxis->GetBinLowEdge(bin);
5541 Double_t xUpValue = pAxis->GetBinUpEdge(bin);
5544 THistRenderingRegion region = {std::make_pair(xPx0, xPx1),
5545 std::make_pair(bin, bin+1)};
5546 regions.push_back(region);
5547 }
5548
5549 } else {
5550
5551 // loop over pixels
5552
5554
5555 for (Int_t pixelIndex=0; pixelIndex<(nPixels-1); pixelIndex++) {
5556 // linear plot
5557 Int_t binLow = pAxis->FindBin(xMin*TMath::Power(10.0, beta*pixelIndex));
5558 Int_t binHigh = pAxis->FindBin(xMin*TMath::Power(10.0, beta*(pixelIndex+1)));
5559 THistRenderingRegion region = { std::make_pair(pixelIndex, pixelIndex+1),
5560 std::make_pair(binLow, binHigh)};
5561 regions.push_back(region);
5562 }
5563 }
5564 } else {
5565 // standard linear plot
5566
5567 if (strategy == Bins) {
5568 // loop over bins
5569 for (Int_t bin=pAxis->GetFirst(); bin<=pAxis->GetLast(); bin++) {
5570
5571 // linear plot. we simply need to find the appropriate bin
5572 // for the
5573 Int_t xPx0 = ((bin - pAxis->GetFirst()) * nPixels)/nBins;
5574 Int_t xPx1 = xPx0 + nPixels/nBins;
5575
5576 // make sure we don't compute beyond our bounds
5577 if (xPx1>= nPixels) xPx1 = nPixels-1;
5578
5579 THistRenderingRegion region = {std::make_pair(xPx0, xPx1),
5580 std::make_pair(bin, bin+1)};
5581 regions.push_back(region);
5582 }
5583 } else {
5584 // loop over pixels
5586 // linear plot
5587 Int_t binLow = (nBins*pixelIndex)/nPixels + pAxis->GetFirst();
5588 Int_t binHigh = binLow + nBins/nPixels;
5589 THistRenderingRegion region = { std::make_pair(pixelIndex, pixelIndex+1),
5590 std::make_pair(binLow, binHigh)};
5591 regions.push_back(region);
5592 }
5593 }
5594 }
5595
5596 return regions;
5597}
5598
5599////////////////////////////////////////////////////////////////////////////////
5600/// [Rendering scheme for the COL2 and COLZ2 options] (\ref HP14)
5601
5603{
5604
5605 if (Hoption.System != kCARTESIAN) {
5606 Error("THistPainter::PaintColorLevelsFast(Option_t*)",
5607 "Only cartesian coordinates supported by 'COL2' option. Using 'COL' option instead.");
5608 PaintColorLevels(nullptr);
5609 return;
5610 }
5611
5612 Double_t z;
5613
5614 // Use existing max or min values. If either is already set
5615 // the appropriate value to use.
5616 Double_t zmin = fH->GetMinimumStored();
5617 Double_t zmax = fH->GetMaximumStored();
5618 Double_t originalZMin = zmin;
5619 Double_t originalZMax = zmax;
5620 if ((zmin == -1111) && (zmax == -1111)) {
5621 fH->GetMinimumAndMaximum(zmin, zmax);
5622 fH->SetMinimum(zmin);
5623 fH->SetMaximum(zmax);
5624 } else if (zmin == -1111) {
5625 zmin = fH->GetMinimum();
5626 fH->SetMinimum(zmin);
5627 } else if (zmax == -1111) {
5628 zmax = fH->GetMaximum();
5629 fH->SetMaximum(zmax);
5630 }
5631
5632 Double_t dz = zmax - zmin;
5633 if (dz <= 0) { // Histogram filled with a constant value
5634 zmax += 0.1*TMath::Abs(zmax);
5635 zmin -= 0.1*TMath::Abs(zmin);
5636 dz = zmax - zmin;
5637 }
5638
5639 if (Hoption.Logz) {
5640 if (zmin > 0) {
5641 zmin = TMath::Log10(zmin);
5642 zmax = TMath::Log10(zmax);
5643 dz = zmax - zmin;
5644 } else {
5645 Error("THistPainter::PaintColorLevelsFast(Option_t*)",
5646 "Cannot plot logz because bin content is less than 0.");
5647 return;
5648 }
5649 }
5650
5651 // Initialize the levels on the Z axis
5652 Int_t ndiv = fH->GetContour();
5653 if (ndiv == 0 ) {
5654 ndiv = gStyle->GetNumberContours();
5655 fH->SetContour(ndiv);
5656 }
5657 std::vector<Double_t> colorBounds(ndiv);
5658 std::vector<Double_t> contours(ndiv, 0);
5659 if (!fH->TestBit(TH1::kUserContour)) {
5660 fH->SetContour(ndiv);
5661 } else {
5662 fH->GetContour(contours.data());
5663 }
5664
5665 Double_t step = 1.0/ndiv;
5666 for (Int_t i=0; i<ndiv; ++i) {
5667 colorBounds[i] = step*i;
5668 }
5669
5670 auto pFrame = gPad->GetFrame();
5671 Int_t px0 = gPad->XtoPixel(pFrame->GetX1());
5672 Int_t px1 = gPad->XtoPixel(pFrame->GetX2());
5673 Int_t py0 = gPad->YtoPixel(pFrame->GetY1());
5674 Int_t py1 = gPad->YtoPixel(pFrame->GetY2());
5675 Int_t nXPixels = px1-px0;
5676 Int_t nYPixels = py0-py1; // y=0 is at the top of the screen
5677
5678 std::vector<Double_t> buffer(nXPixels*nYPixels, 0);
5679
5682 if (xRegions.empty() || yRegions.empty()) {
5683 Error("THistPainter::PaintColorLevelFast(Option_t*)",
5684 "Encountered error while computing rendering regions.");
5685 return;
5686 }
5687
5690 Double_t minValue = 1.;
5691 Double_t maxValue = 0.;
5692 for (auto& yRegion : yRegions) {
5693 for (auto& xRegion : xRegions ) {
5694
5695 const auto& xBinRange = xRegion.fBinRange;
5696 const auto& yBinRange = yRegion.fBinRange;
5697
5698 // sample the range
5699 z = fH->GetBinContent(xBinRange.second-1, yBinRange.second-1);
5700
5701 if (Hoption.Logz) {
5702 if (z > 0) z = TMath::Log10(z);
5703 else z = zmin;
5704 }
5705
5706 // obey the user's max and min values if they were set
5707 if (z > zmax) z = zmax;
5708 if (z < zmin) z = zmin;
5709
5711 // contours are absolute values
5712 auto index = TMath::BinarySearch(contours.size(), contours.data(), z);
5713 z = colorBounds[index];
5714 } else {
5715 Int_t index = 0;
5716 if (dz != 0) {
5717 index = 0.001 + ((z - zmin)/dz)*ndiv;
5718 }
5719
5720 if (index == static_cast<Int_t>(colorBounds.size())) {
5721 index--;
5722 }
5723
5724 // Do a little bookkeeping to use later for getting libAfterImage to produce
5725 // the correct colors
5726 if (index == 0) {
5727 minExists = kTRUE;
5728 } else if (index == static_cast<Int_t>(colorBounds.size()-1)) {
5729 maxExists = kTRUE;
5730 }
5731
5732 z = colorBounds[index];
5733
5734 if (z < minValue) {
5735 minValue = z;
5736 }
5737 if (z > maxValue) {
5738 maxValue = z;
5739 }
5740 }
5741
5742 // fill in the actual pixels
5743 const auto& xPixelRange = xRegion.fPixelRange;
5744 const auto& yPixelRange = yRegion.fPixelRange;
5745 for (Int_t xPx = xPixelRange.first; xPx <= xPixelRange.second; ++xPx) {
5746 for (Int_t yPx = yPixelRange.first; yPx <= yPixelRange.second; ++yPx) {
5748 buffer[pixel] = z;
5749 }
5750 }
5751 } // end px loop
5752 } // end py loop
5753
5754 // This is a bit of a hack to ensure that we span the entire color range and
5755 // don't screw up the colors for a sparse histogram. No one will notice that I set a
5756 // single pixel on the edge of the image to a different color. This is even more
5757 // true because the chosen pixels will be covered by the axis.
5758 if (minValue != maxValue) {
5759 if ( !minExists) {
5760 buffer.front() = 0;
5761 }
5762
5763 if ( !maxExists) {
5764 buffer[buffer.size()-nXPixels] = 0.95;
5765 }
5766 }
5767
5768 // Generate the TImage
5771 pImage->SetImageQuality(TAttImage::kImgBest);
5772 pImage->SetImage(buffer.data(), nXPixels, nYPixels, pPalette);
5773 delete pPalette;
5774
5775 Window_t wid = static_cast<Window_t>(gVirtualX->GetWindowID(gPad->GetPixmapID()));
5776 pImage->PaintImage(wid, px0, py1, 0, 0, nXPixels, nYPixels);
5777 delete pImage;
5778
5780
5781 // Reset the maximum and minimum values to their original values
5782 // when this function was called. If we don't do this, an initial
5783 // value of -1111 will be replaced with the true max or min values.
5786}
5787
5788////////////////////////////////////////////////////////////////////////////////
5789/// [Control function to draw a 2D histogram as a color plot.](\ref HP14)
5790
5792{
5793 Double_t z, e, zc, xk, xstep, yk, ystep, xlow, xup, ylow, yup;
5794
5795 Double_t zmin = fH->GetMinimum();
5796 Double_t zmax = fH->GetMaximum();
5797
5798 Double_t dz = zmax - zmin;
5799 if (dz <= 0) { // Histogram filled with a constant value
5800 zmax += 0.1*TMath::Abs(zmax);
5801 zmin -= 0.1*TMath::Abs(zmin);
5802 dz = zmax - zmin;
5803 }
5804
5805 // In case of option SAME, zmin and zmax values are taken from the
5806 // first plotted 2D histogram.
5807 if (Hoption.Same > 0 && Hoption.Same < 10) {
5808 TH2 *h2;
5809 TIter next(gPad->GetListOfPrimitives());
5810 while ((h2 = (TH2 *)next())) {
5811 if (!h2->InheritsFrom(TH2::Class())) continue;
5812 zmin = h2->GetMinimum();
5813 zmax = h2->GetMaximum();
5814 fH->SetMinimum(zmin);
5815 fH->SetMaximum(zmax);
5816 if (Hoption.Logz) {
5817 if (zmin <= 0) {
5818 zmin = TMath::Log10(zmax*0.001);
5819 } else {
5820 zmin = TMath::Log10(zmin);
5821 }
5822 zmax = TMath::Log10(zmax);
5823 }
5824 dz = zmax - zmin;
5825 break;
5826 }
5827 } else {
5828 if (Hoption.Logz) {
5829 if (zmin > 0) {
5830 zmin = TMath::Log10(zmin);
5831 zmax = TMath::Log10(zmax);
5832 dz = zmax - zmin;
5833 } else {
5834 return;
5835 }
5836 }
5837 }
5838
5841 fH->SetFillStyle(1001);
5842 fH->TAttFill::Modify();
5843
5844 // Initialize the levels on the Z axis
5846 Int_t ndiv = fH->GetContour();
5847 if (ndiv == 0) {
5848 ndiv = gStyle->GetNumberContours();
5849 fH->SetContour(ndiv);
5850 }
5851 Int_t ndivz = TMath::Abs(ndiv);
5852 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
5853 Double_t scale = (dz ? ndivz / dz : 1.0);
5854
5855 Double_t xmin = gPad->GetUxmin();
5856 Double_t xmax = gPad->GetUxmax();
5857 Double_t ymin = gPad->GetUymin();
5858 Double_t ymax = gPad->GetUymax();
5859
5860 // range used for polar coordinates
5861 Double_t pxmin = xmin, pxmax = xmax, pymin = ymin, pymax = ymax, pkr = 0.5;
5862 if ((Hoption.System == kPOLAR) && (Hoption.Polar == 2)) {
5863 pxmin = fXaxis->GetXmin();
5864 pxmax = fXaxis->GetXmax();
5865 if (Hoption.Logx) {
5866 if (pxmax <= 0)
5867 return;
5869 if (pxmin <= 0)
5870 pxmin = pxmax - 5;
5871 else
5873 }
5874 pkr = 0.45; // makes fixed range more pretty
5875 pymin = fYaxis->GetXmin();
5876 pymax = fYaxis->GetXmax();
5877 if (Hoption.Logy) {
5878 if (pymax <= 0)
5879 return;
5881 if (pymin <= 0)
5882 pymin = pymax - 5;
5883 else
5885 } else if ((pymax > 0) && (pymin > 0)) {
5886 // force minimal radius to 0 to display natural polar graphics
5887 pymin = 0;
5888 }
5889 }
5890
5891 if ((Hoption.System == kPOLAR) && (Hoption.Polar == 3)) {
5892 // do not touch boundaries when draw without axis histogram
5893 if (!Hoption.Same)
5894 pkr = 0.45;
5895 // for natural coordinates force minimal radius to 0
5896 if (!Hoption.Logy && (pymax > 0))
5897 pymin = 0;
5898 }
5899
5900 Int_t color;
5901 TProfile2D* prof2d = dynamic_cast<TProfile2D*>(fH);
5902 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
5905 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
5906 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
5907 xk = fXaxis->GetBinLowEdge(i);
5908 xstep = fXaxis->GetBinWidth(i);
5909 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
5910 z = fH->GetBinContent(bin);
5911 e = fH->GetBinError(bin);
5912 // if fH is a profile histogram do not draw empty bins
5913 if (prof2d) {
5914 const Double_t binEntries = prof2d->GetBinEntries(bin);
5915 if (binEntries == 0)
5916 continue;
5917 } else {
5918 // don't draw the empty bins for non-profile histograms
5919 // with positive content
5920 if (z == 0 && e == 0) {
5921 if (zmin >= 0 || Hoption.Logz) continue;
5922 if (Hoption.Color == 2) continue;
5923 }
5924 }
5925
5926 if (Hoption.Logz)
5927 z = z > 0 ? TMath::Log10(z) : zmin;
5928 if (z < zmin && !Hoption.Zero)
5929 continue;
5930 xup = xk + xstep;
5931 xlow = xk;
5932 if (Hoption.Logx) {
5933 if ((xup <= 0) || (xlow <= 0))
5934 continue;
5935 xup = TMath::Log10(xup);
5936 xlow = TMath::Log10(xlow);
5937 }
5938 yup = yk + ystep;
5939 ylow = yk;
5940 if (Hoption.Logy) {
5941 if ((yup <= 0) || (ylow <= 0))
5942 continue;
5943 yup = TMath::Log10(yup);
5944 ylow = TMath::Log10(ylow);
5945 }
5946 if ((xup < xmin) || (yup < ymin) || (xlow > xmax) || (ylow > ymax))
5947 continue;
5948 if (xlow < xmin)
5949 xlow = xmin;
5950 if (ylow < ymin)
5951 ylow = ymin;
5952 if (xup > xmax)
5953 xup = xmax;
5954 if (yup > ymax)
5955 yup = ymax;
5956
5958 zc = fH->GetContourLevelPad(0);
5959 if (z < zc) continue;
5960 color = -1;
5961 for (Int_t k=0; k<ndiv; k++) {
5962 zc = fH->GetContourLevelPad(k);
5963 if (z < zc) {
5964 continue;
5965 } else {
5966 color++;
5967 }
5968 }
5969 } else {
5970 color = Hoption.Zero ? Int_t(0.01+(std::max(z, zmin)-zmin)*scale) : Int_t(0.01+(z-zmin)*scale);
5971 }
5972
5973 Int_t theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
5974 if (theColor > ncolors-1)
5975 theColor = ncolors-1;
5977 if (Hoption.System != kPOLAR) {
5979 fH->TAttFill::Modify();
5980 gPad->PaintBox(xlow, ylow, xup, yup);
5981 } else {
5982 Double_t midx = (xmin + xmax) / 2;
5983 Double_t midy = (ymin + ymax) / 2;
5984 Double_t rx = xmax - xmin;
5985 Double_t ry = ymax - ymin;
5986 Double_t a1, a2;
5987
5988 if (Hoption.Polar == 3) {
5989 a1 = xlow / TMath::Pi() * 180;
5990 a2 = xup / TMath::Pi() * 180;
5991 } else {
5992 a1 = ((xlow - pxmin) / (pxmax - pxmin) - 0.5) * 360;
5993 a2 = ((xup - pxmin) / (pxmax - pxmin) - 0.5) * 360;
5994 }
5995 Double_t r1 = (ylow - pymin) / (pymax - pymin) * rx * pkr;
5996 Double_t r2 = (yup - pymin) / (pymax - pymin) * rx * pkr;
5997
5998 TCrown crown(midx, midy, r1, r2, a1, a2);
5999 crown.SetYXRatio(rx > 0 ? ry / rx : 1);
6000 crown.SetFillColor(fillColor);
6001 crown.SetLineColor(fH->GetLineColor());
6002 crown.SetLineWidth(fH->GetLineWidth());
6003 crown.SetLineStyle(fH->GetLineStyle());
6004 crown.Paint();
6005 }
6006 }
6007 }
6008
6010
6013 fH->TAttFill::Modify();
6014
6015}
6016
6017////////////////////////////////////////////////////////////////////////////////
6018/// [Control function to draw a 2D histogram as a contour plot.](\ref HP16)
6019
6021{
6022
6023 Int_t i, j, count, ncontour, icol, n, lj, m, ix, jx, ljfill;
6024 Int_t itars, mode, ir[4];
6025 Double_t xsave, ysave, thesave,phisave,x[4], y[4], zc[4];
6026
6027 if (Hoption.Contour == 14) {
6028 Hoption.Surf = 12;
6029 Hoption.Axis = 1;
6030 thesave = gPad->GetTheta();
6031 phisave = gPad->GetPhi();
6032 gPad->SetPhi(0.);
6033 gPad->SetTheta(90.);
6035 gPad->SetPhi(phisave);
6036 gPad->SetTheta(thesave);
6037 TView *view = gPad->GetView();
6038 if (view) view->SetBit(kCannotRotate); //tested in ExecuteEvent
6039 PaintAxis();
6040 return;
6041 }
6042
6043 if (Hoption.Same) {
6044 // If the contour is painted on a 3d plot, the contour lines are
6045 // paint in 3d too.
6046 TObject *obj;
6047 TIter next(gPad->GetListOfPrimitives());
6048 while ((obj=next())) {
6049 if (strstr(obj->GetDrawOption(),"surf") ||
6050 strstr(obj->GetDrawOption(),"lego") ||
6051 strstr(obj->GetDrawOption(),"tri")) {
6052 Hoption.Surf = 16;
6054 return;
6055 }
6056 }
6057 }
6058
6059 if (Hoption.Contour == 15) {
6060 TGraphDelaunay2D *dt = nullptr;
6061 TGraphDelaunay *dtOld = nullptr;
6063 dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
6064 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
6065 if (!dt && !dtOld) return;
6066 if (!fGraph2DPainter)
6067 fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
6068 fGraph2DPainter->Paint(option);
6069 return;
6070 }
6071
6072 gPad->SetBit(TGraph::kClipFrame);
6073
6074 std::vector<Double_t> levels(2*kMAXCONTOUR);
6075 std::vector<Double_t> xarr(2*kMAXCONTOUR);
6076 std::vector<Double_t> yarr(2*kMAXCONTOUR);
6077 std::vector<Int_t> itarr(2*kMAXCONTOUR);
6078
6079 Int_t npmax = 0;
6080 for (i=0;i<2*kMAXCONTOUR;i++) itarr[i] = 0;
6081
6082 ncontour = fH->GetContour();
6083 if (ncontour == 0) {
6086 }
6087 if (ncontour > kMAXCONTOUR) {
6088 Warning("PaintContour", "maximum number of contours is %d, asked for %d",
6091 }
6093
6094 for (i=0;i<ncontour;i++) levels[i] = fH->GetContourLevelPad(i);
6098 if (Hoption.Contour == 13) {
6099 fH->TAttLine::Modify();
6100 }
6101
6102 std::vector<std::unique_ptr<TPolyLine>> polys;
6103 TObjArray *contours = nullptr;
6104 TList *list = nullptr;
6105 TGraph *graph = nullptr;
6106 std::vector<Int_t> np;
6107 if (Hoption.Contour == 1 || (Hoption.List && (Hoption.Contour == 11 || Hoption.Contour == 12 || Hoption.Contour == 13))) {
6108 np.resize(ncontour);
6109 for (i=0;i<ncontour;i++)
6110 np[i] = 0;
6111 for (i=0;i<ncontour;i++)
6112 polys.emplace_back(std::make_unique<TPolyLine>(100));
6113 if (Hoption.List == 1) {
6114 contours = (TObjArray*)gROOT->GetListOfSpecials()->FindObject("contours");
6115 if (contours) {
6116 gROOT->GetListOfSpecials()->Remove(contours);
6117 count = contours->GetSize();
6118 for (i=0;i<count;i++) {
6119 list = (TList*)contours->At(i);
6120 if (list) list->Delete();
6121 }
6122 contours->Delete();
6123 delete contours;
6124 }
6126 contours->SetName("contours");
6127 gROOT->GetListOfSpecials()->Add(contours);
6128 for (i=0;i<ncontour;i++) {
6129 list = new TList();
6130 contours->Add(list);
6131 }
6132 }
6133 }
6137
6138 Int_t k,ipoly;
6139 for (j=Hparam.yfirst; j<Hparam.ylast; j++) {
6140 y[0] = fYaxis->GetBinCenter(j);
6141 y[1] = y[0];
6142 y[2] = fYaxis->GetBinCenter(j+1);
6143 y[3] = y[2];
6144 for (i=Hparam.xfirst; i<Hparam.xlast; i++) {
6145 zc[0] = fH->GetBinContent(i, j);
6146 zc[1] = fH->GetBinContent(i+1, j);
6147 zc[2] = fH->GetBinContent(i+1, j+1);
6148 zc[3] = fH->GetBinContent(i, j+1);
6149 if (!IsInside(fXaxis->GetBinCenter(i),fYaxis->GetBinCenter(j))) continue;
6150 if (Hoption.Logz) {
6151 if (zc[0] > 0) zc[0] = TMath::Log10(zc[0]);
6152 else zc[0] = Hparam.zmin;
6153 if (zc[1] > 0) zc[1] = TMath::Log10(zc[1]);
6154 else zc[1] = Hparam.zmin;
6155 if (zc[2] > 0) zc[2] = TMath::Log10(zc[2]);
6156 else zc[2] = Hparam.zmin;
6157 if (zc[3] > 0) zc[3] = TMath::Log10(zc[3]);
6158 else zc[3] = Hparam.zmin;
6159 }
6160 for (k=0;k<4;k++) {
6161 ir[k] = TMath::BinarySearch(ncontour, levels.data(), zc[k]);
6162 }
6163 if (ir[0] != ir[1] || ir[1] != ir[2] || ir[2] != ir[3] || ir[3] != ir[0]) {
6164 x[0] = fXaxis->GetBinCenter(i);
6165 x[3] = x[0];
6166 x[1] = fXaxis->GetBinCenter(i+1);
6167 x[2] = x[1];
6168 if (zc[0] <= zc[1]) n = 0; else n = 1;
6169 if (zc[2] <= zc[3]) m = 2; else m = 3;
6170 if (zc[n] > zc[m]) n = m;
6171 n++;
6172 lj=1;
6173 for (ix=1;ix<=4;ix++) {
6174 m = n%4 + 1;
6175 ljfill = PaintContourLine(zc[n-1],ir[n-1],x[n-1],y[n-1],zc[m-1],
6176 ir[m-1],x[m-1],y[m-1], xarr.data()+lj-1,yarr.data()+lj-1,itarr.data()+lj-1, levels.data());
6177 lj += 2*ljfill;
6178 n = m;
6179 }
6180
6181 if (zc[0] <= zc[1]) n = 0; else n = 1;
6182 if (zc[2] <= zc[3]) m = 2; else m = 3;
6183 if (zc[n] > zc[m]) n = m;
6184 n++;
6185 lj=2;
6186 for (ix=1;ix<=4;ix++) {
6187 if (n == 1) m = 4;
6188 else m = n-1;
6189 ljfill = PaintContourLine(zc[n-1],ir[n-1],x[n-1],y[n-1],zc[m-1],
6190 ir[m-1],x[m-1],y[m-1],xarr.data()+lj-1,yarr.data()+lj-1,itarr.data()+lj-1, levels.data());
6191 lj += 2*ljfill;
6192 n = m;
6193 }
6194
6195 // Re-order endpoints
6196
6197 count = 0;
6198 for (ix=1; ix<=lj-5; ix +=2) {
6199 //count = 0;
6200 while (itarr[ix-1] != itarr[ix]) {
6201 xsave = xarr[ix];
6202 ysave = yarr[ix];
6203 itars = itarr[ix];
6204 for (jx=ix; jx<=lj-5; jx +=2) {
6205 xarr[jx] = xarr[jx+2];
6206 yarr[jx] = yarr[jx+2];
6207 itarr[jx] = itarr[jx+2];
6208 }
6209 xarr[lj-3] = xsave;
6210 yarr[lj-3] = ysave;
6211 itarr[lj-3] = itars;
6212 if (count > 100) break;
6213 count++;
6214 }
6215 }
6216
6217 if (count > 100) continue;
6218 for (ix=1; ix<=lj-2; ix +=2) {
6219 theColor = Int_t((itarr[ix-1]+0.99)*Float_t(ncolors)/Float_t(ndivz));
6221 if (Hoption.Contour == 11) {
6223 }
6224 if (Hoption.Contour == 12) {
6225 mode = icol%5;
6226 if (mode == 0) mode = 5;
6228 }
6229 if (Hoption.Contour != 1) {
6230 fH->TAttLine::Modify();
6231 gPad->PaintPolyLine(2,xarr.data()+ix-1,yarr.data()+ix-1);
6232 if ((Hoption.Contour != 11 && Hoption.Contour != 12 && Hoption.Contour != 13) || !Hoption.List)
6233 continue;
6234 }
6235
6236 ipoly = itarr[ix-1];
6237 if (ipoly >=0 && ipoly <ncontour) {
6238 polys[ipoly]->SetPoint(np[ipoly] ,xarr[ix-1],yarr[ix-1]);
6239 polys[ipoly]->SetPoint(np[ipoly]+1,xarr[ix], yarr[ix]);
6240 np[ipoly] += 2;
6241 if (npmax < np[ipoly]) npmax = np[ipoly];
6242 }
6243 }
6244 } // end of if (ir[0]
6245 } //end of for (i
6246 } //end of for (j
6247
6249 std::vector<Double_t> xp, yp;
6251 Int_t istart;
6252 Int_t first = ncontour;
6253 std::vector<Int_t> polysort;
6255 if (Hoption.Contour != 1) {
6256 if (!Hoption.List || (Hoption.Contour != 11 && Hoption.Contour != 12 && Hoption.Contour != 13))
6257 goto theEND;
6258 }
6259
6260 //The 2 points line generated above are now sorted/merged to generate
6261 //a list of consecutive points.
6262 // If the option "List" has been specified, the list of points is saved
6263 // in the form of TGraph objects in the ROOT list of special objects.
6264 xmin = gPad->GetUxmin();
6265 ymin = gPad->GetUymin();
6266 xp.resize(2*npmax);
6267 yp.resize(2*npmax);
6268 polysort.resize(ncontour);
6269 //find first positive contour
6270 for (ipoly=0;ipoly<ncontour;ipoly++) {
6271 if (levels[ipoly] >= 0) {first = ipoly; break;}
6272 }
6273 //store negative contours from 0 to minimum, then all positive contours
6274 k = 0;
6275 for (ipoly=first-1;ipoly>=0;ipoly--) {polysort[k] = ipoly; k++;}
6276 for (ipoly=first;ipoly<ncontour;ipoly++) {polysort[k] = ipoly; k++;}
6277 // if Contour==1 we can now draw sorted contours, otherwise (11,12,13) just store
6278 contListNb = 0;
6279 if (Hoption.Contour == 1) fH->SetFillStyle(1001);
6280 for (k=0;k<ncontour;k++) {
6281 ipoly = polysort[k];
6282 if (Hoption.List) list = (TList*)contours->At(contListNb);
6283 contListNb++;
6284 if (np[ipoly] == 0)
6285 continue;
6286 Double_t *xx = polys[ipoly]->GetX();
6287 Double_t *yy = polys[ipoly]->GetY();
6288 istart = 0;
6289 while (true) {
6290 iminus = npmax;
6291 iplus = iminus+1;
6292 xp[iminus]= xx[istart]; yp[iminus] = yy[istart];
6293 xp[iplus] = xx[istart+1]; yp[iplus] = yy[istart+1];
6294 xx[istart] = xmin; yy[istart] = ymin;
6295 xx[istart+1] = xmin; yy[istart+1] = ymin;
6296 while (true) {
6297 nadd = 0;
6298 for (i=2;i<np[ipoly];i+=2) {
6299 if ((iplus < 2*npmax-1) && (xx[i] == xp[iplus]) && (yy[i] == yp[iplus])) {
6300 iplus++;
6301 xp[iplus] = xx[i+1]; yp[iplus] = yy[i+1];
6302 xx[i] = xmin; yy[i] = ymin;
6303 xx[i+1] = xmin; yy[i+1] = ymin;
6304 nadd++;
6305 }
6306 if ((iminus > 0) && (xx[i+1] == xp[iminus]) && (yy[i+1] == yp[iminus])) {
6307 iminus--;
6308 xp[iminus] = xx[i]; yp[iminus] = yy[i];
6309 xx[i] = xmin; yy[i] = ymin;
6310 xx[i+1] = xmin; yy[i+1] = ymin;
6311 nadd++;
6312 }
6313 }
6314 if (nadd == 0) break;
6315 }
6318 if (Hoption.Contour == 1) {
6319 if (ndivz > 1) fH->SetFillColor(icol);
6320 fH->TAttFill::Modify();
6321 gPad->PaintFillArea(iplus-iminus+1,xp.data()+iminus,yp.data()+iminus);
6322 }
6323 if (Hoption.List) {
6324 graph = new TGraph(iplus-iminus+1,xp.data()+iminus,yp.data()+iminus);
6325 if (Hoption.Contour == 1)
6326 graph->SetFillColor(icol);
6327 else if (Hoption.Contour == 11)
6328 graph->SetLineColor(icol);
6329 else if (Hoption.Contour == 12) {
6330 mode = icol%5;
6331 if (mode == 0) mode = 5;
6332 graph->SetLineStyle(mode);
6333 }
6334 graph->SetLineWidth(fH->GetLineWidth());
6335 list->Add(graph);
6336 }
6337 //check if more points are left
6338 istart = 0;
6339 for (i=2;i<np[ipoly];i+=2) {
6340 if (xx[i] != xmin && yy[i] != ymin) {
6341 istart = i;
6342 break;
6343 }
6344 }
6345 if (istart == 0) break;
6346 }
6347 }
6348
6349theEND:
6350 gPad->ResetBit(TGraph::kClipFrame);
6355}
6356
6357////////////////////////////////////////////////////////////////////////////////
6358/// Fill the matrix `xarr` and `yarr` for Contour Plot.
6359
6363{
6364
6365 Bool_t vert;
6367 Int_t n, i, icount;
6368
6369 if (x1 == x2) {
6370 vert = kTRUE;
6371 tlen = y2 - y1;
6372 } else {
6373 vert = kFALSE;
6374 tlen = x2 - x1;
6375 }
6376
6377 n = icont1 +1;
6378 tdif = elev2 - elev1;
6379 i = 0;
6380 icount = 0;
6381 while (n <= icont2 && i <= kMAXCONTOUR/2 -3) {
6382 //elev = fH->GetContourLevel(n);
6383 elev = levels[n];
6384 diff = elev - elev1;
6385 pdif = diff/tdif;
6386 xlen = tlen*pdif;
6387 if (vert) {
6388 if (Hoption.Logx)
6389 xarr[i] = TMath::Log10(x1);
6390 else
6391 xarr[i] = x1;
6392 if (Hoption.Logy)
6393 yarr[i] = TMath::Log10(y1 + xlen);
6394 else
6395 yarr[i] = y1 + xlen;
6396 } else {
6397 if (Hoption.Logx)
6398 xarr[i] = TMath::Log10(x1 + xlen);
6399 else
6400 xarr[i] = x1 + xlen;
6401 if (Hoption.Logy)
6402 yarr[i] = TMath::Log10(y1);
6403 else
6404 yarr[i] = y1;
6405 }
6406 itarr[i] = n;
6407 icount++;
6408 i +=2;
6409 n++;
6410 }
6411 return icount;
6412}
6413
6414////////////////////////////////////////////////////////////////////////////////
6415/// [Draw 1D histograms error bars.](\ref HP09)
6416
6418{
6419
6420 // On iOS, we do not highlight histogram, if it's not picked at the moment
6421 // (but part of histogram (axis or pavestat) was picked, that's why this code
6422 // is called at all. This conditional statement never executes on non-iOS platform.
6423 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH) return;
6424
6425 const Int_t kBASEMARKER=8;
6426 Double_t xp, yp, ex1, ex2, ey1, ey2;
6427 Double_t delta;
6429 Double_t xi1, xi2, xi3, xi4, yi1, yi2, yi3, yi4;
6431 Double_t logxmin = 0;
6432 Double_t logymin = 0;
6433 Double_t offset = 0.;
6434 Double_t width = 0.;
6435 Int_t i, k, npoints, first, last, fixbin;
6436 Int_t if1 = 0;
6437 Int_t if2 = 0;
6441 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};
6442 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};
6443
6444 std::vector<Double_t> xline, yline, xsegm, ysegm, xmarker, ymarker;
6446 if (Hoption.Error >= 40) {Hoption.Error -=40; option0 = 1;}
6447 if (Int_t(Hoption.Error/10) == 2) {optionEX0 = 1; Hoption.Error -= 10;}
6448 if (Hoption.Error == 31) {optionEX0 = 1; Hoption.Error = 1;}
6449 if (Hoption.Error == 11) option1 = 1;
6450 if (Hoption.Error == 12) option2 = 1;
6451 if (Hoption.Error == 13) option3 = 1;
6452 if (Hoption.Error == 14) {option4 = 1; option3 = 1;}
6453 if (Hoption.Error == 15) {optionI0 = 1; option3 = 1;}
6454 if (Hoption.Error == 16) {optionI0 = 1; option4 = 1; option3 = 1;}
6455 if (option2+option3 == 0) optionE = 1;
6456 if (Hoption.Error == 0) optionE = 0;
6457 if (fXaxis->GetXbins()->fN) fixbin = 0;
6458 else fixbin = 1;
6459
6460 offset = fH->GetBarOffset();
6461 width = fH->GetBarWidth();
6462
6464 if (optionEX0) {
6465 xerror = 0;
6466 } else {
6467 xerror = gStyle->GetErrorX();
6468 }
6470 if (errormarker == 1) symbolsize = 0.01;
6472 if (errormarker >= 20 && errormarker <= 49) {
6473 sbasex *= cxx[errormarker-20];
6474 sbasey *= cyy[errormarker-20];
6475 }
6476 // set the graphics attributes
6477
6478 fH->TAttLine::Modify();
6479 fH->TAttFill::Modify();
6480 fH->TAttMarker::Modify();
6481
6482 // set the first and last bin
6483
6484 Double_t factor = Hparam.factor;
6485 first = Hparam.xfirst;
6486 last = Hparam.xlast;
6487 npoints = last - first +1;
6488 xmin = gPad->GetUxmin();
6489 xmax = gPad->GetUxmax();
6490 ymin = gPad->GetUymin();
6491 ymax = gPad->GetUymax();
6492
6493 xsegm.reserve(1024);
6494 ysegm.reserve(1024);
6495 if (!xsegm.capacity() || !ysegm.capacity()) {
6496 Error("PaintErrors", "out of memory for lines painting");
6497 return;
6498 }
6499
6500 auto flush_segmentes = [&]() {
6501 if (xsegm.size() > 0) {
6502 gPad->PaintSegments(xsegm.size()/2, xsegm.data(), ysegm.data());
6503 xsegm.clear();
6504 ysegm.clear();
6505 }
6506 };
6507
6509 xsegm.emplace_back(x1);
6510 xsegm.emplace_back(x2);
6511 ysegm.emplace_back(y1);
6512 ysegm.emplace_back(y2);
6513 if (xsegm.size() == xsegm.capacity())
6515 };
6516
6517 auto flush_markers = [&]() {
6518 if (xmarker.size() > 0) {
6519 gPad->PaintPolyMarker(xmarker.size(), xmarker.data(), ymarker.data());
6520 xmarker.clear();
6521 ymarker.clear();
6522 }
6523 };
6524
6525 auto add_marker = [&](Double_t x, Double_t y) {
6526 if (xmarker.capacity() == 0) {
6527 xmarker.reserve(256);
6528 ymarker.reserve(256);
6529 }
6530
6531 xmarker.emplace_back(x);
6532 ymarker.emplace_back(y);
6533 if (xmarker.size() == xmarker.capacity()) {
6535 flush_markers();
6536 }
6537 };
6538
6539
6540 if (option3) {
6541 xline.resize(2*npoints);
6542 yline.resize(2*npoints);
6543 if ((npoints > 0) && (xline.empty() || yline.empty())) {
6544 Error("PaintErrors", "too many points, out of memory");
6545 return;
6546 }
6547 if1 = 1;
6548 if2 = 2*npoints;
6549 }
6550
6551 // compute the offset of the error bars due to the symbol size
6552 s2x = gPad->PixeltoX(Int_t(0.5*sbasex)) - gPad->PixeltoX(0);
6553 s2y =-gPad->PixeltoY(Int_t(0.5*sbasey)) + gPad->PixeltoY(0);
6554
6555 // compute size of the lines at the end of the error bars
6557 bxsize = gPad->PixeltoX(dxend) - gPad->PixeltoX(0);
6558 bysize =-gPad->PixeltoY(dxend) + gPad->PixeltoY(0);
6559
6560
6561 if (fixbin) {
6563 else xp = Hparam.xmin + 0.5*Hparam.xbinsize;
6564 } else {
6565 delta = fH->GetBinWidth(first);
6566 xp = fH->GetBinLowEdge(first) + 0.5*delta;
6567 }
6568
6569 // if errormarker = 0 or symbolsize = 0. no symbol is drawn
6572
6573 // ---------------------- Loop over the points---------------------
6574 for (k=first; k<=last; k++) {
6575
6576 // get the data
6577 // xp = X position of the current point
6578 // yp = Y position of the current point
6579 // ex1 = Low X error
6580 // ex2 = Up X error
6581 // ey1 = Low Y error
6582 // ey2 = Up Y error
6583 // (xi,yi) = Error bars coordinates
6584
6585 // apply offset on errors for bar histograms
6586 Double_t xminTmp = gPad->XtoPad(fXaxis->GetBinLowEdge(k));
6587 Double_t xmaxTmp = gPad->XtoPad(fXaxis->GetBinUpEdge(k));
6588 if (Hoption.Logx) {
6591 }
6594 xmaxTmp = xminTmp + w;
6595 xp = (xminTmp+xmaxTmp)/2.;
6596
6597 if (Hoption.Logx) {
6598 if (xp <= 0) goto L30;
6599 if (xp < logxmin) goto L30;
6600 if (xp > TMath::Power(10,xmax)) break;
6601 } else {
6602 if (xp < xmin) goto L30;
6603 if (xp > xmax) break;
6604 }
6605 yp = factor*fH->GetBinContent(k);
6606 if (optionI0 && yp==0) goto L30;
6607 if (fixbin) {
6609 } else {
6610 delta = fH->GetBinWidth(k);
6611 ex1 = xerror*delta;
6612 }
6613 if (fH->GetBinErrorOption() == TH1::kNormal) {
6614 ey1 = factor*fH->GetBinError(k);
6615 ey2 = ey1;
6616 } else {
6617 ey1 = factor*fH->GetBinErrorLow(k);
6618 ey2 = factor*fH->GetBinErrorUp(k);
6619 }
6620 ex2 = ex1;
6621
6622 xi4 = xp;
6623 xi3 = xp;
6624 xi2 = xp + ex2;
6625 xi1 = xp - ex1;
6626
6627 yi1 = yp;
6628 yi2 = yp;
6629 yi3 = yp - ey1;
6630 yi4 = yp + ey2;
6631
6632 // take the LOG if necessary
6633 if (Hoption.Logx) {
6638 }
6639 if (Hoption.Logy) {
6644 }
6645
6646 // test if error bars are not outside the limits
6647 // otherwise they are truncated
6648
6653
6654 // test if the marker is on the frame limits. If "Yes", the
6655 // marker will not be drawn and the error bars will be readjusted.
6656
6657 drawmarker = kTRUE;
6658 if (!option0 && !option3) {
6659 if (Hoption.Logy && yp < logymin) goto L30;
6660 if (yi1 < ymin || yi1 > ymax) goto L30;
6661 if (Hoption.Error != 0 && yp == 0 && ey1 <= 0) drawmarker = kFALSE;
6662 }
6664
6665 // draw the error rectangles
6666 if (option2) {
6667 if ((yi3 >= ymax) || (yi4 <= ymin))
6668 goto L30;
6669 gPad->PaintBox(xi1,yi3,xi2,yi4);
6670 }
6671
6672 // keep points for fill area drawing
6673 if (option3) {
6674 xline[if1-1] = xi3;
6675 xline[if2-1] = xi3;
6676 yline[if1-1] = yi4;
6677 yline[if2-1] = yi3;
6678 if1++;
6679 if2--;
6680 }
6681
6682 // draw the error bars
6683 if (Hoption.Logy && yp < logymin)
6685 if (optionE && drawmarker) {
6686 if ((yi3 < yi1 - s2y) && (yi3 < ymax))
6688 if ((yi1 + s2y < yi4) && (yi4 > ymin))
6690 // don't duplicate the horizontal line
6691 if (Hoption.Hist != 2) {
6693 if (xi1 < xi3 - s2x)
6695 if (xi3 + s2x < xi2)
6697 }
6698 }
6699 }
6700 if (optionE && !drawmarker && (ey1 != 0 || ey2 !=0)) {
6701 if ((yi3 < yi1) && (yi3 < ymax))
6703 if ((yi1 < yi4) && (yi4 > ymin))
6705 // don't duplicate the horizontal line
6706 if (Hoption.Hist != 2) {
6708 if (xi1 < xi3)
6710 if (xi3 < xi2)
6712 }
6713 }
6714 }
6715
6716 // draw line at the end of the error bars
6717
6718 if (option1 && drawmarker) {
6719
6725 if (xi1 < xi3-s2x)
6727 if (xi2 > xi3+s2x)
6729 }
6730 }
6731
6732 // draw the marker
6733
6734 if (drawmarker)
6735 add_marker(xi3, yi1);
6736
6737L30:
6738 if (fixbin) xp += Hparam.xbinsize;
6739 else {
6740 if (k < last) {
6741 delta = fH->GetBinWidth(k+1);
6742 xp = fH->GetBinLowEdge(k+1) + 0.5*delta;
6743 }
6744 }
6745 } //end of for loop
6746
6748
6749 flush_markers();
6750
6751
6752 // draw the filled area
6753
6754 if (option3) {
6755 TGraph graph;
6756 graph.SetLineStyle(fH->GetLineStyle());
6757 graph.SetLineColor(fH->GetLineColor());
6758 graph.SetLineWidth(fH->GetLineWidth());
6759 graph.SetFillStyle(fH->GetFillStyle());
6760 graph.SetFillColor(fH->GetFillColor());
6761 Int_t logx = gPad->GetLogx();
6762 Int_t logy = gPad->GetLogy();
6763 gPad->SetLogx(0);
6764 gPad->SetLogy(0);
6765
6766 // In some cases the number of points in the fill area is smaller than
6767 // 2*npoints. In such cases the array xline and yline must be arranged
6768 // before being plotted. The next loop does that.
6769 if (if2 > npoints) {
6770 for (i=1; i<if1; i++) {
6771 xline[if1-2+i] = xline[if2-1+i];
6772 yline[if1-2+i] = yline[if2-1+i];
6773 }
6774 npoints = if1-1;
6775 }
6776 if (option4) graph.PaintGraph(2*npoints,xline.data(),yline.data(),"FC");
6777 else graph.PaintGraph(2*npoints,xline.data(),yline.data(),"F");
6778 gPad->SetLogx(logx);
6779 gPad->SetLogy(logy);
6780 }
6781}
6782
6783////////////////////////////////////////////////////////////////////////////////
6784/// Draw 2D histograms errors.
6785
6787{
6788
6789 fH->TAttMarker::Modify();
6790 fH->TAttLine::Modify();
6791
6792 // Define the 3D view
6793 fXbuf[0] = Hparam.xmin;
6794 fYbuf[0] = Hparam.xmax;
6795 fXbuf[1] = Hparam.ymin;
6796 fYbuf[1] = Hparam.ymax;
6797 fXbuf[2] = Hparam.zmin;
6798 fYbuf[2] = Hparam.zmax*(1. + gStyle->GetHistTopMargin());
6799 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
6800 TView *view = gPad ? gPad->GetView() : nullptr;
6801 if (!view) {
6802 Error("Paint2DErrors", "no TView in current pad");
6803 return;
6804 }
6805 Double_t thedeg = 90 - gPad->GetTheta();
6806 Double_t phideg = -90 - gPad->GetPhi();
6807 Double_t psideg = view->GetPsi();
6808 Int_t irep;
6809 view->SetView(phideg, thedeg, psideg, irep);
6810
6811 // Set color/style for back box
6812 fLego->SetFillStyle(gPad->GetFrameFillStyle());
6813 fLego->SetFillColor(gPad->GetFrameFillColor());
6814 fLego->TAttFill::Modify();
6815 Int_t backcolor = gPad->GetFrameFillColor();
6816 if (Hoption.System != kCARTESIAN) backcolor = 0;
6817 view->PadRange(backcolor);
6818 fLego->SetFillStyle(fH->GetFillStyle());
6819 fLego->SetFillColor(fH->GetFillColor());
6820 fLego->TAttFill::Modify();
6821
6822 // Paint the Back Box if needed
6823 if (Hoption.BackBox && !Hoption.Same && !Hoption.Lego && !Hoption.Surf) {
6824 fLego->InitMoveScreen(-1.1,1.1);
6825 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
6827 fLego->BackBox(90);
6828 }
6829
6830 // Paint the Errors
6831 Double_t x, ex, x1, x2;
6832 Double_t y, ey, y1, y2;
6833 Double_t z, ez1, ez2, z1, z2;
6834 Double_t temp1[3],temp2[3];
6836 if (Hoption.Error == 110) {
6837 xyerror = 0;
6838 } else {
6840 }
6841
6843 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
6844 y = fYaxis->GetBinCenter(j);
6846 y1 = y-ey;
6847 y2 = y+ey;
6848 if (Hoption.Logy) {
6849 if (y > 0) y = TMath::Log10(y);
6850 else continue;
6851 if (y1 > 0) y1 = TMath::Log10(y1);
6852 else y1 = Hparam.ymin;
6853 if (y2 > 0) y2 = TMath::Log10(y2);
6854 else y2 = Hparam.ymin;
6855 }
6858 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
6859 xk = fXaxis->GetBinLowEdge(i);
6860 xstep = fXaxis->GetBinWidth(i);
6861 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
6862 Int_t bin = fH->GetBin(i,j);
6863 x = fXaxis->GetBinCenter(i);
6865 x1 = x-ex;
6866 x2 = x+ex;
6867 if (Hoption.Logx) {
6868 if (x > 0) x = TMath::Log10(x);
6869 else continue;
6870 if (x1 > 0) x1 = TMath::Log10(x1);
6871 else x1 = Hparam.xmin;
6872 if (x2 > 0) x2 = TMath::Log10(x2);
6873 else x2 = Hparam.xmin;
6874 }
6875 z = fH->GetBinContent(bin);
6876 if (fH->GetBinErrorOption() == TH1::kNormal) {
6877 ez1 = fH->GetBinError(bin);
6878 ez2 = ez1;
6879 }
6880 else {
6882 ez2 = fH->GetBinErrorUp(bin);
6883 }
6884 z1 = z - ez1;
6885 z2 = z + ez2;
6886 if (Hoption.Logz) {
6887 if (z > 0) z = TMath::Log10(z);
6888 else z = Hparam.zmin;
6889 if (z1 > 0) z1 = TMath::Log10(z1);
6890 else z1 = Hparam.zmin;
6891 if (z2 > 0) z2 = TMath::Log10(z2);
6892 else z2 = Hparam.zmin;
6893
6894 }
6895 if (z <= Hparam.zmin) continue;
6896 if (z > Hparam.zmax) z = Hparam.zmax;
6897
6898 temp1[0] = x1;
6899 temp1[1] = y;
6900 temp1[2] = z;
6901 temp2[0] = x2;
6902 temp2[1] = y;
6903 temp2[2] = z;
6904 gPad->PaintLine3D(temp1, temp2);
6905 temp1[0] = x;
6906 temp1[1] = y1;
6907 temp1[2] = z;
6908 temp2[0] = x;
6909 temp2[1] = y2;
6910 temp2[2] = z;
6911 gPad->PaintLine3D(temp1, temp2);
6912 temp1[0] = x;
6913 temp1[1] = y;
6914 temp1[2] = z1;
6915 temp2[0] = x;
6916 temp2[1] = y;
6917 temp2[2] = z2;
6918 gPad->PaintLine3D(temp1, temp2);
6919 temp1[0] = x;
6920 temp1[1] = y;
6921 temp1[2] = z;
6922 view->WCtoNDC(temp1, &temp2[0]);
6923 gPad->PaintPolyMarker(1, &temp2[0], &temp2[1]);
6924 }
6925 }
6926
6927 // Paint the Front Box if needed
6928 if (Hoption.FrontBox) {
6929 fLego->InitMoveScreen(-1.1,1.1);
6931 fLego->FrontBox(90);
6932 }
6933
6934 // Paint the Axis if needed
6935 if (!Hoption.Axis && !Hoption.Same && !Hoption.Lego && !Hoption.Surf) {
6936 TGaxis axis;
6937 PaintLegoAxis(&axis, 90);
6938 }
6939
6940 fLego.reset();
6941}
6942
6943////////////////////////////////////////////////////////////////////////////////
6944/// Calculate range and clear pad (canvas).
6945
6947{
6948
6949 if (Hoption.Same) return;
6950
6952
6953 if (Hoption.Lego || Hoption.Surf || Hoption.Tri ||
6954 Hoption.Contour == 14 || Hoption.Error >= 100) {
6955 TObject *frame = gPad->FindObject("TFrame");
6956 if (frame) gPad->Remove(frame);
6957 return;
6958 }
6959
6960 //The next statement is always executed on non-iOS platform,
6961 //on iOS depends on pad mode.
6962 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode())
6963 gPad->PaintPadFrame(Hparam.xmin,Hparam.ymin,Hparam.xmax,Hparam.ymax);
6964}
6965
6966////////////////////////////////////////////////////////////////////////////////
6967/// [Paint functions associated to an histogram.](\ref HP28")
6968
6970{
6971 auto lnk = fFunctions->FirstLink();
6972
6973 while (lnk) {
6974 auto obj = lnk->GetObject();
6976 if (obj->InheritsFrom(TF2::Class())) {
6977 if (!obj->TestBit(TF2::kNotDraw)) {
6978 if (Hoption.Lego || Hoption.Surf || Hoption.Error >= 100) {
6979 TF2 *f2 = (TF2*)obj;
6980 f2->SetMinimum(fH->GetMinimum());
6981 f2->SetMaximum(fH->GetMaximum());
6982 f2->SetRange(fH->GetXaxis()->GetXmin(), fH->GetYaxis()->GetXmin(), fH->GetXaxis()->GetXmax(), fH->GetYaxis()->GetXmax() );
6983 f2->Paint("surf same");
6984 } else {
6985 obj->Paint("cont3 same");
6986 }
6987 }
6988 } else if (obj->InheritsFrom(TF1::Class())) {
6989 if (!obj->TestBit(TF1::kNotDraw)) obj->Paint("lsame");
6990 } else {
6991 //Let's make this 'function' selectable on iOS device (for example, it can be TPaveStat).
6992 gPad->PushSelectableObject(obj);
6993
6994 //The next statement is ALWAYS executed on non-iOS platform, on iOS it depends on pad's mode
6995 //and picked object.
6996 if (!gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && obj == gPad->GetSelected()))
6997 obj->Paint(lnk->GetOption());
6998 }
6999 lnk = lnk->Next();
7000 }
7001}
7002
7003////////////////////////////////////////////////////////////////////////////////
7004/// [Control routine to draw 1D histograms](\ref HP01b)
7005
7007{
7008
7009 //On iOS: do not highlight hist, if part of it was selected.
7010 //Never executes on non-iOS platform.
7011 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
7012 return;
7013
7014 static char chopth[17];
7015
7017 Int_t i, j, first, last, nbins, fixbin;
7018 Double_t c1, yb;
7019 yb = 0;
7020
7021 strlcpy(chopth, " ",17);
7022
7025 Double_t baroffset = fH->GetBarOffset();
7026 Double_t barwidth = fH->GetBarWidth();
7029 gStyle->SetBarOffset(baroffset);
7030 gStyle->SetBarWidth(barwidth);
7031
7032 // Create "LIFE" structure to keep current histogram status
7033
7034 first = Hparam.xfirst;
7035 last = Hparam.xlast;
7036 nbins = last - first + 1;
7037
7038 std::vector<Double_t> keepx, keepy;
7039 if (fXaxis->GetXbins()->fN) fixbin = 0;
7040 else fixbin = 1;
7041 if (fixbin) keepx.resize(2);
7042 else keepx.resize(nbins+1);
7043 keepy.resize(nbins);
7044 Double_t logymin = 0;
7046
7047 // Loop on histogram bins
7048
7049 for (j=first; j<=last;j++) {
7051 if (TMath::Abs(ymax-ymin) > 0) {
7053 else yb = c1;
7054 }
7055 if (!Hoption.Line) {
7056 yb = TMath::Max(yb, ymin);
7057 yb = TMath::Min(yb, ymax);
7058 }
7059 keepy[j-first] = yb;
7060 }
7061
7062 // Draw histogram according to value of FillStyle and FillColor
7063
7064 if (fixbin) { keepx[0] = Hparam.xmin; keepx[1] = Hparam.xmax; }
7065 else {
7066 for (i=0; i<nbins; i++) keepx[i] = fXaxis->GetBinLowEdge(i+first);
7067 keepx[nbins] = fXaxis->GetBinUpEdge(nbins-1+first);
7068 }
7069
7070 // Prepare Fill area (systematic with option "Bar").
7071
7073 htype = oldhtype;
7074 if (Hoption.Bar) {
7075 if (htype == 0 || htype == 1000) htype = 1001;
7076 }
7077
7079
7080 // Code option for GrapHist
7081
7082 if (Hoption.Line) chopth[0] = 'L';
7083 if (Hoption.Star) chopth[1] = '*';
7084 if (Hoption.Mark) chopth[2] = 'P';
7085 if (Hoption.Mark == 10) chopth[3] = '0';
7087 if (Hoption.Curve) chopth[3] = 'C';
7088 if (Hoption.Hist > 0) chopth[4] = 'H';
7089 else if (Hoption.Bar) chopth[5] = 'B';
7090 if (Hoption.Logy) chopth[6] = '1';
7091 if (fH->GetFillColor() && htype) {
7092 if (Hoption.Hist > 0 || Hoption.Curve || Hoption.Line) {
7093 chopth[7] = 'F';
7094 }
7095 }
7096 }
7097 if (!fixbin && strlen(chopth)) {
7098 chopth[8] = 'N';
7099 }
7100
7101 if (Hoption.Fill == 2) chopth[13] = '2';
7102
7103 // Option LOGX
7104
7105 if (Hoption.Logx) {
7106 chopth[9] = 'G';
7107 chopth[10] = 'X';
7108 if (fixbin) {
7109 keepx[0] = TMath::Power(10,keepx[0]);
7110 keepx[1] = TMath::Power(10,keepx[1]);
7111 }
7112 }
7113
7114 if (Hoption.Off) {
7115 chopth[11] = ']';
7116 chopth[12] = '[';
7117 }
7118
7119 // Draw the histogram
7120
7121 TGraph graph;
7122 graph.SetLineWidth(lw);
7123 graph.SetLineStyle(fH->GetLineStyle());
7124 graph.SetLineColor(fH->GetLineColor());
7125 graph.SetFillStyle(htype);
7126 graph.SetFillColor(fH->GetFillColor());
7128 graph.SetMarkerSize(fH->GetMarkerSize());
7131
7132 graph.PaintGrapHist(nbins, keepx.data(), keepy.data() ,chopth);
7133
7136
7138}
7139
7140////////////////////////////////////////////////////////////////////////////////
7141/// [Control function to draw a 3D histograms.](\ref HP01d)
7142
7144{
7145
7146 TString cmd;
7147 TString opt = option;
7148 opt.ToLower();
7149 Int_t irep;
7150 Float_t NEntries = fH->GetEntries();
7151
7152 if (fCurrentF3 || strstr(opt,"tf3")) {
7153 PaintTF3();
7154 return;
7155 }
7156
7157 if (NEntries > 0) {
7158 if (Hoption.Box || Hoption.Lego || Hoption.Color) {
7159 if (Hoption.Box == 11 || Hoption.Lego == 11) {
7160 PaintH3Box(1);
7161 } else if (Hoption.Box == 12 || Hoption.Lego == 12 || Hoption.Color == 1) {
7162 PaintH3Box(2);
7163 } else if (Hoption.Box == 13 || Hoption.Lego == 13) {
7164 PaintH3Box(3);
7165 } else {
7167 }
7168 return;
7169 }
7170
7171 if (strstr(opt,"iso")) {
7172 PaintH3Iso();
7173 return;
7174 }
7175 }
7176
7177 TView *view = gPad ? gPad->GetView() : nullptr;
7178 if (!view) return;
7179
7180 if (strstr(opt,"fb")) Hoption.FrontBox = 0;
7181 if (strstr(opt,"bb")) Hoption.BackBox = 0;
7182
7183 Double_t thedeg = 90 - gPad->GetTheta();
7184 Double_t phideg = -90 - gPad->GetPhi();
7185 Double_t psideg = view->GetPsi();
7186 view->SetView(phideg, thedeg, psideg, irep);
7187
7188 if(NEntries > 0) { // Paint as 3D scatter plot
7189 cmd.Form("TPolyMarker3D::PaintH3((TH1 *)0x%zx,\"%s\");",(size_t)fH,option);
7190 gROOT->ProcessLine(cmd.Data());
7191 } else {
7192 TAxis* xAxis = fH->GetXaxis();
7193 TAxis* yAxis = fH->GetYaxis();
7194 TAxis* zAxis = fH->GetZaxis();
7195 Double_t xmin = xAxis->GetXmin();
7196 Double_t xmax = xAxis->GetXmax();
7197 Double_t ymin = yAxis->GetXmin();
7198 Double_t ymax = yAxis->GetXmax();
7199 Double_t zmin = zAxis->GetXmin();
7200 Double_t zmax = zAxis->GetXmax();
7201 view->SetRange(xmin, ymin, zmin, xmax, ymax, zmax); // Set the axis limits (Xmin, Ymin, Zmin, Xmax, Ymax, Zmax)
7202 }
7203
7204 if (Hoption.Same) return;
7205
7206 // Draw axis
7207 view->SetOutlineToCube();
7208 TSeqCollection *ol = view->GetOutline();
7209 if (ol && Hoption.BackBox && Hoption.FrontBox) ol->Paint(option);
7211
7212 if (!Hoption.Axis && !Hoption.Same) {
7213 TGaxis axis;
7214 PaintLegoAxis(&axis, 90);
7215 }
7216
7217 // Draw palette. In case of 4D plot with TTree::Draw() the palette should
7218 // be painted with the option colz.
7219 if (fH->GetDrawOption() && strstr(opt,"colz")) {
7220 Int_t ndiv = fH->GetContour();
7221 if (ndiv == 0 ) {
7222 ndiv = gStyle->GetNumberContours();
7223 fH->SetContour(ndiv);
7224 }
7225 PaintPalette();
7226 }
7227
7228 // Draw title
7229 PaintTitle();
7230
7231 //Draw stats and fit results
7232 TF1 *fit = nullptr;
7233 TIter next(fFunctions);
7234 while (auto obj = next()) {
7235 if (obj->InheritsFrom(TF1::Class())) {
7236 fit = (TF1*)obj;
7237 break;
7238 }
7239 }
7240 if ((Hoption.Same%10) != 1) {
7241 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7243 }
7244 }
7245
7246}
7247
7248////////////////////////////////////////////////////////////////////////////////
7249/// Compute histogram parameters used by the drawing routines.
7250
7252{
7253
7254 if (fH->GetDimension() > 1 || Hoption.Lego || Hoption.Surf) return 1;
7255
7256 Int_t i;
7257 static const char *where = "PaintInit";
7259 Int_t maximum = 0;
7260 Int_t minimum = 0;
7261 if (fH->GetMaximumStored() != -1111) maximum = 1;
7262 if (fH->GetMinimumStored() != -1111) minimum = 1;
7263
7264 // Compute X axis parameters
7265
7266 Int_t last = fXaxis->GetLast();
7267 Int_t first = fXaxis->GetFirst();
7270 Hparam.xlast = last;
7271 Hparam.xfirst = first;
7274
7275 // if log scale in X, replace xmin,max by the log
7276 if (Hoption.Logx) {
7277 if (Hparam.xmax<=0) {
7278 Error(where, "cannot set X axis to log scale");
7279 return 0;
7280 }
7281 if (Hparam.xlowedge <=0 ) {
7282 if (Hoption.Same) {
7283 TH1* h1 = nullptr;
7284 TObject *obj;
7285 TIter next(gPad->GetListOfPrimitives());
7286 while ((obj = (TObject *)next())) {
7287 if (obj->InheritsFrom(TH1::Class())) { h1 = (TH1*)(obj) ; break; }
7288 if (obj->InheritsFrom(THStack::Class())) { h1 = ((THStack*)(obj))->GetHistogram() ; break; }
7289 if (obj->InheritsFrom(TGraph::Class())) { h1 = ((TGraph*)(obj))->GetHistogram() ; break; }
7290 if (obj->InheritsFrom(TMultiGraph::Class())) { h1 = ((TMultiGraph*)(obj))->GetHistogram(); break; }
7291 if (obj->InheritsFrom(TGraph2D::Class())) { h1 = ((TGraph2D*)(obj))->GetHistogram(); break; }
7292 if (obj->InheritsFrom(TF1::Class())) { h1 = ((TF1*)(obj))->GetHistogram(); break; }
7293 }
7294 if (h1) {
7296 } else {
7297 Error(where, "undefined user's coordinates. Cannot use option SAME");
7298 return 0;
7299 }
7300 } else {
7301 for (i=first; i<=last; i++) {
7302 Double_t binLow = fXaxis->GetBinLowEdge(i);
7303 if (binLow>0) {
7304 Hparam.xlowedge = binLow;
7305 break;
7306 }
7307 if (binLow == 0 && fH->GetBinContent(i) !=0) {
7308 Hparam.xlowedge = fXaxis->GetBinUpEdge(i)*0.001;
7309 break;
7310 }
7311 }
7312 if (Hparam.xlowedge<=0) {
7313 Error(where, "cannot set X axis to log scale");
7314 return 0;
7315 }
7316 }
7318 }
7323 if (Hparam.xlast > last) Hparam.xlast = last;
7324 if (Hparam.xfirst < first) Hparam.xfirst = first;
7325 }
7326
7327 // Compute Y axis parameters
7328 Double_t bigp = TMath::Power(10,32);
7329 Double_t ymax = -bigp;
7330 Double_t ymin = bigp;
7331 Double_t c1, e1;
7332 Double_t xv[1];
7333 Double_t fval;
7334 TObject *f;
7335 TF1 *f1;
7336 Double_t allchan = 0;
7337 Int_t nonNullErrors = 0;
7338 TIter next(fFunctions);
7339 for (i=first; i<=last;i++) {
7340 c1 = fH->GetBinContent(i);
7342 if (Hoption.Logy) {
7343 if (c1 > 0) ymin = TMath::Min(ymin,c1);
7344 } else {
7346 }
7347 if (Hoption.Error) {
7349 e1 = fH->GetBinError(i);
7350 else
7351 e1 = fH->GetBinErrorUp(i);
7352 if (e1 > 0) nonNullErrors++;
7355 e1 = fH->GetBinErrorLow(i);
7356
7357 if (Hoption.Logy) {
7358 if (c1-e1>0.01*TMath::Abs(c1)) ymin = TMath::Min(ymin,c1-e1);
7359 } else {
7361 }
7362 }
7363 if (Hoption.Func) {
7364 xv[0] = fXaxis->GetBinCenter(i);
7365 while ((f = (TObject*) next())) {
7366 if (f->IsA() == TF1::Class()) {
7367 f1 = (TF1*)f;
7368 if (xv[0] < f1->GetXmin() || xv[0] > f1->GetXmax()) continue;
7369 fval = f1->Eval(xv[0],0,0);
7370 if (f1->GetMaximumStored() != -1111) fval = TMath::Min(f1->GetMaximumStored(), fval);
7372 if (Hoption.Logy) {
7373 if (c1 > 0 && fval > 0.3*c1) ymin = TMath::Min(ymin,fval);
7374 }
7375 }
7376 }
7377 next.Reset();
7378 }
7379 allchan += c1;
7380 }
7381 if (!nonNullErrors) {
7382 if (Hoption.Error) {
7383 if (!Hoption.Mark && !Hoption.Line && !Hoption.Star && !Hoption.Curve) Hoption.Hist = 2;
7384 Hoption.Error=0;
7385 }
7386 }
7387
7388
7389 // Take into account maximum , minimum
7390
7391 if (Hoption.Logy && ymin <= 0) {
7392 if (ymax >= 1) ymin = TMath::Max(.005,ymax*1e-10);
7393 else ymin = 0.001*ymax;
7394 }
7395
7396 Double_t xm = ymin;
7397 if (maximum) ymax = fH->GetMaximumStored();
7398 if (minimum) xm = fH->GetMinimumStored();
7399 if (Hoption.Logy && xm < 0) {
7400 Error(where, "log scale requested with a negative argument (%f)", xm);
7401 return 0;
7402 } else if (Hoption.Logy && xm>=0 && ymax==0) { // empty histogram in log scale
7403 ymin = 0.01;
7404 ymax = 10.;
7405 } else {
7406 ymin = xm;
7407 }
7408
7409 if (ymin >= ymax) {
7410 if (Hoption.Logy) {
7411 if (ymax > 0) ymin = 0.001*ymax;
7412 else {
7413 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", ymax);
7414 return 0;
7415 }
7416 }
7417 else {
7418 if (ymin > 0) {
7419 ymin = 0;
7420 ymax *= 2;
7421 } else if (ymin < 0) {
7422 ymax = 0;
7423 ymin *= 2;
7424 } else {
7425 ymin = 0;
7426 ymax = 1;
7427 }
7428 }
7429 }
7430
7431 // In some cases, mainly because of precision issues, ymin and ymax could almost equal.
7432 if (TMath::AreEqualRel(ymin,ymax,1E-15)) {
7433 ymin = ymin*(1-1E-14);
7434 ymax = ymax*(1+1E-14);
7435 }
7436
7437 // take into account normalization factor
7438 Hparam.allchan = allchan;
7439 Double_t factor = allchan;
7440 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
7441 if (allchan) factor /= allchan;
7442 if (factor == 0) factor = 1;
7443 Hparam.factor = factor;
7444 ymax = factor*ymax;
7445 ymin = factor*ymin;
7446 //just in case the norm factor is negative
7447 // this may happen with a positive norm factor and a negative integral !
7448 if (ymax < ymin) {
7449 Double_t temp = ymax;
7450 ymax = ymin;
7451 ymin = temp;
7452 }
7453
7454 // For log scales, histogram coordinates are LOG10(ymin) and
7455 // LOG10(ymax). Final adjustment (if not option "Same"
7456 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
7457 // Maximum and Minimum are not defined.
7458 if (Hoption.Logy) {
7459 if (ymin <=0 || ymax <=0) {
7460 Error(where, "Cannot set Y axis to log scale");
7461 return 0;
7462 }
7464 if (!minimum) ymin += TMath::Log10(0.5);
7466 if (!maximum) ymax += TMath::Log10(2*(0.9/0.95));
7467 if (!Hoption.Same) {
7468 Hparam.ymin = ymin;
7469 Hparam.ymax = ymax;
7470 }
7471 return 1;
7472 }
7473
7474 // final adjustment of ymin for linear scale.
7475 // if minimum is not set , then ymin is set to zero if >0
7476 // or to ymin - margin if <0.
7477 if (!minimum) {
7478 if (Hoption.MinimumZero) {
7479 if (ymin >= 0) ymin = 0;
7480 else ymin -= yMARGIN*(ymax-ymin);
7481 } else {
7483 if (ymin >= 0 && (ymin-dymin <= 0)) ymin = 0;
7484 else ymin -= dymin;
7485 }
7486 }
7487
7488 // final adjustment of YMAXI for linear scale (if not option "Same"):
7489 // decrease histogram height to MAX% of allowed height if HMAXIM
7490 // has not been called.
7491 if (!maximum) {
7492 ymax += yMARGIN*(ymax-ymin);
7493 }
7494
7495 Hparam.ymin = ymin;
7496 Hparam.ymax = ymax;
7497 return 1;
7498}
7499
7500////////////////////////////////////////////////////////////////////////////////
7501/// Compute histogram parameters used by the drawing routines for a rotated pad.
7502
7504{
7505
7506 static const char *where = "PaintInitH";
7508 Int_t maximum = 0;
7509 Int_t minimum = 0;
7510 if (fH->GetMaximumStored() != -1111) maximum = 1;
7511 if (fH->GetMinimumStored() != -1111) minimum = 1;
7512
7513 // Compute X axis parameters
7514
7515 Int_t last = fXaxis->GetLast();
7516 Int_t first = fXaxis->GetFirst();
7519 Hparam.xlast = last;
7520 Hparam.xfirst = first;
7523
7524 // if log scale in Y, replace ymin,max by the log
7525 if (Hoption.Logy) {
7526 if (Hparam.xlowedge <=0 ) {
7529 }
7530 if (Hparam.ymin <=0 || Hparam.ymax <=0) {
7531 Error(where, "cannot set Y axis to log scale");
7532 return 0;
7533 }
7538 if (Hparam.xlast > last) Hparam.xlast = last;
7539 }
7540
7541 // Compute Y axis parameters
7542 Double_t bigp = TMath::Power(10,32);
7543 Double_t xmax = -bigp;
7544 Double_t xmin = bigp;
7545 Double_t c1, e1;
7546 Double_t xv[1];
7547 Double_t fval;
7548 Int_t i;
7549 TObject *f;
7550 TF1 *f1;
7551 Double_t allchan = 0;
7552 TIter next(fFunctions);
7553 for (i=first; i<=last;i++) {
7554 c1 = fH->GetBinContent(i);
7557 if (Hoption.Error) {
7558 e1 = fH->GetBinError(i);
7561 }
7562 if (Hoption.Func) {
7563 xv[0] = fXaxis->GetBinCenter(i);
7564 while ((f = (TObject*) next())) {
7565 if (f->IsA() == TF1::Class()) {
7566 f1 = (TF1*)f;
7567 if (xv[0] < f1->GetXmin() || xv[0] > f1->GetXmax()) continue;
7568 fval = f1->Eval(xv[0],0,0);
7570 if (Hoption.Logy) {
7571 if (fval > 0.3*c1) xmin = TMath::Min(xmin,fval);
7572 }
7573 }
7574 }
7575 next.Reset();
7576 }
7577 allchan += c1;
7578 }
7579
7580 // Take into account maximum , minimum
7581
7582 if (Hoption.Logx && xmin <= 0) {
7583 if (xmax >= 1) xmin = TMath::Max(.5,xmax*1e-10);
7584 else xmin = 0.001*xmax;
7585 }
7586 Double_t xm = xmin;
7587 if (maximum) xmax = fH->GetMaximumStored();
7588 if (minimum) xm = fH->GetMinimumStored();
7589 if (Hoption.Logx && xm <= 0) {
7590 Error(where, "log scale requested with zero or negative argument (%f)", xm);
7591 return 0;
7592 }
7593 else xmin = xm;
7594 if (xmin >= xmax) {
7595 if (Hoption.Logx) {
7596 if (xmax > 0) xmin = 0.001*xmax;
7597 else {
7598 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", xmax);
7599 return 0;
7600 }
7601 }
7602 else {
7603 if (xmin > 0) {
7604 xmin = 0;
7605 xmax *= 2;
7606 } else if (xmin < 0) {
7607 xmax = 0;
7608 xmin *= 2;
7609 } else {
7610 xmin = 0;
7611 xmax = 1;
7612 }
7613 }
7614 }
7615
7616 // take into account normalization factor
7617 Hparam.allchan = allchan;
7618 Double_t factor = allchan;
7619 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
7620 if (allchan) factor /= allchan;
7621 if (factor == 0) factor = 1;
7622 Hparam.factor = factor;
7623 xmax = factor*xmax;
7624 xmin = factor*xmin;
7625
7626 // For log scales, histogram coordinates are LOG10(ymin) and
7627 // LOG10(ymax). Final adjustment (if not option "Same"
7628 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
7629 // Maximum and Minimum are not defined.
7630 if (Hoption.Logx) {
7631 if (xmin <=0 || xmax <=0) {
7632 Error(where, "Cannot set Y axis to log scale");
7633 return 0;
7634 }
7636 if (!minimum) xmin += TMath::Log10(0.5);
7638 if (!maximum) xmax += TMath::Log10(2*(0.9/0.95));
7639 if (!Hoption.Same) {
7640 Hparam.xmin = xmin;
7641 Hparam.xmax = xmax;
7642 }
7643 return 1;
7644 }
7645
7646 // final adjustment of ymin for linear scale.
7647 // if minimum is not set , then ymin is set to zero if >0
7648 // or to ymin - margin if <0.
7649 if (!minimum) {
7650 if (xmin >= 0) xmin = 0;
7651 else xmin -= yMARGIN*(xmax-xmin);
7652 }
7653
7654 // final adjustment of YMAXI for linear scale (if not option "Same"):
7655 // decrease histogram height to MAX% of allowed height if HMAXIM
7656 // has not been called.
7657 if (!maximum) {
7658 xmax += yMARGIN*(xmax-xmin);
7659 }
7660 Hparam.xmin = xmin;
7661 Hparam.xmax = xmax;
7662 return 1;
7663}
7664
7665////////////////////////////////////////////////////////////////////////////////
7666/// [Control function to draw a 3D histogram with boxes.](\ref HP25)
7667
7669{
7670 // Predefined box structure
7671 Double_t wxyz[8][3] = { {-1,-1,-1}, {1,-1,-1}, {1,1,-1}, {-1,1,-1},
7672 {-1,-1, 1}, {1,-1, 1}, {1,1, 1}, {-1,1, 1} };
7673 Int_t iface[6][4] = { {0,3,2,1}, {4,5,6,7},
7674 {0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7} };
7675
7676 // Define dimensions of world space
7677 TAxis *xaxis = fH->GetXaxis();
7678 TAxis *yaxis = fH->GetYaxis();
7679 TAxis *zaxis = fH->GetZaxis();
7680
7681 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7682 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7683 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7684 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7685 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7686 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7687
7688 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7689
7690 // Set view
7691 TView *view = gPad ? gPad->GetView() : nullptr;
7692 if (!view) {
7693 Error("PaintH3", "no TView in current pad");
7694 return;
7695 }
7696 Double_t thedeg = 90 - gPad->GetTheta();
7697 Double_t phideg = -90 - gPad->GetPhi();
7698 Double_t psideg = view->GetPsi();
7699 Int_t irep;
7700 view->SetView(phideg, thedeg, psideg, irep);
7701
7702 Int_t backcolor = gPad->GetFrameFillColor();
7703 view->PadRange(backcolor);
7704
7705 // Draw back surfaces of frame box
7706 fLego->InitMoveScreen(-1.1,1.1);
7707 if (Hoption.BackBox) {
7708 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
7710 fLego->BackBox(90);
7711 }
7712
7714
7715 // Define order of drawing
7716 Double_t *tnorm = view->GetTnorm();
7717 if (!tnorm) return;
7718 Int_t incrx = (tnorm[ 8] < 0.) ? -1 : +1;
7719 Int_t incry = (tnorm[ 9] < 0.) ? -1 : +1;
7720 Int_t incrz = (tnorm[10] < 0.) ? -1 : +1;
7721 Int_t ix1 = (incrx == +1) ? xaxis->GetFirst() : xaxis->GetLast();
7722 Int_t iy1 = (incry == +1) ? yaxis->GetFirst() : yaxis->GetLast();
7723 Int_t iz1 = (incrz == +1) ? zaxis->GetFirst() : zaxis->GetLast();
7724 Int_t ix2 = (incrx == +1) ? xaxis->GetLast() : xaxis->GetFirst();
7725 Int_t iy2 = (incry == +1) ? yaxis->GetLast() : yaxis->GetFirst();
7726 Int_t iz2 = (incrz == +1) ? zaxis->GetLast() : zaxis->GetFirst();
7727
7728 // Set graphic attributes (colour, style, etc.)
7733
7734 fH->SetFillStyle(1001);
7735 fH->TAttFill::Modify();
7736 fH->TAttLine::Modify();
7739
7740 // Create bin boxes and draw
7744
7745 Double_t pmin[3], pmax[3], sxyz[8][3];
7746 for (Int_t ix = ix1; ix !=ix2+incrx; ix += incrx) {
7747 pmin[0] = xaxis->GetBinLowEdge(ix);
7748 pmax[0] = xaxis->GetBinUpEdge(ix);
7749 for (Int_t iy = iy1; iy != iy2+incry; iy += incry) {
7750 pmin[1] = yaxis->GetBinLowEdge(iy);
7751 pmax[1] = yaxis->GetBinUpEdge(iy);
7752 for (Int_t iz = iz1; iz != iz2+incrz; iz += incrz) {
7753 pmin[2] = zaxis->GetBinLowEdge(iz);
7754 pmax[2] = zaxis->GetBinUpEdge(iz);
7755 Double_t w = fH->GetBinContent(fH->GetBin(ix,iy,iz));
7756 Bool_t neg = kFALSE;
7757 Int_t n = 5;
7758 if (w<0) {
7759 w = -w;
7760 neg = kTRUE;
7761 }
7762 if (w < wmin) continue;
7763 if (w > wmax) w = wmax;
7764 Double_t scale = (TMath::Power((w-wmin)/(wmax-wmin),1./3.))/2.;
7765 if (scale == 0) continue;
7766 for (Int_t i=0; i<3; ++i) {
7767 Double_t c = (pmax[i] + pmin[i])*0.5;
7768 Double_t d = (pmax[i] - pmin[i])*scale;
7769 for (Int_t k=0; k<8; ++k) { // set bin box vertices
7770 sxyz[k][i] = wxyz[k][i]*d + c;
7771 }
7772 }
7773 for (Int_t k=0; k<8; ++k) { // transform to normalized space
7774 view->WCtoNDC(&sxyz[k][0],&sxyz[k][0]);
7775 }
7776 Double_t x[8], y[8]; // draw bin box faces
7777 for (Int_t k=0; k<6; ++k) {
7778 for (Int_t i=0; i<4; ++i) {
7779 Int_t iv = iface[k][i];
7780 x[i] = sxyz[iv][0];
7781 y[i] = sxyz[iv][1];
7782 }
7783 x[4] = x[0] ; y[4] = y[0];
7784 if (neg) {
7785 x[5] = x[2] ; y[5] = y[2];
7786 x[6] = x[3] ; y[6] = y[3];
7787 x[7] = x[1] ; y[7] = y[1];
7788 n = 8;
7789 } else {
7790 n = 5;
7791 }
7792 Double_t z = (x[2]-x[0])*(y[3]-y[1]) - (y[2]-y[0])*(x[3]-x[1]);
7793 if (z <= 0.) continue;
7794 if (iopt == 2) {
7795 theColor = ncolors*((w-wmin)/(wmax-wmin)) -1;
7797 } else {
7798 if (k == 3 || k == 5) {
7800 } else if (k == 0 || k == 1) {
7802 } else {
7804 }
7805 }
7806 fH->TAttFill::Modify();
7807 gPad->PaintFillArea(4, x, y);
7808 if (iopt != 3)gPad->PaintPolyLine(n, x, y);
7809 }
7810 }
7811 }
7812 }
7813
7814 // Draw front surfaces of frame box
7815 if (Hoption.FrontBox) fLego->FrontBox(90);
7816
7817 // Draw axis and title
7818 if (!Hoption.Axis && !Hoption.Same) {
7819 TGaxis axis;
7820 PaintLegoAxis(&axis, 90);
7821 }
7822 PaintTitle();
7823
7824 // Draw palette. if needed.
7825 if (Hoption.Zscale) {
7826 Int_t ndiv = fH->GetContour();
7827 if (ndiv == 0 ) {
7828 ndiv = gStyle->GetNumberContours();
7829 fH->SetContour(ndiv);
7830 }
7831 PaintPalette();
7832 }
7833
7834 //Draw stats and fit results
7835 TF1 *fit = nullptr;
7836 TIter next(fFunctions);
7837 while (auto obj = next()) {
7838 if (obj->InheritsFrom(TF1::Class())) {
7839 fit = (TF1*)obj;
7840 break;
7841 }
7842 }
7843 if ((Hoption.Same%10) != 1) {
7844 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7846 }
7847 }
7848
7849 fLego.reset();
7850
7853 fH->TAttFill::Modify();
7854}
7855
7856////////////////////////////////////////////////////////////////////////////////
7857/// [Control function to draw a 3D histogram with boxes.](\ref HP25)
7858
7860{
7861 // Predefined box structure
7862 Double_t wxyz[8][3] = {
7863 {-1,-1,-1}, {1,-1,-1}, {1,1,-1}, {-1,1,-1}, // bottom vertices
7864 {-1,-1, 1}, {1,-1, 1}, {1,1, 1}, {-1,1, 1} // top vertices
7865 };
7866 Int_t iface[6][4] = {
7867 {0,3,2,1}, {4,5,6,7}, // bottom and top faces
7868 {0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7} // side faces
7869 };
7870 Double_t normal[6][3] = {
7871 {0,0,-1}, {0,0,1}, // Z-, Z+
7872 {0,-1,0}, {1,0,0}, {0,1,0}, {-1,0,0} // Y-, X+, Y+, X-
7873 };
7874
7875 // Define dimensions of world space
7876 TAxis *xaxis = fH->GetXaxis();
7877 TAxis *yaxis = fH->GetYaxis();
7878 TAxis *zaxis = fH->GetZaxis();
7879
7880 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7881 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7882 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7883 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7884 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7885 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7886
7887 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7888
7889 // Set view
7890 TView *view = gPad ? gPad->GetView() : nullptr;
7891 if (!view) {
7892 Error("PaintH3", "no TView in current pad");
7893 return;
7894 }
7895 Double_t thedeg = 90 - gPad->GetTheta();
7896 Double_t phideg = -90 - gPad->GetPhi();
7897 Double_t psideg = view->GetPsi();
7898 Int_t irep;
7899 view->SetView(phideg, thedeg, psideg, irep);
7900
7901 Int_t backcolor = gPad->GetFrameFillColor();
7902 view->PadRange(backcolor);
7903
7904 // Draw front surfaces of frame box
7905 if (Hoption.FrontBox) {
7906 fLego->InitMoveScreen(-1.1,1.1);
7908 }
7909
7910 // Initialize hidden line removal algorithm "raster screen"
7911 fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
7912
7913 // Define order of drawing
7914 Double_t *tnorm = view->GetTnorm();
7915 if (!tnorm) return;
7916 Int_t incrx = (tnorm[ 8] < 0.) ? +1 : -1;
7917 Int_t incry = (tnorm[ 9] < 0.) ? +1 : -1;
7918 Int_t incrz = (tnorm[10] < 0.) ? +1 : -1;
7919 Int_t ix1 = (incrx == +1) ? xaxis->GetFirst() : xaxis->GetLast();
7920 Int_t iy1 = (incry == +1) ? yaxis->GetFirst() : yaxis->GetLast();
7921 Int_t iz1 = (incrz == +1) ? zaxis->GetFirst() : zaxis->GetLast();
7922 Int_t ix2 = (incrx == +1) ? xaxis->GetLast() : xaxis->GetFirst();
7923 Int_t iy2 = (incry == +1) ? yaxis->GetLast() : yaxis->GetFirst();
7924 Int_t iz2 = (incrz == +1) ? zaxis->GetLast() : zaxis->GetFirst();
7925
7926 // Set line attributes (colour, style, etc.)
7927 fH->TAttLine::Modify();
7928
7929 // Create bin boxes and draw
7930 const Int_t NTMAX = 100;
7931 Double_t tt[NTMAX][2];
7935 Double_t pmin[3], pmax[3], sxyz[8][3], pp[4][2];
7936 for (Int_t ix = ix1; ix !=ix2+incrx; ix += incrx) {
7937 pmin[0] = xaxis->GetBinLowEdge(ix);
7938 pmax[0] = xaxis->GetBinUpEdge(ix);
7939 for (Int_t iy = iy1; iy != iy2+incry; iy += incry) {
7940 pmin[1] = yaxis->GetBinLowEdge(iy);
7941 pmax[1] = yaxis->GetBinUpEdge(iy);
7942 for (Int_t iz = iz1; iz != iz2+incrz; iz += incrz) {
7943 pmin[2] = zaxis->GetBinLowEdge(iz);
7944 pmax[2] = zaxis->GetBinUpEdge(iz);
7945 Double_t w = fH->GetBinContent(fH->GetBin(ix,iy,iz));
7946 Bool_t neg = kFALSE;
7947 if (w<0) {
7948 w = -w;
7949 neg = kTRUE;
7950 }
7951 if (w < wmin) continue;
7952 if (w > wmax) w = wmax;
7953 Double_t scale = (TMath::Power((w-wmin)/(wmax-wmin),1./3.))/2.;
7954 if (scale == 0) continue;
7955 for (Int_t i=0; i<3; ++i) {
7956 Double_t c = (pmax[i] + pmin[i])*0.5;
7957 Double_t d = (pmax[i] - pmin[i])*scale;
7958 for (Int_t k=0; k<8; ++k) { // set bin box vertices
7959 sxyz[k][i] = wxyz[k][i]*d + c;
7960 }
7961 }
7962 for (Int_t k=0; k<8; ++k) { // transform to normalized space
7963 view->WCtoNDC(&sxyz[k][0],&sxyz[k][0]);
7964 }
7965 for (Int_t k=0; k<6; ++k) { // draw box faces
7966 Double_t zn;
7967 view->FindNormal(normal[k][0], normal[k][1], normal[k][2], zn);
7968 if (zn <= 0) continue;
7969 for (Int_t i=0; i<4; ++i) {
7970 Int_t ip = iface[k][i];
7971 pp[i][0] = sxyz[ip][0];
7972 pp[i][1] = sxyz[ip][1];
7973 }
7974 for (Int_t i=0; i<4; ++i) {
7975 Int_t i1 = i;
7976 Int_t i2 = (i == 3) ? 0 : i + 1;
7977 Int_t nt;
7978 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7979 Double_t xdel = pp[i2][0] - pp[i1][0];
7980 Double_t ydel = pp[i2][1] - pp[i1][1];
7981 Double_t x[2], y[2];
7982 for (Int_t it = 0; it < nt; ++it) {
7983 x[0] = pp[i1][0] + xdel*tt[it][0];
7984 y[0] = pp[i1][1] + ydel*tt[it][0];
7985 x[1] = pp[i1][0] + xdel*tt[it][1];
7986 y[1] = pp[i1][1] + ydel*tt[it][1];
7987 gPad->PaintPolyLine(2, x, y);
7988 }
7989 }
7990 if (neg) {
7991 Int_t i1 = 0;
7992 Int_t i2 = 2;
7993 Int_t nt;
7994 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7995 Double_t xdel = pp[i2][0] - pp[i1][0];
7996 Double_t ydel = pp[i2][1] - pp[i1][1];
7997 Double_t x[2], y[2];
7998 for (Int_t it = 0; it < nt; ++it) {
7999 x[0] = pp[i1][0] + xdel*tt[it][0];
8000 y[0] = pp[i1][1] + ydel*tt[it][0];
8001 x[1] = pp[i1][0] + xdel*tt[it][1];
8002 y[1] = pp[i1][1] + ydel*tt[it][1];
8003 gPad->PaintPolyLine(2, x, y);
8004 }
8005 i1 = 1;
8006 i2 = 3;
8007 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
8008 xdel = pp[i2][0] - pp[i1][0];
8009 ydel = pp[i2][1] - pp[i1][1];
8010 for (Int_t it = 0; it < nt; ++it) {
8011 x[0] = pp[i1][0] + xdel*tt[it][0];
8012 y[0] = pp[i1][1] + ydel*tt[it][0];
8013 x[1] = pp[i1][0] + xdel*tt[it][1];
8014 y[1] = pp[i1][1] + ydel*tt[it][1];
8015 gPad->PaintPolyLine(2, x, y);
8016 }
8017 }
8018 fLego->FillPolygonBorder(4, &pp[0][0]); // update raster screen
8019 }
8020 }
8021 }
8022 }
8023
8024 // Draw frame box
8025 if (Hoption.BackBox) {
8026 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
8028 fLego->BackBox(90);
8029 }
8030
8031 if (Hoption.FrontBox) fLego->FrontBox(90);
8032
8033 // Draw axis and title
8034 if (!Hoption.Axis && !Hoption.Same) {
8035 TGaxis axis;
8036 PaintLegoAxis(&axis, 90);
8037 }
8038 PaintTitle();
8039
8040 //Draw stats and fit results
8041 TF1 *fit = nullptr;
8042 TIter next(fFunctions);
8043 while (auto obj = next()) {
8044 if (obj->InheritsFrom(TF1::Class())) {
8045 fit = (TF1*)obj;
8046 break;
8047 }
8048 }
8049 if ((Hoption.Same%10) != 1) {
8050 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
8052 }
8053 }
8054
8055 fLego.reset();
8056}
8057
8058////////////////////////////////////////////////////////////////////////////////
8059/// [Control function to draw a 3D histogram with Iso Surfaces.](\ref HP25)
8060
8062{
8063
8064 const Double_t ydiff = 1;
8065 const Double_t yligh1 = 10;
8066 const Double_t qa = 0.15;
8067 const Double_t qd = 0.15;
8068 const Double_t qs = 0.8;
8070 Int_t i, irep;
8071 Int_t nbcol = 28;
8072 Int_t icol1 = 201;
8073 Int_t ic1 = icol1;
8074 Int_t ic2 = ic1+nbcol;
8075 Int_t ic3 = ic2+nbcol;
8076
8077 TAxis *xaxis = fH->GetXaxis();
8078 TAxis *yaxis = fH->GetYaxis();
8079 TAxis *zaxis = fH->GetZaxis();
8080
8081 Int_t nx = fH->GetNbinsX();
8082 Int_t ny = fH->GetNbinsY();
8083 Int_t nz = fH->GetNbinsZ();
8084
8085 std::vector<Double_t> x(nx);
8086 std::vector<Double_t> y(ny);
8087 std::vector<Double_t> z(nz);
8088
8089 for (i=0; i<nx; i++) x[i] = xaxis->GetBinCenter(i+1);
8090 for (i=0; i<ny; i++) y[i] = yaxis->GetBinCenter(i+1);
8091 for (i=0; i<nz; i++) z[i] = zaxis->GetBinCenter(i+1);
8092
8093 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
8094 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
8095 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
8096 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
8097 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
8098 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
8099
8100 Double_t s[3];
8101 s[0] = fH->GetSumOfWeights()/(fH->GetNbinsX()*fH->GetNbinsY()*fH->GetNbinsZ());
8102 s[1] = 0.5*s[0];
8103 s[2] = 1.5*s[0];
8104
8105 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
8106
8107 TView *view = gPad ? gPad->GetView() : nullptr;
8108 if (!view) {
8109 Error("PaintH3Iso", "no TView in current pad");
8110 return;
8111 }
8112 Double_t thedeg = 90 - gPad->GetTheta();
8113 Double_t phideg = -90 - gPad->GetPhi();
8114 Double_t psideg = view->GetPsi();
8115 view->SetView(phideg, thedeg, psideg, irep);
8116
8117 Int_t backcolor = gPad->GetFrameFillColor();
8118 if (Hoption.System != kCARTESIAN) backcolor = 0;
8119 view->PadRange(backcolor);
8120
8121 Double_t dcol = 0.5/Double_t(nbcol);
8122 TColor *colref = gROOT->GetColor(fH->GetFillColor());
8123 if (!colref) {
8124 return;
8125 }
8126 Float_t r, g, b, hue, light, satur;
8127 colref->GetRGB(r,g,b);
8129 TColor *acol;
8130 for (Int_t col=0;col<nbcol;col++) {
8131 acol = gROOT->GetColor(col+icol1);
8132 TColor::HLStoRGB(hue, .4+col*dcol, satur, r, g, b);
8133 if (acol) acol->SetRGB(r, g, b);
8134 }
8135
8136 fLego->InitMoveScreen(-1.1,1.1);
8137
8138 if (Hoption.BackBox) {
8139 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
8141 fLego->BackBox(90);
8142 }
8143
8144 fLego->LightSource(0, ydiff, 0, 0, 0, irep);
8145 fLego->LightSource(1, yligh1, 1, 1, 1, irep);
8146 fLego->SurfaceProperty(qa, qd, qs, 1, irep);
8147 fmin = ydiff*qa;
8148 fmax = ydiff*qa + (yligh1+0.1)*(qd+qs);
8149 fLego->SetIsoSurfaceParameters(fmin, fmax, nbcol, ic1, ic2, ic3);
8150
8151 fLego->IsoSurface(1, s, nx, ny, nz, x.data(), y.data(), z.data(), "BF");
8152
8153 if (Hoption.FrontBox) {
8154 fLego->InitMoveScreen(-1.1,1.1);
8156 fLego->FrontBox(90);
8157 }
8158 if (!Hoption.Axis && !Hoption.Same) {
8159 TGaxis axis;
8160 PaintLegoAxis(&axis, 90);
8161 }
8162
8163 PaintTitle();
8164
8165 //Draw stats and fit results
8166 TF1 *fit = nullptr;
8167 TIter next(fFunctions);
8168 while (auto obj = next()) {
8169 if (obj->InheritsFrom(TF1::Class())) {
8170 fit = (TF1*)obj;
8171 break;
8172 }
8173 }
8174 if ((Hoption.Same%10) != 1) {
8175 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
8177 }
8178 }
8179
8180 fLego.reset();
8181}
8182
8183////////////////////////////////////////////////////////////////////////////////
8184/// [Control function to draw a 2D histogram as a lego plot.](\ref HP17)
8185
8187{
8188
8189 Int_t raster = 1;
8190 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
8191 Int_t nx = Hparam.xlast - Hparam.xfirst + 1;
8192 Int_t ny = Hparam.ylast - Hparam.yfirst + 1;
8193 Double_t zmin = Hparam.zmin;
8194 Double_t zmax = Hparam.zmax;
8199 Double_t dangle = 10*3.141592/180; //Delta angle for Rapidity option
8200 Double_t deltaz = TMath::Abs(zmin);
8201 if (deltaz == 0) deltaz = 1;
8202 if (zmin >= zmax) {
8203 zmin -= 0.5*deltaz;
8204 zmax += 0.5*deltaz;
8205 }
8206 Double_t z1c = zmin;
8207 Double_t z2c = zmin + (zmax-zmin)*(1+gStyle->GetHistTopMargin());
8208
8209 // Compute the lego limits and instantiate a lego object
8210 fXbuf[0] = -1;
8211 fYbuf[0] = 1;
8212 fXbuf[1] = -1;
8213 fYbuf[1] = 1;
8214 if (Hoption.System == kPOLAR) {
8215 fXbuf[2] = z1c;
8216 fYbuf[2] = z2c;
8217 } else if (Hoption.System == kCYLINDRICAL) {
8218 if (Hoption.Logy) {
8219 if (ylab1 > 0) fXbuf[2] = TMath::Log10(ylab1);
8220 else fXbuf[2] = 0;
8221 if (ylab2 > 0) fYbuf[2] = TMath::Log10(ylab2);
8222 else fYbuf[2] = 0;
8223 } else {
8224 fXbuf[2] = ylab1;
8225 fYbuf[2] = ylab2;
8226 }
8227 z1c = 0; z2c = 1;
8228 } else if (Hoption.System == kSPHERICAL) {
8229 fXbuf[2] = -1;
8230 fYbuf[2] = 1;
8231 z1c = 0; z2c = 1;
8232 } else if (Hoption.System == kRAPIDITY) {
8233 fXbuf[2] = -1/TMath::Tan(dangle);
8234 fYbuf[2] = 1/TMath::Tan(dangle);
8235 } else {
8236 fXbuf[0] = xlab1;
8237 fYbuf[0] = xlab2;
8238 fXbuf[1] = ylab1;
8239 fYbuf[1] = ylab2;
8240 fXbuf[2] = z1c;
8241 fYbuf[2] = z2c;
8242 raster = 0;
8243 }
8244
8245 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data(), Hoption.System);
8246
8247 Int_t nids = -1;
8248 TH1 * hid = nullptr;
8249 Color_t colormain = -1, colordark = -1;
8251
8252 // LEGO3 is like LEGO1 except that the black lines around each lego are not drawn.
8253 if (Hoption.Lego == 13) {
8254 Hoption.Lego = 11;
8255 fLego->SetMesh(0);
8256 }
8257 // LEGO4 is like LEGO1 except no shadows are drawn.
8258 if (Hoption.Lego == 14) {
8259 Hoption.Lego = 11;
8261 }
8262
8263 // Initialize the levels on the Z axis
8264 Int_t ndiv = fH->GetContour();
8265 if (ndiv == 0 ) {
8266 ndiv = gStyle->GetNumberContours();
8267 fH->SetContour(ndiv);
8268 }
8269 Int_t ndivz = TMath::Abs(ndiv);
8270 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
8271
8272 // Initialize colors
8273 if (!fStack) {
8274 fLego->SetEdgeAtt(fH->GetLineColor(),fH->GetLineStyle(),fH->GetLineWidth(),0);
8275 } else {
8276 for (Int_t id=0;id<=fStack->GetSize();id++) {
8277 hid = (TH1*)fStack->At((id==0)?id:id-1);
8278 fLego->SetEdgeAtt(hid->GetLineColor(),hid->GetLineStyle(),hid->GetLineWidth(),id);
8279 }
8280 }
8281
8282 if (Hoption.Lego == 11) {
8283 nids = 1;
8284 if (fStack) nids = fStack->GetSize();
8285 hid = fH;
8286 for (Int_t id=0;id<=nids;id++) {
8287 if (id > 0 && fStack) hid = (TH1*)fStack->At(id-1);
8288 colormain = hid->GetFillColor();
8289 if (colormain == 1) colormain = 17; //avoid drawing with black
8291 else colordark = colormain;
8292 fLego->SetColorMain(colormain,id);
8293 fLego->SetColorDark(colordark,id);
8294 if (id <= 1) fLego->SetColorMain(colormain,-1); // Set Bottom color
8295 if (id == nids) fLego->SetColorMain(colormain,99); // Set Top color
8296 }
8297 }
8298
8299 // Now ready to draw the lego plot
8300 Int_t irep = 0;
8301
8302 TView *view = gPad ? gPad->GetView() : nullptr;
8303 if (!view) {
8304 Error("PaintLego", "no TView in current pad");
8305 return;
8306 }
8307
8308 Double_t thedeg = 90 - gPad->GetTheta();
8309 Double_t phideg = -90 - gPad->GetPhi();
8310 Double_t psideg = view->GetPsi();
8311 view->SetView(phideg, thedeg, psideg, irep);
8312
8313 fLego->SetLineColor(kBlack); // zgrid color for lego1 & lego2
8314 fLego->SetFillStyle(fH->GetFillStyle());
8315
8316 // Set color/style for back box
8317 fLego->SetFillStyle(gPad->GetFrameFillStyle());
8318 fLego->SetFillColor(gPad->GetFrameFillColor());
8319 fLego->TAttFill::Modify();
8320
8321 Int_t backcolor = gPad->GetFrameFillColor();
8322 if (Hoption.System != kCARTESIAN) backcolor = 0;
8323 view->PadRange(backcolor);
8324
8325 fLego->SetFillStyle(fH->GetFillStyle());
8326 fLego->SetFillColor(fH->GetFillColor());
8327 fLego->TAttFill::Modify();
8328
8329 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
8330
8331 if (raster) fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
8332 else fLego->InitMoveScreen(-1.1,1.1);
8333
8334 if (Hoption.Lego == 19) {
8336 if (Hoption.BackBox) fLego->BackBox(90);
8337 if (Hoption.FrontBox) fLego->FrontBox(90);
8338 if (!Hoption.Axis) { TGaxis axis; PaintLegoAxis(&axis, 90); }
8339 return;
8340 }
8341
8342 if (Hoption.Lego == 11 || Hoption.Lego == 12) {
8345 fLego->BackBox(90);
8346 }
8347 }
8348
8349 if (Hoption.Lego == 12) DefineColorLevels(ndivz);
8350
8351 fLego->SetLegoFunction(&TPainter3dAlgorithms::LegoFunction);
8353 if (Hoption.Lego == 11) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode3);
8354 if (Hoption.Lego == 12) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode2);
8355 if (Hoption.System == kPOLAR) {
8356 if (Hoption.Lego == 1) fLego->LegoPolar(1,nx,ny,"FB");
8357 if (Hoption.Lego == 11) fLego->LegoPolar(1,nx,ny,"BF");
8358 if (Hoption.Lego == 12) fLego->LegoPolar(1,nx,ny,"BF");
8359 } else if (Hoption.System == kCYLINDRICAL) {
8360 if (Hoption.Lego == 1) fLego->LegoCylindrical(1,nx,ny,"FB");
8361 if (Hoption.Lego == 11) fLego->LegoCylindrical(1,nx,ny,"BF");
8362 if (Hoption.Lego == 12) fLego->LegoCylindrical(1,nx,ny,"BF");
8363 } else if (Hoption.System == kSPHERICAL) {
8364 if (Hoption.Lego == 1) fLego->LegoSpherical(0,1,nx,ny,"FB");
8365 if (Hoption.Lego == 11) fLego->LegoSpherical(0,1,nx,ny,"BF");
8366 if (Hoption.Lego == 12) fLego->LegoSpherical(0,1,nx,ny,"BF");
8367 } else if (Hoption.System == kRAPIDITY) {
8368 if (Hoption.Lego == 1) fLego->LegoSpherical(1,1,nx,ny,"FB");
8369 if (Hoption.Lego == 11) fLego->LegoSpherical(1,1,nx,ny,"BF");
8370 if (Hoption.Lego == 12) fLego->LegoSpherical(1,1,nx,ny,"BF");
8371 } else {
8372 if (Hoption.Lego == 1) {
8374 fLego->LegoCartesian(90,nx,ny,"FB");}
8375 if (Hoption.Lego == 11) fLego->LegoCartesian(90,nx,ny,"BF");
8376 if (Hoption.Lego == 12) fLego->LegoCartesian(90,nx,ny,"BF");
8377 }
8378
8379 if (Hoption.Lego == 1 || Hoption.Lego == 11) {
8382 fLego->BackBox(90);
8383 }
8384 }
8385 if (Hoption.System == kCARTESIAN) {
8386 fLego->InitMoveScreen(-1.1,1.1);
8388 if (Hoption.FrontBox) fLego->FrontBox(90);
8389 }
8390 if (!Hoption.Axis && !Hoption.Same) {
8391 TGaxis axis;
8392 PaintLegoAxis(&axis, 90);
8393 }
8395 fLego.reset();
8396}
8397
8398////////////////////////////////////////////////////////////////////////////////
8399/// Draw the axis for legos and surface plots.
8400
8402{
8403
8404 static Double_t epsil = 0.001;
8405
8408 Double_t r[24] /* was [3][8] */;
8409 Int_t ndivx, ndivy, ndivz, i;
8410 Double_t x1[3], x2[3], y1[3], y2[3], z1[3], z2[3], av[24] /* was [3][8] */;
8411 static char chopax[8], chopay[8], chopaz[8];
8412 Int_t ix1, ix2, iy1, iy2, iz1, iz2;
8413 Double_t rad;
8414
8415 TView *view = gPad ? gPad->GetView() : nullptr;
8416 if (!view) {
8417 Error("PaintLegoAxis", "no TView in current pad");
8418 return;
8419 }
8420
8421 // In polar coordinates, draw a short line going from the external circle
8422 // corresponding to r = 1 up to r = 1.1
8423 if (Hoption.System == kPOLAR) {
8424 r[0] = 1;
8425 r[1] = 0;
8426 r[2] = 0;
8427 view->WCtoNDC(r, x1);
8428 r[0] = 1.1;
8429 r[1] = 0;
8430 r[2] = 0;
8431 view->WCtoNDC(r, x2);
8432 gPad->PaintLine(x1[0],x1[1],x2[0],x2[1]);
8433 return;
8434 }
8435
8436 if (Hoption.System != kCARTESIAN) return;
8437
8438 rad = TMath::ATan(1.) * 4. /180.;
8439 cosa = TMath::Cos(ang*rad);
8440 sina = TMath::Sin(ang*rad);
8441
8442 view->AxisVertex(ang, av, ix1, ix2, iy1, iy2, iz1, iz2);
8443 for (i = 1; i <= 8; ++i) {
8444 r[i*3 - 3] = av[i*3 - 3] + av[i*3 - 2]*cosa;
8445 r[i*3 - 2] = av[i*3 - 2]*sina;
8446 r[i*3 - 1] = av[i*3 - 1];
8447 }
8448
8449 view->WCtoNDC(&r[ix1*3 - 3], x1);
8450 view->WCtoNDC(&r[ix2*3 - 3], x2);
8451 view->WCtoNDC(&r[iy1*3 - 3], y1);
8452 view->WCtoNDC(&r[iy2*3 - 3], y2);
8453 view->WCtoNDC(&r[iz1*3 - 3], z1);
8454 view->WCtoNDC(&r[iz2*3 - 3], z2);
8455
8456 view->SetAxisNDC(x1, x2, y1, y2, z1, z2);
8457
8458 Double_t *rmin = view->GetRmin();
8459 Double_t *rmax = view->GetRmax();
8460 if (!rmin || !rmax) return;
8461
8462 // Initialize the axis options
8463 if (x1[0] > x2[0]) strlcpy(chopax, "SDH=+",8);
8464 else strlcpy(chopax, "SDH=-",8);
8465 if (y1[0] > y2[0]) strlcpy(chopay, "SDH=+",8);
8466 else strlcpy(chopay, "SDH=-",8);
8467 if (z2[1] > z1[1]) strlcpy(chopaz, "SDH=+",8);
8468 else strlcpy(chopaz, "SDH=-",8);
8469
8470 // Option LOG is required ?
8471 if (Hoption.Logx) strlcat(chopax,"G",8);
8472 if (Hoption.Logy) strlcat(chopay,"G",8);
8473 if (Hoption.Logz) strlcat(chopaz,"G",8);
8474
8475 // Initialize the number of divisions. If the
8476 // number of divisions is negative, option 'N' is required.
8480 if (ndivx < 0) {
8482 strlcat(chopax, "N",8);
8483 }
8484 if (ndivy < 0) {
8486 strlcat(chopay, "N",8);
8487 }
8488 if (ndivz < 0) {
8490 strlcat(chopaz, "N",8);
8491 }
8492
8493 // Set Axis attributes.
8494 // The variable SCALE rescales the VSIZ
8495 // in order to have the same label size for all angles.
8496
8497 axis->SetLineWidth(1);
8498
8499 // X axis drawing
8500 if (TMath::Abs(x1[0] - x2[0]) >= epsil || TMath::Abs(x1[1] - x2[1]) > epsil) {
8503 if (Hoption.Logx && !fH->InheritsFrom(TH3::Class())) {
8504 bmin = TMath::Power(10, rmin[0]);
8505 bmax = TMath::Power(10, rmax[0]);
8506 } else {
8507 bmin = rmin[0];
8508 bmax = rmax[0];
8509 }
8510 // Option time display is required ?
8511 if (fXaxis->GetTimeDisplay()) {
8512 strlcat(chopax,"t",8);
8513 if (strlen(fXaxis->GetTimeFormatOnly()) == 0) {
8515 } else {
8517 }
8518 }
8519 axis->SetOption(chopax);
8520 axis->PaintAxis(x1[0], x1[1], x2[0], x2[1], bmin, bmax, ndivx, chopax);
8521 }
8522
8523 // Y axis drawing
8524 if (TMath::Abs(y1[0] - y2[0]) >= epsil || TMath::Abs(y1[1] - y2[1]) > epsil) {
8527 if (fYaxis->GetTitleOffset() == 0) axis->SetTitleOffset(1.5);
8528
8529 if (fH->GetDimension() < 2) {
8530 strlcpy(chopay, "V=+UN",8);
8531 ndivy = 0;
8532 }
8533 if (TMath::Abs(y1[0] - y2[0]) < epsil) {
8534 y2[0] = y1[0];
8535 }
8536 if (Hoption.Logy && !fH->InheritsFrom(TH3::Class())) {
8537 bmin = TMath::Power(10, rmin[1]);
8538 bmax = TMath::Power(10, rmax[1]);
8539 } else {
8540 bmin = rmin[1];
8541 bmax = rmax[1];
8542 }
8543 // Option time display is required ?
8544 if (fYaxis->GetTimeDisplay()) {
8545 strlcat(chopay,"t",8);
8546 if (strlen(fYaxis->GetTimeFormatOnly()) == 0) {
8548 } else {
8550 }
8551 }
8552 axis->SetOption(chopay);
8553 axis->PaintAxis(y1[0], y1[1], y2[0], y2[1], bmin, bmax, ndivy, chopay);
8554 }
8555
8556 // Z axis drawing
8557 if (TMath::Abs(z1[0] - z2[0]) >= 100*epsil || TMath::Abs(z1[1] - z2[1]) > 100*epsil) {
8559 if (Hoption.Logz && !fH->InheritsFrom(TH3::Class())) {
8560 bmin = TMath::Power(10, rmin[2]);
8561 bmax = TMath::Power(10, rmax[2]);
8562 } else {
8563 bmin = rmin[2];
8564 bmax = rmax[2];
8565 }
8566 // Option time display is required ?
8567 if (fZaxis->GetTimeDisplay()) {
8568 strlcat(chopaz,"t",8);
8569 if (strlen(fZaxis->GetTimeFormatOnly()) == 0) {
8571 } else {
8573 }
8574 }
8575 axis->SetOption(chopaz);
8577 if (ztit.Index(";")>0) {
8578 ztit.Remove(ztit.Index(";"),ztit.Length());
8579 axis->SetTitle(ztit.Data());
8580 }
8581 axis->PaintAxis(z1[0], z1[1], z2[0], z2[1], bmin, bmax, ndivz, chopaz);
8582 }
8583
8584 //fH->SetLineStyle(1); /// otherwise fEdgeStyle[i] gets overwritten!
8585}
8586
8587////////////////////////////////////////////////////////////////////////////////
8588/// [Paint the color palette on the right side of the pad.](\ref HP22)
8589
8591{
8593 TView *view = gPad ? gPad->GetView() : nullptr;
8594 if (palette) {
8595 if (view) {
8596 if (!palette->TestBit(TPaletteAxis::kHasView)) {
8598 delete palette; palette = nullptr;
8599 }
8600 } else {
8601 if (palette->TestBit(TPaletteAxis::kHasView)) {
8603 delete palette; palette = nullptr;
8604 }
8605 }
8606 // make sure the histogram member of the palette is setup correctly. It may not be after a Clone()
8607 if (palette && !palette->GetHistogram()) palette->SetHistogram(fH);
8608 }
8609
8610 if (!palette) {
8611 Double_t xup = gPad->GetUxmax();
8612 Double_t x2 = gPad->PadtoX(gPad->GetX2());
8613 Double_t ymin = gPad->PadtoY(gPad->GetUymin());
8614 Double_t ymax = gPad->PadtoY(gPad->GetUymax());
8615 Double_t xr = 0.05*(gPad->GetX2() - gPad->GetX1());
8616 Double_t xmin = gPad->PadtoX(xup +0.1*xr);
8617 Double_t xmax = gPad->PadtoX(xup + xr);
8618 if (xmax > x2) xmax = gPad->PadtoX(gPad->GetX2()-0.01*xr);
8621 palette->Paint();
8622 }
8623}
8624
8625////////////////////////////////////////////////////////////////////////////////
8626/// [Control function to draw a 2D histogram as a scatter plot.](\ref HP11)
8627
8629{
8630
8631 fH->TAttMarker::Modify();
8632
8633 Int_t k, marker;
8634 Double_t dz, z, xk,xstep, yk, ystep;
8635 Double_t scale = 1;
8637 Double_t zmax = fH->GetMaximum();
8638 Double_t zmin = fH->GetMinimum();
8639 if (zmin == 0 && zmax == 0) return;
8640 if (zmin == zmax) {
8641 zmax += 0.1*TMath::Abs(zmax);
8642 zmin -= 0.1*TMath::Abs(zmin);
8643 }
8645 if (Hoption.Logz) {
8646 if (zmin > 0) zmin = TMath::Log10(zmin);
8647 else zmin = 0;
8648 if (zmax > 0) zmax = TMath::Log10(zmax);
8649 else zmax = 0;
8650 if (zmin == 0 && zmax == 0) return;
8651 dz = zmax - zmin;
8652 scale = 100/dz;
8653 if (ncells > 10000) scale /= 5;
8654 ltest = kTRUE;
8655 } else {
8656 dz = zmax - zmin;
8657 if (dz >= kNMAX || zmax < 1) {
8658 scale = (kNMAX-1)/dz;
8659 if (ncells > 10000) scale /= 5;
8660 ltest = kTRUE;
8661 }
8662 }
8663 if (fH->GetMinimumStored() == -1111) {
8665 if (Hoption.MinimumZero) {
8666 if (zmin >= 0) zmin = 0;
8667 else zmin -= yMARGIN*(zmax-zmin);
8668 } else {
8669 Double_t dzmin = yMARGIN*(zmax-zmin);
8670 if (zmin >= 0 && (zmin-dzmin <= 0)) zmin = 0;
8671 else zmin -= dzmin;
8672 }
8673 }
8674
8675 TString opt = option;
8676 opt.ToLower();
8677 if (opt.Contains("scat=")) {
8678 char optscat[100];
8679 strlcpy(optscat,opt.Data(),100);
8680 char *oscat = strstr(optscat,"scat=");
8681 char *blank = strstr(oscat," "); if (blank) *blank = 0;
8682 sscanf(oscat+5,"%lg",&scale);
8683 }
8684 // use an independent instance of a random generator
8685 // instead of gRandom to avoid conflicts and
8686 // to get same random numbers when drawing the same histogram
8688 marker=0;
8689 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
8692 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
8693 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
8694 xk = fXaxis->GetBinLowEdge(i);
8695 xstep = fXaxis->GetBinWidth(i);
8696 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
8697 z = fH->GetBinContent(bin);
8698 if (z < zmin) z = zmin;
8699 if (z > zmax) z = zmax;
8700 if (Hoption.Logz) {
8701 if (z > 0) z = TMath::Log10(z) - zmin;
8702 } else {
8703 z -= zmin;
8704 }
8705 if (z <= 0) continue;
8706 k = Int_t(z*scale);
8707 if (ltest) k++;
8708 if (k > 0) {
8709 for (Int_t loop=0; loop<k; loop++) {
8710 if (k+marker >= kNMAX) {
8711 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
8712 marker=0;
8713 }
8714 fXbuf[marker] = (random.Rndm()*xstep) + xk;
8715 fYbuf[marker] = (random.Rndm()*ystep) + yk;
8716 if (Hoption.Logx) {
8717 if (fXbuf[marker] > 0) fXbuf[marker] = TMath::Log10(fXbuf[marker]);
8718 else break;
8719 }
8720 if (Hoption.Logy) {
8721 if (fYbuf[marker] > 0) fYbuf[marker] = TMath::Log10(fYbuf[marker]);
8722 else break;
8723 }
8724 if (fXbuf[marker] < gPad->GetUxmin()) break;
8725 if (fYbuf[marker] < gPad->GetUymin()) break;
8726 if (fXbuf[marker] > gPad->GetUxmax()) break;
8727 if (fYbuf[marker] > gPad->GetUymax()) break;
8728 marker++;
8729 }
8730 }
8731 }
8732 }
8733 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
8734
8736}
8737
8738////////////////////////////////////////////////////////////////////////////////
8739/// Static function to paint special objects like vectors and matrices.
8740/// This function is called via `gROOT->ProcessLine` to paint these objects
8741/// without having a direct dependency of the graphics or histogramming
8742/// system.
8743
8745{
8746
8747 if (!obj) return;
8748 TDirectory::TContext ctx{nullptr}; // No self-registration to directories
8749
8750 if (obj->InheritsFrom(TMatrixFBase::Class())) {
8751 // case TMatrixF
8752 TH2F *R__TMatrixFBase = new TH2F((TMatrixFBase &)*obj);
8753 R__TMatrixFBase->SetBit(kCanDelete);
8754 R__TMatrixFBase->Draw(option);
8755
8756 } else if (obj->InheritsFrom(TMatrixDBase::Class())) {
8757 // case TMatrixD
8758 TH2D *R__TMatrixDBase = new TH2D((TMatrixDBase &)*obj);
8759 R__TMatrixDBase->SetBit(kCanDelete);
8760 R__TMatrixDBase->Draw(option);
8761
8762 } else if (obj->InheritsFrom(TVectorF::Class())) {
8763 //case TVectorF
8764 TH1F *R__TVectorF = new TH1F((TVectorF &)*obj);
8765 R__TVectorF->SetBit(kCanDelete);
8766 R__TVectorF->Draw(option);
8767
8768 } else if (obj->InheritsFrom(TVectorD::Class())) {
8769 //case TVectorD
8770 TH1D *R__TVectorD = new TH1D((TVectorD &)*obj);
8771 R__TVectorD->SetBit(kCanDelete);
8772 R__TVectorD->Draw(option);
8773 }
8774}
8775
8776////////////////////////////////////////////////////////////////////////////////
8777/// [Draw the statistics box for 1D and profile histograms.](\ref HP07)
8778
8780{
8781 TString tt, tf;
8782 Int_t dofit;
8783 TPaveStats *stats = nullptr;
8784 TIter next(fFunctions);
8785 while (auto obj = next()) {
8786 if (obj->InheritsFrom(TPaveStats::Class())) {
8787 stats = (TPaveStats*)obj;
8788 break;
8789 }
8790 }
8791
8792 if (stats && dostat) {
8793 dofit = stats->GetOptFit();
8794 dostat = stats->GetOptStat();
8795 } else {
8796 dofit = gStyle->GetOptFit();
8797 }
8798 if (!dofit) fit = nullptr;
8799 if (dofit == 1) dofit = 111;
8800 if (dostat == 1) dostat = 1111;
8801 Int_t print_name = dostat%10;
8802 Int_t print_entries = (dostat/10)%10;
8803 Int_t print_mean = (dostat/100)%10;
8804 Int_t print_stddev = (dostat/1000)%10;
8805 Int_t print_under = (dostat/10000)%10;
8806 Int_t print_over = (dostat/100000)%10;
8807 Int_t print_integral= (dostat/1000000)%10;
8808 Int_t print_skew = (dostat/10000000)%10;
8809 Int_t print_kurt = (dostat/100000000)%10;
8813 Int_t print_fval = dofit%10;
8814 Int_t print_ferrors = (dofit/10)%10;
8815 Int_t print_fchi2 = (dofit/100)%10;
8816 Int_t print_fprob = (dofit/1000)%10;
8818 if (fit) {
8819 if (print_fval < 2) nlinesf += fit->GetNumberFreeParameters();
8820 else nlinesf += fit->GetNpar();
8821 }
8823
8824 // Pavetext with statistics
8825 Bool_t done = kFALSE;
8826 if (!dostat && !fit) {
8827 if (stats) { fFunctions->Remove(stats); delete stats;}
8828 return;
8829 }
8831 if (fit) statw = 1.8*gStyle->GetStatW();
8833 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
8834 stath = 0.25*(nlines+nlinesf)*gStyle->GetStatH();
8835 }
8836 if (stats) {
8837 stats->Clear();
8838 done = kTRUE;
8839 } else {
8840 stats = new TPaveStats(
8843 gStyle->GetStatX(),
8844 gStyle->GetStatY(),"brNDC");
8845
8846 stats->SetParent(fH);
8847 stats->SetOptFit(dofit);
8848 stats->SetOptStat(dostat);
8849 stats->SetFillColor(gStyle->GetStatColor());
8850 stats->SetFillStyle(gStyle->GetStatStyle());
8852 stats->SetTextFont(gStyle->GetStatFont());
8853 if (gStyle->GetStatFont()%10 > 2)
8855 stats->SetFitFormat(gStyle->GetFitFormat());
8857 stats->SetName("stats");
8858
8860 stats->SetTextAlign(12);
8861 stats->SetBit(kCanDelete);
8862 stats->SetBit(kMustCleanup);
8863 }
8864 if (print_name) stats->AddText(fH->GetName());
8865 if (print_entries) {
8866 if (fH->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(fH->GetEntries()+0.5));
8867 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(fH->GetEntries()));
8868 stats->AddText(tt.Data());
8869 }
8870 if (print_mean) {
8871 if (print_mean == 1) {
8872 tf.Form("%s = %s%s",gStringMean.Data(),"%",stats->GetStatFormat());
8873 tt.Form(tf.Data(),fH->GetMean(1));
8874 } else {
8875 tf.Form("%s = %s%s #pm %s%s",gStringMean.Data(),"%",stats->GetStatFormat()
8876 ,"%",stats->GetStatFormat());
8877 tt.Form(tf.Data(),fH->GetMean(1),fH->GetMeanError(1));
8878 }
8879 stats->AddText(tt.Data());
8881 if (print_mean == 1) {
8882 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
8883 tt.Form(tf.Data(),fH->GetMean(2));
8884 } else {
8885 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
8886 ,"%",stats->GetStatFormat());
8887 tt.Form(tf.Data(),fH->GetMean(2),fH->GetMeanError(2));
8888 }
8889 stats->AddText(tt.Data());
8890 }
8891 }
8892 if (print_stddev) {
8893 if (print_stddev == 1) {
8894 tf.Form("%s = %s%s",gStringStdDev.Data(),"%",stats->GetStatFormat());
8895 tt.Form(tf.Data(),fH->GetStdDev(1));
8896 } else {
8897 tf.Form("%s = %s%s #pm %s%s",gStringStdDev.Data(),"%",stats->GetStatFormat()
8898 ,"%",stats->GetStatFormat());
8899 tt.Form(tf.Data(),fH->GetStdDev(1),fH->GetStdDevError(1));
8900 }
8901 stats->AddText(tt.Data());
8903 if (print_stddev == 1) {
8904 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
8905 tt.Form(tf.Data(),fH->GetStdDev(2));
8906 } else {
8907 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
8908 ,"%",stats->GetStatFormat());
8909 tt.Form(tf.Data(),fH->GetStdDev(2),fH->GetStdDevError(2));
8910 }
8911 stats->AddText(tt.Data());
8912 }
8913 }
8914 if (print_under) {
8915 tf.Form("%s = %s%s",gStringUnderflow.Data(),"%",stats->GetStatFormat());
8916 tt.Form(tf.Data(),fH->GetBinContent(0));
8917 stats->AddText(tt.Data());
8918 }
8919 if (print_over) {
8920 tf.Form("%s = %s%s",gStringOverflow.Data(),"%",stats->GetStatFormat());
8921 tt.Form(tf.Data(),fH->GetBinContent(fXaxis->GetNbins()+1));
8922 stats->AddText(tt.Data());
8923 }
8924 if (print_integral) {
8925 if (print_integral == 1) {
8926 tf.Form("%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
8927 tt.Form(tf.Data(),fH->Integral());
8928 } else {
8929 tf.Form("%s = %s%s",gStringIntegralBinWidth.Data(),"%",stats->GetStatFormat());
8930 tt.Form(tf.Data(),fH->Integral("width"));
8931 }
8932 stats->AddText(tt.Data());
8933 }
8934 if (print_skew) {
8935 if (print_skew == 1) {
8936 tf.Form("%s = %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat());
8937 tt.Form(tf.Data(),fH->GetSkewness(1));
8938 } else {
8939 tf.Form("%s = %s%s #pm %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat()
8940 ,"%",stats->GetStatFormat());
8941 tt.Form(tf.Data(),fH->GetSkewness(1),fH->GetSkewness(11));
8942 }
8943 stats->AddText(tt.Data());
8944 }
8945 if (print_kurt) {
8946 if (print_kurt == 1) {
8947 tf.Form("%s = %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat());
8948 tt.Form(tf.Data(),fH->GetKurtosis(1));
8949 } else {
8950 tf.Form("%s = %s%s #pm %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat()
8951 ,"%",stats->GetStatFormat());
8952 tt.Form(tf.Data(),fH->GetKurtosis(1),fH->GetKurtosis(11));
8953 }
8954 stats->AddText(tt.Data());
8955 }
8956
8957 // Draw Fit parameters
8958 if (fit) {
8959 Int_t ndf = fit->GetNDF();
8960 tf.Form("#chi^{2} / ndf = %s%s / %d","%",stats->GetFitFormat(),ndf);
8961 tt.Form(tf.Data(),fit->GetChisquare());
8962 if (print_fchi2) stats->AddText(tt.Data());
8963 if (print_fprob) {
8964 tf.Form("Prob = %s%s","%",stats->GetFitFormat());
8965 tt.Form(tf.Data(),TMath::Prob(fit->GetChisquare(),ndf));
8966 stats->AddText(tt.Data());
8967 }
8968 if (print_fval || print_ferrors) {
8970 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
8971 fit->GetParLimits(ipar,parmin,parmax);
8973 if (print_ferrors) {
8974 tf.Form("%-8s = %s%s #pm %s ", fit->GetParName(ipar), "%",stats->GetFitFormat(),
8975 GetBestFormat(fit->GetParameter(ipar), fit->GetParError(ipar), stats->GetFitFormat()));
8976 tt.Form(tf.Data(),fit->GetParameter(ipar)
8977 ,fit->GetParError(ipar));
8978 } else {
8979 tf.Form("%-8s = %s%s ",fit->GetParName(ipar), "%",stats->GetFitFormat());
8980 tt.Form(tf.Data(),fit->GetParameter(ipar));
8981 }
8982 stats->AddText(tt.Data());
8983 }
8984 }
8985 }
8986
8987 if (!done) fFunctions->Add(stats);
8988 stats->Paint(stats->GetOption());
8989}
8990
8991////////////////////////////////////////////////////////////////////////////////
8992/// [Draw the statistics box for 2D histograms.](\ref HP07)
8993
8995{
8996
8997 if (fH->GetDimension() != 2) return;
8998 TH2 *h2 = (TH2*)fH;
8999
9000 TString tt, tf;
9001 Int_t dofit;
9002 TPaveStats *stats = nullptr;
9003 TIter next(fFunctions);
9004 while (auto obj = next()) {
9005 if (obj->InheritsFrom(TPaveStats::Class())) {
9006 stats = (TPaveStats*)obj;
9007 break;
9008 }
9009 }
9010 if (stats && dostat) {
9011 dofit = stats->GetOptFit();
9012 dostat = stats->GetOptStat();
9013 } else {
9014 dofit = gStyle->GetOptFit();
9015 }
9016 if (dostat == 1) dostat = 1111;
9017 Int_t print_name = dostat%10;
9018 Int_t print_entries = (dostat/10)%10;
9019 Int_t print_mean = (dostat/100)%10;
9020 Int_t print_stddev = (dostat/1000)%10;
9021 Int_t print_under = (dostat/10000)%10;
9022 Int_t print_over = (dostat/100000)%10;
9023 Int_t print_integral= (dostat/1000000)%10;
9024 Int_t print_skew = (dostat/10000000)%10;
9025 Int_t print_kurt = (dostat/100000000)%10;
9027 if (print_under || print_over) nlines += 3;
9028
9029 // Pavetext with statistics
9030 if (!gStyle->GetOptFit()) fit = nullptr;
9031 Bool_t done = kFALSE;
9032 if (!dostat && !fit) {
9033 if (stats) { fFunctions->Remove(stats); delete stats;}
9034 return;
9035 }
9037 if (fit) statw = 1.8*gStyle->GetStatW();
9039 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
9040 stath = 0.25*nlines*gStyle->GetStatH();
9041 }
9042 if (fit) stath += gStyle->GetStatH();
9043 if (stats) {
9044 stats->Clear();
9045 done = kTRUE;
9046 } else {
9047 stats = new TPaveStats(
9050 gStyle->GetStatX(),
9051 gStyle->GetStatY(),"brNDC");
9052
9053 stats->SetParent(fH);
9054 stats->SetOptFit(dofit);
9055 stats->SetOptStat(dostat);
9056 stats->SetFillColor(gStyle->GetStatColor());
9057 stats->SetFillStyle(gStyle->GetStatStyle());
9059 stats->SetName("stats");
9060
9062 stats->SetTextAlign(12);
9063 stats->SetTextFont(gStyle->GetStatFont());
9064 if (gStyle->GetStatFont()%10 > 2)
9066 stats->SetFitFormat(gStyle->GetFitFormat());
9068 stats->SetBit(kCanDelete);
9069 stats->SetBit(kMustCleanup);
9070 }
9071 if (print_name) stats->AddText(h2->GetName());
9072 if (print_entries) {
9073 if (h2->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(h2->GetEntries()+0.5));
9074 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(h2->GetEntries()));
9075 stats->AddText(tt.Data());
9076 }
9077 if (print_mean) {
9078 if (print_mean == 1) {
9079 tf.Form("%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
9080 tt.Form(tf.Data(),h2->GetMean(1));
9081 stats->AddText(tt.Data());
9082 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
9083 tt.Form(tf.Data(),h2->GetMean(2));
9084 stats->AddText(tt.Data());
9085 } else {
9086 tf.Form("%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
9087 ,"%",stats->GetStatFormat());
9088 tt.Form(tf.Data(),h2->GetMean(1),h2->GetMeanError(1));
9089 stats->AddText(tt.Data());
9090 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
9091 ,"%",stats->GetStatFormat());
9092 tt.Form(tf.Data(),h2->GetMean(2),h2->GetMeanError(2));
9093 stats->AddText(tt.Data());
9094 }
9095 }
9096 if (print_stddev) {
9097 if (print_stddev == 1) {
9098 tf.Form("%s = %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat());
9099 tt.Form(tf.Data(),h2->GetStdDev(1));
9100 stats->AddText(tt.Data());
9101 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
9102 tt.Form(tf.Data(),h2->GetStdDev(2));
9103 stats->AddText(tt.Data());
9104 } else {
9105 tf.Form("%s = %s%s #pm %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat()
9106 ,"%",stats->GetStatFormat());
9107 tt.Form(tf.Data(),h2->GetStdDev(1),h2->GetStdDevError(1));
9108 stats->AddText(tt.Data());
9109 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
9110 ,"%",stats->GetStatFormat());
9111 tt.Form(tf.Data(),h2->GetStdDev(2),h2->GetStdDevError(2));
9112 stats->AddText(tt.Data());
9113 }
9114 }
9115 if (print_integral) {
9116 tf.Form("%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
9117 tt.Form(tf.Data(),fH->Integral());
9118 stats->AddText(tt.Data());
9119 }
9120 if (print_skew) {
9121 if (print_skew == 1) {
9122 tf.Form("%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
9123 tt.Form(tf.Data(),h2->GetSkewness(1));
9124 stats->AddText(tt.Data());
9125 tf.Form("%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
9126 tt.Form(tf.Data(),h2->GetSkewness(2));
9127 stats->AddText(tt.Data());
9128 } else {
9129 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
9130 ,"%",stats->GetStatFormat());
9131 tt.Form(tf.Data(),h2->GetSkewness(1),h2->GetSkewness(11));
9132 stats->AddText(tt.Data());
9133 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
9134 ,"%",stats->GetStatFormat());
9135 tt.Form(tf.Data(),h2->GetSkewness(2),h2->GetSkewness(12));
9136 stats->AddText(tt.Data());
9137 }
9138 }
9139 if (print_kurt) {
9140 if (print_kurt == 1) {
9141 tf.Form("%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
9142 tt.Form(tf.Data(),h2->GetKurtosis(1));
9143 stats->AddText(tt.Data());
9144 tf.Form("%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
9145 tt.Form(tf.Data(),h2->GetKurtosis(2));
9146 stats->AddText(tt.Data());
9147 } else {
9148 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
9149 ,"%",stats->GetStatFormat());
9150 tt.Form(tf.Data(),h2->GetKurtosis(1),h2->GetKurtosis(11));
9151 stats->AddText(tt.Data());
9152 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
9153 ,"%",stats->GetStatFormat());
9154 tt.Form(tf.Data(),h2->GetKurtosis(2),h2->GetKurtosis(12));
9155 stats->AddText(tt.Data());
9156 }
9157 }
9158 if (print_under || print_over) {
9159 //get 3*3 under/overflows for 2d hist
9160 Double_t unov[9];
9161
9162 Int_t cellsX = h2->GetXaxis()->GetNbins() + 1;
9163 Int_t cellsY = h2->GetYaxis()->GetNbins() + 1;
9164 Int_t firstX = std::max(1, h2->GetXaxis()->GetFirst());
9165 Int_t firstY = std::max(1, h2->GetYaxis()->GetFirst());
9166 Int_t lastX = std::min(h2->GetXaxis()->GetLast(), h2->GetXaxis()->GetNbins());
9167 Int_t lastY = std::min(h2->GetYaxis()->GetLast(), h2->GetYaxis()->GetNbins());
9168
9169 unov[0] = h2->Integral( 0, firstX-1, lastY+1, cellsY );
9170 unov[1] = h2->Integral(firstX , lastX , lastY+1, cellsY );
9171 unov[2] = h2->Integral(lastX+1, cellsX , lastY+1, cellsY );
9172 unov[3] = h2->Integral( 0, firstX-1, firstY , lastY );
9173 unov[4] = h2->Integral(firstX , lastX , firstY , lastY );
9174 unov[5] = h2->Integral(lastX+1, cellsX , firstY , lastY );
9175 unov[6] = h2->Integral( 0, firstX-1, 0, firstY-1);
9176 unov[7] = h2->Integral(firstX, lastX, 0, firstY-1);
9177 unov[8] = h2->Integral(lastX+1, cellsX , 0, firstY-1);
9178
9179 tt.Form("%g|%g|%g\n", unov[0], unov[1], unov[2]);
9180 stats->AddText(tt.Data());
9181 tt.Form("%g|%g|%g\n", unov[3], unov[4], unov[5]);
9182 stats->AddText(tt.Data());
9183 tt.Form("%g|%g|%g\n", unov[6], unov[7], unov[8]);
9184 stats->AddText(tt.Data());
9185 }
9186
9187 // Draw Fit parameters
9188 if (fit) {
9189 Int_t ndf = fit->GetNDF();
9190 tt.Form("#chi^{2} / ndf = %6.4g / %d",fit->GetChisquare(),ndf);
9191 stats->AddText(tt.Data());
9192 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
9193 tt.Form("%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
9194 ,fit->GetParameter(ipar)
9195 ,fit->GetParError(ipar));
9196 stats->AddText(tt.Data());
9197 }
9198 }
9199
9200 if (!done) fFunctions->Add(stats);
9201 stats->Paint(stats->GetOption());
9202}
9203
9204////////////////////////////////////////////////////////////////////////////////
9205/// [Draw the statistics box for 3D histograms.](\ref HP07)
9206
9208{
9209
9210 if (fH->GetDimension() != 3) return;
9211 TH3 *h3 = (TH3*)fH;
9212
9213 TString tt, tf;
9214 Int_t dofit;
9215 TPaveStats *stats = nullptr;
9216 TIter next(fFunctions);
9217 while (auto obj = next()) {
9218 if (obj->InheritsFrom(TPaveStats::Class())) {
9219 stats = (TPaveStats*)obj;
9220 break;
9221 }
9222 }
9223 if (stats && dostat) {
9224 dofit = stats->GetOptFit();
9225 dostat = stats->GetOptStat();
9226 } else {
9227 dofit = gStyle->GetOptFit();
9228 }
9229 if (dostat == 1) dostat = 1111;
9230 Int_t print_name = dostat%10;
9231 Int_t print_entries = (dostat/10)%10;
9232 Int_t print_mean = (dostat/100)%10;
9233 Int_t print_stddev = (dostat/1000)%10;
9234 Int_t print_under = (dostat/10000)%10;
9235 Int_t print_over = (dostat/100000)%10;
9236 Int_t print_integral= (dostat/1000000)%10;
9237 Int_t print_skew = (dostat/10000000)%10;
9238 Int_t print_kurt = (dostat/100000000)%10;
9240 if (print_under || print_over) nlines += 3;
9241
9242 // Pavetext with statistics
9243 if (!gStyle->GetOptFit()) fit = nullptr;
9244 Bool_t done = kFALSE;
9245 if (!dostat && !fit) {
9246 if (stats) { fFunctions->Remove(stats); delete stats;}
9247 return;
9248 }
9250 if (fit) statw = 1.8*gStyle->GetStatW();
9252 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
9253 stath = 0.25*nlines*gStyle->GetStatH();
9254 }
9255 if (fit) stath += gStyle->GetStatH();
9256 if (stats) {
9257 stats->Clear();
9258 done = kTRUE;
9259 } else {
9260 stats = new TPaveStats(
9263 gStyle->GetStatX(),
9264 gStyle->GetStatY(),"brNDC");
9265
9266 stats->SetParent(fH);
9267 stats->SetOptFit(dofit);
9268 stats->SetOptStat(dostat);
9269 stats->SetFillColor(gStyle->GetStatColor());
9270 stats->SetFillStyle(gStyle->GetStatStyle());
9272 stats->SetName("stats");
9273
9275 stats->SetTextAlign(12);
9276 stats->SetTextFont(gStyle->GetStatFont());
9277 stats->SetFitFormat(gStyle->GetFitFormat());
9279 stats->SetBit(kCanDelete);
9280 stats->SetBit(kMustCleanup);
9281 }
9282 if (print_name) stats->AddText(h3->GetName());
9283 if (print_entries) {
9284 if (h3->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(h3->GetEntries()+0.5));
9285 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(h3->GetEntries()+0.5));
9286 stats->AddText(tt.Data());
9287 }
9288 if (print_mean) {
9289 if (print_mean == 1) {
9290 tf.Form("%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
9291 tt.Form(tf.Data(),h3->GetMean(1));
9292 stats->AddText(tt.Data());
9293 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
9294 tt.Form(tf.Data(),h3->GetMean(2));
9295 stats->AddText(tt.Data());
9296 tf.Form("%s = %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat());
9297 tt.Form(tf.Data(),h3->GetMean(3));
9298 stats->AddText(tt.Data());
9299 } else {
9300 tf.Form("%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
9301 ,"%",stats->GetStatFormat());
9302 tt.Form(tf.Data(),h3->GetMean(1),h3->GetMeanError(1));
9303 stats->AddText(tt.Data());
9304 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
9305 ,"%",stats->GetStatFormat());
9306 tt.Form(tf.Data(),h3->GetMean(2),h3->GetMeanError(2));
9307 stats->AddText(tt.Data());
9308 tf.Form("%s = %s%s #pm %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat()
9309 ,"%",stats->GetStatFormat());
9310 tt.Form(tf.Data(),h3->GetMean(3),h3->GetMeanError(3));
9311 stats->AddText(tt.Data());
9312 }
9313 }
9314 if (print_stddev) {
9315 if (print_stddev == 1) {
9316 tf.Form("%s = %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat());
9317 tt.Form(tf.Data(),h3->GetStdDev(1));
9318 stats->AddText(tt.Data());
9319 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
9320 tt.Form(tf.Data(),h3->GetStdDev(2));
9321 stats->AddText(tt.Data());
9322 tf.Form("%s = %s%s",gStringStdDevZ.Data(),"%",stats->GetStatFormat());
9323 tt.Form(tf.Data(),h3->GetStdDev(3));
9324 stats->AddText(tt.Data());
9325 } else {
9326 tf.Form("%s = %s%s #pm %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat()
9327 ,"%",stats->GetStatFormat());
9328 tt.Form(tf.Data(),h3->GetStdDev(1),h3->GetStdDevError(1));
9329 stats->AddText(tt.Data());
9330 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
9331 ,"%",stats->GetStatFormat());
9332 tt.Form(tf.Data(),h3->GetStdDev(2),h3->GetStdDevError(2));
9333 stats->AddText(tt.Data());
9334 tf.Form("%s = %s%s #pm %s%s",gStringStdDevZ.Data(),"%",stats->GetStatFormat()
9335 ,"%",stats->GetStatFormat());
9336 tt.Form(tf.Data(),h3->GetStdDev(3),h3->GetStdDevError(3));
9337 stats->AddText(tt.Data());
9338 }
9339 }
9340 if (print_integral) {
9341 tt.Form("%s = %6.4g",gStringIntegral.Data(),h3->Integral());
9342 stats->AddText(tt.Data());
9343 }
9344 if (print_skew) {
9345 if (print_skew == 1) {
9346 tf.Form("%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
9347 tt.Form(tf.Data(),h3->GetSkewness(1));
9348 stats->AddText(tt.Data());
9349 tf.Form("%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
9350 tt.Form(tf.Data(),h3->GetSkewness(2));
9351 stats->AddText(tt.Data());
9352 tf.Form("%s = %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat());
9353 tt.Form(tf.Data(),h3->GetSkewness(3));
9354 stats->AddText(tt.Data());
9355 } else {
9356 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
9357 ,"%",stats->GetStatFormat());
9358 tt.Form(tf.Data(),h3->GetSkewness(1),h3->GetSkewness(11));
9359 stats->AddText(tt.Data());
9360 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
9361 ,"%",stats->GetStatFormat());
9362 tt.Form(tf.Data(),h3->GetSkewness(2),h3->GetSkewness(12));
9363 stats->AddText(tt.Data());
9364 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat()
9365 ,"%",stats->GetStatFormat());
9366 tt.Form(tf.Data(),h3->GetSkewness(3),h3->GetSkewness(13));
9367 stats->AddText(tt.Data());
9368 }
9369 }
9370 if (print_kurt) {
9371 if (print_kurt == 1) {
9372 tf.Form("%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
9373 tt.Form(tf.Data(),h3->GetKurtosis(1));
9374 stats->AddText(tt.Data());
9375 tf.Form("%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
9376 tt.Form(tf.Data(),h3->GetKurtosis(2));
9377 stats->AddText(tt.Data());
9378 tf.Form("%s = %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat());
9379 tt.Form(tf.Data(),h3->GetKurtosis(3));
9380 stats->AddText(tt.Data());
9381 } else {
9382 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
9383 ,"%",stats->GetStatFormat());
9384 tt.Form(tf.Data(),h3->GetKurtosis(1),h3->GetKurtosis(11));
9385 stats->AddText(tt.Data());
9386 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
9387 ,"%",stats->GetStatFormat());
9388 tt.Form(tf.Data(),h3->GetKurtosis(2),h3->GetKurtosis(12));
9389 stats->AddText(tt.Data());
9390 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat()
9391 ,"%",stats->GetStatFormat());
9392 tt.Form(tf.Data(),h3->GetKurtosis(3),h3->GetKurtosis(13));
9393 stats->AddText(tt.Data());
9394 }
9395 }
9396 if (print_under || print_over) {
9397 // no underflow - overflow printing for a 3D histogram
9398 // one would need a 3D table
9399 }
9400
9401 // Draw Fit parameters
9402 if (fit) {
9403 Int_t ndf = fit->GetNDF();
9404 tt.Form("#chi^{2} / ndf = %6.4g / %d",fit->GetChisquare(),ndf);
9405 stats->AddText(tt.Data());
9406 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
9407 tt.Form("%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
9408 ,fit->GetParameter(ipar)
9409 ,fit->GetParError(ipar));
9410 stats->AddText(tt.Data());
9411 }
9412 }
9413
9414 if (!done) fFunctions->Add(stats);
9415 stats->Paint(stats->GetOption());
9416}
9417
9418////////////////////////////////////////////////////////////////////////////////
9419/// [Control function to draw a 2D histogram as a surface plot.](\ref HP18)
9420
9422{
9423
9424 const Double_t ydiff = 1;
9425 const Double_t yligh1 = 10;
9426 const Double_t qa = 0.15;
9427 const Double_t qd = 0.15;
9428 const Double_t qs = 0.8;
9430 Int_t raster = 0;
9431 Int_t irep = 0;
9432
9433 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
9436 Double_t zmin = Hparam.zmin;
9437 Double_t zmax = Hparam.zmax;
9442 Double_t dangle = 10*3.141592/180; //Delta angle for Rapidity option
9443 Double_t deltaz = TMath::Abs(zmin);
9444 if (deltaz == 0) deltaz = 1;
9445 if (zmin >= zmax) {
9446 zmin -= 0.5*deltaz;
9447 zmax += 0.5*deltaz;
9448 }
9449 Double_t z1c = zmin;
9450 Double_t z2c = zmin + (zmax-zmin)*(1+gStyle->GetHistTopMargin());
9451 // Compute the lego limits and instantiate a lego object
9452 fXbuf[0] = -1;
9453 fYbuf[0] = 1;
9454 fXbuf[1] = -1;
9455 fYbuf[1] = 1;
9456 if (Hoption.System >= kPOLAR && (Hoption.Surf == 1 || Hoption.Surf == 13)) raster = 1;
9457 if (Hoption.System == kPOLAR) {
9458 fXbuf[2] = z1c;
9459 fYbuf[2] = z2c;
9460 } else if (Hoption.System == kCYLINDRICAL) {
9461 if (Hoption.Logy) {
9462 if (ylab1 > 0) fXbuf[2] = TMath::Log10(ylab1);
9463 else fXbuf[2] = 0;
9464 if (ylab2 > 0) fYbuf[2] = TMath::Log10(ylab2);
9465 else fYbuf[2] = 0;
9466 } else {
9467 fXbuf[2] = ylab1;
9468 fYbuf[2] = ylab2;
9469 }
9470 z1c = 0; z2c = 1;
9471 } else if (Hoption.System == kSPHERICAL) {
9472 fXbuf[2] = -1;
9473 fYbuf[2] = 1;
9474 z1c = 0; z2c = 1;
9475 } else if (Hoption.System == kRAPIDITY) {
9476 fXbuf[2] = -1/TMath::Tan(dangle);
9477 fYbuf[2] = 1/TMath::Tan(dangle);
9478 } else {
9479 fXbuf[0] = xlab1;
9480 fYbuf[0] = xlab2;
9481 fXbuf[1] = ylab1;
9482 fYbuf[1] = ylab2;
9483 fXbuf[2] = z1c;
9484 fYbuf[2] = z2c;
9485 }
9486
9487 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data(), Hoption.System);
9488 fLego->SetEdgeAtt(fH->GetLineColor(),fH->GetLineStyle(),fH->GetLineWidth(),0);
9489 fLego->SetFillColor(fH->GetFillColor());
9490
9491 // Initialize the levels on the Z axis
9492 Int_t ndiv = fH->GetContour();
9493 if (ndiv == 0 ) {
9494 ndiv = gStyle->GetNumberContours();
9495 fH->SetContour(ndiv);
9496 }
9497 Int_t ndivz = TMath::Abs(ndiv);
9498 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
9499
9500 if (Hoption.Surf == 13 || Hoption.Surf == 15) fLego->SetMesh(3);
9501 if (Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) fLego->SetMesh(0);
9502
9503 // Close the surface in case of non cartesian coordinates.
9504
9505 if (Hoption.System != kCARTESIAN) {nx++; ny++;}
9506
9507 // Now ready to draw the surface plot
9508
9509 TView *view = gPad ? gPad->GetView() : nullptr;
9510 if (!view) {
9511 Error("PaintSurface", "no TView in current pad");
9512 return;
9513 }
9514
9515 Double_t thedeg = 90 - gPad->GetTheta();
9516 Double_t phideg = -90 - gPad->GetPhi();
9517 Double_t psideg = view->GetPsi();
9518 view->SetView(phideg, thedeg, psideg, irep);
9519
9520 // Set color/style for back box
9521 if (Hoption.Same) {
9522 fLego->SetFillStyle(0);
9523 fLego->SetFillColor(1);
9524 } else {
9525 fLego->SetFillStyle(gPad->GetFrameFillStyle());
9526 fLego->SetFillColor(gPad->GetFrameFillColor());
9527 }
9528 fLego->TAttFill::Modify();
9529
9530 Int_t backcolor = gPad->GetFrameFillColor();
9531 if (Hoption.System != kCARTESIAN) backcolor = 0;
9532 view->PadRange(backcolor);
9533
9534 fLego->SetFillStyle(fH->GetFillStyle());
9535 fLego->SetFillColor(fH->GetFillColor());
9536 fLego->TAttFill::Modify();
9537
9538 // Draw the filled contour on top
9540
9542 if (Hoption.Surf == 13 || Hoption.Surf == 15) {
9544 Hoption.Surf = 23;
9545 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9547 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"BF");
9548 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9549 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9550 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9551 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"BF");
9553 fLego->SetMesh(1);
9554 }
9555
9556 if (raster) fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
9557 else fLego->InitMoveScreen(-1.1,1.1);
9558
9559 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) {
9560 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9563 fLego->BackBox(90);
9564 }
9565 }
9566
9567 // Gouraud Shading surface
9568 if (Hoption.Surf == 14) {
9569 // Set light sources
9570 fLego->LightSource(0, ydiff, 0,0,0,irep);
9571 fLego->LightSource(1, yligh1 ,1,1,1,irep);
9572 fLego->SurfaceProperty(qa, qd, qs, 1, irep);
9573 fmin = ydiff*qa;
9574 fmax = fmin + (yligh1+0.1)*(qd+qs);
9575 Int_t nbcol = 28;
9576 icol1 = 201;
9577 Double_t dcol = 0.5/Double_t(nbcol);
9578 TColor *colref = gROOT->GetColor(fH->GetFillColor());
9579 if (!colref) return;
9581 colref->GetRGB(r,g,b);
9583 TColor *acol;
9584 for (Int_t col=0;col<nbcol;col++) {
9585 acol = gROOT->GetColor(col+icol1);
9586 TColor::HLStoRGB(hue,.4+col*dcol,satur,r,g,b);
9587 if (acol) acol->SetRGB(r,g,b);
9588 }
9589 fLego->Spectrum(nbcol, fmin, fmax, icol1, 1, irep);
9590 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::GouraudFunction);
9592 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"BF");
9593 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9594 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9595 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9596 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"BF");
9597 } else if (Hoption.Surf == 15) {
9598 // The surface is not drawn in this case.
9599 } else {
9600 // Draw the surface
9601 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 16 || Hoption.Surf == 17) {
9603 } else {
9604 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9605 }
9606 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9607 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceRaster1);
9608 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode2);
9609 if (Hoption.System == kPOLAR) {
9610 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfacePolar(1,nx,ny,"FB");
9611 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfacePolar(1,nx,ny,"BF");
9612 } else if (Hoption.System == kCYLINDRICAL) {
9613 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceCylindrical(1,nx,ny,"FB");
9614 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9615 } else if (Hoption.System == kSPHERICAL) {
9616 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceSpherical(0,1,nx,ny,"FB");
9617 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9618 } else if (Hoption.System == kRAPIDITY) {
9619 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceSpherical(1,1,nx,ny,"FB");
9620 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9621 } else {
9622 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove1);
9623 if (Hoption.Surf == 16) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove3);
9624 if (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16) fLego->SurfaceCartesian(90,nx,ny,"FB");
9625 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCartesian(90,nx,ny,"BF");
9626 }
9627 }
9628
9629 // Paint the line contour on top for option SURF7
9630 if (Hoption.Surf == 17) {
9631 fLego->InitMoveScreen(-1.1,1.1);
9632 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9633 Hoption.Surf = 23;
9634 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9636 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"FB");
9637 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"FB");
9638 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"FB");
9639 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"FB");
9640 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"FB");
9641 }
9642
9643 if ((!Hoption.Same) &&
9644 (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16)) {
9647 fLego->BackBox(90);
9648 }
9649 }
9650 if (Hoption.System == kCARTESIAN) {
9651 fLego->InitMoveScreen(-1.1,1.1);
9653 if (Hoption.FrontBox) fLego->FrontBox(90);
9654 }
9655 if (!Hoption.Axis && !Hoption.Same) {
9656 TGaxis axis;
9657 PaintLegoAxis(&axis, 90);
9658 }
9659
9661
9662 fLego.reset();
9663}
9664
9665////////////////////////////////////////////////////////////////////////////////
9666/// Control function to draw a table using Delaunay triangles.
9667
9669{
9670
9671 TGraphDelaunay2D *dt = nullptr;
9672 TGraphDelaunay *dtOld = nullptr;
9673
9674 // Check if fH contains a TGraphDelaunay2D
9676 dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
9677 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
9678 if (!dt && !dtOld) return;
9679
9680 // If needed, create a TGraph2DPainter
9681 if (!fGraph2DPainter)
9682 fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
9683
9684 // Define the 3D view
9685 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
9686 if (Hoption.Same) {
9687 TView *viewsame = gPad ? gPad->GetView() : nullptr;
9688 if (!viewsame) {
9689 Error("PaintTriangles", "no TView in current pad, do not use option SAME");
9690 return;
9691 }
9692 Double_t *rmin = viewsame->GetRmin();
9693 Double_t *rmax = viewsame->GetRmax();
9694 if (!rmin || !rmax) return;
9695 fXbuf[0] = rmin[0];
9696 fYbuf[0] = rmax[0];
9697 fXbuf[1] = rmin[1];
9698 fYbuf[1] = rmax[1];
9699 fXbuf[2] = rmin[2];
9700 fYbuf[2] = rmax[2];
9701 fH->SetMaximum(rmax[2]);
9702 fH->SetMinimum(rmin[2]);
9703 fH->GetXaxis()->SetRangeUser(rmin[0],rmax[0]);
9704 fH->GetYaxis()->SetRangeUser(rmin[1],rmax[1]);
9705 } else {
9706 fXbuf[0] = Hparam.xmin;
9707 fYbuf[0] = Hparam.xmax;
9708 fXbuf[1] = Hparam.ymin;
9709 fYbuf[1] = Hparam.ymax;
9710 fXbuf[2] = Hparam.zmin;
9711 fYbuf[2] = Hparam.zmax;
9712 }
9713
9714 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
9715 TView *view = gPad ? gPad->GetView() : nullptr;
9716 if (!view) {
9717 Error("PaintTriangles", "no TView in current pad");
9718 return;
9719 }
9720 Double_t thedeg = 90 - gPad->GetTheta();
9721 Double_t phideg = -90 - gPad->GetPhi();
9722 Double_t psideg = view->GetPsi();
9723 Int_t irep;
9724 view->SetView(phideg, thedeg, psideg, irep);
9725
9726 // Set color/style for back box
9727 fLego->SetFillStyle(gPad->GetFrameFillStyle());
9728 fLego->SetFillColor(gPad->GetFrameFillColor());
9729 fLego->TAttFill::Modify();
9730 Int_t backcolor = gPad->GetFrameFillColor();
9731 if (Hoption.System != kCARTESIAN) backcolor = 0;
9732 view->PadRange(backcolor);
9733 fLego->SetFillStyle(fH->GetFillStyle());
9734 fLego->SetFillColor(fH->GetFillColor());
9735 fLego->TAttFill::Modify();
9736
9737 // Paint the Back Box if needed
9738 if (Hoption.BackBox && !Hoption.Same) {
9739 fLego->InitMoveScreen(-1.1,1.1);
9740 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9742 fLego->BackBox(90);
9743 }
9744
9745 // Paint the triangles
9746 fGraph2DPainter->Paint(option);
9747
9748 // Paint the Front Box if needed
9749 if (Hoption.FrontBox) {
9750 fLego->InitMoveScreen(-1.1,1.1);
9752 fLego->FrontBox(90);
9753 }
9754
9755 // Paint the Axis if needed
9756 if (!Hoption.Axis && !Hoption.Same) {
9757 TGaxis axis;
9758 PaintLegoAxis(&axis, 90);
9759 }
9760
9762
9763 fLego.reset();
9764}
9765
9766////////////////////////////////////////////////////////////////////////////////
9767/// Define the color levels used to paint legos, surfaces etc..
9768
9770{
9771
9772 Int_t i, irep;
9773
9774 // Initialize the color levels
9775 if (ndivz >= 100) {
9776 Warning("PaintSurface", "too many color levels, %d >= 100, reset to 99", ndivz);
9777 ndivz = 99;
9778 }
9779 std::vector<Double_t> funlevel(ndivz+1);
9780 std::vector<Int_t> colorlevel(ndivz+1);
9783 for (i = 0; i < ndivz; ++i) {
9785 theColor = Int_t((i+0.99)*Float_t(ncolors)/Float_t(ndivz));
9787 }
9789 fLego->ColorFunction(ndivz, funlevel.data(), colorlevel.data(), irep);
9790}
9791
9792////////////////////////////////////////////////////////////////////////////////
9793/// [Control function to draw 2D/3D histograms (tables).](\ref HP01c)
9794
9796{
9797
9798 // Fill Hparam structure with histo parameters
9799 if (!TableInit()) return;
9800
9801 // Draw histogram frame
9802 PaintFrame();
9803
9804 // If palette option not specified, delete a possible existing palette
9805 if (!Hoption.Zscale) {
9806 TObject *palette = fFunctions->FindObject("palette");
9807 if (palette) { fFunctions->Remove(palette); delete palette;}
9808 }
9809
9810 // Do not draw the histogram. Only the attached functions will be drawn.
9811 if (Hoption.Func == 2) {
9812 if (Hoption.Zscale) {
9813 Int_t ndiv = fH->GetContour();
9814 if (ndiv == 0 ) {
9815 ndiv = gStyle->GetNumberContours();
9816 fH->SetContour(ndiv);
9817 }
9818 PaintPalette();
9819 }
9820
9821 // Draw the histogram according to the option
9822 } else {
9823 if (fH->InheritsFrom(TH2Poly::Class()) && Hoption.Axis<=0) {
9824 if (Hoption.Fill) PaintTH2PolyBins("f");
9828 if (Hoption.Line) PaintTH2PolyBins("l");
9829 if (Hoption.Mark) PaintTH2PolyBins("P");
9830 } else if (Hoption.Axis<=0) {
9834 if (Hoption.Color) {
9837 }
9840 if (Hoption.Error >= 100) Paint2DErrors(option);
9842 }
9846 }
9847
9848 // Draw histogram title
9849 PaintTitle();
9850
9851 // Draw the axes
9852 if (!Hoption.Lego && !Hoption.Surf &&
9853 !Hoption.Tri && !(Hoption.Error >= 100)) PaintAxis(kFALSE);
9854
9855 TF1 *fit = nullptr;
9856 TIter next(fFunctions);
9857 while (auto obj = next()) {
9858 if (obj->InheritsFrom(TF1::Class())) {
9859 fit = (TF1*)obj;
9860 break;
9861 }
9862 }
9863 if ((Hoption.Same%10) != 1) {
9864 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
9865 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
9866 //ALWAYS executed on non-iOS platform.
9867 //On iOS, depends on mode.
9869 }
9870 }
9871 }
9872}
9873
9874////////////////////////////////////////////////////////////////////////////////
9875/// Control function to draw a TH2Poly bins' contours.
9876///
9877/// - option = "F" draw the bins as filled areas.
9878/// - option = "L" draw the bins as line.
9879/// - option = "P" draw the bins as markers.
9880
9882{
9883
9884 //Do not highlight the histogram, if its part was picked.
9885 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH) return;
9886
9887 TString opt = option;
9888 opt.ToLower();
9889 Bool_t line = kFALSE;
9890 Bool_t fill = kFALSE;
9891 Bool_t mark = kFALSE;
9892 if (opt.Contains("l")) line = kTRUE;
9893 if (opt.Contains("f")) fill = kTRUE;
9894 if (opt.Contains("p")) mark = kTRUE;
9895
9896 TH2PolyBin *b;
9897 Double_t z;
9898
9899 TIter next(((TH2Poly*)fH)->GetBins());
9900 TObject *obj, *poly;
9901
9902 while ((obj=next())) {
9903 b = (TH2PolyBin*)obj;
9904 z = b->GetContent();
9905 if (z==0 && Hoption.Zero) continue; // Do not draw empty bins in case of option "COL0 L"
9906 poly = b->GetPolygon();
9907
9908 // Paint the TGraph bins.
9909 if (poly->IsA() == TGraph::Class()) {
9910 TGraph *g = (TGraph*)poly;
9911 g->TAttLine::Modify();
9912 g->TAttMarker::Modify();
9913 g->TAttFill::Modify();
9914 if (line) {
9915 Int_t fs = g->GetFillStyle();
9917 g->SetFillStyle(0);
9919 g->Paint("F");
9921 g->SetFillStyle(fs);
9922 }
9923 if (fill) g->Paint("F");
9924 if (mark) g->Paint("P");
9925 }
9926
9927 // Paint the TMultiGraph bins.
9928 if (poly->IsA() == TMultiGraph::Class()) {
9930 TList *gl = mg->GetListOfGraphs();
9931 if (!gl) return;
9932 TGraph *g;
9933 TIter nextg(gl);
9934 while ((g = (TGraph*) nextg())) {
9935 g->TAttLine::Modify();
9936 g->TAttMarker::Modify();
9937 g->TAttFill::Modify();
9938 if (line) {
9939 Int_t fs = g->GetFillStyle();
9941 g->SetFillStyle(0);
9943 g->Paint("F");
9945 g->SetFillStyle(fs);
9946 }
9947 if (fill) g->Paint("F");
9948 if (mark) g->Paint("P");
9949 }
9950 }
9951 }
9952}
9953
9954////////////////////////////////////////////////////////////////////////////////
9955/// [Control function to draw a TH2Poly as a color plot.](\ref HP20a)
9956
9958{
9959
9960 //Do not highlight the histogram, if its part was picked.
9961 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
9962 return;
9963
9964 Int_t ncolors, color, theColor;
9965 Double_t z, zc;
9966 Double_t zmin = fH->GetMinimum();
9967 Double_t zmax = fH->GetMaximum();
9968 if (Hoption.Logz) {
9969 if (zmax > 0) {
9970 if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
9971 zmin = TMath::Log10(zmin);
9972 zmax = TMath::Log10(zmax);
9973 } else {
9974 return;
9975 }
9976 }
9977 Double_t dz = zmax - zmin;
9978
9979 // Initialize the levels on the Z axis
9981 Int_t ndiv = fH->GetContour();
9982 if (ndiv == 0 ) {
9983 ndiv = gStyle->GetNumberContours();
9984 fH->SetContour(ndiv);
9985 }
9986 Int_t ndivz = TMath::Abs(ndiv);
9987 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
9989
9990 TIter next(((TH2Poly*)fH)->GetBins());
9991
9992 while (auto obj = next()) {
9993 TH2PolyBin *b = (TH2PolyBin*)obj;
9994 TObject *poly = b->GetPolygon();
9995
9996 z = b->GetContent();
9997 if (z==0 && Hoption.Zero) continue;
9998 if (Hoption.Logz) {
9999 if (z > 0) z = TMath::Log10(z);
10000 else z = zmin;
10001 }
10002 if (z < zmin) continue;
10003
10004 // Define the bin color.
10006 zc = fH->GetContourLevelPad(0);
10007 if (z < zc) continue;
10008 color = -1;
10009 for (Int_t k=0; k<ndiv; k++) {
10010 zc = fH->GetContourLevelPad(k);
10011 if (z < zc) {
10012 continue;
10013 } else {
10014 color++;
10015 }
10016 }
10017 } else {
10018 color = Int_t(0.01+(z-zmin)*scale);
10019 }
10020 theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
10021 if (theColor > ncolors-1) theColor = ncolors-1;
10022
10024
10025 // Paint the TGraph bins.
10026 if (poly->IsA() == TGraph::Class()) {
10027 TGraph *g = (TGraph*)poly;
10028 auto origin = g->GetFillColor();
10029 g->SetFillColor(rootColor);
10030 g->TAttFill::Modify();
10031 g->Paint("F");
10032 g->SetFillColor(origin);
10033 }
10034
10035 // Paint the TMultiGraph bins.
10036 if (poly->IsA() == TMultiGraph::Class()) {
10039 while (auto g = (TGraph*) nextg()) {
10040 auto origin = g->GetFillColor();
10041 g->SetFillColor(rootColor);
10042 g->TAttFill::Modify();
10043 g->Paint("F");
10044 g->SetFillColor(origin);
10045 }
10046 }
10047 }
10049}
10050
10051////////////////////////////////////////////////////////////////////////////////
10052/// [Control function to draw a TH2Poly as a scatter plot.](\ref HP20a)
10053
10055{
10056
10057 //Do not highlight the histogram, if its part was selected.
10058 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
10059 return;
10060
10061 Int_t k, loop, marker=0;
10062 Double_t z, xk,xstep, yk, ystep, xp, yp;
10063 Double_t scale = 1;
10064 Double_t zmin = fH->GetMinimum();
10065 Double_t zmax = fH->GetMaximum();
10066 if (Hoption.Logz) {
10067 if (zmax > 0) {
10068 if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
10069 zmin = TMath::Log10(zmin);
10070 zmax = TMath::Log10(zmax);
10071 } else {
10072 return;
10073 }
10074 }
10075 Double_t dz = zmax - zmin;
10076 scale = (kNMAX-1)/dz;
10077
10078
10079 // use an independent instance of a random generator
10080 // instead of gRandom to avoid conflicts and
10081 // to get same random numbers when drawing the same histogram
10083
10084 TH2PolyBin *b;
10085
10086 TIter next(((TH2Poly*)fH)->GetBins());
10087 TObject *obj, *poly;
10088
10089 Double_t maxarea = 0, a;
10090 while ((obj=next())) {
10091 b = (TH2PolyBin*)obj;
10092 a = b->GetArea();
10093 if (a>maxarea) maxarea = a;
10094 }
10095
10096 next.Reset();
10097
10098 while ((obj=next())) {
10099 b = (TH2PolyBin*)obj;
10100 poly = b->GetPolygon();
10101 z = b->GetContent();
10102 if (z < zmin) z = zmin;
10103 if (z > zmax) z = zmax;
10104 if (Hoption.Logz) {
10105 if (z > 0) z = TMath::Log10(z) - zmin;
10106 } else {
10107 z -= zmin;
10108 }
10109 k = Int_t((z*scale)*(b->GetArea()/maxarea));
10110 xk = b->GetXMin();
10111 yk = b->GetYMin();
10112 xstep = b->GetXMax()-xk;
10113 ystep = b->GetYMax()-yk;
10114
10115 // Paint the TGraph bins.
10116 if (poly->IsA() == TGraph::Class()) {
10117 TGraph *g = (TGraph*)poly;
10118 if (k <= 0 || z <= 0) continue;
10119 loop = 0;
10120 while (loop<k) {
10121 if (k+marker >= kNMAX) {
10122 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10123 marker=0;
10124 }
10125 xp = (random.Rndm()*xstep) + xk;
10126 yp = (random.Rndm()*ystep) + yk;
10127 if (g->IsInside(xp,yp)) {
10128 fXbuf[marker] = xp;
10129 fYbuf[marker] = yp;
10130 marker++;
10131 loop++;
10132 }
10133 }
10134 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10135 }
10136
10137 // Paint the TMultiGraph bins.
10138 if (poly->IsA() == TMultiGraph::Class()) {
10140 TList *gl = mg->GetListOfGraphs();
10141 if (!gl) return;
10142 if (k <= 0 || z <= 0) continue;
10143 loop = 0;
10144 while (loop<k) {
10145 if (k+marker >= kNMAX) {
10146 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10147 marker=0;
10148 }
10149 xp = (random.Rndm()*xstep) + xk;
10150 yp = (random.Rndm()*ystep) + yk;
10151 if (mg->IsInside(xp,yp)) {
10152 fXbuf[marker] = xp;
10153 fYbuf[marker] = yp;
10154 marker++;
10155 loop++;
10156 }
10157 }
10158 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10159 }
10160 }
10161 PaintTH2PolyBins("l");
10162}
10163
10164////////////////////////////////////////////////////////////////////////////////
10165/// [Control function to draw a TH2Poly as a text plot.](\ref HP20a)
10166
10168{
10169
10170 TLatex text;
10171 text.SetTextFont(gStyle->GetTextFont());
10172 text.SetTextColor(fH->GetMarkerColor());
10173 text.SetTextSize(0.02*fH->GetMarkerSize());
10174
10175 Double_t x, y, z, e, angle = 0;
10176 TString tt, tf;
10177 tf.Form("%s%s","%",gStyle->GetPaintTextFormat());
10178 if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
10179 Int_t opt = (Int_t)Hoption.Text/1000;
10180
10181 text.SetTextAlign(22);
10182 if (Hoption.Text == 1) angle = 0;
10183 text.SetTextAngle(angle);
10184 text.TAttText::Modify();
10185
10186 TH2PolyBin *b;
10187
10188 TIter next(((TH2Poly*)fH)->GetBins());
10189 TObject *obj, *p;
10190
10191 while ((obj=next())) {
10192 b = (TH2PolyBin*)obj;
10193 p = b->GetPolygon();
10194 x = (b->GetXMin()+b->GetXMax())/2;
10195 if (Hoption.Logx) {
10196 if (x > 0) x = TMath::Log10(x);
10197 else continue;
10198 }
10199 y = (b->GetYMin()+b->GetYMax())/2;
10200 if (Hoption.Logy) {
10201 if (y > 0) y = TMath::Log10(y);
10202 else continue;
10203 }
10204 z = b->GetContent();
10205 if (z < fH->GetMinimum() || (z == 0 && !Hoption.MinimumZero)) continue;
10206 if (opt==2) {
10207 e = fH->GetBinError(b->GetBinNumber());
10208 tf.Form("#splitline{%s%s}{#pm %s%s}",
10210 "%",gStyle->GetPaintTextFormat());
10211 tt.Form(tf.Data(),z,e);
10212 } else {
10213 tt.Form(tf.Data(),z);
10214 }
10215 if (opt==3) text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),p->GetName());
10216 else text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),tt.Data());
10217 }
10218
10219 PaintTH2PolyBins("l");
10220}
10221
10222////////////////////////////////////////////////////////////////////////////////
10223/// [Control function to draw a 1D/2D histograms with the bin values.](\ref HP15)
10224
10226{
10227
10228 TLatex text;
10229 text.SetTextFont(((int)gStyle->GetTextFont()/10)*10+2); // font precision must be 2
10230 text.SetTextColor(fH->GetMarkerColor());
10231 text.SetTextSize(0.02*fH->GetMarkerSize());
10232
10233 Double_t x, y, z, e, angle = 0;
10234 TString tt, tf;
10235 tf.Form("%s%s","%",gStyle->GetPaintTextFormat());
10236 if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
10237
10238 // 1D histograms
10239 if (fH->GetDimension() == 1) {
10241 Double_t yt;
10242 TProfile *hp = (TProfile*)fH;
10243 if (Hoption.Text>2000 && fH->InheritsFrom(TProfile::Class())) {
10244 Hoption.Text = Hoption.Text-2000;
10245 getentries = kTRUE;
10246 }
10247 if (Hoption.Text == 1) angle = 90;
10248 text.SetTextAlign(11);
10249 if (angle == 90) text.SetTextAlign(12);
10250 if (angle == 0) text.SetTextAlign(21);
10251 text.TAttText::Modify();
10252 Double_t dt = 0.02*(gPad->GetY2()-gPad->GetY1());
10253 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10254 if (Hoption.Bar) {
10255 x = fH->GetXaxis()->GetBinLowEdge(i)+
10256 fH->GetXaxis()->GetBinWidth(i)*
10257 (fH->GetBarOffset()+0.5*fH->GetBarWidth());
10258 } else {
10259 x = fH->GetXaxis()->GetBinCenter(i);
10260 }
10261 y = fH->GetBinContent(i);
10262 yt = y;
10263 if (Hoption.MinimumZero && y<0) y = 0;
10264 if (getentries) yt = hp->GetBinEntries(i);
10265 if (yt == 0.) continue;
10266 tt.Form(tf.Data(),yt);
10267 if (Hoption.Logx) {
10268 if (x > 0) x = TMath::Log10(x);
10269 else continue;
10270 }
10271 if (Hoption.Logy) {
10272 if (y > 0) y = TMath::Log10(y);
10273 else continue;
10274 }
10275 if (y >= gPad->GetY2()) continue;
10276 if (y <= gPad->GetY1()) continue;
10277 text.PaintLatex(x,y+0.2*dt,angle,0.02*fH->GetMarkerSize(),tt.Data());
10278 }
10279
10280 // 2D histograms
10281 } else {
10282 Double_t zmin = Hparam.zmin;
10283 if (Hoption.Logz) zmin = TMath::Power(10,Hparam.zmin);
10284
10285 text.SetTextAlign(22);
10286 if (Hoption.Text == 1) angle = 0;
10287 text.SetTextAngle(angle);
10288 text.TAttText::Modify();
10289 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
10290 y = fYaxis->GetBinCenter(j);
10291 if (Hoption.Logy) {
10292 if (y > 0) y = TMath::Log10(y);
10293 else continue;
10294 }
10295 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10296 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
10297 x = fXaxis->GetBinCenter(i);
10298 if (Hoption.Logx) {
10299 if (x > 0) x = TMath::Log10(x);
10300 else continue;
10301 }
10302 if (!IsInside(x,y)) continue;
10303 z = fH->GetBinContent(bin);
10304 if (z < zmin || (z == 0 && !Hoption.MinimumZero)) continue;
10305 if (Hoption.Text>2000) {
10306 e = fH->GetBinError(bin);
10307 tf.Form("#splitline{%s%s}{#pm %s%s}",
10309 "%",gStyle->GetPaintTextFormat());
10310 tt.Form(tf.Data(),z,e);
10311 } else {
10312 tt.Form(tf.Data(),z);
10313 }
10314 text.PaintLatex(x,y+fH->GetBarOffset()*fYaxis->GetBinWidth(j),
10315 angle,0.02*fH->GetMarkerSize(),tt.Data());
10316 }
10317 }
10318 }
10319}
10320
10321////////////////////////////////////////////////////////////////////////////////
10322/// [Control function to draw a 3D implicit functions.](\ref HP27)
10323
10325{
10326
10327 Int_t irep;
10328
10329 TAxis *xaxis = fH->GetXaxis();
10330 TAxis *yaxis = fH->GetYaxis();
10331 TAxis *zaxis = fH->GetZaxis();
10332
10333 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
10334 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
10335 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
10336 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
10337 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
10338 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
10339
10340 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
10341
10342 TView *view = gPad ? gPad->GetView() : nullptr;
10343 if (!view) {
10344 Error("PaintTF3", "no TView in current pad");
10345 return;
10346 }
10347 Double_t thedeg = 90 - gPad->GetTheta();
10348 Double_t phideg = -90 - gPad->GetPhi();
10349 Double_t psideg = view->GetPsi();
10350 view->SetView(phideg, thedeg, psideg, irep);
10351
10352 fLego->InitMoveScreen(-1.1,1.1);
10353
10354 if (Hoption.BackBox) {
10355 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
10357 fLego->BackBox(90);
10358 }
10359
10361
10362 fLego->ImplicitFunction(fCurrentF3, fXbuf.data(), fYbuf.data(), fH->GetNbinsX(),
10363 fH->GetNbinsY(),
10364 fH->GetNbinsZ(), "BF");
10365
10366 if (Hoption.FrontBox) {
10367 fLego->InitMoveScreen(-1.1,1.1);
10369 fLego->FrontBox(90);
10370 }
10371 if (!Hoption.Axis && !Hoption.Same) {
10372 TGaxis axis;
10373 PaintLegoAxis(&axis, 90);
10374 }
10375
10376 PaintTitle();
10377
10378 fLego.reset();
10379}
10380
10381/////////////////////////////////////////////////////////////new TGaxis///////////////////
10382/// Draw the histogram title
10383///
10384/// The title is drawn according to the title alignment returned by
10385/// `GetTitleAlign()`. It is a 2 digits integer): hv
10386///
10387/// where `h` is the horizontal alignment and `v` is the
10388/// vertical alignment.
10389///
10390/// - `h` can get the values 1 2 3 for left, center, and right
10391/// - `v` can get the values 1 2 3 for bottom, middle and top
10392///
10393/// for instance the default alignment is: 13 (left top)
10394
10396{
10397 // probably best place for calls PaintHighlightBin
10398 // calls after paint histo (1D or 2D) and before paint title and stats
10399 if (!gPad->GetView()) PaintHighlightBin();
10400
10401 if (Hoption.Same) return;
10402 if (fH->TestBit(TH1::kNoTitle)) return;
10403 Int_t nt = strlen(fH->GetTitle());
10404 TPaveText *title = nullptr;
10405 TObject *obj;
10406 TIter next(gPad->GetListOfPrimitives());
10407 while ((obj = next())) {
10408 if (!obj->InheritsFrom(TPaveText::Class())) continue;
10409 title = (TPaveText*)obj;
10410 if (strcmp(title->GetName(),"title")) {title = nullptr; continue;}
10411 break;
10412 }
10413 if (nt == 0 || gStyle->GetOptTitle() <= 0) {
10414 if (title) delete title;
10415 return;
10416 }
10419
10420 if (ht <= 0) {
10421 if (gStyle->GetTitleFont("")%10 == 3) {
10422 Double_t hw = (Double_t) TMath::Max(gPad->GetPadWidth(), gPad->GetPadHeight());
10423 if (hw > 0)
10424 ht = 1.1 * (gStyle->GetTitleSize("")/hw);
10425 } else {
10426 ht = 1.1*gStyle->GetTitleFontSize();
10427 }
10428 }
10429 if (ht <= 0) ht = 0.05;
10430 if (wt <= 0) {
10431 TLatex l;
10432 l.SetTextSize(ht);
10433 l.SetTitle(fH->GetTitle());
10434 // adjustment in case the title has several lines (#splitline)
10435 ht = TMath::Max(ht, 1.2*l.GetYsize()/(gPad->GetY2() - gPad->GetY1()));
10436 Double_t wndc = l.GetXsize()/(gPad->GetX2() - gPad->GetX1());
10437 wt = TMath::Min(0.7, 0.02+wndc);
10438 }
10439 if (title) {
10440 TText *t0 = (TText*)title->GetLine(0);
10441 if (t0) {
10442 if (!strcmp(t0->GetTitle(),fH->GetTitle())) return;
10443 t0->SetTitle(fH->GetTitle());
10444 if (wt > 0) title->SetX2NDC(title->GetX1NDC()+wt);
10445 }
10446 return;
10447 }
10448
10450 if (talh < 1) talh = 1; else if (talh > 3) talh = 3;
10452 if (talv < 1) talv = 1; else if (talv > 3) talv = 3;
10454 xpos = gStyle->GetTitleX();
10455 ypos = gStyle->GetTitleY();
10456 if (talh == 2) xpos = xpos-wt/2.;
10457 if (talh == 3) xpos = xpos-wt;
10458 if (talv == 2) ypos = ypos+ht/2.;
10459 if (talv == 1) ypos = ypos+ht;
10460
10461 TPaveText *ptitle = new TPaveText(xpos, ypos-ht, xpos+wt, ypos,"blNDC");
10462
10463 // box with the histogram title
10464 ptitle->SetFillColor(gStyle->GetTitleFillColor());
10465 ptitle->SetFillStyle(gStyle->GetTitleStyle());
10466 ptitle->SetName("title");
10467 ptitle->SetBorderSize(gStyle->GetTitleBorderSize());
10468 ptitle->SetTextColor(gStyle->GetTitleTextColor());
10469 ptitle->SetTextFont(gStyle->GetTitleFont(""));
10470 if (gStyle->GetTitleFont("")%10 > 2)
10471 ptitle->SetTextSize(gStyle->GetTitleFontSize());
10472 ptitle->AddText(fH->GetTitle());
10473 ptitle->SetBit(kCanDelete);
10474 ptitle->Draw();
10475 ptitle->Paint("blNDC");
10476
10477 if(!gPad->IsEditable()) delete ptitle;
10478}
10479
10480////////////////////////////////////////////////////////////////////////////////
10481/// Process message `mess`.
10482
10483void THistPainter::ProcessMessage(const char *mess, const TObject *obj)
10484{
10485 if (!strcmp(mess,"SetF3")) {
10486 fCurrentF3 = (TF3 *)obj;
10487 }
10488}
10489
10490////////////////////////////////////////////////////////////////////////////////
10491/// Static function.
10492///
10493/// Convert Right Ascension, Declination to X,Y using an AITOFF projection.
10494/// This procedure can be used to create an all-sky map in Galactic
10495/// coordinates with an equal-area Aitoff projection. Output map
10496/// coordinates are zero longitude centered.
10497/// Also called Hammer-Aitoff projection (first presented by Ernst von Hammer in 1892)
10498///
10499/// source: GMT
10500///
10501/// code from Ernst-Jan Buis
10502
10504{
10505
10506 Double_t x, y;
10507
10509 Double_t delta = b*TMath::DegToRad();
10510 Double_t r2 = TMath::Sqrt(2.);
10511 Double_t f = 2*r2/TMath::Pi();
10512 Double_t cdec = TMath::Cos(delta);
10515 y = TMath::Sin(delta)*r2/denom;
10516 x *= TMath::RadToDeg()/f;
10517 y *= TMath::RadToDeg()/f;
10518 // x *= -1.; // for a skymap swap left<->right
10519 Al = x;
10520 Ab = y;
10521
10522 return 0;
10523}
10524
10525////////////////////////////////////////////////////////////////////////////////
10526/// Static function
10527///
10528/// Probably the most famous of the various map projections, the Mercator projection
10529/// takes its name from Mercator who presented it in 1569. It is a cylindrical, conformal projection
10530/// with no distortion along the equator.
10531/// The Mercator projection has been used extensively for world maps in which the distortion towards
10532/// the polar regions grows rather large, thus incorrectly giving the impression that, for example,
10533/// Greenland is larger than South America. In reality, the latter is about eight times the size of
10534/// Greenland. Also, the Former Soviet Union looks much bigger than Africa or South America. One may wonder
10535/// whether this illusion has had any influence on U.S. foreign policy.' (Source: GMT)
10536/// code from Ernst-Jan Buis
10537
10539{
10540
10541 Al = l;
10543 Ab = TMath::Log(aid);
10544 return 0;
10545}
10546
10547////////////////////////////////////////////////////////////////////////////////
10548/// Static function code for sinusoidal projection
10549/// from Ernst-Jan Buis
10550/// Source https://en.wikipedia.org/wiki/Sinusoidal_projection
10551
10553{
10554
10555 Al = l*cos(b*TMath::DegToRad());
10556 Ab = b;
10557 return 0;
10558}
10559
10560////////////////////////////////////////////////////////////////////////////////
10561/// Static function code for parabolic projection
10562/// from Ernst-Jan Buis
10563
10565{
10566
10567 Al = l*(2.*TMath::Cos(2*b*TMath::DegToRad()/3) - 1);
10568 Ab = 180*TMath::Sin(b*TMath::DegToRad()/3);
10569 return 0;
10570}
10571
10572////////////////////////////////////////////////////////////////////////////////
10573/// Static function.
10574///
10575/// Convert Right Ascension, Declination to X,Y using an MOLLWEIDE projection.
10576/// This procedure can be used to create an all-sky map in Galactic
10577/// coordinates with an equal-area Mollweide projection. Output map
10578/// coordinates are zero longitude centered.
10579/// It is also known as the Babinet projection, homalographic projection, homolographic projection, and elliptical projection.
10580/// Source: https://en.wikipedia.org/wiki/Mollweide_projection
10581///
10582/// code from Marco Meyer-Conde
10583
10585{
10586
10587 Double_t theta0 = b * TMath::DegToRad(), theta = theta0;
10588
10589 for (int i = 0; i < 100; i++) {
10590 Double_t num = 2 * theta + TMath::Sin(2 * theta) - TMath::Pi() * TMath::Sin(theta0);
10591 Double_t den = 4 * TMath::Power(TMath::Cos(theta), 2);
10592
10593 if (den < 1e-20) {
10594 theta = theta0;
10595 break;
10596 }
10597
10598 theta -= num / den;
10599
10600 if (TMath::Abs(num / den) < 1e-4) break;
10601 }
10602
10603 Al = l * TMath::Cos(theta);
10604 Ab = 90 * TMath::Sin(theta);
10605
10606 return 0;
10607}
10608
10609////////////////////////////////////////////////////////////////////////////////
10610/// Recompute the histogram range following graphics operations.
10611
10613{
10614
10615 if (Hoption.Same) return;
10616
10617 // Compute x,y range
10619 xmax = Hparam.xmax,
10620 ymin = Hparam.ymin,
10621 ymax = Hparam.ymax,
10622 xscale = 1;
10623
10624 std::function<Int_t(Double_t,Double_t,Double_t&,Double_t&)> func;
10625
10626 if (Hoption.Proj == 1) {
10627 func = ProjectAitoff2xy;
10628 xscale = 0.9999;
10629 } else if (Hoption.Proj == 2) {
10630 if (Hparam.ymin <= -90 || Hparam.ymax >= 90) {
10631 Warning("Mercator Projection", "Latitude out of range %f or %f", Hparam.ymin, Hparam.ymax);
10632 Hoption.Proj = 0;
10633 } else {
10636 }
10637 } else if (Hoption.Proj == 3) {
10638 func = ProjectSinusoidal2xy;
10639 } else if (Hoption.Proj == 4) {
10640 func = ProjectParabolic2xy;
10641 } else if (Hoption.Proj == 5) {
10642 func = ProjectMollweide2xy;
10643 }
10644
10645 if (func) {
10647
10651 func(Hparam.xmax, Hparam.ymin, xmax, ymin);
10652
10653 if (xmin > xmin_aid) xmin = xmin_aid;
10654 if (ymin > ymin_aid) ymin = ymin_aid;
10655 if (xmax < xmax_aid) xmax = xmax_aid;
10656 if (ymax < ymax_aid) ymax = ymax_aid;
10657 if (Hparam.ymin < 0 && Hparam.ymax > 0) {
10658 // there is an 'equator', check its range in the plot..
10659 func(Hparam.xmin*xscale, 0, xmin_aid, ymin_aid);
10660 func(Hparam.xmax*xscale, 0, xmax_aid, ymin_aid);
10661 if (xmin > xmin_aid) xmin = xmin_aid;
10662 if (xmax < xmax_aid) xmax = xmax_aid;
10663 }
10664 if (Hparam.xmin < 0 && Hparam.xmax > 0) {
10665 func(0, Hparam.ymin, xmin_aid, ymin_aid);
10666 func(0, Hparam.ymax, xmax_aid, ymax_aid);
10667 if (ymin > ymin_aid) ymin = ymin_aid;
10668 if (ymax < ymax_aid) ymax = ymax_aid;
10669 }
10670 }
10671
10672 Hparam.xmin = xmin;
10673 Hparam.xmax = xmax;
10674 Hparam.ymin = ymin;
10675 Hparam.ymax = ymax;
10676
10677 Double_t dx = xmax-xmin;
10678 Double_t dy = ymax-ymin;
10679 Double_t dxr = dx/(1 - gPad->GetLeftMargin() - gPad->GetRightMargin());
10680 Double_t dyr = dy/(1 - gPad->GetBottomMargin() - gPad->GetTopMargin());
10681
10682 // Range() could change the size of the pad pixmap and therefore should
10683 // be called before the other paint routines
10684 gPad->Range(xmin - dxr*gPad->GetLeftMargin(),
10685 ymin - dyr*gPad->GetBottomMargin(),
10686 xmax + dxr*gPad->GetRightMargin(),
10687 ymax + dyr*gPad->GetTopMargin());
10688 gPad->RangeAxis(xmin, ymin, xmax, ymax);
10689}
10690
10691////////////////////////////////////////////////////////////////////////////////
10692/// Set current histogram to `h`
10693
10695{
10696
10697 if (h == nullptr) return;
10698 fH = h;
10699 fXaxis = h->GetXaxis();
10700 fYaxis = h->GetYaxis();
10701 fZaxis = h->GetZaxis();
10703}
10704
10705////////////////////////////////////////////////////////////////////////////////
10706/// Initialize various options to draw 2D histograms.
10707
10709{
10710
10711 static const char *where = "TableInit";
10712
10713 Int_t first, last;
10715 Double_t zmin, zmax;
10716 Int_t maximum = 0;
10717 Int_t minimum = 0;
10718 if (fH->GetMaximumStored() != -1111) maximum = 1;
10719 if (fH->GetMinimumStored() != -1111) minimum = 1;
10720
10721 // ----------------- Compute X axis parameters
10722 first = fXaxis->GetFirst();
10723 last = fXaxis->GetLast();
10724 Hparam.xlast = last;
10725 Hparam.xfirst = first;
10730
10731 // if log scale in X, replace xmin,max by the log
10732 if (Hoption.Logx) {
10733 // find the first edge of a bin that is > 0
10734 if (Hparam.xlowedge <=0 ) {
10737 }
10738 if (Hparam.xmin <=0 || Hparam.xmax <=0) {
10739 Error(where, "cannot set X axis to log scale");
10740 return 0;
10741 }
10743 if (Hparam.xfirst < first) Hparam.xfirst = first;
10745 if (Hparam.xlast > last) Hparam.xlast = last;
10748 }
10749
10750 // ----------------- Compute Y axis parameters
10751 first = fYaxis->GetFirst();
10752 last = fYaxis->GetLast();
10753 Hparam.ylast = last;
10754 Hparam.yfirst = first;
10757 if (!Hparam.ybinsize) Hparam.ybinsize = 1;
10760
10761 // if log scale in Y, replace ymin,max by the log
10762 if (Hoption.Logy) {
10763 if (Hparam.ylowedge <=0 ) {
10766 }
10767 if (Hparam.ymin <=0 || Hparam.ymax <=0) {
10768 Error(where, "cannot set Y axis to log scale");
10769 return 0;
10770 }
10772 if (Hparam.yfirst < first) Hparam.yfirst = first;
10774 if (Hparam.ylast > last) Hparam.ylast = last;
10777 }
10778
10779
10780 // ----------------- Compute Z axis parameters
10781 Double_t bigp = TMath::Power(10,32);
10782 zmax = -bigp;
10783 zmin = bigp;
10784 Double_t c1, e1;
10785 Double_t allchan = 0;
10786 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
10787 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10788 c1 = fH->GetBinContent(i,j);
10789 zmax = TMath::Max(zmax,c1);
10790 if (Hoption.Error) {
10791 e1 = fH->GetBinError(i,j);
10792 zmax = TMath::Max(zmax,c1+e1);
10793 }
10794 zmin = TMath::Min(zmin,c1);
10795 allchan += c1;
10796 }
10797 }
10798
10799 // Take into account maximum , minimum
10800
10801 if (maximum) zmax = fH->GetMaximumStored();
10802 if (minimum) zmin = fH->GetMinimumStored();
10803 if (Hoption.Logz && zmax < 0) {
10804 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10805 return 0;
10806 } else if (Hoption.Logz && zmin>=0 && zmax==0) { // empty histogram in log scale
10807 zmin = 0.01;
10808 zmax = 10.;
10809 }
10810 if (zmin >= zmax) {
10811 if (Hoption.Logz) {
10812 if (zmax > 0) zmin = 0.001*zmax;
10813 else {
10814 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10815 return 0;
10816 }
10817 }
10818 }
10819
10820 // take into account normalization factor
10821 Hparam.allchan = allchan;
10822 Double_t factor = allchan;
10823 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
10824 if (allchan) factor /= allchan;
10825 if (factor == 0) factor = 1;
10826 Hparam.factor = factor;
10827 zmax = factor*zmax;
10828 zmin = factor*zmin;
10829 c1 = zmax;
10830 if (TMath::Abs(zmin) > TMath::Abs(c1)) c1 = zmin;
10831
10832 // For log scales, histogram coordinates are log10(ymin) and
10833 // log10(ymax). Final adjustment (if not option "Same")
10834 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
10835 // Maximum and Minimum are not defined.
10836 if (Hoption.Logz) {
10837 if (zmin <= 0) {
10838 zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
10839 fH->SetMinimum(zmin);
10840 }
10841 zmin = TMath::Log10(zmin);
10842 if (!minimum) zmin += TMath::Log10(0.5);
10843 zmax = TMath::Log10(zmax);
10844 if (!maximum) zmax += TMath::Log10(2*(0.9/0.95));
10845 goto LZMIN;
10846 }
10847
10848 // final adjustment of YMAXI for linear scale (if not option "Same"):
10849 // decrease histogram height to MAX% of allowed height if HMAXIM
10850 // has not been called.
10851 // MAX% is the value in percent which has been set in HPLSET
10852 // (default is 90%).
10853 if (!maximum) {
10854 zmax += yMARGIN*(zmax-zmin);
10855 }
10856
10857 // final adjustment of ymin for linear scale.
10858 // if minimum is not set , then ymin is set to zero if >0
10859 // or to ymin - yMARGIN if <0.
10860 if (!minimum) {
10861 if (Hoption.MinimumZero) {
10862 if (zmin >= 0) zmin = 0;
10863 else zmin -= yMARGIN*(zmax-zmin);
10864 } else {
10865 Double_t dzmin = yMARGIN*(zmax-zmin);
10866 if (zmin >= 0 && (zmin-dzmin <= 0)) zmin = 0;
10867 else zmin -= dzmin;
10868 }
10869 }
10870
10871LZMIN:
10872 Hparam.zmin = zmin;
10873 Hparam.zmax = zmax;
10874
10875 // Set bar offset and width
10878
10879 return 1;
10880}
10881
10882////////////////////////////////////////////////////////////////////////////////
10883/// This function returns the best format to print the error value (e)
10884/// knowing the parameter value (v) and the format (f) used to print it.
10885
10887{
10888
10889 static TString ef;
10890 TString tf, tv;
10891
10892 // print v with the format f in tv.
10893 tf.Form("%s%s","%",f);
10894 tv.Form(tf.Data(),v);
10895
10896 // Analyse tv.
10897 int ie = tv.Index("e");
10898 int iE = tv.Index("E");
10899 int id = tv.Index(".");
10900
10901 // v has been printed with the exponent notation.
10902 // There is 2 cases, the exponent is positive or negative
10903 if (ie >= 0 || iE >= 0) {
10904 if (tv.Index("+") >= 0) {
10905 if (e < 1) {
10906 ef.Form("%s.1f","%");
10907 } else {
10908 if (ie >= 0) {
10909 ef.Form("%s.%de","%",ie-id-1);
10910 } else {
10911 ef.Form("%s.%dE","%",iE-id-1);
10912 }
10913 }
10914 } else {
10915 if (ie >= 0) {
10916 ef.Form("%s.%de","%",ie-id-1);
10917 } else {
10918 ef.Form("%s.%dE","%",iE-id-1);
10919 }
10920 }
10921
10922 // There is not '.' in tv. e will be printed with one decimal digit.
10923 } else if (id < 0) {
10924 ef.Form("%s.1f","%");
10925
10926 // There is a '.' in tv and no exponent notation. e's decimal part will
10927 // have the same number of digits as v's one.
10928 } else {
10929 ef.Form("%s.%df","%",tv.Length()-id-1);
10930 }
10931
10932 return ef.Data();
10933}
10934
10935////////////////////////////////////////////////////////////////////////////////
10936/// Set projection.
10937
10939{
10940 if (fShowProjection2) {
10941 auto name2 = TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2);
10942 auto c2 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name2.Data()));
10943 if (c2) c2->Close();
10944 fShowProjection2 = 0;
10945 }
10946 if (fShowProjection) {
10947 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10948 auto c1 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name1.Data()));
10949 if (c1) c1->Close();
10950 fShowProjection = 0;
10951 }
10952
10953 if (nbins <= 0) return;
10954
10955 TString opt = option;
10956 opt.ToLower();
10957 Int_t projection = 0;
10958 if (opt.Contains("x")) projection = 1;
10959 if (opt.Contains("y")) projection = 2;
10960 if (opt.Contains("z")) projection = 3;
10961 if (opt.Contains("xy")) projection = 4;
10962 if (opt.Contains("yx")) projection = 5;
10963 if (opt.Contains("xz")) projection = 6;
10964 if (opt.Contains("zx")) projection = 7;
10965 if (opt.Contains("yz")) projection = 8;
10966 if (opt.Contains("zy")) projection = 9;
10967 if (projection < 4) fShowOption = option+1;
10968 else fShowOption = option+2;
10970 fShowProjection2 = 0;
10971 gROOT->MakeDefCanvas();
10972 gPad->SetName(TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection).Data());
10973 gPad->SetGrid();
10974}
10975
10977{
10978 if (fShowProjection2) {
10979 auto name2 = TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2);
10980 auto c2 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name2.Data()));
10981 if (c2) c2->Close();
10982 fShowProjection2 = 0;
10983 }
10984 if (fShowProjection) {
10985 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10986 auto c1 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name1.Data()));
10987 if (c1) c1->Close();
10988 fShowProjection = 0;
10989 }
10990
10991 if ((nbinsX <= 0) || (nbinsY <= 0)) return;
10992
10993
10994 TString opt = option;
10995 opt.ToLower();
10996 Int_t projection = 0;
10997 if (opt.Contains("x")) projection = 1;
10998 if (opt.Contains("y")) projection = 2;
10999 if (opt.Contains("z")) projection = 3;
11000 if (opt.Contains("xy")) projection = 4;
11001 if (opt.Contains("yx")) projection = 5;
11002 if (opt.Contains("xz")) projection = 6;
11003 if (opt.Contains("zx")) projection = 7;
11004 if (opt.Contains("yz")) projection = 8;
11005 if (opt.Contains("zy")) projection = 9;
11006 if (projection < 4) fShowOption = option+1;
11007 else fShowOption = option+2;
11010 gROOT->MakeDefCanvas();
11011 gPad->SetName(TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection).Data());
11012 gPad->SetGrid();
11013 gROOT->MakeDefCanvas();
11014 gPad->SetName(TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2).Data());
11015 gPad->SetGrid();
11016}
11017
11018
11019////////////////////////////////////////////////////////////////////////////////
11020/// Show projection onto X.
11021
11023{
11024
11026 gPad->SetDoubleBuffer(0); // turn off double buffer mode
11027 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
11028
11029 // Erase old position and draw a line at current position
11030 static int pyold1 = 0;
11031 static int pyold2 = 0;
11032 float uxmin = gPad->GetUxmin();
11033 float uxmax = gPad->GetUxmax();
11034 int pxmin = gPad->XtoAbsPixel(uxmin);
11035 int pxmax = gPad->XtoAbsPixel(uxmax);
11036 Float_t upy = gPad->AbsPixeltoY(py);
11037 Float_t y = gPad->PadtoY(upy);
11038 Int_t biny1 = fH->GetYaxis()->FindBin(y);
11040 Int_t py1 = gPad->YtoAbsPixel(gPad->GetLogy() ? TMath::Log10(fH->GetYaxis()->GetBinLowEdge(biny1)) : fH->GetYaxis()->GetBinLowEdge(biny1));
11041 Int_t py2 = gPad->YtoAbsPixel(gPad->GetLogy() ? TMath::Log10(fH->GetYaxis()->GetBinUpEdge(biny2)) : fH->GetYaxis()->GetBinUpEdge(biny2));
11042
11044 gVirtualX->DrawBox(pxmin,py1,pxmax,py2,TVirtualX::kFilled);
11045 pyold1 = py1;
11046 pyold2 = py2;
11047
11048 // Create or set the new canvas proj x
11050 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
11051 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(name1.Data());
11052 if (c) {
11053 c->Clear();
11054 } else {
11055 fShowProjection = 0;
11056 fShowProjection2 = 0;
11057 pyold1 = 0;
11058 pyold2 = 0;
11059 return;
11060 }
11061 c->cd();
11062 c->SetLogy(ctxt.GetSaved()->GetLogz());
11063 c->SetLogx(ctxt.GetSaved()->GetLogx());
11064
11065 // Draw slice corresponding to mouse position
11066 TString prjName = TString::Format("slice_px_of_%s",fH->GetName());
11067 TH1D *hp = ((TH2*)fH)->ProjectionX(prjName, biny1, biny2);
11068 if (hp) {
11069 hp->SetFillColor(38);
11070 // apply a patch from Oliver Freyermuth to set the title in the projection
11071 // using the range of the projected Y values
11072 if (biny1 == biny2) {
11075 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11077 if (fH->GetYaxis()->GetLabels() != nullptr) {
11078 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf] %s", biny1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetYaxis()->GetBinLabel(biny1)));
11079 } else {
11080 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf]", biny1, valuePrecision, valueFrom, valuePrecision, valueTo));
11081 }
11082 } else {
11085 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11086 // biny1 is used here to get equal precision no matter how large the binrange is,
11087 // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
11089 if (fH->GetYaxis()->GetLabels() != nullptr) {
11090 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)));
11091 } else {
11092 hp->SetTitle(TString::Format("ProjectionX of biny=[%d,%d] [y=%.*lf..%.*lf]", biny1, biny2, valuePrecision, valueFrom, valuePrecision, valueTo));
11093 }
11094 }
11095 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11096 hp->SetYTitle(((TH2*)fH)->GetZaxis()->GetTitle() ? ((TH2*)fH)->GetZaxis()->GetTitle() : "Number of Entries");
11097 hp->Draw();
11098 c->Update();
11099 }
11100}
11101
11102////////////////////////////////////////////////////////////////////////////////
11103/// Show projection onto Y.
11104
11106{
11107
11109 if (fShowProjection2)
11111 gPad->SetDoubleBuffer(0); // turn off double buffer mode
11112 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
11113
11114 // Erase old position and draw a line at current position
11115 static int pxold1 = 0;
11116 static int pxold2 = 0;
11117 float uymin = gPad->GetUymin();
11118 float uymax = gPad->GetUymax();
11119 int pymin = gPad->YtoAbsPixel(uymin);
11120 int pymax = gPad->YtoAbsPixel(uymax);
11121 Float_t upx = gPad->AbsPixeltoX(px);
11122 Float_t x = gPad->PadtoX(upx);
11123 Int_t binx1 = fH->GetXaxis()->FindBin(x);
11125 Int_t px1 = gPad->XtoAbsPixel(gPad->GetLogx() ? TMath::Log10(fH->GetXaxis()->GetBinLowEdge(binx1)) : fH->GetXaxis()->GetBinLowEdge(binx1));
11126 Int_t px2 = gPad->XtoAbsPixel(gPad->GetLogx() ? TMath::Log10(fH->GetXaxis()->GetBinUpEdge(binx2)) : fH->GetXaxis()->GetBinUpEdge(binx2));
11127
11129 gVirtualX->DrawBox(px1,pymin,px2,pymax,TVirtualX::kFilled);
11130 pxold1 = px1;
11131 pxold2 = px2;
11132
11133 // Create or set the new canvas proj y
11135
11136 TString name2 = fShowProjection2 ? TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2)
11137 : TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
11138
11139 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(name2.Data());
11140 if (c) {
11141 c->Clear();
11142 } else {
11143 fShowProjection = 0;
11144 fShowProjection2 = 0;
11145 pxold1 = 0;
11146 pxold2 = 0;
11147 return;
11148 }
11149 c->cd();
11150 c->SetLogy(ctxt.GetSaved()->GetLogz());
11151 c->SetLogx(ctxt.GetSaved()->GetLogy());
11152
11153 // Draw slice corresponding to mouse position
11154 TString prjName = TString::Format("slice_py_of_%s",fH->GetName());
11155 TH1D *hp = ((TH2*)fH)->ProjectionY(prjName, binx1, binx2);
11156 if (hp) {
11157 hp->SetFillColor(38);
11158 // apply a patch from Oliver Freyermuth to set the title in the projection
11159 // using the range of the projected X values
11160 if (binx1 == binx2) {
11163 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11165 if (fH->GetXaxis()->GetLabels() != nullptr) {
11166 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf] [%s]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetXaxis()->GetBinLabel(binx1)));
11167 } else {
11168 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo));
11169 }
11170 } else {
11173 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11174 // binx1 is used here to get equal precision no matter how large the binrange is,
11175 // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
11177 if (fH->GetXaxis()->GetLabels() != nullptr) {
11178 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)));
11179 } else {
11180 hp->SetTitle(TString::Format("ProjectionY of binx=[%d,%d] [x=%.*lf..%.*lf]", binx1, binx2, valuePrecision, valueFrom, valuePrecision, valueTo));
11181 }
11182 }
11183 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11184 hp->SetYTitle(((TH2*)fH)->GetZaxis()->GetTitle() ? ((TH2*)fH)->GetZaxis()->GetTitle() : "Number of Entries");
11185 hp->Draw(fShowProjection2 ? "hbar" : "");
11186 c->Update();
11187 }
11188}
11189
11190////////////////////////////////////////////////////////////////////////////////
11191/// Show projection (specified by `fShowProjection`) of a `TH3`.
11192/// The drawing option for the projection is in `fShowOption`.
11193///
11194/// First implementation; R.Brun
11195///
11196/// Full implementation: Tim Tran (timtran@jlab.org) April 2006
11197
11199{
11200
11201 Int_t nbins=(Int_t)fShowProjection/100; //decode nbins
11202 if (fH->GetDimension() < 3) {
11203 if (fShowProjection2 % 100 == 1) {
11204 ShowProjectionY(px, py);
11205 }
11206 if (fShowProjection % 100 == 1) {
11207 ShowProjectionX(px, py);
11208 return;
11209 }
11210 if (fShowProjection % 100 == 2) {
11211 ShowProjectionY(px, py);
11212 return;
11213 }
11214 }
11215
11216 gPad->SetDoubleBuffer(0); // turn off double buffer mode
11217 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
11218
11219 // Erase old position and draw a line at current position
11220 TView *view = gPad->GetView();
11221 if (!view) return;
11222 TH3 *h3 = (TH3*)fH;
11223 TAxis *xaxis = h3->GetXaxis();
11224 TAxis *yaxis = h3->GetYaxis();
11225 TAxis *zaxis = h3->GetZaxis();
11226 Double_t u[3],xx[3];
11227
11228 static TPoint line1[2];//store end points of a line, initialised 0 by default
11229 static TPoint line2[2];// second line when slice thickness > 1 bin thickness
11230 static TPoint line3[2];
11231 static TPoint line4[2];
11232 static TPoint endface1[5];
11233 static TPoint endface2[5];
11234 static TPoint rect1[5];//store vertices of the polyline (rectangle), initialsed 0 by default
11235 static TPoint rect2[5];// second rectangle when slice thickness > 1 bin thickness
11236
11237 Double_t uxmin = gPad->GetUxmin();
11238 Double_t uxmax = gPad->GetUxmax();
11239 Double_t uymin = gPad->GetUymin();
11240 Double_t uymax = gPad->GetUymax();
11241
11242 int pxmin = gPad->XtoAbsPixel(uxmin);
11243 int pxmax = gPad->XtoAbsPixel(uxmax);
11244 if (pxmin==pxmax) return;
11245 int pymin = gPad->YtoAbsPixel(uymin);
11246 int pymax = gPad->YtoAbsPixel(uymax);
11247 if (pymin==pymax) return;
11250 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(TString::Format("c_%zx_projection_%d",
11251 (size_t)fH, fShowProjection).Data());
11252 if (!c) {
11253 fShowProjection = 0;
11254 return;
11255 }
11256
11258
11259 switch ((Int_t)fShowProjection%100) {
11260 case 1:
11261 // "x"
11262 {
11263 Int_t firstY = yaxis->GetFirst();
11264 Int_t lastY = yaxis->GetLast();
11266 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11267 yaxis->SetRange(biny,biny2);
11268 Int_t firstZ = zaxis->GetFirst();
11269 Int_t lastZ = zaxis->GetLast();
11271 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11272 zaxis->SetRange(binz,binz2);
11273 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11274 if (nbins>1 && line1[0].GetX()) {
11275 gVirtualX->DrawPolyLine(2,line2);
11276 gVirtualX->DrawPolyLine(2,line3);
11277 gVirtualX->DrawPolyLine(2,line4);
11278 gVirtualX->DrawPolyLine(5,endface1);
11279 gVirtualX->DrawPolyLine(5,endface2);
11280 }
11281 xx[0] = xaxis->GetXmin();
11282 xx[2] = zaxis->GetBinCenter(binz);
11283 xx[1] = yaxis->GetBinCenter(biny);
11284 view->WCtoNDC(xx,u);
11285 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11286 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11287 xx[0] = xaxis->GetXmax();
11288 view->WCtoNDC(xx,u);
11289 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11290 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11291 gVirtualX->DrawPolyLine(2,line1);
11292 if (nbins>1) {
11293 xx[0] = xaxis->GetXmin();
11294 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11295 xx[1] = yaxis->GetBinCenter(biny);
11296 view->WCtoNDC(xx,u);
11297 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11298 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11299 xx[0] = xaxis->GetXmax();
11300 view->WCtoNDC(xx,u);
11301 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11302 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11303
11304 xx[0] = xaxis->GetXmin();
11305 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11306 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11307 view->WCtoNDC(xx,u);
11308 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11309 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11310 xx[0] = xaxis->GetXmax();
11311 view->WCtoNDC(xx,u);
11312 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11313 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11314
11315 xx[0] = xaxis->GetXmin();
11316 xx[2] = zaxis->GetBinCenter(binz);
11317 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11318 view->WCtoNDC(xx,u);
11319 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11320 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11321 xx[0] = xaxis->GetXmax();
11322 view->WCtoNDC(xx,u);
11323 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11324 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11325
11326 endface1[0].SetX(line1[0].GetX());
11327 endface1[0].SetY(line1[0].GetY());
11328 endface1[1].SetX(line2[0].GetX());
11329 endface1[1].SetY(line2[0].GetY());
11330 endface1[2].SetX(line3[0].GetX());
11331 endface1[2].SetY(line3[0].GetY());
11332 endface1[3].SetX(line4[0].GetX());
11333 endface1[3].SetY(line4[0].GetY());
11334 endface1[4].SetX(line1[0].GetX());
11335 endface1[4].SetY(line1[0].GetY());
11336
11337 endface2[0].SetX(line1[1].GetX());
11338 endface2[0].SetY(line1[1].GetY());
11339 endface2[1].SetX(line2[1].GetX());
11340 endface2[1].SetY(line2[1].GetY());
11341 endface2[2].SetX(line3[1].GetX());
11342 endface2[2].SetY(line3[1].GetY());
11343 endface2[3].SetX(line4[1].GetX());
11344 endface2[3].SetY(line4[1].GetY());
11345 endface2[4].SetX(line1[1].GetX());
11346 endface2[4].SetY(line1[1].GetY());
11347
11348 gVirtualX->DrawPolyLine(2,line2);
11349 gVirtualX->DrawPolyLine(2,line3);
11350 gVirtualX->DrawPolyLine(2,line4);
11351 gVirtualX->DrawPolyLine(5,endface1);
11352 gVirtualX->DrawPolyLine(5,endface2);
11353 }
11354 c->Clear();
11355 c->cd();
11356 TH1 *hp = h3->Project3D("x");
11357 yaxis->SetRange(firstY,lastY);
11358 zaxis->SetRange(firstZ,lastZ);
11359 if (hp) {
11360 hp->SetFillColor(38);
11361 if (nbins == 1)
11362 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny),
11363 binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
11364 else {
11365 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),
11366 binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
11367 }
11368 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11369 hp->SetYTitle("Number of Entries");
11370 hp->Draw(fShowOption.Data());
11371 }
11372 }
11373 break;
11374
11375 case 2:
11376 // "y"
11377 {
11378 Int_t firstX = xaxis->GetFirst();
11379 Int_t lastX = xaxis->GetLast();
11381 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11382 xaxis->SetRange(binx,binx2);
11383 Int_t firstZ = zaxis->GetFirst();
11384 Int_t lastZ = zaxis->GetLast();
11386 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11387 zaxis->SetRange(binz,binz2);
11388 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11389 if (nbins>1 && line1[0].GetX()) {
11390 gVirtualX->DrawPolyLine(2,line2);
11391 gVirtualX->DrawPolyLine(2,line3);
11392 gVirtualX->DrawPolyLine(2,line4);
11393 gVirtualX->DrawPolyLine(5,endface1);
11394 gVirtualX->DrawPolyLine(5,endface2);
11395 }
11396 xx[0]=xaxis->GetBinCenter(binx);
11397 xx[2] = zaxis->GetBinCenter(binz);
11398 xx[1] = yaxis->GetXmin();
11399 view->WCtoNDC(xx,u);
11400 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11401 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11402 xx[1] = yaxis->GetXmax();
11403 view->WCtoNDC(xx,u);
11404 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11405 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11406 gVirtualX->DrawPolyLine(2,line1);
11407 if (nbins>1) {
11408 xx[1] = yaxis->GetXmin();
11409 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11410 xx[0] = xaxis->GetBinCenter(binx);
11411 view->WCtoNDC(xx,u);
11412 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11413 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11414 xx[1] = yaxis->GetXmax();
11415 view->WCtoNDC(xx,u);
11416 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11417 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11418
11419 xx[1] = yaxis->GetXmin();
11420 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11421 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11422 view->WCtoNDC(xx,u);
11423 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11424 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11425 xx[1] = yaxis->GetXmax();
11426 view->WCtoNDC(xx,u);
11427 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11428 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11429
11430 xx[1] = yaxis->GetXmin();
11431 xx[2] = zaxis->GetBinCenter(binz);
11432 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11433 view->WCtoNDC(xx,u);
11434 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11435 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11436 xx[1] = yaxis->GetXmax();
11437 view->WCtoNDC(xx,u);
11438 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11439 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11440
11441 endface1[0].SetX(line1[0].GetX());
11442 endface1[0].SetY(line1[0].GetY());
11443 endface1[1].SetX(line2[0].GetX());
11444 endface1[1].SetY(line2[0].GetY());
11445 endface1[2].SetX(line3[0].GetX());
11446 endface1[2].SetY(line3[0].GetY());
11447 endface1[3].SetX(line4[0].GetX());
11448 endface1[3].SetY(line4[0].GetY());
11449 endface1[4].SetX(line1[0].GetX());
11450 endface1[4].SetY(line1[0].GetY());
11451
11452 endface2[0].SetX(line1[1].GetX());
11453 endface2[0].SetY(line1[1].GetY());
11454 endface2[1].SetX(line2[1].GetX());
11455 endface2[1].SetY(line2[1].GetY());
11456 endface2[2].SetX(line3[1].GetX());
11457 endface2[2].SetY(line3[1].GetY());
11458 endface2[3].SetX(line4[1].GetX());
11459 endface2[3].SetY(line4[1].GetY());
11460 endface2[4].SetX(line1[1].GetX());
11461 endface2[4].SetY(line1[1].GetY());
11462
11463 gVirtualX->DrawPolyLine(2,line2);
11464 gVirtualX->DrawPolyLine(2,line3);
11465 gVirtualX->DrawPolyLine(2,line4);
11466 gVirtualX->DrawPolyLine(5,endface1);
11467 gVirtualX->DrawPolyLine(5,endface2);
11468 }
11469 c->Clear();
11470 c->cd();
11471 TH1 *hp = h3->Project3D("y");
11472 xaxis->SetRange(firstX,lastX);
11473 zaxis->SetRange(firstZ,lastZ);
11474 if (hp) {
11475 hp->SetFillColor(38);
11476 if (nbins == 1)
11477 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
11478 binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
11479 else
11480 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),
11481 binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
11482 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11483 hp->SetYTitle("Number of Entries");
11484 hp->Draw(fShowOption.Data());
11485 }
11486 }
11487 break;
11488
11489 case 3:
11490 // "z"
11491 {
11492 Int_t firstX = xaxis->GetFirst();
11493 Int_t lastX = xaxis->GetLast();
11495 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11496 xaxis->SetRange(binx,binx2);
11497 Int_t firstY = yaxis->GetFirst();
11498 Int_t lastY = yaxis->GetLast();
11500 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11501 yaxis->SetRange(biny,biny2);
11502 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11503 if (nbins>1 && line1[0].GetX()) {
11504 gVirtualX->DrawPolyLine(2,line2);
11505 gVirtualX->DrawPolyLine(2,line3);
11506 gVirtualX->DrawPolyLine(2,line4);
11507 gVirtualX->DrawPolyLine(5,endface1);
11508 gVirtualX->DrawPolyLine(5,endface2);
11509 }
11510 xx[0] = xaxis->GetBinCenter(binx);
11511 xx[1] = yaxis->GetBinCenter(biny);
11512 xx[2] = zaxis->GetXmin();
11513 view->WCtoNDC(xx,u);
11514 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11515 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11516 xx[2] = zaxis->GetXmax();
11517 view->WCtoNDC(xx,u);
11518 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11519 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11520 gVirtualX->DrawPolyLine(2,line1);
11521 if (nbins>1) {
11522 xx[2] = zaxis->GetXmin();
11523 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11524 xx[0] = xaxis->GetBinCenter(binx);
11525 view->WCtoNDC(xx,u);
11526 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11527 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11528 xx[2] = zaxis->GetXmax();
11529 view->WCtoNDC(xx,u);
11530 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11531 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11532
11533 xx[2] = zaxis->GetXmin();
11534 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11535 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11536 view->WCtoNDC(xx,u);
11537 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11538 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11539 xx[2] = zaxis->GetXmax();
11540 view->WCtoNDC(xx,u);
11541 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11542 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11543
11544 xx[2] = zaxis->GetXmin();
11545 xx[1] = yaxis->GetBinCenter(biny);
11546 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11547 view->WCtoNDC(xx,u);
11548 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11549 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11550 xx[2] = zaxis->GetXmax();
11551 view->WCtoNDC(xx,u);
11552 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11553 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11554
11555 endface1[0].SetX(line1[0].GetX());
11556 endface1[0].SetY(line1[0].GetY());
11557 endface1[1].SetX(line2[0].GetX());
11558 endface1[1].SetY(line2[0].GetY());
11559 endface1[2].SetX(line3[0].GetX());
11560 endface1[2].SetY(line3[0].GetY());
11561 endface1[3].SetX(line4[0].GetX());
11562 endface1[3].SetY(line4[0].GetY());
11563 endface1[4].SetX(line1[0].GetX());
11564 endface1[4].SetY(line1[0].GetY());
11565
11566 endface2[0].SetX(line1[1].GetX());
11567 endface2[0].SetY(line1[1].GetY());
11568 endface2[1].SetX(line2[1].GetX());
11569 endface2[1].SetY(line2[1].GetY());
11570 endface2[2].SetX(line3[1].GetX());
11571 endface2[2].SetY(line3[1].GetY());
11572 endface2[3].SetX(line4[1].GetX());
11573 endface2[3].SetY(line4[1].GetY());
11574 endface2[4].SetX(line1[1].GetX());
11575 endface2[4].SetY(line1[1].GetY());
11576
11577 gVirtualX->DrawPolyLine(2,line2);
11578 gVirtualX->DrawPolyLine(2,line3);
11579 gVirtualX->DrawPolyLine(2,line4);
11580 gVirtualX->DrawPolyLine(5,endface1);
11581 gVirtualX->DrawPolyLine(5,endface2);
11582 }
11583 c->Clear();
11584 c->cd();
11585 TH1 *hp = h3->Project3D("z");
11586 xaxis->SetRange(firstX,lastX);
11587 yaxis->SetRange(firstY,lastY);
11588 if (hp) {
11589 hp->SetFillColor(38);
11590 if (nbins == 1)
11591 hp->SetTitle(TString::Format("ProjectionZ of binx=%d [x=%.1f..%.1f] biny=%d [y=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
11592 biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny)));
11593 else
11594 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),
11595 biny, biny2, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny2) ) );
11596 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11597 hp->SetYTitle("Number of Entries");
11598 hp->Draw(fShowOption.Data());
11599 }
11600 }
11601 break;
11602
11603 case 4:
11604 // "xy"
11605 {
11606 Int_t first = zaxis->GetFirst();
11607 Int_t last = zaxis->GetLast();
11608 Int_t binz = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11609 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11610 zaxis->SetRange(binz,binz2);
11611 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11612 if (nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11613 xx[0] = xaxis->GetXmin();
11614 xx[1] = yaxis->GetXmax();
11615 xx[2] = zaxis->GetBinCenter(binz);
11616 view->WCtoNDC(xx,u);
11617 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11618 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11619 rect1[4].SetX(rect1[0].GetX());
11620 rect1[4].SetY(rect1[0].GetY());
11621 xx[0] = xaxis->GetXmax();
11622 view->WCtoNDC(xx,u);
11623 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11624 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11625 xx[1] = yaxis->GetXmin();
11626 view->WCtoNDC(xx,u);
11627 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11628 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11629 xx[0] = xaxis->GetXmin();
11630 view->WCtoNDC(xx,u);
11631 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11632 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11633 gVirtualX->DrawPolyLine(5,rect1);
11634 if (nbins>1) {
11635 xx[0] = xaxis->GetXmin();
11636 xx[1] = yaxis->GetXmax();
11637 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11638 view->WCtoNDC(xx,u);
11639 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11640 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11641 rect2[4].SetX(rect2[0].GetX());
11642 rect2[4].SetY(rect2[0].GetY());
11643 xx[0] = xaxis->GetXmax();
11644 view->WCtoNDC(xx,u);
11645 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11646 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11647 xx[1] = yaxis->GetXmin();
11648 view->WCtoNDC(xx,u);
11649 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11650 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11651 xx[0] = xaxis->GetXmin();
11652 view->WCtoNDC(xx,u);
11653 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11654 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11655 gVirtualX->DrawPolyLine(5,rect2);
11656 }
11657
11658 c->Clear();
11659 c->cd();
11660 TH2 *hp = (TH2*)h3->Project3D("xy");
11661 zaxis->SetRange(first,last);
11662 if (hp) {
11663 hp->SetFillColor(38);
11664 if (nbins==1)hp->SetTitle(TString::Format("ProjectionXY of binz=%d [z=%.1f..%.f]", binz,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz)));
11665 else hp->SetTitle(TString::Format("ProjectionXY, binz=[%d,%d] [z=%.1f..%.1f]", binz,binz2,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz2)));
11666 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11667 hp->SetYTitle(fH->GetXaxis()->GetTitle());
11668 hp->SetZTitle("Number of Entries");
11669 hp->Draw(fShowOption.Data());
11670 }
11671 }
11672 break;
11673
11674 case 5:
11675 // "yx"
11676 {
11677 Int_t first = zaxis->GetFirst();
11678 Int_t last = zaxis->GetLast();
11679 Int_t binz = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11680 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11681 zaxis->SetRange(binz,binz2);
11682 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11683 if (nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11684 xx[0] = xaxis->GetXmin();
11685 xx[1] = yaxis->GetXmax();
11686 xx[2] = zaxis->GetBinCenter(binz);
11687 view->WCtoNDC(xx,u);
11688 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11689 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11690 rect1[4].SetX(rect1[0].GetX());
11691 rect1[4].SetY(rect1[0].GetY());
11692 xx[0] = xaxis->GetXmax();
11693 view->WCtoNDC(xx,u);
11694 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11695 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11696 xx[1] = yaxis->GetXmin();
11697 view->WCtoNDC(xx,u);
11698 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11699 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11700 xx[0] = xaxis->GetXmin();
11701 view->WCtoNDC(xx,u);
11702 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11703 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11704 gVirtualX->DrawPolyLine(5,rect1);
11705 if (nbins>1) {
11706 xx[0] = xaxis->GetXmin();
11707 xx[1] = yaxis->GetXmax();
11708 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11709 view->WCtoNDC(xx,u);
11710 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11711 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11712 rect2[4].SetX(rect2[0].GetX());
11713 rect2[4].SetY(rect2[0].GetY());
11714 xx[0] = xaxis->GetXmax();
11715 view->WCtoNDC(xx,u);
11716 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11717 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11718 xx[1] = yaxis->GetXmin();
11719 view->WCtoNDC(xx,u);
11720 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11721 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11722 xx[0] = xaxis->GetXmin();
11723 view->WCtoNDC(xx,u);
11724 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11725 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11726 gVirtualX->DrawPolyLine(5,rect2);
11727 }
11728 c->Clear();
11729 c->cd();
11730 TH2 *hp = (TH2*)h3->Project3D("yx");
11731 zaxis->SetRange(first,last);
11732 if (hp) {
11733 hp->SetFillColor(38);
11734 if (nbins==1)hp->SetTitle(TString::Format("ProjectionYX of binz=%d [z=%.1f..%.f]", binz,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz)));
11735 else hp->SetTitle(TString::Format("ProjectionYX, binz=[%d,%d] [z=%.1f..%.1f]", binz,binz2,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz2)));
11736 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11737 hp->SetYTitle(fH->GetYaxis()->GetTitle());
11738 hp->SetZTitle("Number of Entries");
11739 hp->Draw(fShowOption.Data());
11740 }
11741 }
11742 break;
11743
11744 case 6:
11745 // "xz"
11746 {
11747 Int_t first = yaxis->GetFirst();
11748 Int_t last = yaxis->GetLast();
11749 Int_t biny = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11750 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11751 yaxis->SetRange(biny,biny2);
11752 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11753 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11754 xx[0] = xaxis->GetXmin();
11755 xx[2] = zaxis->GetXmax();
11756 xx[1] = yaxis->GetBinCenter(biny);
11757 view->WCtoNDC(xx,u);
11758 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11759 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11760 rect1[4].SetX(rect1[0].GetX());
11761 rect1[4].SetY(rect1[0].GetY());
11762 xx[0] = xaxis->GetXmax();
11763 view->WCtoNDC(xx,u);
11764 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11765 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11766 xx[2] = zaxis->GetXmin();
11767 view->WCtoNDC(xx,u);
11768 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11769 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11770 xx[0] = xaxis->GetXmin();
11771 view->WCtoNDC(xx,u);
11772 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11773 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11774 gVirtualX->DrawPolyLine(5,rect1);
11775 if (nbins>1) {
11776 xx[0] = xaxis->GetXmin();
11777 xx[2] = zaxis->GetXmax();
11778 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11779 view->WCtoNDC(xx,u);
11780 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11781 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11782 rect2[4].SetX(rect2[0].GetX());
11783 rect2[4].SetY(rect2[0].GetY());
11784 xx[0] = xaxis->GetXmax();
11785 view->WCtoNDC(xx,u);
11786 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11787 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11788 xx[2] = zaxis->GetXmin();
11789 view->WCtoNDC(xx,u);
11790 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11791 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11792 xx[0] = xaxis->GetXmin();
11793 view->WCtoNDC(xx,u);
11794 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11795 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11796 gVirtualX->DrawPolyLine(5,rect2);
11797 }
11798 c->Clear();
11799 c->cd();
11800 TH2 *hp = (TH2*)h3->Project3D("xz");
11801 yaxis->SetRange(first,last);
11802 if (hp) {
11803 hp->SetFillColor(38);
11804 if (nbins==1)hp->SetTitle(TString::Format("ProjectionXZ of biny=%d [y=%.1f..%.f]", biny,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny)));
11805 else hp->SetTitle(TString::Format("ProjectionXZ, biny=[%d,%d] [y=%.1f..%.1f]", biny,biny2,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny2)));
11806 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11807 hp->SetYTitle(fH->GetXaxis()->GetTitle());
11808 hp->SetZTitle("Number of Entries");
11809 hp->Draw(fShowOption.Data());
11810 }
11811 }
11812 break;
11813
11814 case 7:
11815 // "zx"
11816 {
11817 Int_t first = yaxis->GetFirst();
11818 Int_t last = yaxis->GetLast();
11819 Int_t biny = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11820 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11821 yaxis->SetRange(biny,biny2);
11822 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11823 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11824 xx[0] = xaxis->GetXmin();
11825 xx[2] = zaxis->GetXmax();
11826 xx[1] = yaxis->GetBinCenter(biny);
11827 view->WCtoNDC(xx,u);
11828 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11829 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11830 rect1[4].SetX(rect1[0].GetX());
11831 rect1[4].SetY(rect1[0].GetY());
11832 xx[0] = xaxis->GetXmax();
11833 view->WCtoNDC(xx,u);
11834 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11835 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11836 xx[2] = zaxis->GetXmin();
11837 view->WCtoNDC(xx,u);
11838 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11839 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11840 xx[0] = xaxis->GetXmin();
11841 view->WCtoNDC(xx,u);
11842 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11843 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11844 gVirtualX->DrawPolyLine(5,rect1);
11845 if (nbins>1) {
11846 xx[0] = xaxis->GetXmin();
11847 xx[2] = zaxis->GetXmax();
11848 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11849 view->WCtoNDC(xx,u);
11850 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11851 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11852 rect2[4].SetX(rect2[0].GetX());
11853 rect2[4].SetY(rect2[0].GetY());
11854 xx[0] = xaxis->GetXmax();
11855 view->WCtoNDC(xx,u);
11856 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11857 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11858 xx[2] = zaxis->GetXmin();
11859 view->WCtoNDC(xx,u);
11860 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11861 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11862 xx[0] = xaxis->GetXmin();
11863 view->WCtoNDC(xx,u);
11864 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11865 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11866 gVirtualX->DrawPolyLine(5,rect2);
11867 }
11868 c->Clear();
11869 c->cd();
11870 TH2 *hp = (TH2*)h3->Project3D("zx");
11871 yaxis->SetRange(first,last);
11872 if (hp) {
11873 hp->SetFillColor(38);
11874 if (nbins==1)hp->SetTitle(TString::Format("ProjectionZX of biny=%d [y=%.1f..%.f]", biny,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny)));
11875 else hp->SetTitle(TString::Format("ProjectionZX, biny=[%d,%d] [y=%.1f..%.1f]", biny,biny2,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny2)));
11876 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11877 hp->SetYTitle(fH->GetZaxis()->GetTitle());
11878 hp->SetZTitle("Number of Entries");
11879 hp->Draw(fShowOption.Data());
11880 }
11881 }
11882 break;
11883
11884 case 8:
11885 // "yz"
11886 {
11887 Int_t first = xaxis->GetFirst();
11888 Int_t last = xaxis->GetLast();
11889 Int_t binx = first + Int_t((last-first)*(px-pxmin)/(pxmax-pxmin));
11890 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11891 xaxis->SetRange(binx,binx2);
11892 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11893 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11894 xx[2] = zaxis->GetXmin();
11895 xx[1] = yaxis->GetXmax();
11896 xx[0] = xaxis->GetBinCenter(binx);
11897 view->WCtoNDC(xx,u);
11898 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11899 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11900 rect1[4].SetX(rect1[0].GetX());
11901 rect1[4].SetY(rect1[0].GetY());
11902 xx[2] = zaxis->GetXmax();
11903 view->WCtoNDC(xx,u);
11904 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11905 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11906 xx[1] = yaxis->GetXmin();
11907 view->WCtoNDC(xx,u);
11908 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11909 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11910 xx[2] = zaxis->GetXmin();
11911 view->WCtoNDC(xx,u);
11912 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11913 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11914 gVirtualX->DrawPolyLine(5,rect1);
11915 if (nbins>1) {
11916 xx[2] = zaxis->GetXmin();
11917 xx[1] = yaxis->GetXmax();
11918 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11919 view->WCtoNDC(xx,u);
11920 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11921 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11922 rect2[4].SetX(rect2[0].GetX());
11923 rect2[4].SetY(rect2[0].GetY());
11924 xx[2] = zaxis->GetXmax();
11925 view->WCtoNDC(xx,u);
11926 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11927 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11928 xx[1] = yaxis->GetXmin();
11929 view->WCtoNDC(xx,u);
11930 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11931 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11932 xx[2] = zaxis->GetXmin();
11933 view->WCtoNDC(xx,u);
11934 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11935 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11936 gVirtualX->DrawPolyLine(5,rect2);
11937 }
11938 c->Clear();
11939 c->cd();
11940 TH2 *hp = (TH2*)h3->Project3D("yz");
11941 xaxis->SetRange(first,last);
11942 if (hp) {
11943 hp->SetFillColor(38);
11944 if (nbins==1)hp->SetTitle(TString::Format("ProjectionYZ of binx=%d [x=%.1f..%.f]", binx,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx)));
11945 else hp->SetTitle(TString::Format("ProjectionYZ, binx=[%d,%d] [x=%.1f..%.1f]", binx,binx2,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx2)));
11946 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11947 hp->SetYTitle(fH->GetYaxis()->GetTitle());
11948 hp->SetZTitle("Number of Entries");
11949 hp->Draw(fShowOption.Data());
11950 }
11951 }
11952 break;
11953
11954 case 9:
11955 // "zy"
11956 {
11957 Int_t first = xaxis->GetFirst();
11958 Int_t last = xaxis->GetLast();
11959 Int_t binx = first + Int_t((last-first)*(px-pxmin)/(pxmax-pxmin));
11960 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11961 xaxis->SetRange(binx,binx2);
11962 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11963 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11964 xx[2] = zaxis->GetXmin();
11965 xx[1] = yaxis->GetXmax();
11966 xx[0] = xaxis->GetBinCenter(binx);
11967 view->WCtoNDC(xx,u);
11968 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11969 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11970 rect1[4].SetX(rect1[0].GetX());
11971 rect1[4].SetY(rect1[0].GetY());
11972 xx[2] = zaxis->GetXmax();
11973 view->WCtoNDC(xx,u);
11974 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11975 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11976 xx[1] = yaxis->GetXmin();
11977 view->WCtoNDC(xx,u);
11978 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11979 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11980 xx[2] = zaxis->GetXmin();
11981 view->WCtoNDC(xx,u);
11982 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11983 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11984 gVirtualX->DrawPolyLine(5,rect1);
11985 if (nbins>1) {
11986 xx[2] = zaxis->GetXmin();
11987 xx[1] = yaxis->GetXmax();
11988 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11989 view->WCtoNDC(xx,u);
11990 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11991 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11992 rect2[4].SetX(rect2[0].GetX());
11993 rect2[4].SetY(rect2[0].GetY());
11994 xx[2] = zaxis->GetXmax();
11995 view->WCtoNDC(xx,u);
11996 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11997 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11998 xx[1] = yaxis->GetXmin();
11999 view->WCtoNDC(xx,u);
12000 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
12001 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
12002 xx[2] = zaxis->GetXmin();
12003 view->WCtoNDC(xx,u);
12004 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
12005 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
12006 gVirtualX->DrawPolyLine(5,rect2);
12007 }
12008 c->Clear();
12009 c->cd();
12010 TH2 *hp = (TH2*)h3->Project3D("zy");
12011 xaxis->SetRange(first,last);
12012 if (hp) {
12013 hp->SetFillColor(38);
12014 if (nbins==1)hp->SetTitle(TString::Format("ProjectionZY of binx=%d [x=%.1f..%.f]", binx,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx)));
12015 else hp->SetTitle(TString::Format("ProjectionZY, binx=[%d,%d] [x=%.1f..%.1f]", binx,binx2,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx2)));
12016 hp->SetXTitle(fH->GetYaxis()->GetTitle());
12017 hp->SetYTitle(fH->GetZaxis()->GetTitle());
12018 hp->SetZTitle("Number of Entries");
12019 hp->Draw(fShowOption.Data());
12020 }
12021 }
12022 break;
12023 }
12024 c->Update();
12025}
@ kMouseMotion
Definition Buttons.h:23
@ kWheelUp
Definition Buttons.h:18
@ kButton1Motion
Definition Buttons.h:20
@ kButton1Up
Definition Buttons.h:19
@ kWheelDown
Definition Buttons.h:18
@ kButton1Down
Definition Buttons.h:17
@ kButton1Locate
Definition Buttons.h:22
@ kArrowVer
Definition GuiTypes.h:375
@ kPointer
Definition GuiTypes.h:376
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
Style number (short)
Definition RtypesCore.h:97
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:60
short Color_t
Color number (short)
Definition RtypesCore.h:100
unsigned int UInt_t
Unsigned integer 4 bytes (unsigned int)
Definition RtypesCore.h:61
short Width_t
Line width (short)
Definition RtypesCore.h:99
float Float_t
Float 4 bytes (float)
Definition RtypesCore.h:72
short Short_t
Signed Short integer 2 bytes (short)
Definition RtypesCore.h:54
constexpr Bool_t kFALSE
Definition RtypesCore.h:109
double Double_t
Double 8 bytes.
Definition RtypesCore.h:74
constexpr Bool_t kTRUE
Definition RtypesCore.h:108
const char Option_t
Option string (const char)
Definition RtypesCore.h:81
#define BIT(n)
Definition Rtypes.h:91
@ kBlack
Definition Rtypes.h:66
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
R__EXTERN TEnv * gEnv
Definition TEnv.h:126
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t option
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void pixel
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t wmin
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize 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:417
R__EXTERN TStyle * gStyle
Definition TStyle.h:442
R__EXTERN TSystem * gSystem
Definition TSystem.h:582
const Int_t kCARTESIAN
Definition TView3D.cxx:32
const Int_t kPOLAR
Definition TView3D.cxx:33
#define gPad
#define gVirtualX
Definition TVirtualX.h:377
polygon * polys
Definition X3DBuffer.c:24
Draw all kinds of Arrows.
Definition TArrow.h:29
virtual Int_t GetNdivisions() const
Definition TAttAxis.h:37
virtual Float_t GetLabelOffset() const
Definition TAttAxis.h:41
virtual Float_t GetLabelSize() const
Definition TAttAxis.h:42
virtual Float_t GetTickLength() const
Definition TAttAxis.h:46
virtual Float_t GetTitleOffset() const
Definition TAttAxis.h:44
virtual Color_t GetFillColor() const
Return the fill area color.
Definition TAttFill.h:32
virtual Style_t GetFillStyle() const
Return the fill area style.
Definition TAttFill.h:33
virtual void SetFillColor(Color_t fcolor)
Set the fill area color.
Definition TAttFill.h:40
virtual void SetFillStyle(Style_t fstyle)
Set the fill area style.
Definition TAttFill.h:42
virtual Color_t GetLineColor() const
Return the line color.
Definition TAttLine.h:36
virtual void SetLineStyle(Style_t lstyle)
Set the line style.
Definition TAttLine.h:46
virtual Width_t GetLineWidth() const
Return the line width.
Definition TAttLine.h:38
virtual void SetLineWidth(Width_t lwidth)
Set the line width.
Definition TAttLine.h:47
virtual void SetLineColor(Color_t lcolor)
Set the line color.
Definition TAttLine.h:44
virtual Style_t GetLineStyle() const
Return the line style.
Definition TAttLine.h:37
virtual Style_t GetMarkerStyle() const
Return the marker style.
Definition TAttMarker.h:34
virtual void SetMarkerColor(Color_t mcolor=1)
Set the marker color.
Definition TAttMarker.h:41
virtual Color_t GetMarkerColor() const
Return the marker color.
Definition TAttMarker.h:33
virtual Size_t GetMarkerSize() const
Return the marker size.
Definition TAttMarker.h:35
virtual void SetMarkerStyle(Style_t mstyle=1)
Set the marker style.
Definition TAttMarker.h:43
virtual void SetMarkerSize(Size_t msize=1)
Set the marker size.
Definition TAttMarker.h:48
static Style_t GetMarkerStyleBase(Style_t style)
Internal helper function that returns the corresponding marker style with line width 1 for the given ...
virtual void SetTextAlign(Short_t align=11)
Set the text alignment.
Definition TAttText.h:48
virtual Font_t GetTextFont() const
Return the text font.
Definition TAttText.h:38
virtual void SetTextAngle(Float_t tangle=0)
Set the text angle.
Definition TAttText.h:49
virtual void SetTextColor(Color_t tcolor=1)
Set the text color.
Definition TAttText.h:50
virtual void SetTextFont(Font_t tfont=62)
Set the text font.
Definition TAttText.h:52
virtual void SetTextSize(Float_t tsize=1)
Set the text size.
Definition TAttText.h:53
Class to manage histogram axis.
Definition TAxis.h:32
virtual Bool_t GetTimeDisplay() const
Definition TAxis.h:133
Bool_t IsAlphanumeric() const
Definition TAxis.h:90
const char * GetTitle() const override
Returns title of object.
Definition TAxis.h:137
virtual Double_t GetBinCenter(Int_t bin) const
Return center of bin.
Definition TAxis.cxx:482
Bool_t CanExtend() const
Definition TAxis.h:88
const TArrayD * GetXbins() const
Definition TAxis.h:138
Double_t GetXmax() const
Definition TAxis.h:142
@ kAxisRange
Definition TAxis.h:66
const char * GetBinLabel(Int_t bin) const
Return label for bin.
Definition TAxis.cxx:444
virtual Int_t FindBin(Double_t x)
Find bin number corresponding to abscissa x.
Definition TAxis.cxx:293
virtual Double_t GetBinLowEdge(Int_t bin) const
Return low edge of bin.
Definition TAxis.cxx:522
virtual Int_t FindFixBin(Double_t x) const
Find bin number corresponding to abscissa x
Definition TAxis.cxx:422
const char * ChooseTimeFormat(Double_t axislength=0)
Choose a reasonable time format from the coordinates in the active pad and the number of divisions in...
Definition TAxis.cxx:127
Int_t GetLast() const
Return last bin on the axis i.e.
Definition TAxis.cxx:473
virtual const char * GetTimeFormatOnly() const
Return only the time format from the string fTimeFormat.
Definition TAxis.cxx:604
Double_t GetXmin() const
Definition TAxis.h:141
Int_t GetNbins() const
Definition TAxis.h:127
virtual void SetRangeUser(Double_t ufirst, Double_t ulast)
Set the viewing range for the axis from ufirst to ulast (in user coordinates, that is,...
Definition TAxis.cxx:1090
virtual const char * GetTimeFormat() const
Definition TAxis.h:134
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width.
Definition TAxis.cxx:546
virtual Double_t GetBinUpEdge(Int_t bin) const
Return up edge of bin.
Definition TAxis.cxx:532
Int_t GetFirst() const
Return first bin on the axis i.e.
Definition TAxis.cxx:462
THashList * GetLabels() const
Definition TAxis.h:123
Create a Box.
Definition TBox.h:22
The candle plot painter class.
Definition TCandle.h:27
CandleOption
Definition TCandle.h:30
static Bool_t SupportAlpha()
Static function returning "true" if transparency is supported.
Definition TCanvas.cxx:2489
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:2994
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
The color creation and management class.
Definition TColor.h:22
static void RGBtoHLS(Float_t r, Float_t g, Float_t b, Float_t &h, Float_t &l, Float_t &s)
Definition TColor.h:83
static Int_t GetColor(const char *hexcolor)
Static method returning color number for color specified by hex color string of form: "#rrggbb",...
Definition TColor.cxx:1926
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:2095
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:2138
static void HLStoRGB(Float_t h, Float_t l, Float_t s, Float_t &r, Float_t &g, Float_t &b)
Definition TColor.h:78
To draw a Crown.
Definition TCrown.h:19
Graphical cut class.
Definition TCutG.h:20
static TClass * Class()
TDirectory::TContext keeps track and restore the current directory.
Definition TDirectory.h:89
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition TEnv.cxx:511
1-Dim function class
Definition TF1.h:182
virtual Double_t GetXmax() const
Definition TF1.h:525
virtual Int_t GetNDF() const
Return the number of degrees of freedom in the fit the fNDF parameter has been previously computed du...
Definition TF1.cxx:1939
virtual void GetParLimits(Int_t ipar, Double_t &parmin, Double_t &parmax) const
Return limits for parameter ipar.
Definition TF1.cxx:1990
virtual Double_t GetParError(Int_t ipar) const
Return value of parameter number ipar.
Definition TF1.cxx:1980
static TClass * Class()
Double_t GetChisquare() const
Return the Chisquare after fitting. See ROOT::Fit::FitResult::Chi2()
Definition TF1.h:409
virtual void SetMaximum(Double_t maximum=-1111)
Set the maximum value along Y for this function In case the function is already drawn,...
Definition TF1.cxx:3449
virtual Double_t GetMaximumStored() const
Definition TF1.h:438
virtual Int_t GetNpar() const
Definition TF1.h:446
virtual Int_t GetNumberFreeParameters() const
Return the number of free parameters.
Definition TF1.cxx:1950
@ kNotDraw
Definition TF1.h:297
virtual void SetMinimum(Double_t minimum=-1111)
Set the minimum value along Y for this function In case the function is already drawn,...
Definition TF1.cxx:3462
virtual const char * GetParName(Int_t ipar) const
Definition TF1.h:494
virtual Double_t Eval(Double_t x, Double_t y=0, Double_t z=0, Double_t t=0) const
Evaluate this function.
Definition TF1.cxx:1446
virtual Double_t GetXmin() const
Definition TF1.h:521
virtual Double_t GetParameter(Int_t ipar) const
Definition TF1.h:477
A 2-Dim function with parameters.
Definition TF2.h:29
void Paint(Option_t *option="") override
Paint this 2-D function with its current attributes.
Definition TF2.cxx:805
void SetRange(Double_t xmin, Double_t xmax) override
Initialize the upper and lower bounds to draw the function.
Definition TF2.h:133
static TClass * Class()
TF3 defines a 3D Function with Parameters.
Definition TF3.h:28
The axis painter class.
Definition TGaxis.h:26
void SetTimeFormat(const char *tformat)
Change the format used for time plotting.
Definition TGaxis.cxx:2937
virtual void PaintAxis(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax, Double_t &wmin, Double_t &wmax, Int_t &ndiv, Option_t *chopt="", Double_t gridlength=0, Bool_t drawGridOnly=kFALSE)
Control function to draw an axis.
Definition TGaxis.cxx:1006
void SetTitleOffset(Float_t titleoffset=1)
Definition TGaxis.h:130
virtual void SetTitle(const char *title="")
Change the title of the axis.
Definition TGaxis.cxx:2910
void SetLabelOffset(Float_t labeloffset)
Definition TGaxis.h:108
virtual void ImportAxisAttributes(TAxis *axis)
Internal method to import TAxis attributes to this TGaxis.
Definition TGaxis.cxx:953
void SetTickSize(Float_t ticksize)
Definition TGaxis.h:124
void SetLabelSize(Float_t labelsize)
Definition TGaxis.h:109
void SetOption(Option_t *option="")
To set axis options.
Definition TGaxis.cxx:2902
Graphics object made of three arrays X, Y and Z with the same number of points each.
Definition TGraph2D.h:41
static TClass * Class()
TGraphDelaunay2D generates a Delaunay triangulation of a TGraph2D.
TGraphDelaunay generates a Delaunay triangulation of a TGraph2D.
A TGraph is an object made of two arrays X and Y with npoints each.
Definition TGraph.h:41
static TClass * Class()
@ kClipFrame
Clip to the frame boundary.
Definition TGraph.h:75
void PaintGraph(Int_t npoints, const Double_t *x, const Double_t *y, Option_t *chopt)
Draw the (x,y) as a graph.
Definition TGraph.cxx:2018
void PaintGrapHist(Int_t npoints, const Double_t *x, const Double_t *y, Option_t *chopt)
Draw the (x,y) as a histogram.
Definition TGraph.cxx:2027
1-D histogram with a double per channel (see TH1 documentation)
Definition TH1.h:926
1-D histogram with a float per channel (see TH1 documentation)
Definition TH1.h:878
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:109
TAxis * GetZaxis()
Definition TH1.h:573
virtual EBinErrorOpt GetBinErrorOption() const
Definition TH1.h:517
virtual Float_t GetBarWidth() const
Definition TH1.h:501
virtual Double_t GetMinimumStored() const
Definition TH1.h:537
virtual Float_t GetBarOffset() const
Definition TH1.h:500
static TClass * Class()
virtual Double_t GetStdDev(Int_t axis=1) const
Returns the Standard Deviation (Sigma).
Definition TH1.cxx:7816
virtual Int_t GetNbinsY() const
Definition TH1.h:542
virtual Double_t GetBinError(Int_t bin) const
Return value of error associated to bin number bin.
Definition TH1.cxx:9293
virtual Int_t GetNbinsZ() const
Definition TH1.h:543
virtual Double_t GetNormFactor() const
Definition TH1.h:545
virtual Double_t GetMean(Int_t axis=1) const
For axis = 1,2 or 3 returns the mean value of the histogram along X,Y or Z axis.
Definition TH1.cxx:7744
virtual Double_t GetSkewness(Int_t axis=1) const
Definition TH1.cxx:7880
virtual Double_t GetContourLevelPad(Int_t level) const
Return the value of contour number "level" in Pad coordinates.
Definition TH1.cxx:8669
virtual Int_t GetDimension() const
Definition TH1.h:527
@ kNoTitle
Don't draw the histogram title.
Definition TH1.h:408
@ kUserContour
User specified contour levels.
Definition TH1.h:404
@ kNoStats
Don't draw stats box.
Definition TH1.h:403
TAxis * GetXaxis()
Definition TH1.h:571
virtual Double_t GetSumOfWeights() const
Return the sum of weights across all bins excluding under/overflows.
Definition TH1.h:559
virtual Int_t GetBin(Int_t binx, Int_t biny=0, Int_t binz=0) const
Return Global bin number corresponding to binx,y,z.
Definition TH1.cxx:5137
virtual Double_t GetMaximum(Double_t maxval=FLT_MAX) const
Return maximum value smaller than maxval of bins in the range, unless the value has been overridden b...
Definition TH1.cxx:8778
virtual Int_t GetNbinsX() const
Definition TH1.h:541
virtual void SetMaximum(Double_t maximum=-1111)
Definition TH1.h:652
TAxis * GetYaxis()
Definition TH1.h:572
virtual Double_t GetBinErrorLow(Int_t bin) const
Return lower error associated to bin number bin.
Definition TH1.cxx:9309
virtual void SetMinimum(Double_t minimum=-1111)
Definition TH1.h:653
virtual Double_t Integral(Option_t *option="") const
Return integral of bin contents.
Definition TH1.cxx:8170
virtual void SetBinContent(Int_t bin, Double_t content)
Set bin content see convention for numbering bins in TH1::GetBin In case the bin number is greater th...
Definition TH1.cxx:9452
virtual Double_t GetBinLowEdge(Int_t bin) const
Return bin lower edge for 1D histogram.
Definition TH1.cxx:9382
virtual Double_t GetEntries() const
Return the current number of entries.
Definition TH1.cxx:4574
TList * GetListOfFunctions() const
Definition TH1.h:488
virtual Double_t GetMeanError(Int_t axis=1) const
Return standard error of mean of this histogram along the X axis.
Definition TH1.cxx:7784
virtual Double_t GetMaximumStored() const
Definition TH1.h:533
virtual void GetMinimumAndMaximum(Double_t &min, Double_t &max) const
Retrieve the minimum and maximum values in the histogram.
Definition TH1.cxx:8964
virtual Int_t GetMaximumBin() const
Return location of bin with maximum value in the range.
Definition TH1.cxx:8810
@ kNormal
Errors with Normal (Wald) approximation: errorUp=errorLow= sqrt(N)
Definition TH1.h:115
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition TH1.cxx:5239
virtual Int_t GetContour(Double_t *levels=nullptr)
Return contour values into array levels if pointer levels is non zero.
Definition TH1.cxx:8640
const Double_t * GetBuffer() const
Definition TH1.h:483
virtual Bool_t IsHighlight() const
Definition TH1.h:585
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width for 1D histogram.
Definition TH1.cxx:9393
virtual void SetContour(Int_t nlevels, const Double_t *levels=nullptr)
Set the number and values of contour levels.
Definition TH1.cxx:8716
virtual Double_t GetBinErrorUp(Int_t bin) const
Return upper error associated to bin number bin.
Definition TH1.cxx:9340
virtual Int_t GetSumw2N() const
Definition TH1.h:562
virtual Double_t GetStdDevError(Int_t axis=1) const
Return error of standard deviation estimation for Normal distribution.
Definition TH1.cxx:7864
virtual Double_t GetMinimum(Double_t minval=-FLT_MAX) const
Return minimum value larger than minval of bins in the range, unless the value has been overridden by...
Definition TH1.cxx:8868
virtual void LabelsDeflate(Option_t *axis="X")
Reduce the number of bins for the axis passed in the option to the number of bins having a label.
Definition TH1.cxx:5423
virtual Int_t BufferEmpty(Int_t action=0)
Fill histogram with all entries in the buffer.
Definition TH1.cxx:1445
virtual Double_t GetKurtosis(Int_t axis=1) const
Definition TH1.cxx:7953
2-D histogram with a double per channel (see TH1 documentation)
Definition TH2.h:400
2-D histogram with a float per channel (see TH1 documentation)
Definition TH2.h:345
Helper class to represent a bin in the TH2Poly histogram.
Definition TH2Poly.h:25
2D Histogram with Polygonal Bins
Definition TH2Poly.h:66
static TClass * Class()
Service class for 2-D histogram classes.
Definition TH2.h:30
TH1D * ProjectionY(const char *name="_py", Int_t firstxbin=0, Int_t lastxbin=-1, Option_t *option="") const
Project a 2-D histogram into a 1-D histogram along Y (integration along X).
Definition TH2.cxx:2464
TH1D * ProjectionX(const char *name="_px", Int_t firstybin=0, Int_t lastybin=-1, Option_t *option="") const
Project a 2-D histogram into a 1-D histogram along X (integration along Y).
Definition TH2.cxx:2421
Double_t GetBinContent(Int_t binx, Int_t biny) const override
Definition TH2.h:97
static TClass * Class()
Double_t Integral(Option_t *option="") const override
Return integral of bin contents.
Definition TH2.cxx:1289
The 3-D histogram classes derived from the 1-D histogram classes.
Definition TH3.h:45
static TClass * Class()
The Histogram stack class.
Definition THStack.h:40
static TClass * Class()
The histogram painter class.
static Int_t ProjectSinusoidal2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function code for sinusoidal projection from Ernst-Jan Buis Source https://en....
void Paint(Option_t *option="") override
Control routine to paint any kind of histograms
TAxis * fYaxis
Pointer to Y axis.
std::unique_ptr< TPainter3dAlgorithms > fLego
Pointer to a TPainter3dAlgorithms object.
std::vector< Double_t > fXbuf
X buffer coordinates.
Int_t fXHighlightBin
X highlight bin.
TF3 * fCurrentF3
Current TF3 function.
virtual void PaintErrors(Option_t *option)
Draw 1D histograms error bars.
~THistPainter() override
destructor.
Int_t fShowProjection2
True if a second projection must be drawn (when calling SetShowProjectionXY on a TH2)
virtual void PaintTF3()
Control function to draw a 3D implicit functions.
virtual Int_t TableInit()
Initialize various options to draw 2D histograms.
virtual void PaintTH2PolyScatterPlot(Option_t *option)
Control function to draw a TH2Poly as a scatter plot.
static Int_t ProjectMollweide2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
static Int_t ProjectAitoff2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
virtual void PaintText(Option_t *option)
Control function to draw a 1D/2D histograms with the bin values.
Int_t DistancetoPrimitive(Int_t px, Int_t py) override
Compute the distance from the point px,py to a line.
virtual void PaintAxis(Bool_t drawGridOnly=kFALSE)
Draw axis (2D case) of an histogram.
virtual void PaintColorLevelsFast(Option_t *option)
[Rendering scheme for the COL2 and COLZ2 options] (HP14)
virtual Int_t PaintInit()
Compute histogram parameters used by the drawing routines.
virtual void Paint2DErrors(Option_t *option)
Draw 2D histograms errors.
Int_t fYHighlightBin
Y highlight bin.
virtual void PaintCandlePlot(Option_t *option)
Control function to draw a 2D histogram as a candle (box) plot or violin plot
virtual void PaintScatterPlot(Option_t *option)
Control function to draw a 2D histogram as a scatter plot.
void SetShowProjectionXY(const char *option, Int_t nbinsY, Int_t nbinsX) override
virtual void PaintLego(Option_t *option)
Control function to draw a 2D histogram as a lego plot.
virtual void PaintH3(Option_t *option="")
Control function to draw a 3D histograms.
Int_t fNcuts
Number of graphical cuts.
TString fShowOption
Option to draw the projection.
virtual void PaintHighlightBin(Option_t *option="")
Paint highlight bin as TBox object.
virtual void PaintTH2PolyBins(Option_t *option)
Control function to draw a TH2Poly bins' contours.
virtual Int_t PaintContourLine(Double_t elev1, Int_t icont1, Double_t x1, Double_t y1, Double_t elev2, Int_t icont2, Double_t x2, Double_t y2, Double_t *xarr, Double_t *yarr, Int_t *itarr, Double_t *levels)
Fill the matrix xarr and yarr for Contour Plot.
Int_t fShowProjection
True if a projection must be drawn.
virtual void PaintLegoAxis(TGaxis *axis, Double_t ang)
Draw the axis for legos and surface plots.
virtual void PaintTriangles(Option_t *option)
Control function to draw a table using Delaunay triangles.
virtual void HighlightBin(Int_t px, Int_t py)
Check on highlight bin.
virtual void PaintH3Box(Int_t iopt)
Control function to draw a 3D histogram with boxes.
Int_t MakeCuts(char *cutsopt) override
Decode string choptin and fill Graphical cuts structure.
TList * fFunctions
Pointer to histogram list of functions.
void DrawPanel() override
Display a panel with all histogram drawing options.
std::unique_ptr< TPie > fPie
Pointer to a TPie in case of option PIE.
static void PaintSpecialObjects(const TObject *obj, Option_t *option)
Static function to paint special objects like vectors and matrices.
virtual void PaintTitle()
new TGaxis/////////////////// Draw the histogram title
virtual void PaintTH2PolyColorLevels(Option_t *option)
Control function to draw a TH2Poly as a color plot.
virtual std::vector< THistRenderingRegion > ComputeRenderingRegions(TAxis *pAxis, Int_t nPixels, bool isLog)
Returns the rendering regions for an axis to use in the COL2 option.
virtual void ShowProjectionX(Int_t px, Int_t py)
Show projection onto X.
virtual void PaintPalette()
Paint the color palette on the right side of the pad.
TAxis * fXaxis
Pointer to X axis.
virtual void PaintStat2(Int_t dostat, TF1 *fit)
Draw the statistics box for 2D histograms.
virtual void PaintArrows(Option_t *option)
Control function to draw a table as an arrow plot
virtual void RecalculateRange()
Recompute the histogram range following graphics operations.
void PaintStat(Int_t dostat, TF1 *fit) override
Draw the statistics box for 1D and profile histograms.
static Int_t ProjectParabolic2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function code for parabolic projection from Ernst-Jan Buis.
std::unique_ptr< TGraph2DPainter > fGraph2DPainter
Pointer to a TGraph2DPainter object.
virtual void PaintBarH(Option_t *option)
Draw a bar char in a rotated pad (X vertical, Y horizontal)
virtual void PaintStat3(Int_t dostat, TF1 *fit)
Draw the statistics box for 3D histograms.
virtual void PaintSurface(Option_t *option)
Control function to draw a 2D histogram as a surface plot.
TList * fStack
Pointer to stack of histograms (if any)
THistPainter()
Default constructor.
TH1 * fH
Pointer to histogram to paint.
virtual void PaintTH2PolyText(Option_t *option)
Control function to draw a TH2Poly as a text plot.
virtual void ShowProjection3(Int_t px, Int_t py)
Show projection (specified by fShowProjection) of a TH3.
TAxis * fZaxis
Pointer to Z axis.
void SetHistogram(TH1 *h) override
Set current histogram to h
virtual void PaintFunction(Option_t *option)
[Paint functions associated to an histogram.](HP28")
virtual void PaintBar(Option_t *option)
Draw a bar-chart in a normal pad.
static Int_t ProjectMercator2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
virtual void PaintBoxes(Option_t *option)
Control function to draw a 2D histogram as a box plot
virtual Int_t MakeChopt(Option_t *option)
Decode string choptin and fill Hoption structure.
char * GetObjectInfo(Int_t px, Int_t py) const override
Display the histogram info (bin number, contents, integral up to bin corresponding to cursor position...
TList * GetContourList(Double_t contour) const override
Get a contour (as a list of TGraphs) using the Delaunay triangulation.
void ProcessMessage(const char *mess, const TObject *obj) override
Process message mess.
void SetShowProjection(const char *option, Int_t nbins) override
Set projection.
virtual void ShowProjectionY(Int_t px, Int_t py)
Show projection onto Y.
static const char * GetBestFormat(Double_t v, Double_t e, const char *f)
This function returns the best format to print the error value (e) knowing the parameter value (v) an...
virtual void PaintContour(Option_t *option)
Control function to draw a 2D histogram as a contour plot.
TCutG * fCuts[kMaxCuts]
Pointers to graphical cuts.
virtual void PaintTable(Option_t *option)
Control function to draw 2D/3D histograms (tables).
void ExecuteEvent(Int_t event, Int_t px, Int_t py) override
Execute the actions corresponding to event.
virtual Int_t PaintInitH()
Compute histogram parameters used by the drawing routines for a rotated pad.
virtual void PaintFrame()
Calculate range and clear pad (canvas).
Int_t fCutsOpt[kMaxCuts]
Sign of each cut.
virtual void PaintH3Iso()
Control function to draw a 3D histogram with Iso Surfaces.
std::vector< Double_t > fYbuf
Y buffer coordinates.
virtual void PaintH3BoxRaster()
Control function to draw a 3D histogram with boxes.
virtual void PaintHist(Option_t *option)
Control routine to draw 1D histograms
void SetHighlight() override
Set highlight (enable/disable) mode for fH.
virtual void DefineColorLevels(Int_t ndivz)
Define the color levels used to paint legos, surfaces etc..
TString fObjectInfo
virtual void PaintColorLevels(Option_t *option)
Control function to draw a 2D histogram as a color plot.
Bool_t IsInside(Int_t x, Int_t y) override
Return kTRUE if the cell ix, iy is inside one of the graphical cuts.
A class to define a conversion from pixel values to pixel color.
Definition TAttImage.h:33
static TImagePalette * CreateCOLPalette(Int_t nContours)
Factory method to creates an image palette for histogram plotting.
An abstract interface to image processing library.
Definition TImage.h:29
static TImage * Create()
Create an image.
Definition TImage.cxx:34
void Reset()
To draw Mathematical Formula.
Definition TLatex.h:20
A doubly linked list.
Definition TList.h:38
TObject * FindObject(const char *name) const override
Find an object in this list using its name.
Definition TList.cxx:708
void Add(TObject *obj) override
Definition TList.h:81
TObject * Remove(TObject *obj) override
Remove object from the list.
Definition TList.cxx:952
TObject * First() const override
Return the first object in the list. Returns 0 when list is empty.
Definition TList.cxx:789
virtual TObjLink * FirstLink() const
Definition TList.h:107
TObject * At(Int_t idx) const override
Returns the object at position idx. Returns 0 if idx is out of range.
Definition TList.cxx:487
void AddFirst(TObject *obj) override
Add object at the beginning of the list.
Definition TList.cxx:97
TMatrixTBase.
static TClass * Class()
A TMultiGraph is a collection of TGraph (or derived) objects.
Definition TMultiGraph.h:34
TList * GetListOfGraphs() const
Definition TMultiGraph.h:67
static TClass * Class()
virtual Int_t IsInside(Double_t x, Double_t y) const
Return 1 if the point (x,y) is inside one of the graphs 0 otherwise.
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:50
An array of TObjects.
Definition TObjArray.h:31
Mother of all ROOT objects.
Definition TObject.h:42
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:461
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:204
virtual Option_t * GetDrawOption() const
Get option used by the graphics system to draw this object.
Definition TObject.cxx:444
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1082
virtual TObject * FindObject(const char *name) const
Must be redefined in derived classes.
Definition TObject.cxx:424
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:886
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:548
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1096
virtual const char * GetTitle() const
Returns title of object.
Definition TObject.cxx:506
void ResetBit(UInt_t f)
Definition TObject.h:203
@ kCannotPick
if object in a pad cannot be picked
Definition TObject.h:76
@ kCanDelete
if object in a list can be deleted
Definition TObject.h:71
@ kMustCleanup
if object destructor must call RecursiveRemove()
Definition TObject.h:73
void DrawFaceMove3(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 3rd variant for "MOVING SCREEN" algorithm (draw level lines only)
void DrawLevelLines(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw level lines without hidden line removal.
void SurfaceFunction(Int_t ia, Int_t ib, Double_t *f, Double_t *t)
Service function for Surfaces.
void DrawFaceMode1(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *t)
Draw face - 1st variant (2 colors: 1st for external surface, 2nd for internal)
void GouraudFunction(Int_t ia, Int_t ib, Double_t *f, Double_t *t)
Find part of surface with luminosity in the corners.
void DrawFaceMove1(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 1st variant for "MOVING SCREEN" algorithm (draw face with level lines)
void DrawFaceRaster2(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 2nd variant for "RASTER SCREEN" algorithm (draw face for stacked lego plot)
void LegoFunction(Int_t ia, Int_t ib, Int_t &nv, Double_t *ab, Double_t *vv, Double_t *t)
Service function for Legos.
void DrawFaceMove2(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 2nd variant for "MOVING SCREEN" algorithm (draw face for stacked lego plot)
void DrawFaceRaster1(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 1st variant for "RASTER SCREEN" algorithm (draw face with level lines)
void DrawFaceMode3(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *t)
Draw face - 3rd option (draw face for stacked lego plot)
void DrawFaceMode2(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *t)
Draw face - 2nd option (fill in correspondence with function levels)
The palette painting class.
The histogram statistics painter class.
Definition TPaveStats.h:18
Int_t GetOptStat() const
Return the stat option.
virtual void SetStatFormat(const char *format="6.4g")
Change (i.e. set) the format for printing statistics.
void SetOptStat(Int_t stat=1)
Set the stat option.
virtual const char * GetFitFormat() const
Definition TPaveStats.h:35
virtual void SetFitFormat(const char *format="5.4g")
Change (i.e. set) the format for printing fit parameters in statistics box.
Int_t GetOptFit() const
Return the fit option.
void SetParent(TObject *obj) override
Definition TPaveStats.h:53
void SetOptFit(Int_t fit=1)
Set the fit option.
virtual const char * GetStatFormat() const
Definition TPaveStats.h:36
void Paint(Option_t *option="") override
Paint the pave stat.
static TClass * Class()
A Pave (see TPave) with text, lines or/and boxes inside.
Definition TPaveText.h:21
virtual TText * AddText(Double_t x1, Double_t y1, const char *label)
Add a new Text line to this pavetext at given coordinates.
static TClass * Class()
void Clear(Option_t *option="") override
Clear all lines in this pavetext.
virtual TText * GetLine(Int_t number) const
Get Pointer to line number in this pavetext.
const char * GetName() const override
Returns name of object.
Definition TPave.h:58
virtual void SetName(const char *name="")
Definition TPave.h:81
virtual void SetBorderSize(Int_t bordersize=4)
Sets the border size of the TPave box and shadow.
Definition TPave.h:79
Option_t * GetOption() const override
Definition TPave.h:59
Double_t GetX1NDC() const
Definition TPave.h:61
virtual void SetX2NDC(Double_t x2)
Definition TPave.h:85
void SetX(SCoord_t x)
Definition TPoint.h:48
void SetY(SCoord_t y)
Definition TPoint.h:49
Profile2D histograms are used to display the mean value of Z and its error for each cell in X,...
Definition TProfile2D.h:27
static TClass * Class()
Profile Histogram.
Definition TProfile.h:32
static TClass * Class()
Random number generator class based on the maximally equidistributed combined Tausworthe generator by...
Definition TRandom2.h:27
Sequenceable collection abstract base class.
Basic string class.
Definition TString.h:138
void ToLower()
Change string to lower-case.
Definition TString.cxx:1189
const char * Data() const
Definition TString.h:386
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:2459
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2437
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:643
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:662
Int_t GetOptStat() const
Definition TStyle.h:247
Color_t GetStatTextColor() const
Definition TStyle.h:260
Float_t GetTitleX() const
Definition TStyle.h:282
Int_t GetOptTitle() const
Definition TStyle.h:248
Float_t GetStatFontSize() const
Definition TStyle.h:263
Float_t GetBarOffset() const
Definition TStyle.h:184
Float_t GetStatX() const
Definition TStyle.h:266
Float_t GetTitleSize(Option_t *axis="X") const
Return title size.
Definition TStyle.cxx:1241
Float_t GetTitleY() const
Definition TStyle.h:283
Style_t GetTitleFont(Option_t *axis="X") const
Return title font.
Definition TStyle.cxx:1217
Bool_t GetHistMinimumZero() const
Definition TStyle.h:239
Float_t GetStatY() const
Definition TStyle.h:267
Color_t GetTitleFillColor() const
Definition TStyle.h:273
Style_t GetTitleStyle() const
Definition TStyle.h:275
Color_t GetStatColor() const
Definition TStyle.h:259
Float_t GetBarWidth() const
Definition TStyle.h:185
void SetDrawBorder(Int_t drawborder=1)
Definition TStyle.h:346
Float_t GetStatH() const
Definition TStyle.h:269
Width_t GetTitleBorderSize() const
Definition TStyle.h:277
Int_t GetColorPalette(Int_t i) const
Return color number i in current palette.
Definition TStyle.cxx:1102
Float_t GetErrorX() const
Definition TStyle.h:188
Double_t GetHistTopMargin() const
Definition TStyle.h:240
void SetBarOffset(Float_t baroff=0.5)
Definition TStyle.h:339
Float_t GetEndErrorSize() const
Definition TStyle.h:187
Int_t GetDrawBorder() const
Definition TStyle.h:186
Width_t GetStatBorderSize() const
Definition TStyle.h:261
Color_t GetTitleTextColor() const
Definition TStyle.h:274
void SetBarWidth(Float_t barwidth=0.5)
Definition TStyle.h:340
Float_t GetTitleH() const
Definition TStyle.h:285
Style_t GetStatStyle() const
Definition TStyle.h:264
Float_t GetStatW() const
Definition TStyle.h:268
const char * GetFitFormat() const
Definition TStyle.h:201
const char * GetStatFormat() const
Definition TStyle.h:265
Int_t GetNumberOfColors() const
Return number of colors in the color palette.
Definition TStyle.cxx:1176
Int_t GetOptFit() const
Definition TStyle.h:246
Int_t GetNumberContours() const
Definition TStyle.h:243
const char * GetPaintTextFormat() const
Definition TStyle.h:252
Style_t GetStatFont() const
Definition TStyle.h:262
Float_t GetTitleFontSize() const
Definition TStyle.h:276
Int_t GetTitleAlign() const
Definition TStyle.h:272
Float_t GetTitleW() const
Definition TStyle.h:284
virtual int Load(const char *module, const char *entry="", Bool_t system=kFALSE)
Load a shared library.
Definition TSystem.cxx:1872
Base class for several text objects.
Definition TText.h:22
TVectorT.
Definition TVectorT.h:29
static TClass * Class()
See TView3D.
Definition TView.h:25
virtual Double_t GetPsi()=0
virtual Double_t * GetRmax()=0
virtual void SetAxisNDC(const Double_t *x1, const Double_t *x2, const Double_t *y1, const Double_t *y2, const Double_t *z1, const Double_t *z2)=0
virtual Double_t * GetRmin()=0
virtual void WCtoNDC(const Float_t *pw, Float_t *pn)=0
virtual void SetOutlineToCube()=0
virtual Int_t GetDistancetoAxis(Int_t axis, Int_t px, Int_t py, Double_t &ratio)=0
virtual Double_t * GetTnorm()=0
virtual void ExecuteRotateView(Int_t event, Int_t px, Int_t py)=0
virtual TSeqCollection * GetOutline()=0
virtual void PadRange(Int_t rback)=0
virtual void SetRange(const Double_t *min, const Double_t *max)=0
virtual void FindNormal(Double_t x, Double_t y, Double_t z, Double_t &zn)=0
virtual void AxisVertex(Double_t ang, Double_t *av, Int_t &ix1, Int_t &ix2, Int_t &iy1, Int_t &iy2, Int_t &iz1, Int_t &iz2)=0
virtual void SetView(Double_t longitude, Double_t latitude, Double_t psi, Int_t &irep)=0
Abstract base class used by ROOT graphics editor.
static TVirtualPadEditor * GetPadEditor(Bool_t load=kTRUE)
Returns the pad editor dialog. Static method.
small helper class to store/restore gPad context in TPad methods
Definition TVirtualPad.h:61
TVirtualPad is an abstract base class for the Pad and Canvas classes.
Definition TVirtualPad.h:51
TLine * line
void box(Int_t pat, Double_t x1, Double_t y1, Double_t x2, Double_t y2)
Definition fillpatterns.C:1
Double_t y[n]
Definition legend1.C:17
return c1
Definition legend1.C:41
Double_t x[n]
Definition legend1.C:17
Double_t ey[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
Double_t ex[n]
Definition legend1.C:17
TH1F * h1
Definition legend1.C:5
TF1 * f1
Definition legend1.C:11
return c2
Definition legend2.C:14
Int_t Nint(T x)
Round to nearest integer. Rounds half integers to the nearest even integer.
Definition TMath.h:706
Short_t Max(Short_t a, Short_t b)
Returns the largest of a and b.
Definition TMathBase.h:249
Double_t Prob(Double_t chi2, Int_t ndf)
Computation of the probability for a certain Chi-squared (chi2) and number of degrees of freedom (ndf...
Definition TMath.cxx:637
Double_t ATan(Double_t)
Returns the principal value of the arc tangent of x, expressed in radians.
Definition TMath.h:653
constexpr Double_t PiOver2()
Definition TMath.h:54
Double_t Log(Double_t x)
Returns the natural logarithm of x.
Definition TMath.h:769
constexpr Double_t DegToRad()
Conversion from degree to radian: .
Definition TMath.h:82
Double_t Sqrt(Double_t x)
Returns the square root of x.
Definition TMath.h:675
LongDouble_t Power(LongDouble_t x, LongDouble_t y)
Returns x raised to the power y.
Definition TMath.h:734
Short_t Min(Short_t a, Short_t b)
Returns the smallest of a and b.
Definition TMathBase.h:197
Double_t Cos(Double_t)
Returns the cosine of an angle of x radians.
Definition TMath.h:607
constexpr Double_t Pi()
Definition TMath.h:40
Bool_t AreEqualRel(Double_t af, Double_t bf, Double_t relPrec)
Comparing floating points.
Definition TMath.h:429
Double_t Sin(Double_t)
Returns the sine of an angle of x radians.
Definition TMath.h:601
Double_t Tan(Double_t)
Returns the tangent of an angle of x radians.
Definition TMath.h:613
Long64_t BinarySearch(Long64_t n, const T *array, T value)
Binary search in an array of n values to locate value.
Definition TMathBase.h:329
constexpr Double_t RadToDeg()
Conversion from radian to degree: .
Definition TMath.h:75
Double_t Log10(Double_t x)
Returns the common (base-10) logarithm of x.
Definition TMath.h:775
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:122
Histograms' drawing options structure.
Definition Hoption.h: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:60
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:49
int Text
"TEXT" Draw 2D plot with the content of each cell.
Definition Hoption.h:51
int Color
"COL" Draw 2D plot with Colored boxes.
Definition Hoption.h:43
int AxisPos
"X+" and "Y+" Axis position
Definition Hoption.h:61
int List
"LIST" Generate the TObjArray "contours". To be used with option "CONT"
Definition Hoption.h:59
int Logx
log scale in X. Also set by histogram option
Definition Hoption.h:71
int Zscale
"Z" Display the color palette.
Definition Hoption.h:56
int MinimumZero
"MIN0" or gStyle->GetHistMinimumZero()
Definition Hoption.h:64
int Contour
"CONTn" Draw 2D plot as a Contour plot (0 <= n <= 5).
Definition Hoption.h:45
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:46
long Candle
"CANDLE" and "VIOLIN" Draw a 2D histogram as candle/box plot or violin plot.
Definition Hoption.h:54
int Spec
"SPEC" TSpectrum graphics
Definition Hoption.h:62
int FrontBox
"FB" Suppress the front box for the 3D plots.
Definition Hoption.h:57
int Pie
"PIE" Draw 1D plot as a pie chart.
Definition Hoption.h:53
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:63
int Logz
log scale in Z. Also set by histogram option
Definition Hoption.h:73
int Tri
"TRI" Draw TGraph2D with Delaunay triangles.
Definition Hoption.h:52
int BackBox
"BB" Suppress the back box for the 3D plots.
Definition Hoption.h:58
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:48
int Bar
"B", "BAR" and "HBAR" A Bar chart is drawn at each point.
Definition Hoption.h:31
int Polar
"POL" Draw 2D plot with Polar coordinates.
Definition Hoption.h:44
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:47
int Surf
"SURF" and "SURFn" Draw as a Surface ((1 <= n <= 4).
Definition Hoption.h:50
int Logy
log scale in Y. Also set by histogram option
Definition Hoption.h:72
int System
"POL", "CYL", "SPH" and "PSR" Type of coordinate system for 3D plots.
Definition Hoption.h:55
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