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 "TVirtualPadPainter.h"
62#include "TVirtualPadEditor.h"
63#include "TVirtualX.h"
64#include "TEnv.h"
65#include "TPoint.h"
66#include "TImage.h"
67#include "TCandle.h"
68#include "strlcpy.h"
69
70/*! \class THistPainter
71 \ingroup Histpainter
72 \brief The histogram painter class. Implements all histograms' drawing's options.
73
74- [Introduction](\ref HP00)
75- [Histograms' plotting options](\ref HP01)
76 - [Options supported for 1D and 2D histograms](\ref HP01a)
77 - [Options supported for 1D histograms](\ref HP01b)
78 - [Options supported for 2D histograms](\ref HP01c)
79 - [Options supported for 3D histograms](\ref HP01d)
80 - [Options supported for histograms' stacks (THStack)](\ref HP01e)
81- [Setting the Style](\ref HP02)
82- [Setting line, fill, marker, and text attributes](\ref HP03)
83- [Setting Tick marks on the histogram axis](\ref HP04)
84- [Giving titles to the X, Y and Z axis](\ref HP05)
85- [The option SAME](\ref HP060)
86 - [Limitations](\ref HP060a)
87- [Colors automatically picked in palette](\ref HP061)
88- [Superimposing two histograms with different scales in the same pad](\ref HP06)
89- [Statistics Display](\ref HP07)
90- [Fit Statistics](\ref HP08)
91- [The error bars options](\ref HP09)
92- [The bar chart option](\ref HP100)
93- [The BAR and HBAR options](\ref HP10)
94- [The SCATter plot option (legacy draw option)](\ref HP11)
95- [The ARRow option](\ref HP12)
96- [The BOX option](\ref HP13)
97- [The COLor option (default for 2D and 3D histograms)](\ref HP14)
98- [The CANDLE and VIOLIN options](\ref HP140)
99 - [The CANDLE option](\ref HP140a)
100 - [The VIOLIN option](\ref HP140b)
101- [The TEXT and TEXTnn Option](\ref HP15)
102- [The CONTour options](\ref HP16)
103 - [The LIST option](\ref HP16a)
104 - [The AITOFF, MERCATOR, SINUSOIDAL and PARABOLIC options](\ref HP16b)
105- [The LEGO options](\ref HP17)
106- [The SURFace options](\ref HP18)
107- [Cylindrical, Polar, Spherical and PseudoRapidity/Phi options](\ref HP19)
108- [Base line for bar-charts and lego plots](\ref HP20)
109- [TH2Poly Drawing](\ref HP20a)
110- [The SPEC option](\ref HP21)
111- [Option Z : Adding the color palette on the right side of the pad](\ref HP22)
112- [Setting the color palette](\ref HP23)
113- [Drawing a sub-range of a 2-D histogram; the [cutg] option](\ref HP24)
114- [Drawing options for 3D histograms](\ref HP25)
115- [Drawing option for histograms' stacks](\ref HP26)
116- [Drawing of 3D implicit functions](\ref HP27)
117- [Associated functions drawing](\ref HP28)
118- [Drawing using OpenGL](\ref HP29)
119 - [General information: plot types and supported options](\ref HP29a)
120 - [TH3 as color boxes](\ref HP290)
121 - [TH3 as boxes (spheres)](\ref HP29b)
122 - [TH3 as iso-surface(s)](\ref HP29c)
123 - [TF3 (implicit function)](\ref HP29d)
124 - [Parametric surfaces](\ref HP29e)
125 - [Interaction with the plots](\ref HP29f)
126 - [Selectable parts](\ref HP29g)
127 - [Rotation and zooming](\ref HP29h)
128 - [Panning](\ref HP29i)
129 - [Box cut](\ref HP29j)
130 - [Plot specific interactions (dynamic slicing etc.)](\ref HP29k)
131 - [Surface with option GLSURF](\ref HP29l)
132 - [TF3](\ref HP29m)
133 - [Box](\ref HP29n)
134 - [Iso](\ref HP29o)
135 - [Parametric plot](\ref HP29p)
136- [Highlight mode for histogram](\ref HP30)
137 - [Highlight mode and user function](\ref HP30a)
138
139
140\anchor HP00
141## Introduction
142
143
144Histograms are drawn via the `THistPainter` class. Each histogram has a
145pointer to its own painter (to be usable in a multithreaded program). When the
146canvas has to be redrawn, the `Paint` function of each objects in the
147pad is called. In case of histograms, `TH1::Paint` invokes directly
148`THistPainter::Paint`.
149
150To draw a histogram `h` it is enough to do:
151
152 h->Draw();
153
154`h` can be of any kind: 1D, 2D or 3D. To choose how the histogram will
155be drawn, the `Draw()` method can be invoked with an option. For instance
156to draw a 2D histogram as a lego plot it is enough to do:
157
158 h->Draw("lego");
159
160`THistPainter` offers many options to paint 1D, 2D and 3D histograms.
161
162When the `Draw()` method of a histogram is called for the first time
163(`TH1::Draw`), it creates a `THistPainter` object and saves a
164pointer to this "painter" as a data member of the histogram. The
165`THistPainter` class specializes in the drawing of histograms. It is
166separated from the histogram so that one can have histograms without the
167graphics overhead, for example in a batch program. Each histogram having its own
168painter (rather than a central singleton painter painting all histograms), allows
169two histograms to be drawn in two threads without overwriting the painter's
170values.
171
172When a displayed histogram is filled again, there is no need to call the
173`Draw()` method again; the image will be refreshed the next time the
174pad will be updated.
175
176A pad is updated after one of these three actions:
177
1781. a carriage control on the ROOT command line,
1792. a click inside the pad,
1803. a call to `TPad::Update`.
181
182
183By default a call to `TH1::Draw()` clears the pad of all objects
184before drawing the new image of the histogram. One can use the `SAME`
185option to leave the previous display intact and superimpose the new histogram.
186The same histogram can be drawn with different graphics options in different
187pads.
188
189When a displayed histogram is deleted, its image is automatically removed
190from the pad.
191
192To create a copy of the histogram when drawing it, one can use
193`TH1::DrawClone()`. This will clone the histogram and allow to change
194and delete the original one without affecting the clone.
195
196
197\anchor HP01
198### Histograms' plotting options
199
200
201Most options can be concatenated with or without spaces or commas, for example:
202
203 h->Draw("E1 SAME");
204
205The options are not case sensitive:
206
207 h->Draw("e1 same");
208
209
210The default drawing option can be set with `TH1::SetOption` and retrieve
211using `TH1::GetOption`:
212
213 root [0] h->Draw(); // Draw "h" using the standard histogram representation.
214 root [1] h->Draw("E"); // Draw "h" using error bars
215 root [3] h->SetOption("E"); // Change the default drawing option for "h"
216 root [4] h->Draw(); // Draw "h" using error bars
217 root [5] h->GetOption(); // Retrieve the default drawing option for "h"
218 (const Option_t* 0xa3ff948)"E"
219
220
221\anchor HP01a
222#### Options supported for 1D and 2D histograms
223
224| Option | Description |
225|----------|-------------------------------------------------------------------|
226| "E" | Draw error bars. |
227| "AXIS" | Draw only axis. |
228| "AXIG" | Draw only grid (if the grid is requested). |
229| \anchor OPTHIST "HIST" | When an histogram has errors it is visualized by default with error bars. To visualize it without errors use the option "HIST" together with the required option (eg "hist same c"). The "HIST" option can also be used to plot only the histogram and not the associated function(s). |
230| "FUNC" | When an histogram has a fitted function, this option allows to draw the fit result only. |
231| "SAME" | Superimpose on previous picture in the same pad. |
232| "SAMES" | Same as "SAME" and draw the statistics box|
233| "PFC" | Palette Fill Color: histogram's fill color is taken in the current palette. |
234| "PLC" | Palette Line Color: histogram's line color is taken in the current palette. |
235| "PMC" | Palette Marker Color: histogram's marker color is taken in the current palette. |
236| "LEGO" | Draw a lego plot with hidden line removal. |
237| "LEGO1" | Draw a lego plot with hidden surface removal. |
238| "LEGO2" | Draw a lego plot using colors to show the cell contents When the option "0" is used with any LEGO option, the empty bins are not drawn.|
239| "LEGO3" | Draw a lego plot with hidden surface removal, like LEGO1 but the border lines of each lego-bar are not drawn.|
240| "LEGO4" | Draw a lego plot with hidden surface removal, like LEGO1 but without the shadow effect on each lego-bar.|
241| "TEXT" | Draw bin contents as text (format set via `gStyle->SetPaintTextFormat`).|
242| "TEXTnn" | Draw bin contents as text at angle nn (0 < nn <= 90). |
243| "X+" | The X-axis is drawn on the top side of the plot. |
244| "Y+" | The Y-axis is drawn on the right side of the plot. |
245| "MIN0" | Set minimum value for the Y axis to 0, equivalent to gStyle->SetHistMinimumZero(). |
246
247
248\anchor HP01b
249#### Options supported for 1D histograms
250
251| Option | Description |
252|----------|-------------------------------------------------------------------|
253| " " | Default. |
254| "AH" | Draw histogram without axis. "A" can be combined with any drawing option. For instance, "AC" draws the histogram as a smooth Curve without axis.|
255| "][" | When this option is selected the first and last vertical lines of the histogram are not drawn.|
256| "B" | Bar chart option.|
257| "BAR" | Like option "B", but bars can be drawn with a 3D effect.|
258| "HBAR" | Like option "BAR", but bars are drawn horizontally.|
259| "C" | Draw a smooth Curve through the histogram bins.|
260| "E0" | Draw error bars. Markers are drawn for bins with 0 contents. Combined with E1 or E2 it avoids error bars clipping|
261| "E1" | Draw error bars with perpendicular lines at the edges.|
262| "E2" | Draw error bars with rectangles.|
263| "E3" | Draw a fill area through the end points of the vertical error bars.|
264| "E4" | Draw a smoothed filled area through the end points of the error bars.|
265| "E5" | Like E3 but ignore the bins with 0 contents.|
266| "E6" | Like E4 but ignore the bins with 0 contents.|
267| "X0" | When used with one of the "E" option, it suppress the error bar along X as `gStyle->SetErrorX(0)` would do.|
268| "L" | Draw a line through the bin contents.|
269| "P" | Draw current marker at each bin except empty bins.|
270| "P*" | Draw a star marker at each bin except empty bins.|
271| "P0" | Draw current marker at each bin including empty bins.|
272| "PIE" | Draw histogram as a Pie Chart.|
273| "*H" | Draw histogram with a * at each bin.|
274| "LF2" | Draw histogram like with option "L" but with a fill area. Note that "L" draws also a fill area if the hist fill color is set but the fill area corresponds to the histogram contour.|
275
276
277
278\anchor HP01c
279#### Options supported for 2D histograms
280
281| Option | Description |
282|--------------|------------------------------------------------------------------|
283| " " | Default (color plot).|
284| "ARR" | Arrow mode. Shows gradient between adjacent cells.|
285| "BOX" | A box is drawn for each cell with surface proportional to the content's absolute value. A negative content is marked with a X. |
286| "BOX1" | A button is drawn for each cell with surface proportional to content's absolute value. A sunken button is drawn for negative values a raised one for positive.|
287| "COL" | A box is drawn for each cell with a color scale varying with contents. All the none empty bins (bins with content and error equal to 0) are painted. Empty bins are not painted unless some bins have a negative content because in that case the null bins might be not empty. `TProfile2D` histograms are handled differently because, for this type of 2D histograms, it is possible to know if an empty bin has been filled or not. So even if all the bins' contents are positive some empty bins might be painted. And vice versa, if some bins have a negative content some empty bins might be not painted (default).|
288| "COL1" | Same as "COL" but in case of histogram with negative content the empty bins are not drawn.
289| "COLZ" | Same as "COL". In addition the color palette is also drawn.|
290| "COL2" | Alternative rendering algorithm to "COL". Can significantly improve rendering performance for large, non-sparse 2-D histograms.|
291| "COLZ2" | Same as "COL2". In addition the color palette is also drawn.|
292| "Z CJUST" | In combination with colored options "COL","CONT0" etc: Justify labels in the color palette at color boundaries. For more details see `TPaletteAxis`|
293| "CANDLE" | Draw a candle plot along X axis.|
294| "CANDLEX" | Same as "CANDLE".|
295| "CANDLEY" | Draw a candle plot along Y axis.|
296| "CANDLEXn" | Draw a candle plot along X axis. Different candle-styles with n from 1 to 6.|
297| "CANDLEYn" | Draw a candle plot along Y axis. Different candle-styles with n from 1 to 6.|
298| "VIOLIN" | Draw a violin plot along X axis.|
299| "VIOLINX" | Same as "VIOLIN".|
300| "VIOLINY" | Draw a violin plot along Y axis.|
301| "VIOLINXn" | Draw a violin plot along X axis. Different violin-styles with n being 1 or 2.|
302| "VIOLINYn" | Draw a violin plot along Y axis. Different violin-styles with n being 1 or 2.|
303| "CONT" | Draw a contour plot (same as CONT0).|
304| "CONT0" | Draw a contour plot using surface colors to distinguish contours.|
305| "CONT1" | Draw a contour plot using line styles to distinguish contours.|
306| "CONT2" | Draw a contour plot using the same line style for all contours.|
307| "CONT3" | Draw a contour plot using fill area colors.|
308| "CONT4" | Draw a contour plot using surface colors (SURF option at theta = 0).|
309| "LIST" | Generate a list of TGraph objects for each contour.|
310| "SAME0" | Same as "SAME" but do not use the z-axis range of the first plot. |
311| "SAMES0" | Same as "SAMES" but do not use the z-axis range of the first plot. |
312| "CYL" | Use Cylindrical coordinates. The X coordinate is mapped on the angle and the Y coordinate on the cylinder length.|
313| "POL" | Use Polar coordinates. The visible X range mapped on the angle and the visible Y coordinate on the radius.|
314| "POLF" | Fixed Polar coordinates. The histogram X coordinate mapped on the angle and the Y coordinate on the radius.|
315| "POLN" | Natural Polar coordinates. The X coordinate directly represent angle in radian and the Y coordinate is the radius.|
316| "SPH" | Use Spherical coordinates. The X coordinate is mapped on the latitude and the Y coordinate on the longitude.|
317| "PSR" | Use PseudoRapidity/Phi coordinates. The X coordinate is mapped on Phi.|
318| "SURF" | Draw a surface plot with hidden line removal.|
319| "SURF1" | Draw a surface plot with hidden surface removal.|
320| "SURF2" | Draw a surface plot using colors to show the cell contents.|
321| "SURF3" | Same as SURF with in addition a contour view drawn on the top.|
322| "SURF4" | Draw a surface using Gouraud shading.|
323| "SURF5" | Same as SURF3 but only the colored contour is drawn. Used with option CYL, SPH or PSR it allows to draw colored contours on a sphere, a cylinder or a in pseudo rapidity space. In cartesian or polar coordinates, option SURF3 is used.|
324| "AITOFF" | Draw a contour via an AITOFF projection.|
325| "MERCATOR" | Draw a contour via an Mercator projection.|
326| "SINUSOIDAL" | Draw a contour via an Sinusoidal projection.|
327| "PARABOLIC" | Draw a contour via an Parabolic projection.|
328| "MOLLWEIDE" | Draw a contour via an Mollweide projection.|
329| "LEGO9" | Draw the 3D axis only. Mainly needed for internal use |
330| "FB" | With LEGO or SURFACE, suppress the Front-Box.|
331| "BB" | With LEGO or SURFACE, suppress the Back-Box.|
332| "A" | With LEGO or SURFACE, suppress the axis.|
333| "SCAT" | Draw a scatter-plot (legacy draw option).|
334| "[cutg]" | Draw only the sub-range selected by the TCutG named "cutg".|
335
336
337
338\anchor HP01d
339#### Options supported for 3D histograms
340
341| Option | Description |
342|----------|-------------------------------------------------------------------|
343| " " | Default (color plot).|
344| "ISO" | Draw a Gouraud shaded 3d iso surface through a 3d histogram. It paints one surface at the value computed as follow: `SumOfWeights/(NbinsX*NbinsY*NbinsZ)`.|
345| "BOX" | Draw a for each cell with volume proportional to the content's absolute value. An hidden line removal algorithm is used|
346| "BOX1" | Same as BOX but an hidden surface removal algorithm is used|
347| "BOX2" | The boxes' colors are picked in the current palette according to the bins' contents|
348| "BOX2Z" | Same as "BOX2". In addition the color palette is also drawn.|
349| "BOX3" | Same as BOX1, but the border lines of each lego-bar are not drawn.|
350| "LEGO" | Same as `BOX`.|
351
352\anchor HP01e
353#### Options supported for histograms' stacks (`THStack`)
354
355| Option | Description |
356|------------|-----------------------------------------------------------------|
357| " " | Default, the histograms are drawn on top of each other (as lego plots for 2D histograms).|
358| "NOSTACK" | Histograms in the stack are all paint in the same pad as if the option `SAME` had been specified.|
359| "NOSTACKB" | Histograms are drawn next to each other as bar charts.|
360| "PADS" | The current pad/canvas is subdivided into a number of pads equal to the number of histograms in the stack and each histogram is paint into a separate pad.|
361| "PADSn" | Like PADS but the current pad/canvas is subdivided into a `n` columns, automatically calculating the number of rows.|
362| "PFC" | Palette Fill Color: stack's fill color is taken in the current palette. |
363| "PLC" | Palette Line Color: stack's line color is taken in the current palette. |
364| "PMC" | Palette Marker Color: stack's marker color is taken in the current palette. |
365
366
367
368\anchor HP02
369### Setting the Style
370
371
372Histograms use the current style (`gStyle`). When one changes the current
373style and would like to propagate the changes to the histogram,
374`TH1::UseCurrentStyle` should be called. Call `UseCurrentStyle` on
375each histogram is needed.
376
377To force all the histogram to use the current style use:
378
379 gROOT->ForceStyle();
380
381All the histograms read after this call will use the current style.
382
383
384\anchor HP03
385### Setting line, fill, marker, and text attributes
386
387
388The histogram classes inherit from the attribute classes:
389`TAttLine`, `TAttFill` and `TAttMarker`.
390See the description of these classes for the list of options.
391
392
393\anchor HP04
394### Setting Tick marks on the histogram axis
395
396
397The `TPad::SetTicks` method specifies the type of tick marks on the axis.
398If ` tx = gPad->GetTickx()` and `ty = gPad->GetTicky()` then:
399
400 tx = 1; tick marks on top side are drawn (inside)
401 tx = 2; tick marks and labels on top side are drawn
402 ty = 1; tick marks on right side are drawn (inside)
403 ty = 2; tick marks and labels on right side are drawn
404
405By default only the left Y axis and X bottom axis are drawn
406(`tx = ty = 0`)
407
408`TPad::SetTicks(tx,ty)` allows to set these options.
409See also The `TAxis` functions to set specific axis attributes.
410
411In case multiple color filled histograms are drawn on the same pad, the fill
412area may hide the axis tick marks. One can force a redraw of the axis over all
413the histograms by calling:
414
415 gPad->RedrawAxis();
416
417
418\anchor HP05
419### Giving titles to the X, Y and Z axis
420
421
422 h->GetXaxis()->SetTitle("X axis title");
423 h->GetYaxis()->SetTitle("Y axis title");
424
425The histogram title and the axis titles can be any `TLatex` string.
426The titles are part of the persistent histogram.
427
428
429\anchor HP060
430### The option "SAME"
431
432
433By default, when an histogram is drawn, the current pad is cleared before
434drawing. In order to keep the previous drawing and draw on top of it the
435option `SAME` should be use. The histogram drawn with the option
436`SAME` uses the coordinates system available in the current pad.
437
438This option can be used alone or combined with any valid drawing option but
439some combinations must be use with care.
440
441\anchor HP060a
442#### Limitations
443
444- It does not work when combined with the `LEGO` and `SURF` options unless the
445 histogram plotted with the option `SAME` has exactly the same
446 ranges on the X, Y and Z axis as the currently drawn histogram. To superimpose
447 lego plots [histograms' stacks](\ref HP26) should be used.
448
449
450\anchor HP061
451### Colors automatically picked in palette
452
453\since **ROOT version 6.09/01**
454
455When several histograms are painted in the same canvas thanks to the option "SAME"
456or via a `THStack` it might be useful to have an easy and automatic way to choose
457their color. The simplest way is to pick colors in the current active color
458palette. Palette coloring for histogram is activated thanks to the options `PFC`
459(Palette Fill Color), `PLC` (Palette Line Color) and `PMC` (Palette Marker Color).
460When one of these options is given to `TH1::Draw` the histogram get its color
461from the current color palette defined by `gStyle->SetPalette(...)`. The color
462is determined according to the number of objects having palette coloring in
463the current pad.
464
465Begin_Macro(source)
466../../../tutorials/hist/hist005_TH1_palettecolor.C
467End_Macro
468
469Begin_Macro(source)
470../../../tutorials/hist/hist027_THStack_palette_color.C
471End_Macro
472
473Begin_Macro(source)
474../../../tutorials/hist/hist025_THStack_2d_palette_color.C
475End_Macro
476
477\anchor HP06
478### Superimposing two histograms with different scales in the same pad
479
480
481The following example creates two histograms, the second histogram is the bins
482integral of the first one. It shows a procedure to draw the two histograms in
483the same pad and it draws the scale of the second histogram using a new vertical
484axis on the right side. See also the tutorial `transpad.C` for a variant
485of this example.
486
487Begin_Macro(source)
488{
489 auto c1 = new TCanvas("c1","c1",600,400);
490 // create/fill draw h1
491 gStyle->SetOptStat(kFALSE);
492 auto h1 = new TH1F("h1","Superimposing two histograms with different scales",100,-3,3);
493 Int_t i;
494 for (i=0;i<10000;i++) h1->Fill(gRandom->Gaus(0,1));
495 h1->Draw();
496 c1->Update();
497
498 // create hint1 filled with the bins integral of h1
499 auto hint1 = new TH1F("hint1","h1 bins integral",100,-3,3);
500 float sum = 0.f;
501 for (i=1;i<=100;i++) {
502 sum += h1->GetBinContent(i);
503 hint1->SetBinContent(i,sum);
504 }
505
506 // scale hint1 to the pad coordinates
507 float rightmax = 1.1*hint1->GetMaximum();
508 float scale = gPad->GetUymax()/rightmax;
509 hint1->SetLineColor(kRed);
510 hint1->Scale(scale);
511 hint1->Draw("same");
512
513 // draw an axis on the right side
514 auto axis = new TGaxis(gPad->GetUxmax(),gPad->GetUymin(),
515 gPad->GetUxmax(), gPad->GetUymax(),0,rightmax,510,"+L");
516 axis->SetLineColor(kRed);
517 axis->SetTextColor(kRed);
518 axis->Draw();
519}
520End_Macro
521
522
523\anchor HP07
524### Statistics Display
525
526
527The type of information shown in the histogram statistics box can be selected
528with:
529
530 gStyle->SetOptStat(mode);
531
532The `mode` has up to nine digits that can be set to on (1 or 2), off (0).
533
534 mode = ksiourmen (default = 000001111)
535 k = 1; kurtosis printed
536 k = 2; kurtosis and kurtosis error printed
537 s = 1; skewness printed
538 s = 2; skewness and skewness error printed
539 i = 1; integral of bins printed
540 i = 2; integral of bins with option "width" printed
541 o = 1; number of overflows printed
542 u = 1; number of underflows printed
543 r = 1; standard deviation printed
544 r = 2; standard deviation and standard deviation error printed
545 m = 1; mean value printed
546 m = 2; mean and mean error values printed
547 e = 1; number of entries printed
548 n = 1; name of histogram is printed
549
550For example:
551
552 gStyle->SetOptStat(11);
553
554displays only the name of histogram and the number of entries, whereas:
555
556 gStyle->SetOptStat(1101);
557
558displays the name of histogram, mean value and standard deviation.
559
560<b>WARNING 1:</b> never do:
561
562 gStyle->SetOptStat(0001111);
563
564but instead do:
565
566 gStyle->SetOptStat(1111);
567
568because `0001111` will be taken as an octal number!
569
570<b>WARNING 2:</b> for backward compatibility with older versions
571
572 gStyle->SetOptStat(1);
573
574is taken as:
575
576 gStyle->SetOptStat(1111)
577
578To print only the name of the histogram do:
579
580 gStyle->SetOptStat(1000000001);
581
582<b>NOTE</b> that in case of 2D histograms, when selecting only underflow
583(10000) or overflow (100000), the statistics box will show all combinations
584of underflow/overflows and not just one single number.
585
586The parameter mode can be any combination of the letters `kKsSiIourRmMen`
587
588 k : kurtosis printed
589 K : kurtosis and kurtosis error printed
590 s : skewness printed
591 S : skewness and skewness error printed
592 i : integral of bins printed
593 I : integral of bins with option "width" printed
594 o : number of overflows printed
595 u : number of underflows printed
596 r : standard deviation printed
597 R : standard deviation and standard deviation error printed
598 m : mean value printed
599 M : mean value mean error values printed
600 e : number of entries printed
601 n : name of histogram is printed
602
603For example, to print only name of histogram and number of entries do:
604
605 gStyle->SetOptStat("ne");
606
607To print only the name of the histogram do:
608
609 gStyle->SetOptStat("n");
610
611The default value is:
612
613 gStyle->SetOptStat("nemr");
614
615When a histogram is painted, a `TPaveStats` object is created and added
616to the list of functions of the histogram. If a `TPaveStats` object
617already exists in the histogram list of functions, the existing object is just
618updated with the current histogram parameters.
619
620Once a histogram is painted, the statistics box can be accessed using
621`h->FindObject("stats")`. In the command line it is enough to do:
622
623 Root > h->Draw()
624 Root > TPaveStats *st = (TPaveStats*)h->FindObject("stats")
625
626because after `h->Draw()` the histogram is automatically painted. But
627in a script file the painting should be forced using `gPad->Update()`
628in order to make sure the statistics box is created:
629
630 h->Draw();
631 gPad->Update();
632 TPaveStats *st = (TPaveStats*)h->FindObject("stats");
633
634Without `gPad->Update()` the line `h->FindObject("stats")` returns a null pointer.
635
636When a histogram is drawn with the option `SAME`, the statistics box
637is not drawn. To force the statistics box drawing with the option
638`SAME`, the option `SAMES` must be used.
639If the new statistics box hides the previous statistics box, one can change
640its position with these lines (`h` being the pointer to the histogram):
641
642 Root > TPaveStats *st = (TPaveStats*)h->FindObject("stats")
643 Root > st->SetX1NDC(newx1); //new x start position
644 Root > st->SetX2NDC(newx2); //new x end position
645
646To change the type of information for an histogram with an existing
647`TPaveStats` one should do:
648
649 st->SetOptStat(mode);
650
651Where `mode` has the same meaning than when calling `gStyle->SetOptStat(mode)`
652(see above).
653
654One can delete the statistics box for a histogram `TH1* h` with:
655
656 h->SetStats(0)
657
658and activate it again with:
659
660 h->SetStats(1).
661
662Labels used in the statistics box ("Mean", "Std Dev", ...) can be changed from
663`$ROOTSYS/etc/system.rootrc` or `.rootrc` (look for the string `Hist.Stats.`).
664
665
666\anchor HP08
667### Fit Statistics
668
669
670The type of information about fit parameters printed in the histogram statistics
671box can be selected via the parameter mode. The parameter mode can be
672`= pcev` (default `= 0111`)
673
674 p = 1; print Probability
675 c = 1; print Chisquare/Number of degrees of freedom
676 e = 1; print errors (if e=1, v must be 1)
677 v = 1; print name/values of parameters
678
679Example:
680
681 gStyle->SetOptFit(1011);
682
683print fit probability, parameter names/values and errors.
684
6851. When `v = 1` is specified, only the non-fixed parameters are shown.
6862. When `v = 2` all parameters are shown.
687
688Note: `gStyle->SetOptFit(1)` means "default value", so it is equivalent
689to `gStyle->SetOptFit(111)`
690
691
692\anchor HP09
693### The error bars options
694
695
696| Option | Description |
697|----------|-------------------------------------------------------------------|
698| "E" | Default. Shows only the error bars, not a marker.|
699| "E1" | Small lines are drawn at the end of the error bars.|
700| "E2" | Error rectangles are drawn.|
701| "E3" | A filled area is drawn through the end points of the vertical error bars.|
702| "E4" | A smoothed filled area is drawn through the end points of the vertical error bars.|
703| "E0" | Draw error bars. Markers are drawn for bins with 0 contents. Combined with E1 or E2 it avoids error bars clipping|
704| "E5" | Like E3 but ignore the bins with 0 contents.|
705| "E6" | Like E4 but ignore the bins with 0 contents.|
706| "X0" | When used with one of the "E" option, it suppress the error bar along X as `gStyle->SetErrorX(0)` would do.|
707
708Begin_Macro(source)
709{
710 auto c1 = new TCanvas("c1","c1",600,400);
711 auto he = new TH1F("he","Distribution drawn with error bars (option E1) ",100,-3,3);
712 for (int i=0; i<10000; i++) he->Fill(gRandom->Gaus(0,1));
713 gStyle->SetEndErrorSize(3);
714 gStyle->SetErrorX(1.);
715 he->SetMarkerStyle(20);
716 he->Draw("E1");
717}
718End_Macro
719
720The options "E3" and "E4" draw an error band through the end points of the
721vertical error bars. With "E4" the error band is smoothed. Because of the
722smoothing algorithm used some artefacts may appear at the end of the band
723like in the following example. In such cases "E3" should be used instead
724of "E4".
725
726Begin_Macro(source)
727{
728 auto ce4 = new TCanvas("ce4","ce4",600,400);
729 ce4->Divide(2,1);
730 auto he4 = new TH1F("he4","Distribution drawn with option E4",100,-3,3);
731 Int_t i;
732 for (i=0;i<10000;i++) he4->Fill(gRandom->Gaus(0,1));
733 he4->SetFillColor(kRed);
734 he4->GetXaxis()->SetRange(40,48);
735 ce4->cd(1);
736 he4->Draw("E4");
737 ce4->cd(2);
738 auto he3 = (TH1F*)he4->DrawClone("E3");
739 he3->SetTitle("Distribution drawn option E3");
740}
741End_Macro
742
7432D histograms can be drawn with error bars as shown is the following example:
744
745Begin_Macro(source)
746{
747 auto c2e = new TCanvas("c2e","c2e",600,400);
748 auto h2e = new TH2F("h2e","TH2 drawn with option E",40,-4,4,40,-20,20);
749 float px, py;
750 for (Int_t i = 0; i < 25000; i++) {
751 gRandom->Rannor(px,py);
752 h2e->Fill(px,5*py);
753 }
754 h2e->Draw("E");
755}
756End_Macro
757
758
759\anchor HP100
760### The bar chart option
761
762
763The option "B" allows to draw simple vertical bar charts.
764The bar width is controlled with `TH1::SetBarWidth()`,
765and the bar offset within the bin, with `TH1::SetBarOffset()`.
766These two settings are useful to draw several histograms on the
767same plot as shown in the following example:
768
769Begin_Macro(source)
770{
771 int i;
772 const Int_t nx = 8;
773 string os_X[nx] = {"8","32","128","512","2048","8192","32768","131072"};
774 float d_35_0[nx] = {0.75, -3.30, -0.92, 0.10, 0.08, -1.69, -1.29, -2.37};
775 float d_35_1[nx] = {1.01, -3.02, -0.65, 0.37, 0.34, -1.42, -1.02, -2.10};
776
777 auto cb = new TCanvas("cb","cb",600,400);
778 cb->SetGrid();
779
780 gStyle->SetHistMinimumZero();
781
782 auto h1b = new TH1F("h1b","Option B example",nx,0,nx);
783 h1b->SetFillColor(4);
784 h1b->SetBarWidth(0.4);
785 h1b->SetBarOffset(0.1);
786 h1b->SetStats(0);
787 h1b->SetMinimum(-5);
788 h1b->SetMaximum(5);
789
790 for (i=1; i<=nx; i++) {
791 h1b->SetBinContent(i, d_35_0[i-1]);
792 h1b->GetXaxis()->SetBinLabel(i,os_X[i-1].c_str());
793 }
794
795 h1b->Draw("b");
796
797 auto h2b = new TH1F("h2b","h2b",nx,0,nx);
798 h2b->SetFillColor(38);
799 h2b->SetBarWidth(0.4);
800 h2b->SetBarOffset(0.5);
801 h2b->SetStats(0);
802 for (i=1;i<=nx;i++) h2b->SetBinContent(i, d_35_1[i-1]);
803
804 h2b->Draw("b same");
805}
806End_Macro
807
808
809\anchor HP10
810### The "BAR" and "HBAR" options
811
812
813When the option `bar` or `hbar` is specified, a bar chart is drawn. A vertical
814bar-chart is drawn with the options `bar`, `bar0`, `bar1`, `bar2`, `bar3`, `bar4`.
815An horizontal bar-chart is drawn with the options `hbar`, `hbar0`, `hbar1`,
816`hbar2`, `hbar3`, `hbar4` (hist006_TH1_bar_charts.C).
817
818- The bar is filled with the histogram fill color.
819- The left side of the bar is drawn with a light fill color.
820- The right side of the bar is drawn with a dark fill color.
821- The percentage of the bar drawn with either the light or dark color is:
822 - 0% for option "(h)bar" or "(h)bar0"
823 - 10% for option "(h)bar1"
824 - 20% for option "(h)bar2"
825 - 30% for option "(h)bar3"
826 - 40% for option "(h)bar4"
827
828When an histogram has errors the option ["HIST"](\ref OPTHIST) together with the `(h)bar` option.
829
830Begin_Macro(source)
831../../../tutorials/hist/hist006_TH1_bar_charts.C
832End_Macro
833
834To control the bar width (default is the bin width) `TH1::SetBarWidth()`
835should be used.
836
837To control the bar offset (default is 0) `TH1::SetBarOffset()` should
838be used.
839
840These two parameters are useful when several histograms are plotted using
841the option `SAME`. They allow to plot the histograms next to each other.
842
843
844\anchor HP11
845### The SCATter plot option (legacy draw option)
846
847\attention
848Use of option `SCAT` has been deprecated. It was the default drawing option for 2D and
8493D histograms. The new default option is `COL` (heat-map).
850
851
852For each cell (i,j) a number of points proportional to the cell content is
853drawn. A maximum of `kNMAX` points per cell is drawn. If the maximum is above
854`kNMAX` contents are normalized to `kNMAX` (`kNMAX=2000`).
855If option is of the form `scat=ff`, (eg `scat=1.8`,
856`scat=1e-3`), then `ff` is used as a scale factor to compute the
857number of dots. `scat=1` is the default.
858
859By default the scatter plot is painted with a "dot marker" which not scalable
860(see the `TAttMarker` documentation). To change the marker size, a scalable marker
861type should be used. For instance a circle (marker style 20).
862
863Begin_Macro(source)
864{
865 auto c1 = new TCanvas("c1","c1",600,400);
866 auto hscat = new TH2F("hscat","Option SCATter example (default for 2D histograms) ",40,-4,4,40,-20,20);
867 float px, py;
868 for (Int_t i = 0; i < 25000; i++) {
869 gRandom->Rannor(px,py);
870 hscat->Fill(px,5*py);
871 hscat->Fill(3+0.5*px,2*py-10.);
872 }
873 hscat->Draw("scat=0.5"); // This a legacy draw option. Please consider using TScatter
874}
875End_Macro
876
877
878\anchor HP12
879### The ARRow option
880
881
882Shows gradient between adjacent cells. For each cell (i,j) an arrow is drawn
883The orientation of the arrow follows the cell gradient.
884
885Begin_Macro(source)
886{
887 auto c1 = new TCanvas("c1","c1",600,400);
888 auto harr = new TH2F("harr","Option ARRow example",20,-4,4,20,-20,20);
889 harr->SetLineColor(kRed);
890 float px, py;
891 for (Int_t i = 0; i < 25000; i++) {
892 gRandom->Rannor(px,py);
893 harr->Fill(px,5*py);
894 harr->Fill(3+0.5*px,2*py-10.,0.1);
895 }
896 harr->Draw("ARR");
897}
898End_Macro
899
900\since **ROOT version 6.17/01**
901
902The option `ARR` can be combined with the option `COL` or `COLZ`.
903
904Begin_Macro(source)
905{
906 auto c1 = new TCanvas("c1","c1",600,400);
907 auto harr = new TH2F("harr","Option ARR + COLZ example",20,-4,4,20,-20,20);
908 harr->SetStats(0);
909 float px, py;
910 for (Int_t i = 0; i < 25000; i++) {
911 gRandom->Rannor(px,py);
912 harr->Fill(px,5*py);
913 harr->Fill(3+0.5*px,2*py-10.,0.1);
914 }
915 harr->Draw("ARR COLZ");
916}
917End_Macro
918
919
920\anchor HP13
921### The BOX option
922
923
924For each cell (i,j) a box is drawn. The size (surface) of the box is
925proportional to the absolute value of the cell content.
926The cells with a negative content are drawn with a `X` on top of the box.
927
928Begin_Macro(source)
929{
930 auto c1 = new TCanvas("c1","c1",600,400);
931 auto hbox = new TH2F("hbox","Option BOX example",3,0,3,3,0,3);
932 hbox->SetFillColor(42);
933 hbox->Fill(0.5, 0.5, 1.);
934 hbox->Fill(0.5, 1.5, 4.);
935 hbox->Fill(0.5, 2.5, 3.);
936 hbox->Fill(1.5, 0.5, 2.);
937 hbox->Fill(1.5, 1.5, 12.);
938 hbox->Fill(1.5, 2.5, -6.);
939 hbox->Fill(2.5, 0.5, -4.);
940 hbox->Fill(2.5, 1.5, 6.);
941 hbox->Fill(2.5, 2.5, 0.5);
942 hbox->Draw("BOX");
943}
944End_Macro
945
946With option `BOX1` a button is drawn for each cell with surface
947proportional to content's absolute value. A sunken button is drawn for
948negative values a raised one for positive.
949
950Begin_Macro(source)
951{
952 auto c1 = new TCanvas("c1","c1",600,400);
953 auto hbox1 = new TH2F("hbox1","Option BOX1 example",3,0,3,3,0,3);
954 hbox1->SetFillColor(42);
955 hbox1->Fill(0.5, 0.5, 1.);
956 hbox1->Fill(0.5, 1.5, 4.);
957 hbox1->Fill(0.5, 2.5, 3.);
958 hbox1->Fill(1.5, 0.5, 2.);
959 hbox1->Fill(1.5, 1.5, 12.);
960 hbox1->Fill(1.5, 2.5, -6.);
961 hbox1->Fill(2.5, 0.5, -4.);
962 hbox1->Fill(2.5, 1.5, 6.);
963 hbox1->Fill(2.5, 2.5, 0.5);
964 hbox1->Draw("BOX1");
965}
966End_Macro
967
968When the option `SAME` (or "SAMES") is used with the option `BOX`,
969the boxes' sizes are computed taking the previous plots into account. The range
970along the Z axis is imposed by the first plot (the one without option
971`SAME`); therefore the order in which the plots are done is relevant.
972
973Begin_Macro(source)
974{
975 auto c1 = new TCanvas("c1","c1",600,400);
976 auto hb1 = new TH2F("hb1","Example of BOX plots with option SAME ",40,-3,3,40,-3,3);
977 auto hb2 = new TH2F("hb2","hb2",40,-3,3,40,-3,3);
978 auto hb3 = new TH2F("hb3","hb3",40,-3,3,40,-3,3);
979 auto hb4 = new TH2F("hb4","hb4",40,-3,3,40,-3,3);
980 for (Int_t i=0;i<1000;i++) {
981 double x,y;
982 gRandom->Rannor(x,y);
983 if (x>0 && y>0) hb1->Fill(x,y,4);
984 if (x<0 && y<0) hb2->Fill(x,y,3);
985 if (x>0 && y<0) hb3->Fill(x,y,2);
986 if (x<0 && y>0) hb4->Fill(x,y,1);
987 }
988 hb1->SetFillColor(1);
989 hb2->SetFillColor(2);
990 hb3->SetFillColor(3);
991 hb4->SetFillColor(4);
992 hb1->Draw("box");
993 hb2->Draw("box same");
994 hb3->Draw("box same");
995 hb4->Draw("box same");
996}
997End_Macro
998
999\since **ROOT version 6.17/01:**
1000
1001Sometimes the change of the range of the Z axis is unwanted, in which case, one
1002can use `SAME0` (or `SAMES0`) option to opt out of this change.
1003
1004Begin_Macro(source)
1005{
1006 auto h2 = new TH2F("h2"," ",10,0,10,10,20,30);
1007 auto hf = (TH2F*)h2->Clone("hf");
1008 h2->SetBit(TH1::kNoStats);
1009 hf->SetBit(TH1::kNoStats);
1010 h2->Fill(5,22);
1011 h2->Fill(5,23);
1012 h2->Fill(6,22);
1013 h2->Fill(6,23);
1014 hf->Fill(6,23);
1015 hf->Fill(6,23);
1016 hf->Fill(6,23);
1017 hf->Fill(6,23);
1018 hf->Fill(5,23);
1019
1020 auto hf_copy1 = hf->Clone("hf_copy1");
1021 TLatex lt;
1022
1023 auto cx = new TCanvas(); cx->Divide(2,1);
1024
1025 cx->cd(1);
1026 h2->Draw("box");
1027 hf->Draw("text colz same");
1028 lt.DrawLatexNDC(0.3,0.5,"SAME");
1029
1030 cx->cd(2);
1031 h2->Draw("box");
1032 hf_copy1->Draw("text colz same0");
1033 lt.DrawLatexNDC(0.3,0.5,"SAME0");
1034}
1035End_Macro
1036
1037
1038\anchor HP14
1039### The COLor option (default for 2D histograms)
1040
1041The magnitude of individual cell (i,j) is represented as a color picked in the current color palette.
1042This data visualization technique is often called a heat map (or heat-map).
1043
1044The color table used is defined in the current style.
1045
1046If the histogram's minimum and maximum are the same (flat histogram), the
1047mapping on colors is not possible, therefore nothing is painted. To paint a
1048flat histogram it is enough to set the histogram minimum
1049(`TH1::SetMinimum()`) different from the bins' content.
1050
1051The default number of color levels used to paint the cells is 20.
1052It can be changed with `TH1::SetContour()` or
1053`TStyle::SetNumberContours()`. The higher this number is, the smoother
1054is the color change between cells.
1055
1056The color palette in TStyle can be modified via `gStyle->SetPalette()`.
1057
1058All the non-empty bins are painted. Empty bins (bins with content and error equal to 0) are
1059not painted unless some bins have a negative content because in that case the null bins
1060might be not empty.
1061
1062`TProfile2D` histograms are handled differently because, for this type of 2D
1063histograms, it is possible to know if an empty bin has been filled or not. So even
1064if all the bins' contents are positive some empty bins might be painted. And vice versa,
1065if some bins have a negative content some empty bins might be not painted.
1066
1067Combined with the option `COL`, the option `Z` allows to
1068display the color palette defined by `gStyle->SetPalette()`.
1069
1070In the following example, the histogram has only positive bins; the empty
1071bins (containing 0) are not drawn.
1072
1073Begin_Macro(source)
1074{
1075 auto c1 = new TCanvas("c1","c1",600,400);
1076 auto hcol1 = new TH2F("hcol1","Option COLor example ",40,-4,4,40,-20,20);
1077 float px, py;
1078 for (Int_t i = 0; i < 25000; i++) {
1079 gRandom->Rannor(px,py);
1080 hcol1->Fill(px,5*py);
1081 }
1082 hcol1->Draw("COLZ");
1083}
1084End_Macro
1085
1086In the first plot of following example, the histogram has some negative bins;
1087the empty bins (containing 0) are drawn. In some cases one wants to not draw
1088empty bins (containing 0) of histograms having a negative minimum. The option
1089`1`, used to produce the second plot in the following picture, allows to do that.
1090
1091Begin_Macro(source)
1092{
1093 auto c1 = new TCanvas("c1","c1",600,600);
1094 c1->Divide(1,2);
1095 auto hcol23 = new TH2F("hcol23","Option COLZ example ",40,-4,4,40,-20,20);
1096 auto hcol24 = new TH2F("hcol24","Option COLZ1 example ",40,-4,4,40,-20,20);
1097 float px, py;
1098 for (Int_t i = 0; i < 25000; i++) {
1099 gRandom->Rannor(px,py);
1100 hcol23->Fill(px,5*py);
1101 hcol24->Fill(px,5*py);
1102 }
1103 hcol23->Fill(0.,0.,-200.);
1104 hcol24->Fill(0.,0.,-200.);
1105 c1->cd(1); hcol23->Draw("COLZ");
1106 c1->cd(2); hcol24->Draw("COLZ1");
1107}
1108End_Macro
1109
1110When the maximum of the histogram is set to a smaller value than the real maximum,
1111 the bins having a content between the new maximum and the real maximum are
1112painted with the color corresponding to the new maximum.
1113
1114When the minimum of the histogram is set to a greater value than the real minimum,
1115 the bins having a value between the real minimum and the new minimum are not drawn
1116 unless the option `0` is set.
1117In other words, option `COLZ0` forces the painting of bins with content < set minimum with
1118 a color corresponding to the set minimum. In contrast, option `COLZ` would not draw values
1119 smaller than the specified minimum. Note that both `COLZ` and `COLZ0` still do not draw
1120 empty bins, ie bins with `content == error == 0`, if the set min is not negative.
1121(Note that option `COLZ0` for TH2Poly has a different behavior than for TH2.)
1122
1123The following example illustrates the option `0` combined with the option `COL`.
1124
1125Begin_Macro(source)
1126{
1127 auto c1 = new TCanvas("c1","c1",600,600);
1128 c1->Divide(1,2);
1129 auto hcol21 = new TH2F("hcol21","Option COLZ",40,-4,4,40,-20,20);
1130 auto hcol22 = new TH2F("hcol22","Option COLZ0",40,-4,4,40,-20,20);
1131 float px, py;
1132 for (Int_t i = 0; i < 25000; i++) {
1133 gRandom->Rannor(px,py);
1134 hcol21->Fill(px,5*py);
1135 hcol22->Fill(px,5*py);
1136 }
1137 hcol21->SetBit(TH1::kNoStats);
1138 hcol22->SetBit(TH1::kNoStats);
1139 c1->cd(1); hcol21->Draw("COLZ");
1140 c1->cd(2); hcol22->Draw("COLZ0");
1141 hcol21->SetMaximum(100);
1142 hcol21->SetMinimum(40);
1143 hcol22->SetMaximum(100);
1144 hcol22->SetMinimum(40);
1145}
1146End_Macro
1147
1148Note that the behavior of `COLZ` is not symmetric: it does not draw values below the specified minimum,
1149but does draw values above the specified maximum by clipping them to the maximum color. In contrast, `COLZ0`
1150clips color on both lower and upper sides. Both `COLZ0` and `COLZ` exclude drawing empty bins (`content == error == 0`),
1151if the set minimum is not negative.
1152
1153\since **ROOT version 6.09/01:**
1154
1155When the option SAME (or "SAMES") is used with the option COL, the boxes' color
1156are computed taking the previous plots into account. The range along the Z axis
1157is imposed by the first plot (the one without option SAME); therefore the order
1158in which the plots are done is relevant. Same as [in the `BOX` option](\ref HP13), one can use
1159`SAME0` (or `SAMES0`) to opt out of this imposition.
1160
1161Begin_Macro(source)
1162{
1163 auto c = new TCanvas("c","Example of col plots with option SAME",200,10,700,500);
1164 auto h1 = new TH2F("h1","h1",40,-3,3,40,-3,3);
1165 auto h2 = new TH2F("h2","h2",40,-3,3,40,-3,3);
1166 auto h3 = new TH2F("h3","h3",40,-3,3,40,-3,3);
1167 auto h4 = new TH2F("h4","h4",40,-3,3,40,-3,3);
1168 h1->SetBit(TH1::kNoStats);
1169 for (Int_t i=0;i<5000;i++) {
1170 double x,y;
1171 gRandom->Rannor(x,y);
1172 if(x>0 && y>0) h1->Fill(x,y,4);
1173 if(x<0 && y<0) h2->Fill(x,y,3);
1174 if(x>0 && y<0) h3->Fill(x,y,2);
1175 if(x<0 && y>0) h4->Fill(x,y,1);
1176 }
1177 h1->Draw("colz");
1178 h2->Draw("col same");
1179 h3->Draw("col same");
1180 h4->Draw("col same");
1181}
1182End_Macro
1183
1184The option `COL` can be combined with the option `POL`:
1185
1186Begin_Macro(source)
1187{
1188 auto c1 = new TCanvas("c1","c1",600,400);
1189 auto hcol1 = new TH2F("hcol1","Option COLor combined with POL",40,-4,4,40,-4,4);
1190 float px, py;
1191 for (Int_t i = 0; i < 25000; i++) {
1192 gRandom->Rannor(px,py);
1193 hcol1->Fill(px,py);
1194 }
1195 hcol1->Draw("COLZPOL");
1196}
1197End_Macro
1198
1199\since **ROOT version 6.07/03:**
1200
1201A second rendering technique is also available with the COL2 and COLZ2 options.
1202
1203These options provide potential performance improvements compared to the standard
1204COL option. The performance comparison of the COL2 to the COL option depends on
1205the histogram and the size of the rendering region in the current pad. In general,
1206a small (approx. less than 100 bins per axis), sparsely populated TH2 will render
1207faster with the COL option.
1208
1209However, for larger histograms (approx. more than 100 bins per axis)
1210that are not sparse, the COL2 option will provide up to 20 times performance improvements.
1211For example, a 1000x1000 bin TH2 that is not sparse will render an order of magnitude
1212faster with the COL2 option.
1213
1214The COL2 option will also scale its performance based on the size of the
1215pixmap the histogram image is being rendered into. It also is much better optimized for
1216sessions where the user is forwarding X11 windows through an `ssh` connection.
1217
1218For the most part, the COL2 and COLZ2 options are a drop in replacement to the COL
1219and COLZ options. There is one major difference and that concerns the treatment of
1220bins with zero content. The COL2 and COLZ2 options color these bins the color of zero.
1221
1222COL2 option renders the histogram as a bitmap. Therefore it cannot be saved in vector
1223graphics file format like PostScript or PDF (an empty image will be generated). It can
1224be saved only in bitmap files like PNG format for instance.
1225
1226
1227\anchor HP140
1228### The CANDLE and VIOLIN options
1229
1230The mechanism behind Candle plots and Violin plots is very similar. Because of this they are
1231implemented in the same class TCandle. The keywords CANDLE or VIOLIN will initiate the drawing of
1232the corresponding plots. Followed by the keyword the user can select a plot direction (X or V for
1233vertical projections, or Y or H for horizontal projections) and/or predefined definitions
1234(1-6 for candles, 1-2 for violins). The order doesn't matter. Default is X and 1.
1235
1236Instead of using the predefined representations, the candle and violin parameters can be
1237changed individually. In that case the option have the following form:
1238
1239 CANDLEX(<option-string>)
1240 CANDLEY(<option-string>)
1241 VIOLINX(<option-string>)
1242 VIOLINY(<option-string>).
1243
1244All zeros at the beginning of `option-string` can be omitted.
1245
1246`option-string` consists eight values, defined as follow:
1247
1248 "CANDLEX(zhpawMmb)"
1249
1250Where:
1251
1252 - `b = 0`; no box drawn
1253 - `b = 1`; the box is drawn. As the candle-plot is also called a box-plot it
1254 makes sense in the very most cases to always draw the box
1255 - `b = 2`; draw a filled box with border
1256
1257 - `m = 0`; no median drawn
1258 - `m = 1`; median is drawn as a line
1259 - `m = 2`; median is drawn with errors (notches)
1260 - `m = 3`; median is drawn as a circle
1261
1262 - `M = 0`; no mean drawn
1263 - `M = 1`; mean is drawn as a dashed line
1264 - `M = 3`; mean is drawn as a circle
1265
1266 - `w = 0`; no whisker drawn
1267 - `w = 1`; whisker is drawn to end of distribution.
1268 - `w = 2`; whisker is drawn to max 1.5*iqr
1269
1270 - `a = 0`; no anchor drawn
1271 - `a = 1`; the anchors are drawn
1272
1273 - `p = 0`; no points drawn
1274 - `p = 1`; only outliers are drawn
1275 - `p = 2`; all datapoints are drawn
1276 - `p = 3`: all datapoints are drawn scattered
1277
1278 - `h = 0`; no histogram is drawn
1279 - `h = 1`; histogram at the left or bottom side is drawn
1280 - `h = 2`; histogram at the right or top side is drawn
1281 - `h = 3`; histogram at left and right or top and bottom (violin-style) is drawn
1282
1283 - `z = 0`; no zero indicator line is drawn
1284 - `z = 1`; zero indicator line is drawn.
1285
1286As one can see all individual options for both candle and violin plots can be accessed by this
1287mechanism. In deed the keywords CANDLE(<option-string>) and VIOLIN(<option-string>) have the same
1288meaning. So you can parametrise an option-string for a candle plot and use the keywords VIOLIN and
1289vice versa, if you wish.
1290
1291Using a logarithmic x- or y-axis is possible for candle and violin charts.
1292
1293\since **ROOT version 6.11/01**
1294
1295a logarithmic z-axis is possible, too but will only affect violin charts of course.
1296
1297\anchor HP140a
1298#### The CANDLE option
1299
1300<a href="http://en.wikipedia.org/wiki/Box_plot">A Candle plot</a> (also known as
1301a "box plot" or "whisker plot") was invented in 1977 by John Tukey. It is a convenient
1302way to describe graphically a data distribution (D) with only five numbers:
1303
1304 1. The minimum value of the distribution D (bottom or left whisker).
1305 2. The lower quartile (Q1): 25% of the data points in D are less than Q1 (bottom of the box).
1306 3. The median (M): 50% of the data points in D are less than M.
1307 4. The upper quartile (Q3): 75% of the data points in D are less than Q3 (top of the box).
1308 5. The maximum value of the distribution D (top or right whisker).
1309
1310In this implementation a TH2 is considered as a collection of TH1 along
1311X (option `CANDLE` or `CANDLEX`) or Y (option `CANDLEY`).
1312Each TH1 is represented as one candle.
1313
1314Begin_Macro(source)
1315../../../tutorials/hist/hist052_Graphics_candle_plot_whiskers.C
1316End_Macro
1317
1318The candle reduces the information coming from a whole distribution into few values.
1319Independently from the number of entries or the significance of the underlying distribution
1320a candle will always look like a candle. So candle plots should be used carefully in
1321particular with unknown distributions. The definition of a candle is based on
1322__unbinned data__. Here, candles are created from binned data. Because of this, the
1323deviation is connected to the bin width used. The calculation of the quantiles
1324normally done on unbinned data also. Because data are binned, this will
1325only work the best possible way within the resolution of one bin
1326
1327Because of all these facts one should take care that:
1328
1329 - there are enough points per candle
1330 - the bin width is small enough (more bins will increase the maximum
1331 available resolution of the quantiles although there will be some
1332 bins with no entries)
1333 - never make a candle-plot if the underlying distribution is double-distributed
1334 - only create candles of distributions that are more-or-less gaussian (the
1335 MPV should be not too far away from the mean).
1336
1337#### What a candle is made of
1338
1339\since **ROOT version 6.07/05**
1340
1341##### The box
1342The box displays the position of the inter-quantile-range of the underlying
1343distribution. The box contains 25% of the distribution below the median
1344and 25% of the distribution above the median. If the underlying distribution is large
1345enough and gaussian shaped the end-points of the box represent \f$ 0.6745\times\sigma \f$
1346(Where \f$ \sigma \f$ is the standard deviation of the gaussian). The width and
1347the position of the box can be modified by SetBarWidth() and SetBarOffset().
1348The +-25% quantiles are calculated by the GetQuantiles() methods.
1349
1350\since **ROOT version 6.11/01**
1351
1352Using the static function TCandle::SetBoxRange(double) the box definition will be
1353overwritten. E.g. using a box range of 0.68 will redefine the area of the lower box edge
1354to the upper box edge in order to cover 68% of the distribution illustrated by that candle.
1355The static function will affect all candle-charts in the running program.
1356Default is 0.5.
1357
1358Using the static function TCandle::SetScaledCandle(bool) the width of the box (and the
1359whole candle) can be influenced. Deactivated, the width is constant (to be set by
1360SetBarWidth() ). Activated, the width of the boxes will be scaled to each other based on the
1361amount of data in the corresponding candle, the maximum width can be influenced by
1362SetBarWidth(). The static function will affect all candle-charts in the running program.
1363Default is false. Scaling between multiple candle-charts (using "same" or THStack) is not
1364supported, yet
1365
1366##### The Median
1367For a sorted list of numbers, the median is the value in the middle of the list.
1368E.g. if a sorted list is made of five numbers "1,2,3,6,7" 3 will be the median
1369because it is in the middle of the list. If the number of entries is even the
1370average of the two values in the middle will be used. As histograms are binned
1371data, the situation is a bit more complex. The following example shows this:
1372
1373~~~ {.cpp}
1374void quantiles() {
1375 auto h = new TH1I("h","h",10,0,10);
1376 //h->Fill(3);
1377 //h->Fill(3);
1378 h->Fill(4);
1379 h->Draw();
1380 double p = 0.;
1381 double q = 0.;
1382 h->GetQuantiles(1,&q,&p);
1383
1384 cout << "Median is: " << q << std::endl;
1385}
1386~~~
1387
1388Here the bin-width is 1.0. If the two Fill(3) are commented out, as there are currently,
1389the example will return a calculated median of 4.5, because that's the bin center
1390of the bin in which the value 4.0 has been dropped. If the two Fill(3) are not
1391commented out, it will return 3.75, because the algorithm tries to evenly distribute
1392the individual values of a bin with bin content > 0. It means the sorted list
1393would be "3.25, 3.75, 4.5".
1394
1395The consequence is a median of 3.75. This shows how important it is to use a
1396small enough bin-width when using candle-plots on binned data.
1397If the distribution is large enough and gaussian shaped the median will be exactly
1398equal to the mean.
1399The median can be shown as a line or as a circle or not shown at all.
1400
1401In order to show the significance of the median notched candle plots apply a "notch" or
1402narrowing of the box around the median. The significance is defined by
1403\f$ 1.57\times\frac{iqr}{N} \f$ and will be represented as the size of the notch
1404(where iqr is the size of the box and N is the number of entries of the whole
1405distribution). Candle plots like these are usually called "notched candle plots".
1406
1407In case the significance of the median is greater that the size of the box, the
1408box will have an unnatural shape. Usually it means the chart has not enough data,
1409or that representing this uncertainty is not useful
1410
1411##### The Mean
1412The mean can be drawn as a dashed line or as a circle or not drawn at all.
1413The mean is the arithmetic average of the values in the distribution.
1414It is calculated using GetMean(). Because histograms are
1415binned data, the mean value can differ from a calculation on the raw-data.
1416If the distribution is large enough and gaussian shaped the mean will be
1417exactly the median.
1418
1419##### The Whiskers
1420The whiskers represent the part of the distribution not covered by the box.
1421The upper 25% and the lower 25% of the distribution are located within the whiskers.
1422Two representations are available.
1423
1424 - A simple one (using w=1) defining the lower whisker from the lowest data value
1425 to the bottom of the box, and the upper whisker from the top of the box to the
1426 highest data value. In this representation the whisker-lines are dashed.
1427 - A more complex one having a further restriction. The whiskers are still connected
1428 to the box but their length cannot exceed \f$ 1.5\times iqr \f$. So it might
1429 be that the outermost part of the underlying distribution will not be covered
1430 by the whiskers. Usually these missing parts will be represented by the outliers
1431 (see points). Of course the upper and the lower whisker may differ in length.
1432 In this representation the whiskers are drawn as solid lines.
1433
1434\since **ROOT version 6.11/01**
1435
1436Using the static function TCandle::SetWhiskerRange(double) the whisker definition w=1
1437will be overwritten. E.g. using a whisker-range of 0.95 and w=1 will redefine the area of
1438the lower whisker to the upper whisker in order to cover 95% of the distribution inside
1439that candle. The static function will affect all candle-charts in the running program.
1440Default is 1.
1441
1442If the distribution is large enough and gaussian shaped, the maximum length of
1443the whisker will be located at \f$ \pm 2.698 \sigma \f$ (when using the
14441.5*iqr-definition (w=2), where \f$ \sigma \f$ is the standard deviation
1445(see picture above). In that case 99.3% of the total distribution will be covered
1446by the box and the whiskers, whereas 0.7% are represented by the outliers.
1447
1448##### The Anchors
1449The anchors have no special meaning in terms of statistical calculation. They mark
1450the end of the whiskers and they have the width of the box. Both representation
1451with and without anchors are common.
1452
1453##### The Points
1454Depending on the configuration the points can have different meanings:
1455 - If p=1 the points represent the outliers. If they are shown, it means
1456 some parts of the underlying distribution are not covered by the whiskers.
1457 This can only occur when the whiskers are set to option w=2. Here the whiskers
1458 can have a maximum length of \f$ 1.5 \times iqr \f$. So any points outside the
1459 whiskers will be drawn as outliers. The outliers will be represented by crosses.
1460 - If p=2 all points in the distribution will be painted as crosses. This is
1461 useful for small datasets only (up to 10 or 20 points per candle).
1462 The outliers are shown along the candle. Because the underlying distribution
1463 is binned, is frequently occurs that a bin contains more than one value.
1464 Because of this the points will be randomly scattered within their bin along
1465 the candle axis. If the bin content for a bin is exactly 1 (usually
1466 this happens for the outliers) if will be drawn in the middle of the bin along
1467 the candle axis. As the maximum number of points per candle is limited by kNMax/2
1468 on very large datasets scaling will be performed automatically. In that case one
1469 would loose all outliers because they have usually a bin content of 1 (and a
1470 bin content between 0 and 1 after the scaling). Because of this all bin contents
1471 between 0 and 1 - after the scaling - will be forced to be 1.
1472 - As the drawing of all values on large datasets can lead to big amounts of crosses,
1473 one can show all values as a scatter plot instead by choosing p=3. The points will be
1474 drawn as dots and will be scattered within the width of the candle. The color
1475 of the points will be the color of the candle-chart.
1476
1477##### Other Options
1478Is is possible to combine all options of candle and violin plots with each other. E.g. a box-plot
1479with a histogram.
1480
1481#### How to use the candle-plots drawing option
1482
1483There are six predefined candle-plot representations:
1484
1485 - "CANDLEX1": Standard candle (whiskers cover the whole distribution)
1486 - "CANDLEX2": Standard candle with better whisker definition + outliers.
1487 It is a good compromise
1488 - "CANDLEX3": Like candle2 but with a mean as a circle.
1489 It is easier to distinguish mean and median
1490 - "CANDLEX4": Like candle3 but showing the uncertainty of the median as well
1491 (notched candle plots).
1492 For bigger datasets per candle
1493 - "CANDLEX5": Like candle2 but showing all data points.
1494 For very small datasets
1495 - "CANDLEX6": Like candle2 but showing all datapoints scattered.
1496 For huge datasets
1497
1498
1499The following picture shows how the six predefined representations look.
1500
1501Begin_Macro
1502{
1503 auto c1 = new TCanvas("c1","c1",700,800);
1504 c1->Divide(2,3);
1505 gStyle->SetOptStat(kFALSE);
1506
1507 auto hcandle = new TH2F("hcandle"," ",10,-4,4,40,-20,20);
1508 float px, py;
1509 for (Int_t i = 0; i < 15000; i++) {
1510 gRandom->Rannor(px,py);
1511 hcandle->Fill(px,5*py);
1512 }
1513 hcandle->SetMarkerSize(0.5);
1514
1515 TH2F *h2;
1516 for (Int_t i=1; i<7; i++) {
1517 c1->cd(i);
1518 h2 = (TH2F*)hcandle->DrawClone(Form("CANDLE%d",i));
1519 h2->SetTitle(Form("CANDLE%d",i));
1520 }
1521}
1522End_Macro
1523
1524
1525#### Example 1
1526Box and improved whisker, no mean, no median, no anchor no outliers
1527
1528 h1->Draw("CANDLEX(2001)");
1529
1530#### Example 2
1531A Candle-definition like "CANDLEX2" (New standard candle with better whisker definition + outliers)
1532
1533 h1->Draw("CANDLEX(112111)");
1534
1535#### Example 3
1536The following example shows how several candle plots can be super-imposed using
1537the option SAME. Note that the bar-width and bar-offset are active on candle plots.
1538Also the color, the line width, the size of the points and so on can be changed by the
1539standard attribute setting methods such as SetLineColor() SetLineWidth().
1540
1541Begin_Macro(source)
1542../../../tutorials/hist/hist049_Graphics_candle_plot.C
1543End_Macro
1544
1545\anchor HP140b
1546#### The VIOLIN option
1547
1548<a href="http://en.wikipedia.org/wiki/Violin_plot">A violin plot</a> is a candle plot
1549that also encodes the pdf information at each point.
1550
1551
1552Quartiles and mean are also represented at each point, with a marker
1553and two lines.
1554
1555In this implementation a TH2 is considered as a collection of TH1 along
1556X (option `VIOLIN` or `VIOLINX`) or Y (option `VIOLINY`).
1557
1558#### What a violin is made of
1559
1560\since **ROOT version 6.09/02**
1561
1562##### The histogram
1563The histogram is typically drawn to both directions with respect to the middle-line of the
1564corresponding bin. This can be achieved by using h=3. It is possible to draw a histogram only to
1565one side (h=1, or h=2).
1566The maximum number of bins in the histogram is limited to 500, if the number of bins in the used
1567histogram is higher it will be rebinned automatically. The maximum height of the histogram can
1568be modified by using SetBarWidth() and the position can be changed with SetBarOffset().
1569A solid fill style is recommended.
1570
1571\since **ROOT version 6.11/01**
1572
1573Using the static function TCandle::SetScaledViolin(bool) the height of the histogram or the
1574violin can be influenced. Activated, the height of the bins of the individual violins will be
1575scaled with respect to each other, the maximum height can be influenced by SetBarWidth().
1576Deactivated, the height of the bin with the maximum content of each individual violin is
1577set to a constant value using SetBarWidth(). The static function will affect all violin-charts
1578in the running program. Default is true. Scaling between multiple violin-charts
1579(using "same" or THStack) is not supported, yet.
1580
1581##### The zero indicator line
1582Typical for violin charts is a line in the background over the whole histogram indicating
1583the bins with zero entries. The zero indicator line can be activated with z=1. The line color
1584will always be the same as the fill-color of the histogram.
1585
1586##### The Mean
1587The Mean is illustrated with the same mechanism as used for candle plots. Usually a circle is used.
1588
1589##### Whiskers
1590The whiskers are illustrated by the same mechanism as used for candle plots. There is only one
1591difference. When using the simple whisker definition (w=1) and the zero indicator line (z=1), then
1592the whiskers will be forced to be solid (usually hashed)
1593
1594##### Points
1595The points are illustrated by the same mechanism as used for candle plots. E.g. VIOLIN2 uses
1596better whisker definition (w=2) and outliers (p=1).
1597
1598##### Other options
1599It is possible to combine all options of candle or violin plots with each other. E.g. a violin plot
1600including a box-plot.
1601
1602#### How to use the violin-plots drawing option
1603
1604There are two predefined violin-plot representations:
1605 - "VIOLINX1": Standard violin (histogram, mean, whisker over full distribution,
1606 zero indicator line)
1607 - "VIOLINX2": Line VIOLINX1 both with better whisker definition + outliers.
1608
1609A solid fill style is recommended for this plot (as opposed to a hollow or
1610hashed style).
1611
1612Begin_Macro(source)
1613{
1614 auto c1 = new TCanvas("c1","c1",600,400);
1615 Int_t nx(6), ny(40);
1616 double xmin(0.0), xmax(+6.0), ymin(0.0), ymax(+4.0);
1617 auto hviolin = new TH2F("hviolin", "Option VIOLIN example", nx, xmin, xmax, ny, ymin, ymax);
1618 TF1 f1("f1", "gaus", +0,0 +4.0);
1619 double x,y;
1620 for (Int_t iBin=1; iBin<hviolin->GetNbinsX(); ++iBin) {
1621 double xc = hviolin->GetXaxis()->GetBinCenter(iBin);
1622 f1.SetParameters(1, 2.0+TMath::Sin(1.0+xc), 0.2+0.1*(xc-xmin)/xmax);
1623 for(Int_t i=0; i<10000; ++i){
1624 x = xc;
1625 y = f1.GetRandom();
1626 hviolin->Fill(x, y);
1627 }
1628 }
1629 hviolin->SetFillColor(kGray);
1630 hviolin->SetMarkerStyle(20);
1631 hviolin->SetMarkerSize(0.5);
1632 hviolin->Draw("VIOLIN");
1633 c1->Update();
1634}
1635End_Macro
1636
1637The next example illustrates a time development of a certain value:
1638
1639Begin_Macro(source)
1640../../../tutorials/hist/hist047_Graphics_candle_decay.C
1641End_Macro
1642
1643
1644\anchor HP15
1645### The TEXT and TEXTnn Option
1646
1647
1648For each bin the content is printed. The text attributes are:
1649
1650- text font = current TStyle font (`gStyle->SetTextFont()`).
1651- text size = 0.02*padheight*markersize (if `h` is the histogram drawn
1652 with the option `TEXT` the marker size can be changed with
1653 `h->SetMarkerSize(markersize)`).
1654- text color = marker color.
1655
1656By default the format `g` is used. This format can be redefined
1657by calling `gStyle->SetPaintTextFormat()`.
1658
1659It is also possible to use `TEXTnn` in order to draw the text with
1660the angle `nn` (`0 < nn <= 90`).
1661
1662For 2D histograms the text is plotted in the center of each non empty cells.
1663It is possible to plot empty cells by calling `gStyle->SetHistMinimumZero()`
1664or providing MIN0 draw option. For 1D histogram the text is plotted at a y
1665position equal to the bin content.
1666
1667For 2D histograms when the option "E" (errors) is combined with the option
1668text ("TEXTE"), the error for each bin is also printed.
1669
1670Begin_Macro(source)
1671{
1672 auto c01 = new TCanvas("c01","c01",700,400);
1673 c01->Divide(2,1);
1674 auto htext1 = new TH1F("htext1","Option TEXT on 1D histograms ",10,-4,4);
1675 auto htext2 = new TH2F("htext2","Option TEXT on 2D histograms ",10,-4,4,10,-20,20);
1676 float px, py;
1677 for (Int_t i = 0; i < 25000; i++) {
1678 gRandom->Rannor(px,py);
1679 htext1->Fill(px,0.1);
1680 htext2->Fill(px,5*py,0.1);
1681 }
1682 gStyle->SetPaintTextFormat("4.1f m");
1683 htext2->SetMarkerSize(1.8);
1684 c01->cd(1);
1685 htext2->Draw("TEXT45");
1686 c01->cd(2);
1687 htext1->Draw();
1688 htext1->Draw("HIST TEXT0 SAME");
1689}
1690End_Macro
1691
1692\since **ROOT version 6.07/07:**
1693
1694In case several histograms are drawn on top ot each other (using option `SAME`),
1695the text can be shifted using `SetBarOffset()`. It specifies an offset for the
1696text position in each cell, in percentage of the bin width.
1697
1698Begin_Macro(source)
1699{
1700 auto c03 = new TCanvas("c03","c03",700,400);
1701 gStyle->SetOptStat(0);
1702 auto htext3 = new TH2F("htext3","Several 2D histograms drawn with option TEXT",10,-4,4,10,-20,20);
1703 auto htext4 = new TH2F("htext4","htext4",10,-4,4,10,-20,20);
1704 auto htext5 = new TH2F("htext5","htext5",10,-4,4,10,-20,20);
1705 float px, py;
1706 for (Int_t i = 0; i < 25000; i++) {
1707 gRandom->Rannor(px,py);
1708 htext3->Fill(4*px,20*py,0.1);
1709 htext4->Fill(4*px,20*py,0.5);
1710 htext5->Fill(4*px,20*py,1.0);
1711 }
1712 htext4->SetMarkerSize(1.8);
1713 htext5->SetMarkerSize(1.8);
1714 htext5->SetMarkerColor(kRed);
1715 htext4->SetBarOffset(0.2);
1716 htext5->SetBarOffset(-0.2);
1717 htext3->Draw("COL");
1718 htext4->Draw("TEXT SAME");
1719 htext5->Draw("TEXT SAME");
1720}
1721End_Macro
1722
1723In the case of profile histograms it is possible to print the number
1724of entries instead of the bin content. It is enough to combine the
1725option "E" (for entries) with the option "TEXT".
1726
1727Begin_Macro(source)
1728{
1729 auto c02 = new TCanvas("c02","c02",700,400);
1730 c02->Divide(2,1);
1731 gStyle->SetPaintTextFormat("g");
1732
1733 auto profile = new TProfile("profile","profile",10,0,10);
1734 profile->SetMarkerSize(2.2);
1735 profile->Fill(0.5,1);
1736 profile->Fill(1.5,2);
1737 profile->Fill(2.5,3);
1738 profile->Fill(3.5,4);
1739 profile->Fill(4.5,5);
1740 profile->Fill(5.5,5);
1741 profile->Fill(6.5,4);
1742 profile->Fill(7.5,3);
1743 profile->Fill(8.5,2);
1744 profile->Fill(9.5,1);
1745 c02->cd(1); profile->Draw("HIST TEXT0");
1746 c02->cd(2); profile->Draw("HIST TEXT0E");
1747}
1748End_Macro
1749
1750\anchor HP16
1751### The CONTour options
1752
1753
1754The following contour options are supported:
1755
1756| Option | Description |
1757|----------|-----------------------------------------------------------------------------|
1758| "CONT" | Draw a contour plot (same as CONT0). |
1759| "CONT0" | Draw a contour plot using surface colors to distinguish contours. |
1760| "CONT1" | Draw a contour plot using the line colors to distinguish contours. |
1761| "CONT2" | Draw a contour plot using the line styles (1 to 5) to distinguish contours. |
1762| "CONT3" | Draw a contour plot using the same line style for all contours. |
1763| "CONT4" | Draw a contour plot using surface colors (`SURF` option at theta = 0). |
1764
1765
1766The following example shows a 2D histogram plotted with the option
1767`CONTZ`. The option `CONT` draws a contour plot using surface
1768colors to distinguish contours. Combined with the option `CONT` (or
1769`CONT0`), the option `Z` allows to display the color palette
1770defined by `gStyle->SetPalette()`.
1771
1772Begin_Macro(source)
1773{
1774 auto c1 = new TCanvas("c1","c1",600,400);
1775 auto hcontz = new TH2F("hcontz","Option CONTZ example ",40,-4,4,40,-20,20);
1776 float px, py;
1777 for (Int_t i = 0; i < 25000; i++) {
1778 gRandom->Rannor(px,py);
1779 hcontz->Fill(px-1,5*py);
1780 hcontz->Fill(2+0.5*px,2*py-10.,0.1);
1781 }
1782 hcontz->Draw("CONTZ");
1783}
1784End_Macro
1785
1786The following example shows a 2D histogram plotted with the option
1787`CONT1Z`. The option `CONT1` draws a contour plot using the
1788line colors to distinguish contours. Combined with the option `CONT1`,
1789the option `Z` allows to display the color palette defined by
1790`gStyle->SetPalette()`.
1791
1792Begin_Macro(source)
1793{
1794 auto c1 = new TCanvas("c1","c1",600,400);
1795 auto hcont1 = new TH2F("hcont1","Option CONT1Z example ",40,-4,4,40,-20,20);
1796 float px, py;
1797 for (Int_t i = 0; i < 25000; i++) {
1798 gRandom->Rannor(px,py);
1799 hcont1->Fill(px-1,5*py);
1800 hcont1->Fill(2+0.5*px,2*py-10.,0.1);
1801 }
1802 hcont1->Draw("CONT1Z");
1803}
1804End_Macro
1805
1806The following example shows a 2D histogram plotted with the option
1807`CONT2`. The option `CONT2` draws a contour plot using the
1808line styles (1 to 5) to distinguish contours.
1809
1810Begin_Macro(source)
1811{
1812 auto c1 = new TCanvas("c1","c1",600,400);
1813 auto hcont2 = new TH2F("hcont2","Option CONT2 example ",40,-4,4,40,-20,20);
1814 float px, py;
1815 for (Int_t i = 0; i < 25000; i++) {
1816 gRandom->Rannor(px,py);
1817 hcont2->Fill(px-1,5*py);
1818 hcont2->Fill(2+0.5*px,2*py-10.,0.1);
1819 }
1820 hcont2->Draw("CONT2");
1821}
1822End_Macro
1823
1824The following example shows a 2D histogram plotted with the option
1825`CONT3`. The option `CONT3` draws contour plot using the same line style for
1826all contours.
1827
1828Begin_Macro(source)
1829{
1830 auto c1 = new TCanvas("c1","c1",600,400);
1831 auto hcont3 = new TH2F("hcont3","Option CONT3 example ",40,-4,4,40,-20,20);
1832 float px, py;
1833 for (Int_t i = 0; i < 25000; i++) {
1834 gRandom->Rannor(px,py);
1835 hcont3->Fill(px-1,5*py);
1836 hcont3->Fill(2+0.5*px,2*py-10.,0.1);
1837 }
1838 hcont3->SetLineStyle(kDotted);
1839 hcont3->Draw("CONT3");
1840}
1841End_Macro
1842
1843The following example shows a 2D histogram plotted with the option
1844`CONT4`. The option `CONT4` draws a contour plot using surface
1845colors to distinguish contours (`SURF` option at theta = 0). Combined
1846with the option `CONT` (or `CONT0`), the option `Z`
1847allows to display the color palette defined by `gStyle->SetPalette()`.
1848
1849Begin_Macro(source)
1850{
1851 auto c1 = new TCanvas("c1","c1",600,400);
1852 auto hcont4 = new TH2F("hcont4","Option CONT4Z example ",40,-4,4,40,-20,20);
1853 float px, py;
1854 for (Int_t i = 0; i < 25000; i++) {
1855 gRandom->Rannor(px,py);
1856 hcont4->Fill(px-1,5*py);
1857 hcont4->Fill(2+0.5*px,2*py-10.,0.1);
1858 }
1859 hcont4->Draw("CONT4Z");
1860}
1861End_Macro
1862
1863The default number of contour levels is 20 equidistant levels and can be changed
1864with `TH1::SetContour()` or `TStyle::SetNumberContours()`.
1865
1866\anchor HP16a
1867#### The LIST option
1868
1869When option `LIST` is specified together with option
1870`CONT`, the points used to draw the contours are saved in
1871`TGraph` objects:
1872
1873 h->Draw("CONT LIST");
1874 gPad->Update();
1875
1876The contour are saved in `TGraph` objects once the pad is painted.
1877Therefore to use this functionality in a macro, `gPad->Update()`
1878should be performed after the histogram drawing. Once the list is
1879built, the contours are accessible in the following way:
1880
1881 TObjArray *contours = (TObjArray*)gROOT->GetListOfSpecials()->FindObject("contours");
1882 Int_t ncontours = contours->GetSize();
1883 TList *list = (TList*)contours->At(i);
1884
1885Where `i` is a contour number, and list contains a list of
1886`TGraph` objects.
1887For one given contour, more than one disjoint polyline may be generated.
1888The number of TGraphs per contour is given by:
1889
1890 list->GetSize();
1891
1892To access the first graph in the list one should do:
1893
1894 TGraph *gr1 = (TGraph*)list->First();
1895
1896
1897The following example (hist102_TH2_contour_list.C) shows how to use this functionality.
1898
1899Begin_Macro(source)
1900../../../tutorials/hist/hist102_TH2_contour_list.C
1901End_Macro
1902
1903\anchor HP16b
1904#### The AITOFF, MERCATOR, SINUSOIDAL and PARABOLIC options
1905
1906The following options select the `CONT4` option and are useful for
1907sky maps or exposure maps (earth.C).
1908
1909| Option | Description |
1910|--------------|---------------------------------------------------------------|
1911| "AITOFF" | Draw a contour via an AITOFF projection.|
1912| "MERCATOR" | Draw a contour via an Mercator projection.|
1913| "SINUSOIDAL" | Draw a contour via an Sinusoidal projection.|
1914| "PARABOLIC" | Draw a contour via an Parabolic projection.|
1915
1916Begin_Macro(source)
1917../../../tutorials/visualisation/graphics/earth.C
1918End_Macro
1919
1920
1921\anchor HP17
1922### The LEGO options
1923
1924
1925In a lego plot the cell contents are drawn as 3-d boxes. The height of each box
1926is proportional to the cell content. The lego aspect is control with the
1927following options:
1928
1929| Option | Description |
1930|----------|-------------------------------------------------------------------|
1931| "LEGO" | Draw a lego plot using the hidden lines removal technique.|
1932| "LEGO1" | Draw a lego plot using the hidden surface removal technique.|
1933| "LEGO2" | Draw a lego plot using colors to show the cell contents.|
1934| "LEGO3" | Draw a lego plot with hidden surface removal, like LEGO1 but the border lines of each lego-bar are not drawn.|
1935| "LEGO4" | Draw a lego plot with hidden surface removal, like LEGO1 but without the shadow effect on each lego-bar.|
1936| "0" | When used with any LEGO option, the empty bins are not drawn.|
1937
1938
1939See the limitations with [the option "SAME"](\ref HP060a).
1940
1941Line attributes can be used in lego plots to change the edges' style.
1942
1943The following example shows a 2D histogram plotted with the option
1944`LEGO`. The option `LEGO` draws a lego plot using the hidden
1945lines removal technique.
1946
1947Begin_Macro(source)
1948{
1949 auto c2 = new TCanvas("c2","c2",600,400);
1950 auto hlego = new TH2F("hlego","Option LEGO example ",40,-4,4,40,-20,20);
1951 float px, py;
1952 for (Int_t i = 0; i < 25000; i++) {
1953 gRandom->Rannor(px,py);
1954 hlego->Fill(px-1,5*py);
1955 hlego->Fill(2+0.5*px,2*py-10.,0.1);
1956 }
1957 hlego->Draw("LEGO");
1958}
1959End_Macro
1960
1961The following example shows a 2D histogram plotted with the option
1962`LEGO1`. The option `LEGO1` draws a lego plot using the
1963hidden surface removal technique. Combined with any `LEGOn` option, the
1964option `0` allows to not drawn the empty bins.
1965
1966Begin_Macro(source)
1967{
1968 auto c2 = new TCanvas("c2","c2",600,400);
1969 auto hlego1 = new TH2F("hlego1","Option LEGO1 example (with option 0) ",40,-4,4,40,-20,20);
1970 float px, py;
1971 for (Int_t i = 0; i < 25000; i++) {
1972 gRandom->Rannor(px,py);
1973 hlego1->Fill(px-1,5*py);
1974 hlego1->Fill(2+0.5*px,2*py-10.,0.1);
1975 }
1976 hlego1->SetFillColor(kYellow);
1977 hlego1->Draw("LEGO1 0");
1978}
1979End_Macro
1980
1981The following example shows a 2D histogram plotted with the option
1982`LEGO3`. Like the option `LEGO1`, the option `LEGO3`
1983draws a lego plot using the hidden surface removal technique but doesn't draw
1984the border lines of each individual lego-bar. This is very useful for histograms
1985having many bins. With such histograms the option `LEGO1` gives a black
1986image because of the border lines. This option also works with stacked legos.
1987
1988Begin_Macro(source)
1989{
1990 auto c2 = new TCanvas("c2","c2",600,400);
1991 auto hlego3 = new TH2F("hlego3","Option LEGO3 example",40,-4,4,40,-20,20);
1992 float px, py;
1993 for (Int_t i = 0; i < 25000; i++) {
1994 gRandom->Rannor(px,py);
1995 hlego3->Fill(px-1,5*py);
1996 hlego3->Fill(2+0.5*px,2*py-10.,0.1);
1997 }
1998 hlego3->SetFillColor(kRed);
1999 hlego3->Draw("LEGO3");
2000}
2001End_Macro
2002
2003The following example shows a 2D histogram plotted with the option
2004`LEGO2`. The option `LEGO2` draws a lego plot using colors to
2005show the cell contents. Combined with the option `LEGO2`, the option
2006`Z` allows to display the color palette defined by
2007`gStyle->SetPalette()`.
2008
2009Begin_Macro(source)
2010{
2011 auto c2 = new TCanvas("c2","c2",600,400);
2012 auto hlego2 = new TH2F("hlego2","Option LEGO2Z example ",40,-4,4,40,-20,20);
2013 float px, py;
2014 for (Int_t i = 0; i < 25000; i++) {
2015 gRandom->Rannor(px,py);
2016 hlego2->Fill(px-1,5*py);
2017 hlego2->Fill(2+0.5*px,2*py-10.,0.1);
2018 }
2019 hlego2->Draw("LEGO2Z");
2020}
2021End_Macro
2022
2023
2024
2025\anchor HP18
2026### The "SURFace" options
2027
2028
2029In a surface plot, cell contents are represented as a mesh.
2030The height of the mesh is proportional to the cell content.
2031
2032| Option | Description |
2033|----------|-------------------------------------------------------------------|
2034| "SURF" | Draw a surface plot using the hidden line removal technique.|
2035| "SURF1" | Draw a surface plot using the hidden surface removal technique.|
2036| "SURF2" | Draw a surface plot using colors to show the cell contents.|
2037| "SURF3" | Same as `SURF` with an additional filled contour plot on top.|
2038| "SURF4" | Draw a surface using the Gouraud shading technique.|
2039| "SURF5" | Used with one of the options CYL, PSR and CYL this option allows to draw a filled contour plot.|
2040| "SURF6" | This option should not be used directly. It is used internally when the CONT is used with option the option SAME on a 3D plot.|
2041| "SURF7" | Same as `SURF2` with an additional line contour plot on top.|
2042
2043
2044
2045See the limitations with [the option "SAME"](\ref HP060a).
2046
2047The following example shows a 2D histogram plotted with the option
2048`SURF`. The option `SURF` draws a lego plot using the hidden
2049lines removal technique.
2050
2051Begin_Macro(source)
2052{
2053 auto c2 = new TCanvas("c2","c2",600,400);
2054 auto hsurf = new TH2F("hsurf","Option SURF example ",30,-4,4,30,-20,20);
2055 float px, py;
2056 for (Int_t i = 0; i < 25000; i++) {
2057 gRandom->Rannor(px,py);
2058 hsurf->Fill(px-1,5*py);
2059 hsurf->Fill(2+0.5*px,2*py-10.,0.1);
2060 }
2061 hsurf->Draw("SURF");
2062}
2063End_Macro
2064
2065The following example shows a 2D histogram plotted with the option
2066`SURF1`. The option `SURF1` draws a surface plot using the
2067hidden surface removal technique. Combined with the option `SURF1`,
2068the option `Z` allows to display the color palette defined by
2069`gStyle->SetPalette()`.
2070
2071Begin_Macro(source)
2072{
2073 auto c2 = new TCanvas("c2","c2",600,400);
2074 auto hsurf1 = new TH2F("hsurf1","Option SURF1 example ",30,-4,4,30,-20,20);
2075 float px, py;
2076 for (Int_t i = 0; i < 25000; i++) {
2077 gRandom->Rannor(px,py);
2078 hsurf1->Fill(px-1,5*py);
2079 hsurf1->Fill(2+0.5*px,2*py-10.,0.1);
2080 }
2081 hsurf1->Draw("SURF1");
2082}
2083End_Macro
2084
2085The following example shows a 2D histogram plotted with the option
2086`SURF2`. The option `SURF2` draws a surface plot using colors
2087to show the cell contents. Combined with the option `SURF2`, the option
2088`Z` allows to display the color palette defined by
2089`gStyle->SetPalette()`.
2090
2091Begin_Macro(source)
2092{
2093 auto c2 = new TCanvas("c2","c2",600,400);
2094 auto hsurf2 = new TH2F("hsurf2","Option SURF2 example ",30,-4,4,30,-20,20);
2095 float px, py;
2096 for (Int_t i = 0; i < 25000; i++) {
2097 gRandom->Rannor(px,py);
2098 hsurf2->Fill(px-1,5*py);
2099 hsurf2->Fill(2+0.5*px,2*py-10.,0.1);
2100 }
2101 hsurf2->Draw("SURF2");
2102}
2103End_Macro
2104
2105The following example shows a 2D histogram plotted with the option
2106`SURF3`. The option `SURF3` draws a surface plot using the
2107hidden line removal technique with, in addition, a filled contour view drawn on the
2108top. Combined with the option `SURF3`, the option `Z` allows
2109to display the color palette defined by `gStyle->SetPalette()`.
2110
2111Begin_Macro(source)
2112{
2113 auto c2 = new TCanvas("c2","c2",600,400);
2114 auto hsurf3 = new TH2F("hsurf3","Option SURF3 example ",30,-4,4,30,-20,20);
2115 float px, py;
2116 for (Int_t i = 0; i < 25000; i++) {
2117 gRandom->Rannor(px,py);
2118 hsurf3->Fill(px-1,5*py);
2119 hsurf3->Fill(2+0.5*px,2*py-10.,0.1);
2120 }
2121 hsurf3->Draw("SURF3");
2122}
2123End_Macro
2124
2125The following example shows a 2D histogram plotted with the option
2126`SURF4`. The option `SURF4` draws a surface using the Gouraud
2127shading technique.
2128
2129Begin_Macro(source)
2130{
2131 auto c2 = new TCanvas("c2","c2",600,400);
2132 auto hsurf4 = new TH2F("hsurf4","Option SURF4 example ",30,-4,4,30,-20,20);
2133 float px, py;
2134 for (Int_t i = 0; i < 25000; i++) {
2135 gRandom->Rannor(px,py);
2136 hsurf4->Fill(px-1,5*py);
2137 hsurf4->Fill(2+0.5*px,2*py-10.,0.1);
2138 }
2139 hsurf4->SetFillColor(kOrange);
2140 hsurf4->Draw("SURF4");
2141}
2142End_Macro
2143
2144The following example shows a 2D histogram plotted with the option
2145`SURF5 CYL`. Combined with the option `SURF5`, the option
2146`Z` allows to display the color palette defined by `gStyle->SetPalette()`.
2147
2148Begin_Macro(source)
2149{
2150 auto c2 = new TCanvas("c2","c2",600,400);
2151 auto hsurf5 = new TH2F("hsurf4","Option SURF5 example ",30,-4,4,30,-20,20);
2152 float px, py;
2153 for (Int_t i = 0; i < 25000; i++) {
2154 gRandom->Rannor(px,py);
2155 hsurf5->Fill(px-1,5*py);
2156 hsurf5->Fill(2+0.5*px,2*py-10.,0.1);
2157 }
2158 hsurf5->Draw("SURF5 CYL");
2159}
2160End_Macro
2161
2162The following example shows a 2D histogram plotted with the option
2163`SURF7`. The option `SURF7` draws a surface plot using the
2164hidden surfaces removal technique with, in addition, a line contour view drawn on the
2165top. Combined with the option `SURF7`, the option `Z` allows
2166to display the color palette defined by `gStyle->SetPalette()`.
2167
2168Begin_Macro(source)
2169{
2170 auto c2 = new TCanvas("c2","c2",600,400);
2171 auto hsurf7 = new TH2F("hsurf3","Option SURF7 example ",30,-4,4,30,-20,20);
2172 float px, py;
2173 for (Int_t i = 0; i < 25000; i++) {
2174 gRandom->Rannor(px,py);
2175 hsurf7->Fill(px-1,5*py);
2176 hsurf7->Fill(2+0.5*px,2*py-10.,0.1);
2177 }
2178 hsurf7->Draw("SURF7");
2179}
2180End_Macro
2181
2182As shown in the following example, when a contour plot is painted on top of a
2183surface plot using the option `SAME`, the contours appear in 3D on the
2184surface.
2185
2186Begin_Macro(source)
2187{
2188 auto c20=new TCanvas("c20","c20",600,400);
2189 int NBins = 50;
2190 double d = 2;
2191 auto hsc = new TH2F("hsc", "Surface and contour with option SAME ", NBins, -d, d, NBins, -d, d);
2192 for (int bx = 1; bx <= NBins; ++bx) {
2193 for (int by = 1; by <= NBins; ++by) {
2194 double x = hsc->GetXaxis()->GetBinCenter(bx);
2195 double y = hsc->GetYaxis()->GetBinCenter(by);
2196 hsc->SetBinContent(bx, by, exp(-x*x)*exp(-y*y));
2197 }
2198 }
2199 hsc->Draw("surf2");
2200 hsc->Draw("CONT1 SAME");
2201}
2202End_Macro
2203
2204
2205\anchor HP19
2206### Cylindrical, Polar, Spherical and PseudoRapidity/Phi options
2207
2208
2209Legos and surfaces plots are represented by default in Cartesian coordinates.
2210Combined with any `LEGOn` or `SURFn` options the following
2211options allow to draw a lego or a surface in other coordinates systems.
2212
2213| Option | Description |
2214|----------|-------------------------------------------------------------------|
2215| "CYL" | Use Cylindrical coordinates. The X coordinate is mapped on the angle and the Y coordinate on the cylinder length.|
2216| "POL" | Use Polar coordinates. The X coordinate is mapped on the angle and the Y coordinate on the radius.|
2217| "SPH" | Use Spherical coordinates. The X coordinate is mapped on the latitude and the Y coordinate on the longitude.|
2218| "PSR" | Use PseudoRapidity/Phi coordinates. The X coordinate is mapped on Phi.|
2219
2220
2221
2222<b>WARNING:</b> Axis are not drawn with these options.
2223
2224The following example shows the same histogram as a lego plot is the four
2225different coordinates systems.
2226
2227Begin_Macro(source)
2228{
2229 auto c3 = new TCanvas("c3","c3",600,400);
2230 c3->Divide(2,2);
2231 auto hlcc = new TH2F("hlcc","Cylindrical coordinates",20,-4,4,20,-20,20);
2232 float px, py;
2233 for (Int_t i = 0; i < 25000; i++) {
2234 gRandom->Rannor(px,py);
2235 hlcc->Fill(px-1,5*py);
2236 hlcc->Fill(2+0.5*px,2*py-10.,0.1);
2237 }
2238 hlcc->SetFillColor(kYellow);
2239 c3->cd(1); hlcc->Draw("LEGO1 CYL");
2240 c3->cd(2); auto hlpc = (TH2F*) hlcc->DrawClone("LEGO1 POL");
2241 hlpc->SetTitle("Polar coordinates");
2242 c3->cd(3); auto hlsc = (TH2F*) hlcc->DrawClone("LEGO1 SPH");
2243 hlsc->SetTitle("Spherical coordinates");
2244 c3->cd(4); auto hlprpc = (TH2F*) hlcc->DrawClone("LEGO1 PSR");
2245 hlprpc->SetTitle("PseudoRapidity/Phi coordinates");
2246}
2247End_Macro
2248
2249The following example shows the same histogram as a surface plot is the four different coordinates systems.
2250
2251Begin_Macro(source)
2252{
2253 auto c4 = new TCanvas("c4","c4",600,400);
2254 c4->Divide(2,2);
2255 auto hscc = new TH2F("hscc","Cylindrical coordinates",20,-4,4,20,-20,20);
2256 float px, py;
2257 for (Int_t i = 0; i < 25000; i++) {
2258 gRandom->Rannor(px,py);
2259 hscc->Fill(px-1,5*py);
2260 hscc->Fill(2+0.5*px,2*py-10.,0.1);
2261 }
2262 c4->cd(1); hscc->Draw("SURF1 CYL");
2263 c4->cd(2); auto hspc = (TH2F*) hscc->DrawClone("SURF1 POL");
2264 hspc->SetTitle("Polar coordinates");
2265 c4->cd(3); auto hssc = (TH2F*) hscc->DrawClone("SURF1 SPH");
2266 hssc->SetTitle("Spherical coordinates");
2267 c4->cd(4); auto hsprpc = (TH2F*) hscc->DrawClone("SURF1 PSR");
2268 hsprpc->SetTitle("PseudoRapidity/Phi coordinates");
2269}
2270End_Macro
2271
2272
2273\anchor HP20
2274### Base line for bar-charts and lego plots
2275
2276
2277By default the base line used to draw the boxes for bar-charts and lego plots is
2278the histogram minimum. It is possible to force this base line to be 0, using MIN0 draw
2279option or with the command:
2280
2281 gStyle->SetHistMinimumZero();
2282
2283Begin_Macro(source)
2284{
2285 auto c5 = new TCanvas("c5","c5",700,400);
2286 c5->Divide(2,1);
2287 auto hz1 = new TH1F("hz1","Bar-chart drawn from 0",20,-3,3);
2288 auto hz2 = new TH2F("hz2","Lego plot drawn from 0",20,-3,3,20,-3,3);
2289 Int_t i;
2290 double x,y;
2291 hz1->SetFillColor(kBlue);
2292 hz2->SetFillColor(kBlue);
2293 for (i=0;i<10000;i++) {
2294 x = gRandom->Gaus(0,1);
2295 y = gRandom->Gaus(0,1);
2296 if (x>0) {
2297 hz1->Fill(x,1);
2298 hz2->Fill(x,y,1);
2299 } else {
2300 hz1->Fill(x,-1);
2301 hz2->Fill(x,y,-2);
2302 }
2303 }
2304 c5->cd(1); hz1->Draw("bar2 min0");
2305 c5->cd(2); hz2->Draw("lego1 min0");
2306}
2307End_Macro
2308
2309This option also works for horizontal plots. The example given in the section
2310["The bar chart option"](\ref HP100) appears as follow:
2311
2312Begin_Macro(source)
2313{
2314 int i;
2315 const Int_t nx = 8;
2316 string os_X[nx] = {"8","32","128","512","2048","8192","32768","131072"};
2317 float d_35_0[nx] = {0.75, -3.30, -0.92, 0.10, 0.08, -1.69, -1.29, -2.37};
2318 float d_35_1[nx] = {1.01, -3.02, -0.65, 0.37, 0.34, -1.42, -1.02, -2.10};
2319
2320 auto cbh = new TCanvas("cbh","cbh",400,600);
2321 cbh->SetGrid();
2322
2323 auto h1bh = new TH1F("h1bh","Option HBAR centered on 0",nx,0,nx);
2324 h1bh->SetFillColor(4);
2325 h1bh->SetBarWidth(0.4);
2326 h1bh->SetBarOffset(0.1);
2327 h1bh->SetStats(0);
2328 h1bh->SetMinimum(-5);
2329 h1bh->SetMaximum(5);
2330
2331 for (i=1; i<=nx; i++) {
2332 h1bh->Fill(os_X[i-1].c_str(), d_35_0[i-1]);
2333 h1bh->GetXaxis()->SetBinLabel(i,os_X[i-1].c_str());
2334 }
2335
2336 h1bh->Draw("hbar min0");
2337
2338 auto h2bh = new TH1F("h2bh","h2bh",nx,0,nx);
2339 h2bh->SetFillColor(38);
2340 h2bh->SetBarWidth(0.4);
2341 h2bh->SetBarOffset(0.5);
2342 h2bh->SetStats(0);
2343 for (i=1;i<=nx;i++) h2bh->Fill(os_X[i-1].c_str(), d_35_1[i-1]);
2344
2345 h2bh->Draw("hbar min0 same");
2346}
2347End_Macro
2348
2349
2350\anchor HP20a
2351### TH2Poly Drawing
2352
2353
2354The following options are supported:
2355
2356| Option | Description |
2357|----------|-------------------------------------------------------------------|
2358| "SCAT" | Draw a scatter plot (legacy draw option).|
2359| "COL" | Draw a color plot. All the bins are painted even the empty bins (default).|
2360| "COLZ" | Same as "COL". In addition the color palette is also drawn.|
2361| "0" | When used with any COL options, the empty bins are not drawn.|
2362| "TEXT" | Draw bin contents as text (format set via `gStyle->SetPaintTextFormat`).|
2363| "TEXTN" | Draw bin names as text.|
2364| "TEXTnn" | Draw bin contents as text at angle nn (0 < nn <= 90).|
2365| "L" | Draw the bins boundaries as lines. The lines attributes are the TGraphs ones.|
2366| "P" | Draw the bins boundaries as markers. The markers attributes are the TGraphs ones.|
2367| "F" | Draw the bins boundaries as filled polygons. The filled polygons attributes are the TGraphs ones.|
2368
2369
2370
2371`TH2Poly` can be drawn as a color plot (option COL). `TH2Poly` bins can have any
2372shapes. The bins are defined as graphs. The following macro is a very simple
2373example showing how to book a TH2Poly and draw it.
2374
2375Begin_Macro(source)
2376{
2377 auto ch2p1 = new TCanvas("ch2p1","ch2p1",600,400);
2378 auto h2p = new TH2Poly();
2379 h2p->SetName("h2poly_name");
2380 h2p->SetTitle("h2poly_title");
2381 double px1[] = {0, 5, 6};
2382 double py1[] = {0, 0, 5};
2383 double px2[] = {0, -1, -1, 0};
2384 double py2[] = {0, 0, -1, 3};
2385 double px3[] = {4, 3, 0, 1, 2.4};
2386 double py3[] = {4, 3.7, 1, 3.7, 2.5};
2387 h2p->AddBin(3, px1, py1);
2388 h2p->AddBin(4, px2, py2);
2389 h2p->AddBin(5, px3, py3);
2390 h2p->Fill(0.1, 0.01, 3);
2391 h2p->Fill(-0.5, -0.5, 7);
2392 h2p->Fill(-0.7, -0.5, 1);
2393 h2p->Fill(1, 3, 1.5);
2394 double fx[] = {0.1, -0.5, -0.7, 1};
2395 double fy[] = {0.01, -0.5, -0.5, 3};
2396 double fw[] = {3, 1, 1, 1.5};
2397 h2p->FillN(4, fx, fy, fw);
2398 h2p->Draw("col");
2399}
2400End_Macro
2401
2402Rectangular bins are a frequent case. The special version of
2403the `AddBin` method allows to define them more easily like
2404shown in the following example (hist037_TH2Poly_boxes.C).
2405
2406Begin_Macro(source)
2407../../../tutorials/hist/hist037_TH2Poly_boxes.C
2408End_Macro
2409
2410One `TH2Poly` bin can be a list of polygons. Such bins are defined
2411by calling `AddBin` with a `TMultiGraph`. The following example
2412shows a such case:
2413
2414Begin_Macro(source)
2415{
2416 auto ch2p2 = new TCanvas("ch2p2","ch2p2",600,400);
2417
2418 Int_t i, bin;
2419 const Int_t nx = 48;
2420 const char *states [nx] = {
2421 "alabama", "arizona", "arkansas", "california",
2422 "colorado", "connecticut", "delaware", "florida",
2423 "georgia", "idaho", "illinois", "indiana",
2424 "iowa", "kansas", "kentucky", "louisiana",
2425 "maine", "maryland", "massachusetts", "michigan",
2426 "minnesota", "mississippi", "missouri", "montana",
2427 "nebraska", "nevada", "new_hampshire", "new_jersey",
2428 "new_mexico", "new_york", "north_carolina", "north_dakota",
2429 "ohio", "oklahoma", "oregon", "pennsylvania",
2430 "rhode_island", "south_carolina", "south_dakota", "tennessee",
2431 "texas", "utah", "vermont", "virginia",
2432 "washington", "west_virginia", "wisconsin", "wyoming"
2433 };
2434 Double_t pop[nx] = {
2435 4708708, 6595778, 2889450, 36961664, 5024748, 3518288, 885122, 18537969,
2436 9829211, 1545801, 12910409, 6423113, 3007856, 2818747, 4314113, 4492076,
2437 1318301, 5699478, 6593587, 9969727, 5266214, 2951996, 5987580, 974989,
2438 1796619, 2643085, 1324575, 8707739, 2009671, 19541453, 9380884, 646844,
2439 11542645, 3687050, 3825657, 12604767, 1053209, 4561242, 812383, 6296254,
2440 24782302, 2784572, 621760, 7882590, 6664195, 1819777, 5654774, 544270
2441 };
2442
2443 Double_t lon1 = -130;
2444 Double_t lon2 = -65;
2445 Double_t lat1 = 24;
2446 Double_t lat2 = 50;
2447 auto p = new TH2Poly("USA","USA Population",lon1,lon2,lat1,lat2);
2448
2449 TFile::SetCacheFileDir(".");
2450 auto f = TFile::Open("http://root.cern/files/usa.root", "CACHEREAD");
2451
2452 TMultiGraph *mg;
2453 TKey *key;
2454 TIter nextkey(gDirectory->GetListOfKeys());
2455 while ((key = (TKey*)nextkey())) {
2456 TObject *obj = key->ReadObj();
2457 if (obj->InheritsFrom("TMultiGraph")) {
2458 mg = (TMultiGraph*)obj;
2459 bin = p->AddBin(mg);
2460 }
2461 }
2462
2463 for (i=0; i<nx; i++) p->Fill(states[i], pop[i]);
2464
2465 gStyle->SetOptStat(11);
2466 p->Draw("COLZ L");
2467}
2468End_Macro
2469
2470`TH2Poly` histograms can also be plotted using the GL interface using
2471the option "GLLEGO".
2472
2473\since **ROOT version 6.09/01**
2474
2475In some cases it can be useful to not draw the empty bins. the option "0"
2476combined with the option "COL" and "COLZ" allows to do that.
2477
2478Begin_Macro(source)
2479{
2480 auto chc = new TCanvas("chc","chc",600,400);
2481
2482 auto hc = new TH2Poly();
2483 hc->Honeycomb(0,0,.1,25,25);
2484 hc->SetName("hc");
2485 hc->SetTitle("Option COLZ 0");
2486 TRandom ran;
2487 for (int i = 0; i<300; i++) hc->Fill(ran.Gaus(2.,1), ran.Gaus(2.,1));
2488 hc->Draw("colz 0");
2489}
2490End_Macro
2491
2492\anchor HP21
2493### The SPEC option
2494
2495
2496This option allows to use the `TSpectrum2Painter` tools. See the full
2497documentation in `TSpectrum2Painter::PaintSpectrum`.
2498
2499
2500\anchor HP22
2501### Option "Z" : Adding the color palette on the right side of the pad
2502
2503
2504When this option is specified, a color palette with an axis indicating the value
2505of the corresponding color is drawn on the right side of the picture. In case,
2506not enough space is left, one can increase the size of the right margin by
2507calling `TPad::SetRightMargin()`. The attributes used to display the
2508palette axis values are taken from the Z axis of the object. For example, to
2509set the labels size on the palette axis do:
2510
2511 hist->GetZaxis()->SetLabelSize().
2512
2513<b>WARNING:</b> The palette axis is always drawn vertically.
2514
2515
2516\anchor HP23
2517### Setting the color palette
2518
2519
2520To change the color palette `TStyle::SetPalette` should be used, eg:
2521
2522 gStyle->SetPalette(ncolors,colors);
2523
2524For example the option `COL` draws a 2D histogram with cells
2525represented by a box filled with a color index which is a function
2526of the cell content.
2527If the cell content is N, the color index used will be the color number
2528in `colors[N]`, etc. If the maximum cell content is greater than
2529`ncolors`, all cell contents are scaled to `ncolors`.
2530
2531If ` ncolors <= 0`, a default palette (see below) of 50 colors is
2532defined. This palette is recommended for pads, labels ...
2533
2534`if ncolors == 1 && colors == 0`, then a Pretty Palette with a
2535Spectrum Violet->Red is created with 50 colors. That's the default rain bow
2536palette.
2537
2538Other pre-defined palettes with 255 colors are available when `colors == 0`.
2539The following value of `ncolors` give access to:
2540
2541
2542 if ncolors = 51 and colors=0, a Deep Sea palette is used.
2543 if ncolors = 52 and colors=0, a Grey Scale palette is used.
2544 if ncolors = 53 and colors=0, a Dark Body Radiator palette is used.
2545 if ncolors = 54 and colors=0, a two-color hue palette palette is used.(dark blue through neutral gray to bright
2546yellow) if ncolors = 55 and colors=0, a Rain Bow palette is used. if ncolors = 56 and colors=0, an inverted Dark Body
2547Radiator palette is used.
2548
2549
2550If `ncolors > 0 && colors == 0`, the default palette is used with a maximum of ncolors.
2551
2552The default palette defines:
2553
2554- index 0 to 9 : shades of grey
2555- index 10 to 19 : shades of brown
2556- index 20 to 29 : shades of blue
2557- index 30 to 39 : shades of red
2558- index 40 to 49 : basic colors
2559
2560The color numbers specified in the palette can be viewed by selecting
2561the item `colors` in the `VIEW` menu of the canvas tool bar.
2562The red, green, and blue components of a color can be changed thanks to
2563`TColor::SetRGB()`.
2564
2565\since **ROOT version 6.19/01**
2566
2567As default labels and ticks are drawn by `TGAxis` at equidistant (lin or log)
2568points as controlled by SetNdivisions.
2569If option "CJUST" is given labels and ticks are justified at the
2570color boundaries defined by the contour levels.
2571For more details see `TPaletteAxis`
2572
2573\anchor HP24
2574### Drawing a sub-range of a 2D histogram; the [cutg] option
2575
2576
2577Using a `TCutG` object, it is possible to draw a sub-range of a 2D
2578histogram. One must create a graphical cut (mouse or C++) and specify the name
2579of the cut between `[]` in the `Draw()` option.
2580For example (fit2a.C), with a `TCutG` named `cutg`, one can call:
2581
2582 myhist->Draw("surf1 [cutg]");
2583
2584To invert the cut, it is enough to put a `-` in front of its name:
2585
2586 myhist->Draw("surf1 [-cutg]");
2587
2588It is possible to apply several cuts (`,` means logical AND):
2589
2590 myhist->Draw("surf1 [cutg1,cutg2]");
2591
2592Begin_Macro(source)
2593../../../tutorials/fit/fit2a.C
2594End_Macro
2595
2596\anchor HP25
2597### Drawing options for 3D histograms
2598
2599
2600| Option | Description |
2601|----------|-------------------------------------------------------------------|
2602| "SCAT" | Draw a scatter plot (legacy draw option).|
2603| "ISO" | Draw a Gouraud shaded 3d iso surface through a 3d histogram. It paints one surface at the value computed as follow: `SumOfWeights/(NbinsX*NbinsY*NbinsZ)`|
2604| "BOX" | Draw a for each cell with volume proportional to the content's absolute value. An hidden line removal algorithm is used|
2605| "BOX1" | Same as BOX but an hidden surface removal algorithm is used|
2606| "BOX2" | Same as "COL". The boxes' colors are picked in the current palette according to the bins' contents (default)|
2607| "BOX2Z" | Same as "BOX2". In addition the color palette is also drawn.|
2608| "BOX3" | Same as BOX1, but the border lines of each lego-bar are not drawn.|
2609
2610Note that instead of `BOX` one can also use `LEGO`.
2611
2612By default, 3D histograms are drawn as a colored box plots.
2613
2614The following example shows a 3D histogram plotted as a scatter plot.
2615
2616Begin_Macro(source)
2617{
2618 auto c06 = new TCanvas("c06","c06",600,400);
2619 gStyle->SetOptStat(kFALSE);
2620 auto h3scat = new TH3F("h3scat","Option SCAT",15,-2,2,15,-2,2,15,0,4);
2621 double x, y, z;
2622 for (Int_t i=0;i<10000;i++) {
2623 gRandom->Rannor(x, y);
2624 z = x*x + y*y;
2625 h3scat->Fill(x,y,z);
2626 }
2627 h3scat->Draw("SCAT"); // This a legacy draw option
2628}
2629End_Macro
2630
2631The following example shows a 3D histogram plotted with the option `BOX`.
2632
2633Begin_Macro(source)
2634{
2635 auto c16 = new TCanvas("c16","c16",600,400);
2636 gStyle->SetOptStat(kFALSE);
2637 auto h3box = new TH3F("h3box","Option BOX",15,-2,2,15,-2,2,15,0,4);
2638 double x, y, z;
2639 for (Int_t i=0;i<10000;i++) {
2640 gRandom->Rannor(x, y);
2641 z = x*x + y*y;
2642 h3box->Fill(x,y,z);
2643 }
2644 h3box->Draw("BOX");
2645}
2646End_Macro
2647
2648The following example shows a 3D histogram plotted with the option `BOX1`.
2649
2650Begin_Macro(source)
2651{
2652 auto c36 = new TCanvas("c36","c36",600,400);
2653 gStyle->SetOptStat(kFALSE);
2654 auto h3box = new TH3F("h3box","Option BOX1",10,-2.,2.,10,-2.,2.,10,-0.5,2.);
2655 double x, y, z;
2656 for (Int_t i=0;i<10000;i++) {
2657 gRandom->Rannor(x, y);
2658 z = abs(sin(x)/x + cos(y)*y);
2659 h3box->Fill(x,y,z);
2660 }
2661 h3box->SetFillColor(9);
2662 h3box->Draw("BOX1");
2663}
2664End_Macro
2665
2666The following example shows a 3D histogram plotted with the option `BOX2`.
2667
2668Begin_Macro(source)
2669{
2670 auto c56 = new TCanvas("c56","c56",600,400);
2671 gStyle->SetOptStat(kFALSE);
2672 auto h3box = new TH3F("h3box","Option BOX2 (default)",10,-2.,2.,10,-2.,2.,10,-0.5,2.);
2673 double x, y, z;
2674 for (Int_t i=0;i<10000;i++) {
2675 gRandom->Rannor(x, y);
2676 z = abs(sin(x)/x + cos(y)*y);
2677 h3box->Fill(x,y,z);
2678 }
2679 h3box->Draw("BOX2 Z");
2680}
2681End_Macro
2682
2683The following example shows a 3D histogram plotted with the option `BOX3`.
2684
2685Begin_Macro(source)
2686{
2687 auto c46 = new TCanvas("c46","c46",600,400);
2688 c46->SetFillColor(38);
2689 gStyle->SetOptStat(kFALSE);
2690 auto h3box = new TH3F("h3box","Option BOX3",15,-2,2,15,-2,2,15,0,4);
2691 double x, y, z;
2692 for (Int_t i=0;i<10000;i++) {
2693 gRandom->Rannor(x, y);
2694 z = x*x + y*y;
2695 h3box->Fill(x,y,z);
2696 }
2697 h3box->Draw("BOX3");
2698}
2699End_Macro
2700
2701For all the `BOX` options each bin is drawn as a 3D box with a volume proportional
2702to the absolute value of the bin content. The bins with a negative content are
2703drawn with a X on each face of the box as shown in the following example:
2704
2705Begin_Macro(source)
2706{
2707 auto c = new TCanvas("c","c",600,400);
2708 gStyle->SetOptStat(kFALSE);
2709 auto h3box = new TH3F("h3box","Option BOX1 with negative bins",3, 0., 4., 3, 0.,4., 3, 0., 4.);
2710 h3box->Fill(0., 2., 2., 10.);
2711 h3box->Fill(2., 2., 2., 5.);
2712 h3box->Fill(2., 2., .5, 2.);
2713 h3box->Fill(2., 2., 3., -1.);
2714 h3box->Fill(3., 2., 2., -10.);
2715 h3box->SetFillColor(8);
2716 h3box->Draw("box1");
2717}
2718End_Macro
2719
2720The following example shows a 3D histogram plotted with the option `ISO`.
2721
2722Begin_Macro(source)
2723{
2724 auto c26 = new TCanvas("c26","c26",600,400);
2725 gStyle->SetOptStat(kFALSE);
2726 auto h3iso = new TH3F("h3iso","Option ISO",15,-2,2,15,-2,2,15,0,4);
2727 double x, y, z;
2728 for (Int_t i=0;i<10000;i++) {
2729 gRandom->Rannor(x, y);
2730 z = x*x + y*y;
2731 h3iso->Fill(x,y,z);
2732 }
2733 h3iso->SetFillColor(kCyan);
2734 h3iso->Draw("ISO");
2735}
2736End_Macro
2737
2738
2739\anchor HP26
2740### Drawing option for histograms' stacks
2741
2742
2743Stacks of histograms are managed with the `THStack`. A `THStack`
2744is a collection of `TH1` (or derived) objects. For painting only the
2745`THStack` containing `TH1` only or
2746`THStack` containing `TH2` only will be considered.
2747
2748By default, histograms are shown stacked:
2749
27501. The first histogram is paint.
27512. The sum of the first and second, etc...
2752
2753If the option `NOSTACK` is specified, the histograms are all paint in
2754the same pad as if the option `SAME` had been specified. This allows to
2755compute X and Y scales common to all the histograms, like
2756`TMultiGraph` does for graphs.
2757
2758If the option `PADS` is specified, the current pad/canvas is subdivided into
2759a number of pads equal to the number of histograms and each histogram is paint
2760into a separate pad. With `PADSn`, the current pad/canvas is subdivided into
2761`n` columns, automatically calculating the number of rows.
2762
2763The following example shows various types of stacks (hist023_THStack_simple.C).
2764
2765Begin_Macro(source)
2766../../../tutorials/hist/hist023_THStack_simple.C
2767End_Macro
2768
2769The option `nostackb` allows to draw the histograms next to each
2770other as bar charts:
2771
2772Begin_Macro(source)
2773{
2774 auto cst0 = new TCanvas("cst0","cst0",600,400);
2775 auto hs = new THStack("hs","Stacked 1D histograms: option #font[82]{\"nostackb\"}");
2776
2777 auto h1 = new TH1F("h1","h1",10,-4,4);
2778 h1->FillRandom("gaus",20000);
2779 h1->SetFillColor(kRed);
2780 hs->Add(h1);
2781
2782 auto h2 = new TH1F("h2","h2",10,-4,4);
2783 h2->FillRandom("gaus",15000);
2784 h2->SetFillColor(kBlue);
2785 hs->Add(h2);
2786
2787 auto h3 = new TH1F("h3","h3",10,-4,4);
2788 h3->FillRandom("gaus",10000);
2789 h3->SetFillColor(kGreen);
2790 hs->Add(h3);
2791
2792 hs->Draw("nostackb");
2793 hs->GetXaxis()->SetNdivisions(-10);
2794 cst0->SetGridx();
2795}
2796End_Macro
2797
2798If at least one of the histograms in the stack has errors, the whole stack is
2799visualized by default with error bars. To visualize it without errors the
2800option `HIST` should be used.
2801
2802Begin_Macro(source)
2803{
2804 auto cst1 = new TCanvas("cst1","cst1",700,400);
2805 cst1->Divide(2,1);
2806
2807 auto hst11 = new TH1F("hst11", "", 20, -10, 10);
2808 hst11->Sumw2();
2809 hst11->FillRandom("gaus", 1000);
2810 hst11->SetFillColor(kViolet);
2811 hst11->SetLineColor(kViolet);
2812
2813 auto hst12 = new TH1F("hst12", "", 20, -10, 10);
2814 hst12->FillRandom("gaus", 500);
2815 hst12->SetFillColor(kBlue);
2816 hst12->SetLineColor(kBlue);
2817
2818 THStack st1("st1", "st1");
2819 st1.Add(hst11);
2820 st1.Add(hst12);
2821
2822 cst1->cd(1); st1.Draw();
2823 cst1->cd(2); st1.Draw("hist");
2824}
2825End_Macro
2826
2827\anchor HP27
2828### Drawing of 3D implicit functions
2829
2830
28313D implicit functions (`TF3`) can be drawn as iso-surfaces.
2832The implicit function f(x,y,z) = 0 is drawn in cartesian coordinates.
2833In the following example the options "FB" and "BB" suppress the
2834"Front Box" and "Back Box" around the plot.
2835
2836Begin_Macro(source)
2837{
2838 auto c2 = new TCanvas("c2","c2",600,400);
2839 auto f3 = new TF3("f3","sin(x*x+y*y+z*z-36)",-2,2,-2,2,-2,2);
2840 f3->SetClippingBoxOn(0,0,0);
2841 f3->SetFillColor(30);
2842 f3->SetLineColor(15);
2843 f3->Draw("FBBB");
2844}
2845End_Macro
2846
2847
2848\anchor HP28
2849### Associated functions drawing
2850
2851
2852An associated function is created by `TH1::Fit`. More than on fitted
2853function can be associated with one histogram (see `TH1::Fit`).
2854
2855A `TF1` object `f1` can be added to the list of associated
2856functions of an histogram `h` without calling `TH1::Fit`
2857simply doing:
2858
2859 h->GetListOfFunctions()->Add(f1);
2860
2861or
2862
2863 h->GetListOfFunctions()->Add(f1,someoption);
2864
2865To retrieve a function by name from this list, do:
2866
2867 TF1 *f1 = (TF1*)h->GetListOfFunctions()->FindObject(name);
2868
2869or
2870
2871 TF1 *f1 = h->GetFunction(name);
2872
2873Associated functions are automatically painted when an histogram is drawn.
2874To avoid the painting of the associated functions the option `HIST`
2875should be added to the list of the options used to paint the histogram.
2876
2877
2878\anchor HP29
2879### Drawing using OpenGL
2880
2881
2882The class `TGLHistPainter` allows to paint data set using the OpenGL 3D
2883graphics library. The plotting options start with `GL` keyword.
2884In addition, in order to inform canvases that OpenGL should be used to render
28853D representations, the following option should be set:
2886
2887 gStyle->SetCanvasPreferGL(true);
2888
2889
2890\anchor HP29a
2891#### General information: plot types and supported options
2892
2893The following types of plots are provided:
2894
2895For lego plots the supported options are:
2896
2897| Option | Description |
2898|----------|-------------------------------------------------------------------|
2899| "GLLEGO" | Draw a lego plot. It works also for `TH2Poly`.|
2900| "GLLEGO2"| Bins with color levels.|
2901| "GLLEGO3"| Cylindrical bars.|
2902
2903
2904
2905Lego painter in cartesian supports logarithmic scales for X, Y, Z.
2906In polar only Z axis can be logarithmic, in cylindrical only Y.
2907
2908For surface plots (`TF2` and `TH2`) the supported options are:
2909
2910| Option | Description |
2911|-----------|------------------------------------------------------------------|
2912| "GLSURF" | Draw a surface.|
2913| "GLSURF1" | Surface with color levels|
2914| "GLSURF2" | The same as "GLSURF1" but without polygon outlines.|
2915| "GLSURF3" | Color level projection on top of plot (works only in cartesian coordinate system).|
2916| "GLSURF4" | Same as "GLSURF" but without polygon outlines.|
2917
2918
2919
2920The surface painting in cartesian coordinates supports logarithmic scales along
2921X, Y, Z axis. In polar coordinates only the Z axis can be logarithmic,
2922in cylindrical coordinates only the Y axis.
2923
2924Additional options to SURF and LEGO - Coordinate systems:
2925
2926| Option | Description |
2927|----------|-------------------------------------------------------------------|
2928| " " | Default, cartesian coordinates system.|
2929| "POL" | Polar coordinates system.|
2930| "CYL" | Cylindrical coordinates system.|
2931| "SPH" | Spherical coordinates system.|
2932
2933
2934
2935\anchor HP290
2936#### TH3 as color boxes
2937
2938The supported option is:
2939
2940| Option | Description |
2941|----------|-------------------------------------------------------------------|
2942| "GLCOL" | H3 is drawn using semi-transparent colored boxes. See glvox1.C .|
2943
2944
2945
2946\anchor HP29b
2947#### TH3 as boxes (spheres)
2948
2949The supported options are:
2950
2951| Option | Description |
2952|----------|-------------------------------------------------------------------|
2953| "GLBOX" | TH3 as a set of boxes, size of box is proportional to bin content.|
2954| "GLBOX1" | The same as "glbox", but spheres are drawn instead of boxes.|
2955
2956
2957
2958\anchor HP29c
2959#### TH3 as iso-surface(s)
2960
2961The supported option is:
2962
2963| Option | Description |
2964|----------|-------------------------------------------------------------------|
2965| "GLISO" | TH3 is drawn using iso-surfaces.|
2966
2967
2968
2969\anchor HP29d
2970#### TF3 (implicit function)
2971
2972The supported option is:
2973
2974| Option | Description |
2975|----------|-------------------------------------------------------------------|
2976| "GL" | Draw a TF3.|
2977
2978
2979
2980\anchor HP29e
2981#### Parametric surfaces
2982
2983glparametric.C shows how to create parametric equations and visualize the surface.
2984
2985\anchor HP29f
2986#### Interaction with the plots
2987
2988All the interactions are implemented via standard methods
2989`DistancetoPrimitive()` and `ExecuteEvent()`. That's why all the
2990interactions with the OpenGL plots are possible only when the mouse cursor is
2991in the plot's area (the plot's area is the part of a the pad occupied by
2992gl-produced picture). If the mouse cursor is not above gl-picture, the standard
2993pad interaction is performed.
2994
2995\anchor HP29g
2996#### Selectable parts
2997
2998Different parts of the plot can be selected:
2999
3000- xoz, yoz, xoy back planes: When such a plane selected, it's highlighted in green
3001 if the dynamic slicing by this plane is supported, and it's highlighted in red,
3002 if the dynamic slicing is not supported.
3003- The plot itself:
3004 On surfaces, the selected surface is outlined in red. (TF3 and
3005 ISO are not outlined). On lego plots, the selected bin is
3006 highlighted. The bin number and content are displayed in pad's
3007 status bar. In box plots, the box or sphere is highlighted and
3008 the bin info is displayed in pad's status bar.
3009
3010
3011\anchor HP29h
3012#### Rotation and zooming
3013
3014
3015- Rotation:
3016 When the plot is selected, it can be rotated by pressing and
3017 holding the left mouse button and move the cursor.
3018- Zoom/Unzoom:
3019 Mouse wheel or 'j', 'J', 'k', 'K' keys.
3020
3021
3022\anchor HP29i
3023#### Panning
3024
3025The selected plot can be moved in a pad's area by pressing and
3026holding the left mouse button and the shift key.
3027
3028\anchor HP29j
3029#### Box cut
3030
3031Surface, iso, box, TF3 and parametric painters support box cut by
3032pressing the 'c' or 'C' key when the mouse cursor is in a plot's
3033area. That will display a transparent box, cutting away part of the
3034surface (or boxes) in order to show internal part of plot. This box
3035can be moved inside the plot's area (the full size of the box is
3036equal to the plot's surrounding box) by selecting one of the box
3037cut axes and pressing the left mouse button to move it.
3038
3039\anchor HP29k
3040#### Plot specific interactions (dynamic slicing etc.)
3041
3042Currently, all gl-plots support some form of slicing. When back plane
3043is selected (and if it's highlighted in green) you can press and hold
3044left mouse button and shift key and move this back plane inside
3045plot's area, creating the slice. During this "slicing" plot becomes
3046semi-transparent. To remove all slices (and projected curves for
3047surfaces) double click with left mouse button in a plot's area.
3048
3049\anchor HP29l
3050#### Surface with option "GLSURF"
3051
3052The surface profile is displayed on the slicing plane.
3053The profile projection is drawn on the back plane
3054by pressing `'p'` or `'P'` key.
3055
3056\anchor HP29m
3057#### TF3
3058
3059The contour plot is drawn on the slicing plane. For TF3 the color
3060scheme can be changed by pressing 's' or 'S'.
3061
3062\anchor HP29n
3063#### Box
3064
3065The contour plot corresponding to slice plane position is drawn in real time.
3066
3067\anchor HP29o
3068#### Iso
3069
3070Slicing is similar to "GLBOX" option.
3071
3072\anchor HP29p
3073#### Parametric plot
3074
3075No slicing. Additional keys: 's' or 'S' to change color scheme -
3076about 20 color schemes supported ('s' for "scheme"); 'l' or 'L' to
3077increase number of polygons ('l' for "level" of details), 'w' or 'W'
3078to show outlines ('w' for "wireframe").
3079
3080\anchor HP30
3081#### Highlight mode for histogram
3082
3083\since **ROOT version 6.15/01**
3084
3085\image html hlHisto3_top.gif "Highlight mode"
3086
3087Highlight mode is implemented for `TH1` (and for `TGraph`) class. When
3088highlight mode is on, mouse movement over the bin will be represented
3089graphically. Bin will be highlighted as "bin box" (presented by box
3090object). Moreover, any highlight (change of bin) emits signal
3091`TCanvas::Highlighted()` which allows the user to react and call their own
3092function. For a better understanding see also the tutorial `hist043` to `hist046`
3093located in `$ROOTSYS/tutorials/hist/`.
3094
3095Highlight mode is switched on/off by `TH1::SetHighlight()` function
3096or interactively from `TH1` context menu. `TH1::IsHighlight()` to verify
3097whether the highlight mode enabled or disabled, default it is disabled.
3098
3099~~~ {.cpp}
3100 root [0] .x $ROOTSYS/tutorials/hsimple.C
3101 root [1] hpx->SetHighlight(kTRUE) // or interactively from TH1 context menu
3102 root [2] hpx->IsHighlight()
3103 (bool) true
3104~~~
3105
3106\image html hlsimple_nofun.gif "Highlight mode for histogram"
3107
3108\anchor HP30a
3109#### Highlight mode and user function
3110
3111The user can use (connect) `TCanvas::Highlighted()` signal, which is always
3112emitted if there is a highlight bin and call user function via signal
3113and slot communication mechanism. `TCanvas::Highlighted()` is similar
3114`TCanvas::Picked()`
3115
3116- when selected object (histogram as a whole) is different from previous
3117then emit `Picked()` signal
3118- when selected (highlighted) bin from histogram is different from previous
3119then emit `Highlighted()` signal
3120
3121Any user function (or functions) has to be defined
3122`UserFunction(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)`.
3123In example (see below) has name `PrintInfo()`. All parameters of user
3124function are taken from
3125
3126 void TCanvas::Highlighted(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)
3127
3128- `pad` is pointer to pad with highlighted histogram
3129- `obj` is pointer to highlighted histogram
3130- `x` is highlighted x bin for 1D histogram
3131- `y` is highlighted y bin for 2D histogram (for 1D histogram not in use)
3132
3133Example how to create a connection from any `TCanvas` object to a user
3134`UserFunction()` slot (see also `TQObject::Connect()` for additional info)
3135
3136 TQObject::Connect("TCanvas", "Highlighted(TVirtualPad*,TObject*,Int_t,Int_t)",
3137 0, 0, "UserFunction(TVirtualPad*,TObject*,Int_t,Int_t)");
3138
3139or use non-static "simplified" function
3140`TCanvas::HighlightConnect(const char *slot)`
3141
3142 c1->HighlightConnect("UserFunction(TVirtualPad*,TObject*,Int_t,Int_t)");
3143
3144NOTE the signal and slot string must have a form
3145"(TVirtualPad*,TObject*,Int_t,Int_t)"
3146
3147 root [0] .x $ROOTSYS/tutorials/hsimple.C
3148 root [1] hpx->SetHighlight(kTRUE)
3149 root [2] .x hlprint.C
3150
3151file `hlprint.C`
3152~~~ {.cpp}
3153void PrintInfo(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)
3154{
3155 auto h = (TH1F *)obj;
3156 if (!h->IsHighlight()) // after highlight disabled
3157 h->SetTitle("highlight disable");
3158 else
3159 h->SetTitle(TString::Format("bin[%03d] (%5.2f) content %g", x,
3160 h->GetBinCenter(x), h->GetBinContent(x)));
3161 pad->Update();
3162}
3163
3164void hlprint()
3165{
3166 if (!gPad) return;
3167 gPad->GetCanvas()->HighlightConnect("PrintInfo(TVirtualPad*,TObject*,Int_t,Int_t)");
3168}
3169~~~
3170
3171\image html hlsimple.gif "Highlight mode and simple user function"
3172
3173For more complex demo please see for example tree200_temperature.C file.
3174
3175*/
3176
3178
3181
3182const Int_t kNMAX = 2000;
3183
3184const Int_t kMAXCONTOUR = 104;
3186
3187static std::unique_ptr<TBox> gXHighlightBox, gYHighlightBox; // highlight X and Y box
3188
3210
3211
3212////////////////////////////////////////////////////////////////////////////////
3213/// Default constructor.
3214
3216{
3217 fH = nullptr;
3218 fXaxis = nullptr;
3219 fYaxis = nullptr;
3220 fZaxis = nullptr;
3221 fFunctions = nullptr;
3222 fNcuts = 0;
3223 fStack = nullptr;
3224 fShowProjection = 0;
3225 fShowProjection2 = 0;
3226 fShowOption = "";
3227 for (int i=0; i<kMaxCuts; i++) {
3228 fCuts[i] = nullptr;
3229 fCutsOpt[i] = 0;
3230 }
3231 fXHighlightBin = -1;
3232 fYHighlightBin = -1;
3233 fCurrentF3 = nullptr;
3234
3235 gStringEntries = gEnv->GetValue("Hist.Stats.Entries", "Entries");
3236 gStringMean = gEnv->GetValue("Hist.Stats.Mean", "Mean");
3237 gStringMeanX = gEnv->GetValue("Hist.Stats.MeanX", "Mean x");
3238 gStringMeanY = gEnv->GetValue("Hist.Stats.MeanY", "Mean y");
3239 gStringMeanZ = gEnv->GetValue("Hist.Stats.MeanZ", "Mean z");
3240 gStringStdDev = gEnv->GetValue("Hist.Stats.StdDev", "Std Dev");
3241 gStringStdDevX = gEnv->GetValue("Hist.Stats.StdDevX", "Std Dev x");
3242 gStringStdDevY = gEnv->GetValue("Hist.Stats.StdDevY", "Std Dev y");
3243 gStringStdDevZ = gEnv->GetValue("Hist.Stats.StdDevZ", "Std Dev z");
3244 gStringUnderflow = gEnv->GetValue("Hist.Stats.Underflow", "Underflow");
3245 gStringOverflow = gEnv->GetValue("Hist.Stats.Overflow", "Overflow");
3246 gStringIntegral = gEnv->GetValue("Hist.Stats.Integral", "Integral");
3247 gStringIntegralBinWidth = gEnv->GetValue("Hist.Stats.IntegralBinWidth", "Integral(w)");
3248 gStringSkewness = gEnv->GetValue("Hist.Stats.Skewness", "Skewness");
3249 gStringSkewnessX = gEnv->GetValue("Hist.Stats.SkewnessX", "Skewness x");
3250 gStringSkewnessY = gEnv->GetValue("Hist.Stats.SkewnessY", "Skewness y");
3251 gStringSkewnessZ = gEnv->GetValue("Hist.Stats.SkewnessZ", "Skewness z");
3252 gStringKurtosis = gEnv->GetValue("Hist.Stats.Kurtosis", "Kurtosis");
3253 gStringKurtosisX = gEnv->GetValue("Hist.Stats.KurtosisX", "Kurtosis x");
3254 gStringKurtosisY = gEnv->GetValue("Hist.Stats.KurtosisY", "Kurtosis y");
3255 gStringKurtosisZ = gEnv->GetValue("Hist.Stats.KurtosisZ", "Kurtosis z");
3256}
3257
3258////////////////////////////////////////////////////////////////////////////////
3259/// destructor.
3260
3264
3265////////////////////////////////////////////////////////////////////////////////
3266/// Compute the distance from the point px,py to a line.
3267///
3268/// Compute the closest distance of approach from point px,py to elements of
3269/// an histogram. The distance is computed in pixels units.
3270///
3271/// Algorithm: Currently, this simple model computes the distance from the mouse
3272/// to the histogram contour only.
3273
3275{
3276
3277 Double_t defaultLabelSize = 0.04; // See TAttAxis.h for source of this value
3278
3279 const Int_t big = 9999;
3280 const Int_t kMaxDiff = 7;
3281
3282 if (fPie)
3283 return fPie->DistancetoPrimitive(px, py);
3284
3285 Double_t x = gPad->AbsPixeltoX(px);
3286 Double_t x1 = gPad->AbsPixeltoX(px+1);
3287
3288 Int_t puxmin = gPad->XtoAbsPixel(gPad->GetUxmin());
3289 Int_t puymin = gPad->YtoAbsPixel(gPad->GetUymin());
3290 Int_t puxmax = gPad->XtoAbsPixel(gPad->GetUxmax());
3291 Int_t puymax = gPad->YtoAbsPixel(gPad->GetUymax());
3292 Int_t curdist = big;
3294 Bool_t dsame;
3295 TObject *PadPointer = gPad->GetPadPointer();
3296 if (!PadPointer) return 0;
3297 TString doption = PadPointer->GetDrawOption();
3298 Double_t factor = 1;
3299 if (fH->GetNormFactor() != 0) {
3300 factor = fH->GetNormFactor()/fH->GetSumOfWeights();
3301 }
3302 // return if point is not in the histogram area
3303
3304 // If a 3D view exists, check distance to axis
3305 TView *view = gPad->GetView();
3306 Int_t d1,d2,d3;
3307 if (view && Hoption.Contour != 14) {
3308 Double_t ratio;
3309 d3 = view->GetDistancetoAxis(3, px, py, ratio);
3310 if (d3 <= kMaxDiff) {gPad->SetSelected(fZaxis); return 0;}
3311 d1 = view->GetDistancetoAxis(1, px, py, ratio);
3312 if (d1 <= kMaxDiff) {gPad->SetSelected(fXaxis); return 0;}
3313 d2 = view->GetDistancetoAxis(2, px, py, ratio);
3314 if (d2 <= kMaxDiff) {gPad->SetSelected(fYaxis); return 0;}
3315 if ( px > puxmin && px < puxmax && py > puymax && py < puymin) curdist = 1;
3316 goto FUNCTIONS;
3317 }
3318 // check if point is close to an axis
3319 doption.ToLower();
3320 dsame = kFALSE;
3321 if (doption.Contains("same")) dsame = kTRUE;
3322
3324 if (doption.Contains("y+")) {
3326 if (px <= xyaxis+dyaxis && px >= xyaxis && py >puymax && py < puymin) {
3327 if (!dsame) {
3328 if (gPad->IsVertical()) gPad->SetSelected(fYaxis);
3329 else gPad->SetSelected(fXaxis);
3330 return 0;
3331 }
3332 }
3333 } else {
3335 if (px >= xyaxis-dyaxis && px <= xyaxis && py >puymax && py < puymin) {
3336 if (!dsame) {
3337 if (gPad->IsVertical()) gPad->SetSelected(fYaxis);
3338 else gPad->SetSelected(fXaxis);
3339 return 0;
3340 }
3341 }
3342 }
3343
3345 if (doption.Contains("x+")) {
3347 if (py >= yxaxis-dxaxis && py <= yxaxis && px <puxmax && px > puxmin) {
3348 if (!dsame) {
3349 if (gPad->IsVertical()) gPad->SetSelected(fXaxis);
3350 else gPad->SetSelected(fYaxis);
3351 return 0;
3352 }
3353 }
3354 } else {
3356 if (yxaxis < puymin) yxaxis = puymin;
3358 if (!dsame) {
3359 if (gPad->IsVertical()) gPad->SetSelected(fXaxis);
3360 else gPad->SetSelected(fYaxis);
3361 return 0;
3362 }
3363 }
3364 }
3365
3366 if (fH->IsHighlight()) { // only if highlight is enable
3367 if ((px > puxmin) && (py < puymin) && (px < puxmax) && (py > puymax))
3368 HighlightBin(px, py);
3369 }
3370
3371 // if object is 2D or 3D return this object
3372 if (fH->GetDimension() == 2) {
3373 if (fH->InheritsFrom(TH2Poly::Class())) {
3374 TH2Poly *th2 = (TH2Poly*)fH;
3376 gPad->GetRangeAxis(xmin, ymin, xmax, ymax);
3377 Double_t pxu = gPad->AbsPixeltoX(px);
3378 Double_t pyu = gPad->AbsPixeltoY(py);
3379 if ((pxu>xmax) || (pxu < xmin) || (pyu>ymax) || (pyu < ymin)) {
3380 curdist = big;
3381 goto FUNCTIONS;
3382 } else {
3383 Int_t bin = th2->FindBin(pxu, pyu);
3384 if (bin>0) curdist = 1;
3385 else curdist = big;
3386 goto FUNCTIONS;
3387 }
3388 }
3389 Int_t delta2 = 5; //Give a margin of delta2 pixels to be in the 2-d area
3390 if ( px > puxmin + delta2
3391 && px < puxmax - delta2
3392 && py > puymax + delta2
3393 && py < puymin - delta2) {curdist =1; goto FUNCTIONS;}
3394 }
3395
3396 // point is inside histogram area. Find channel number
3397 if (gPad->IsVertical()) {
3398 Int_t bin = fXaxis->FindFixBin(gPad->PadtoX(x));
3399 Int_t binsup = fXaxis->FindFixBin(gPad->PadtoX(x1));
3400 Double_t binval = factor*fH->GetBinContent(bin);
3401 Int_t pybin = gPad->YtoAbsPixel(gPad->YtoPad(binval));
3402 if (binval == 0 && pybin < puymin) pybin = 10000;
3403 // special case if more than one bin for the pixel
3404 if (binsup-bin>1) {
3408 for (Int_t ibin=bin+1; ibin<binsup; ibin++) {
3412 }
3413 Int_t pybinmin = gPad->YtoAbsPixel(gPad->YtoPad(binvalmax));
3414 Int_t pybinmax = gPad->YtoAbsPixel(gPad->YtoPad(binvalmin));
3416 }
3417 if (bin != binsup) { // Mouse on bin border
3419 Int_t pybinsub = gPad->YtoAbsPixel(gPad->YtoPad(binsupval));
3420 if (py <= TMath::Max(pybinsub,pybin) && py >= TMath::Min(pybinsub,pybin) && pybin != 10000) return 0;
3421 }
3422 if (TMath::Abs(py - pybin) <= kMaxDiff) return TMath::Abs(py - pybin);
3423 } else {
3424 Double_t y = gPad->AbsPixeltoY(py);
3425 Double_t y1 = gPad->AbsPixeltoY(py+1);
3426 Int_t bin = fXaxis->FindFixBin(gPad->PadtoY(y));
3427 Int_t binsup = fXaxis->FindFixBin(gPad->PadtoY(y1));
3428 Double_t binval = factor*fH->GetBinContent(bin);
3429 Int_t pxbin = gPad->XtoAbsPixel(gPad->XtoPad(binval));
3430 if (binval == 0 && pxbin > puxmin) pxbin = 10000;
3431 // special case if more than one bin for the pixel
3432 if (binsup-bin>1) {
3436 for (Int_t ibin=bin+1; ibin<binsup; ibin++) {
3440 }
3441 Int_t pxbinmin = gPad->XtoAbsPixel(gPad->XtoPad(binvalmax));
3442 Int_t pxbinmax = gPad->XtoAbsPixel(gPad->XtoPad(binvalmin));
3444 }
3445 if (TMath::Abs(px - pxbin) <= kMaxDiff) return TMath::Abs(px - pxbin);
3446 }
3447 // Loop on the list of associated functions and user objects
3448FUNCTIONS:
3449 TObject *f;
3450 TIter next(fFunctions);
3451 while ((f = (TObject*) next())) {
3452 Int_t dist;
3453 if (f->InheritsFrom(TF1::Class())) dist = f->DistancetoPrimitive(-px,py);
3454 else dist = f->DistancetoPrimitive(px,py);
3455 if (dist < kMaxDiff) {gPad->SetSelected(f); return dist;}
3456 }
3457 return curdist;
3458}
3459
3460////////////////////////////////////////////////////////////////////////////////
3461/// Display a panel with all histogram drawing options.
3462
3464{
3465
3466 gCurrentHist = fH;
3467 if (!gPad) {
3468 Error("DrawPanel", "need to draw histogram first");
3469 return;
3470 }
3472 editor->Show();
3473 gROOT->ProcessLine(TString::Format("((TCanvas*)0x%zx)->Selected((TVirtualPad*)0x%zx,(TObject*)0x%zx,1)",
3474 (size_t)gPad->GetCanvas(), (size_t)gPad, (size_t)fH).Data());
3475}
3476
3477////////////////////////////////////////////////////////////////////////////////
3478/// Execute the actions corresponding to `event`.
3479///
3480/// This function is called when a histogram is clicked with the locator at
3481/// the pixel position px,py.
3482
3484{
3485
3486 if (!gPad) return;
3487
3488 static Int_t bin, px1, py1, px2, py2, pyold;
3489 static std::unique_ptr<TBox> zoombox;
3491
3492 Int_t bin1, bin2;
3493 Double_t xlow, xup, ylow, binval, x, baroffset, barwidth, binwidth;
3494 Bool_t opaque = gPad->OpaqueMoving();
3495
3496 if (!gPad->IsEditable()) return;
3497
3498 if (fPie) {
3499 fPie->ExecuteEvent(event, px, py);
3500 return;
3501 }
3502 // come here if we have a lego/surface in the pad
3503 TView *view = gPad->GetView();
3504
3505 if (!fShowProjection && view && !view->TestBit(kCannotRotate)) {
3506 view->ExecuteRotateView(event, px, py);
3507 return;
3508 }
3509
3510 TAxis *xaxis = fH->GetXaxis();
3511 TAxis *yaxis = fH->GetYaxis();
3512 Int_t dimension = fH->GetDimension();
3513
3514 // In case of option SAME the axis must be the ones of the first drawn histogram
3515 TString IsSame = fH->GetDrawOption();
3516 IsSame.ToLower();
3517 if (IsSame.Index("same")>=0) {
3518 TH1 *h1;
3519 TIter next(gPad->GetListOfPrimitives());
3520 while ((h1 = (TH1 *)next())) {
3521 if (!h1->InheritsFrom(TH1::Class())) continue;
3522 xaxis = h1->GetXaxis();
3523 yaxis = h1->GetYaxis();
3524 break;
3525 }
3526 }
3527
3528 Double_t factor = 1;
3529 if (fH->GetNormFactor() != 0) {
3530 factor = fH->GetNormFactor()/fH->GetSumOfWeights();
3531 }
3532
3533 switch (event) {
3534
3535 case kButton1Down:
3536
3537 if (!opaque) gVirtualX->SetLineColor(-1);
3538 fH->TAttLine::Modify();
3539
3540 if (opaque && dimension ==2) {
3541 zbx1 = gPad->AbsPixeltoX(px);
3542 zbx2 = gPad->AbsPixeltoX(px);
3543 zby1 = gPad->AbsPixeltoY(py);
3544 zby2 = gPad->AbsPixeltoY(py);
3545 px1 = px;
3546 py1 = py;
3547 if (gPad->GetLogx()) {
3548 zbx1 = TMath::Power(10,zbx1);
3549 zbx2 = TMath::Power(10,zbx2);
3550 }
3551 if (gPad->GetLogy()) {
3552 zby1 = TMath::Power(10,zby1);
3553 zby2 = TMath::Power(10,zby2);
3554 }
3555 if (zoombox) Error("ExecuteEvent", "Last zoom box was not deleted");
3556 zoombox = std::make_unique<TBox>(zbx1, zby1, zbx2, zby2);
3557 Int_t ci = TColor::GetColor("#7d7dff");
3558 TColor *zoomcolor = gROOT->GetColor(ci);
3559 if (!TCanvas::SupportAlpha() || !zoomcolor) zoombox->SetFillStyle(3002);
3560 else zoomcolor->SetAlpha(0.5);
3561 zoombox->SetFillColor(ci);
3562 zoombox->Draw();
3563 gPad->Modified();
3564 gPad->Update();
3565 }
3566 // No break !!!
3567
3568 case kMouseMotion:
3569
3570 if (fShowProjection) {ShowProjection3(px,py); break;}
3571
3572 gPad->SetCursor(kPointer);
3573 if (dimension ==1) {
3574 if (Hoption.Bar) {
3575 baroffset = fH->GetBarOffset();
3576 barwidth = fH->GetBarWidth();
3577 } else {
3578 baroffset = 0;
3579 barwidth = 1;
3580 }
3581 x = gPad->AbsPixeltoX(px);
3582 bin = fXaxis->FindFixBin(gPad->PadtoX(x));
3584 xlow = gPad->XtoPad(fXaxis->GetBinLowEdge(bin) + baroffset*binwidth);
3585 xup = gPad->XtoPad(xlow + barwidth*binwidth);
3586 ylow = gPad->GetUymin();
3587 px1 = gPad->XtoAbsPixel(xlow);
3588 px2 = gPad->XtoAbsPixel(xup);
3589 py1 = gPad->YtoAbsPixel(ylow);
3590 py2 = py;
3591 pyold = py;
3592 if (gROOT->GetEditHistograms()) gPad->SetCursor(kArrowVer);
3593 }
3594
3595 break;
3596
3597 case kButton1Motion:
3598
3599 if (dimension ==1) {
3600 if (gROOT->GetEditHistograms()) {
3601 if (!opaque) {
3602 gVirtualX->DrawBox(px1, py1, px2, py2,TVirtualX::kHollow); // Draw the old box
3603 py2 += py - pyold;
3604 gVirtualX->DrawBox(px1, py1, px2, py2,TVirtualX::kHollow); // Draw the new box
3605 pyold = py;
3606 } else {
3607 py2 += py - pyold;
3608 pyold = py;
3609 binval = gPad->PadtoY(gPad->AbsPixeltoY(py2))/factor;
3611 gPad->Modified(kTRUE);
3612 }
3613 }
3614 }
3615
3616 if (opaque && dimension ==2) {
3617 if (TMath::Abs(px1-px)>5 && TMath::Abs(py1-py)>5) {
3618 zbx2 = gPad->AbsPixeltoX(px);
3619 zby2 = gPad->AbsPixeltoY(py);
3620 if (gPad->GetLogx()) zbx2 = TMath::Power(10,zbx2);
3621 if (gPad->GetLogy()) zby2 = TMath::Power(10,zby2);
3622 if (zoombox) {
3623 zoombox->SetX2(zbx2);
3624 zoombox->SetY2(zby2);
3625 }
3626 gPad->Modified();
3627 gPad->Update();
3628 }
3629 }
3630
3631 break;
3632
3633 case kWheelUp:
3634
3635 if (dimension ==2) {
3636 bin1 = xaxis->GetFirst()+1;
3637 bin2 = xaxis->GetLast()-1;
3638 bin1 = TMath::Max(bin1, 1);
3639 bin2 = TMath::Min(bin2, xaxis->GetNbins());
3640 if (bin2>bin1) xaxis->SetRange(bin1,bin2);
3641 bin1 = yaxis->GetFirst()+1;
3642 bin2 = yaxis->GetLast()-1;
3643 bin1 = TMath::Max(bin1, 1);
3644 bin2 = TMath::Min(bin2, yaxis->GetNbins());
3645 if (bin2>bin1) yaxis->SetRange(bin1,bin2);
3646 }
3647 gPad->Modified();
3648 gPad->Update();
3649
3650 break;
3651
3652 case kWheelDown:
3653
3654 if (dimension == 2) {
3655 bin1 = xaxis->GetFirst()-1;
3656 bin2 = xaxis->GetLast()+1;
3657 bin1 = TMath::Max(bin1, 1);
3658 bin2 = TMath::Min(bin2, xaxis->GetNbins());
3659 const bool resetXaxisRange = bin1 == 1 && xaxis->GetFirst() == 1 && bin2 == xaxis->GetNbins() && xaxis->GetLast() == xaxis->GetNbins();
3660 if (bin2>bin1) xaxis->SetRange(bin1,bin2);
3661 if (resetXaxisRange) xaxis->ResetBit(TAxis::kAxisRange);
3662 bin1 = yaxis->GetFirst()-1;
3663 bin2 = yaxis->GetLast()+1;
3664 bin1 = TMath::Max(bin1, 1);
3665 bin2 = TMath::Min(bin2, yaxis->GetNbins());
3666 const bool resetYaxisRange = bin1 == 1 && yaxis->GetFirst() == 1 && bin2 == yaxis->GetNbins() && yaxis->GetLast() == yaxis->GetNbins();
3667 if (bin2>bin1) yaxis->SetRange(bin1,bin2);
3668 if (resetYaxisRange) yaxis->ResetBit(TAxis::kAxisRange);
3669 }
3670 gPad->Modified();
3671 gPad->Update();
3672
3673 break;
3674
3675 case kButton1Up:
3676 if (dimension ==1) {
3677 if (gROOT->GetEditHistograms()) {
3678 binval = gPad->PadtoY(gPad->AbsPixeltoY(py2))/factor;
3680 PaintInit(); // recalculate Hparam structure and recalculate range
3681 }
3682
3683 // might resize pad pixmap so should be called before any paint routine
3685 }
3686 if (opaque && dimension ==2) {
3687 if (zoombox) {
3688 Double_t x1 = TMath::Min(zoombox->GetX1(), zoombox->GetX2());
3689 Double_t x2 = TMath::Max(zoombox->GetX1(), zoombox->GetX2());
3690 Double_t y1 = TMath::Min(zoombox->GetY1(), zoombox->GetY2());
3691 Double_t y2 = TMath::Max(zoombox->GetY1(), zoombox->GetY2());
3692 x1 = TMath::Max(x1,xaxis->GetXmin());
3693 x2 = TMath::Min(x2,xaxis->GetXmax());
3694 y1 = TMath::Max(y1,yaxis->GetXmin());
3695 y2 = TMath::Min(y2,yaxis->GetXmax());
3696 if (x1<x2 && y1<y2) {
3697 xaxis->SetRangeUser(x1, x2);
3698 yaxis->SetRangeUser(y1, y2);
3699 }
3700 zoombox.reset();
3701 }
3702 }
3703 gPad->Modified(kTRUE);
3704 if (opaque) gVirtualX->SetLineColor(-1);
3705
3706 break;
3707
3708 case kButton1Locate:
3709
3710 ExecuteEvent(kButton1Down, px, py);
3711
3712 while (true) {
3713 px = py = 0;
3714 event = gVirtualX->RequestLocator(1, 1, px, py);
3715
3717
3718 if (event != -1) { // button is released
3719 ExecuteEvent(kButton1Up, px, py);
3720 return;
3721 }
3722 }
3723 }
3724}
3725
3726////////////////////////////////////////////////////////////////////////////////
3727/// Get a contour (as a list of TGraphs) using the Delaunay triangulation.
3728
3730{
3731 // Check if fH contains a TGraphDelaunay2D
3733 TGraphDelaunay2D *dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
3734 // try with the old painter
3735 TGraphDelaunay *dtOld = nullptr;
3736 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
3737
3738 if (!dt && !dtOld) return nullptr;
3739
3740 gCurrentHist = fH;
3741
3742 if (!fGraph2DPainter)
3743 ((THistPainter*)this)->fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
3744
3745 return fGraph2DPainter->GetContourList(contour);
3746}
3747
3748////////////////////////////////////////////////////////////////////////////////
3749/// Display the histogram info (bin number, contents, integral up to bin
3750/// corresponding to cursor position px,py.
3751
3753{
3754
3755 if (!gPad) return (char*)"";
3756
3757 Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
3758 Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
3759 Double_t x1 = gPad->PadtoX(gPad->AbsPixeltoX(px+1));
3761 drawOption.ToLower();
3764 if (fH->GetDimension() == 2) {
3765 if (gPad->GetView() || drawOption.Index("cont") >= 0) {
3766 uxmin=gPad->GetUxmin();
3767 uxmax=gPad->GetUxmax();
3770 x = xmin +(xmax-xmin)*(x-uxmin)/(uxmax-uxmin);
3771 uymin=gPad->GetUymin();
3772 uymax=gPad->GetUymax();
3775 y = ymin +(ymax-ymin)*(y-uymin)/(uymax-uymin);
3776 }
3777 }
3779 if (gPad->IsVertical()) {
3780 binx = fXaxis->FindFixBin(x);
3781 if (drawOption.Index("same") >= 0) {
3782 TH1 *h1;
3783 TIter next(gPad->GetListOfPrimitives());
3784 while ((h1 = (TH1 *)next())) {
3785 if (!h1->InheritsFrom(TH1::Class())) continue;
3786 binmin = h1->GetXaxis()->GetFirst();
3787 break;
3788 }
3789 } else {
3790 binmin = fXaxis->GetFirst();
3791 }
3793 // special case if more than 1 bin in x per pixel
3794 if (binx1-binx>1 && fH->GetDimension() == 1) {
3797 for (Int_t ibin=binx+1; ibin<binx1; ibin++) {
3801 binnear=ibin;
3802 }
3803 }
3804 binx = binnear;
3805 }
3806 } else {
3807 x1 = gPad->PadtoY(gPad->AbsPixeltoY(py+1));
3808 binx = fXaxis->FindFixBin(y);
3809 if (drawOption.Index("same") >= 0) {
3810 TH1 *h1;
3811 TIter next(gPad->GetListOfPrimitives());
3812 while ((h1 = (TH1 *)next())) {
3813 if (!h1->InheritsFrom(TH1::Class())) continue;
3814 binmin = h1->GetXaxis()->GetFirst();
3815 break;
3816 }
3817 } else {
3818 binmin = fXaxis->GetFirst();
3819 }
3821 // special case if more than 1 bin in x per pixel
3822 if (binx1-binx>1 && fH->GetDimension() == 1) {
3825 for (Int_t ibin=binx+1; ibin<binx1; ibin++) {
3829 binnear=ibin;
3830 }
3831 }
3832 binx = binnear;
3833 }
3834 }
3835 if (fH->GetDimension() == 1) {
3837 TProfile *tp = (TProfile*)fH;
3838 fObjectInfo.Form("(x=%g, y=%g, binx=%d, binc=%g, bine=%g, binn=%d)",
3840 (Int_t) tp->GetBinEntries(binx));
3841 }
3842 else {
3843 Double_t integ = 0;
3844 for (Int_t bin=binmin;bin<=binx;bin++) {integ += fH->GetBinContent(bin);}
3845 fObjectInfo.Form("(x=%g, y=%g, binx=%d, binc=%g, Sum=%g)",
3847 }
3848 } else if (fH->GetDimension() == 2) {
3849 if (fH->InheritsFrom(TH2Poly::Class())) {
3850 TH2Poly *th2 = (TH2Poly*)fH;
3851 biny = th2->FindBin(x,y);
3852 fObjectInfo.Form("%s (x=%g, y=%g, bin=%d, binc=%g)",
3853 th2->GetBinTitle(biny),x,y,biny,th2->GetBinContent(biny));
3854 }
3855 else if (fH->InheritsFrom(TProfile2D::Class())) {
3857 biny = fYaxis->FindFixBin(y);
3858 Int_t bin = fH->GetBin(binx,biny);
3859 fObjectInfo.Form("(x=%g, y=%g, binx=%d, biny=%d, binc=%g, bine=%g, binn=%d)",
3860 x, y, binx, biny, fH->GetBinContent(bin),
3861 fH->GetBinError(bin), (Int_t) tp->GetBinEntries(bin));
3862 } else {
3863 biny = fYaxis->FindFixBin(y);
3864 fObjectInfo.Form("(x=%g, y=%g, binx=%d, biny=%d, binc=%g bine=%g)",
3867 }
3868 } else {
3869 // 3d case: retrieving the x,y,z bin is not yet implemented
3870 // print just the x,y info
3871 fObjectInfo.Form("(x=%g, y=%g)",x,y);
3872 }
3873
3874 return (char *)fObjectInfo.Data();
3875}
3876
3877////////////////////////////////////////////////////////////////////////////////
3878/// Set highlight (enable/disable) mode for fH
3879
3881{
3882 if (fH->IsHighlight()) return;
3883
3884 fXHighlightBin = -1;
3885 fYHighlightBin = -1;
3886 // delete previous highlight box
3887 if (gXHighlightBox) gXHighlightBox.reset();
3888 if (gYHighlightBox) gYHighlightBox.reset();
3889 // emit Highlighted() signal (user can check on disabled)
3890 if (gPad->GetCanvas()) gPad->GetCanvas()->Highlighted(gPad, fH, fXHighlightBin, fYHighlightBin);
3891}
3892
3893////////////////////////////////////////////////////////////////////////////////
3894/// Check on highlight bin
3895
3897{
3898 // call from DistancetoPrimitive (only if highlight is enable)
3899
3900 Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
3901 Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
3904 if (!gPad->IsVertical()) binx = fXaxis->FindFixBin(y);
3905
3907 if (binx != fXHighlightBin) {
3909 changedBin = kTRUE;
3910 } else if (fH->GetDimension() == 1) return;
3911 if (biny != fYHighlightBin) {
3913 changedBin = kTRUE;
3914 }
3915 if (!changedBin) return;
3916
3917 // Info("HighlightBin", "histo: %p '%s'\txbin: %d, ybin: %d",
3918 // (void *)fH, fH->GetName(), fXHighlightBin, fYHighlightBin);
3919
3920 // paint highlight bin as box (recursive calls PaintHighlightBin)
3921 gPad->Modified(kTRUE);
3922 gPad->Update();
3923
3924 // emit Highlighted() signal
3925 if (gPad->GetCanvas()) gPad->GetCanvas()->Highlighted(gPad, fH, fXHighlightBin, fYHighlightBin);
3926}
3927
3928////////////////////////////////////////////////////////////////////////////////
3929/// Paint highlight bin as TBox object
3930
3932{
3933 // call from PaintTitle
3934
3935 if (!fH->IsHighlight()) return;
3936
3937 Double_t uxmin = gPad->GetUxmin();
3938 Double_t uxmax = gPad->GetUxmax();
3939 Double_t uymin = gPad->GetUymin();
3940 Double_t uymax = gPad->GetUymax();
3941 if (gPad->GetLogx()) {
3942 uxmin = TMath::Power(10.0, uxmin);
3943 uxmax = TMath::Power(10.0, uxmax);
3944 }
3945 if (gPad->GetLogy()) {
3946 uymin = TMath::Power(10.0, uymin);
3947 uymax = TMath::Power(10.0, uymax);
3948 }
3949
3950 // testing specific possibility (after zoom, draw with "same", log, etc.)
3952 if (gPad->IsVertical()) {
3954 if ((hcenter < uxmin) || (hcenter > uxmax)) return;
3955 } else {
3957 if ((hcenter < uymin) || (hcenter > uymax)) return;
3958 }
3959 if (fH->GetDimension() == 2) {
3961 if ((hcenter < uymin) || (hcenter > uymax)) return;
3962 }
3963
3964 // paint X highlight bin (for 1D or 2D)
3966 if (gPad->IsVertical()) {
3969 hby1 = uymin;
3970 hby2 = uymax;
3971 } else {
3972 hbx1 = uxmin;
3973 hbx2 = uxmax;
3976 }
3977
3978 if (!gXHighlightBox) {
3979 gXHighlightBox = std::make_unique<TBox>(hbx1, hby1, hbx2, hby2);
3980 gXHighlightBox->SetBit(kCannotPick);
3981 gXHighlightBox->SetFillColor(TColor::GetColor("#9797ff"));
3982 if (!TCanvas::SupportAlpha()) gXHighlightBox->SetFillStyle(3001);
3983 else gROOT->GetColor(gXHighlightBox->GetFillColor())->SetAlpha(0.5);
3984 }
3985 gXHighlightBox->SetX1(hbx1);
3986 gXHighlightBox->SetX2(hbx2);
3987 gXHighlightBox->SetY1(hby1);
3988 gXHighlightBox->SetY2(hby2);
3989 gXHighlightBox->Paint();
3990
3991 // Info("PaintHighlightBin", "histo: %p '%s'\txbin: %d, ybin: %d",
3992 // (void *)fH, fH->GetName(), fXHighlightBin, fYHighlightBin);
3993
3994 // paint Y highlight bin (only for 2D)
3995 if (fH->GetDimension() != 2) return;
3996 hbx1 = uxmin;
3997 hbx2 = uxmax;
4000
4001 if (!gYHighlightBox) {
4002 gYHighlightBox = std::make_unique<TBox>(hbx1, hby1, hbx2, hby2);
4003 gYHighlightBox->SetBit(kCannotPick);
4004 gYHighlightBox->SetFillColor(gXHighlightBox->GetFillColor());
4005 gYHighlightBox->SetFillStyle(gXHighlightBox->GetFillStyle());
4006 }
4007 gYHighlightBox->SetX1(hbx1);
4008 gYHighlightBox->SetX2(hbx2);
4009 gYHighlightBox->SetY1(hby1);
4010 gYHighlightBox->SetY2(hby2);
4011 gYHighlightBox->Paint();
4012}
4013
4014////////////////////////////////////////////////////////////////////////////////
4015/// Return `kTRUE` if the cell `ix`, `iy` is inside one of the graphical cuts.
4016
4018{
4019
4020 for (Int_t i=0;i<fNcuts;i++) {
4023 if (fCutsOpt[i] > 0) {
4024 if (!fCuts[i]->IsInside(x,y)) return kFALSE;
4025 } else {
4026 if (fCuts[i]->IsInside(x,y)) return kFALSE;
4027 }
4028 }
4029 return kTRUE;
4030}
4031
4032////////////////////////////////////////////////////////////////////////////////
4033/// Return `kTRUE` if the point `x`, `y` is inside one of the graphical cuts.
4034
4036{
4037
4038 for (Int_t i=0;i<fNcuts;i++) {
4039 if (fCutsOpt[i] > 0) {
4040 if (!fCuts[i]->IsInside(x,y)) return kFALSE;
4041 } else {
4042 if (fCuts[i]->IsInside(x,y)) return kFALSE;
4043 }
4044 }
4045 return kTRUE;
4046}
4047
4048////////////////////////////////////////////////////////////////////////////////
4049/// Decode string `choptin` and fill Hoption structure.
4050
4052{
4053
4054 char *l;
4055 char chopt[128];
4057 strlcpy(chopt,choptin,128);
4060
4068 Hoption.Candle = 0;
4069 Hoption.Polar = 0;
4070
4071 // special 2D options
4072 Hoption.List = 0;
4073 Hoption.Zscale = 0;
4074 Hoption.FrontBox = 1;
4075 Hoption.BackBox = 1;
4077
4078 Hoption.Zero = 0;
4079
4081
4082 //check for graphical cuts
4083 MakeCuts(chopt);
4084
4085 for (Int_t i=0;i<nch;i++) chopt[i] = toupper(chopt[i]);
4086 if (hdim > 1) Hoption.Color = 1; // Default drawing option for 2D and 3D histograms
4087 if (!nch) Hoption.Hist = 1;
4088 if (fFunctions->First()) Hoption.Func = 1;
4089 if (fH->GetSumw2N() && hdim == 1) Hoption.Error = 2;
4090
4091 char *l1 = strstr(chopt,"PFC"); // Automatic Fill Color
4092 char *l2 = strstr(chopt,"PLC"); // Automatic Line Color
4093 char *l3 = strstr(chopt,"PMC"); // Automatic Marker Color
4094 if (l1 || l2 || l3) {
4095 Int_t i = gPad->NextPaletteColor();
4096 if (l1) {memcpy(l1," ",3); fH->SetFillColor(i);}
4097 if (l2) {memcpy(l2," ",3); fH->SetLineColor(i);}
4098 if (l3) {memcpy(l3," ",3); fH->SetMarkerColor(i);}
4099 Hoption.Hist = 1; // Make sure something is drawn in case there is no drawing option specified.
4100 }
4101
4102 l = strstr(chopt,"MIN0");
4103 if (l) {
4104 Hoption.MinimumZero = 1;
4105 memcpy(l," ",4);
4106 }
4107
4108 l = strstr(chopt,"SPEC");
4109 if (l) {
4110 Hoption.Color = 0;
4111 memcpy(l," ",4);
4112 Int_t bs=0;
4113 l = strstr(chopt,"BF(");
4114 if (l) {
4115 if (sscanf(&l[3],"%d",&bs) > 0) {
4116 Int_t i=0;
4117 while (l[i]!=')') {
4118 l[i] = ' ';
4119 i++;
4120 }
4121 l[i] = ' ';
4122 }
4123 }
4124 Hoption.Spec = TMath::Max(1600,bs);
4125 return 1;
4126 }
4127
4128 l = strstr(chopt,"GL");
4129 if (l) {
4130 memcpy(l," ",2);
4131 }
4132 l = strstr(chopt,"X+");
4133 if (l) {
4134 Hoption.AxisPos = 10;
4135 memcpy(l," ",2);
4136 }
4137 l = strstr(chopt,"Y+");
4138 if (l) {
4139 Hoption.AxisPos += 1;
4140 memcpy(l," ",2);
4141 }
4142 if ((Hoption.AxisPos == 10 || Hoption.AxisPos == 1) && (nch == 2)) Hoption.Hist = 1;
4143 if (Hoption.AxisPos == 11 && nch == 4) Hoption.Hist = 1;
4144
4145 l = strstr(chopt,"SAMES");
4146 if (l) {
4147 if (nch == 5) Hoption.Hist = 1;
4148 Hoption.Same = 2;
4149 memcpy(l," ",5);
4150 if (l[5] == '0') { Hoption.Same += 10; l[5] = ' '; }
4151 }
4152 l = strstr(chopt,"SAME");
4153 if (l) {
4154 if (nch == 4) Hoption.Hist = 1;
4155 Hoption.Same = 1;
4156 memcpy(l," ",4);
4157 if (l[4] == '0') { Hoption.Same += 10; l[4] = ' '; }
4158 }
4159
4160 l = strstr(chopt,"SCAT");
4161 if (l) {
4162 Warning("MakeChopt","option SCAT is deprecated.");
4163 Hoption.Scat = 1;
4164 memcpy(l," ",4);
4165 Hoption.Color = 0;
4166 }
4167
4168 l = strstr(chopt,"PIE");
4169 if (l) {
4170 Hoption.Pie = 1;
4171 memcpy(l," ",3);
4172 }
4173
4174
4175 l = strstr(chopt,"CANDLE");
4176 if (l) {
4178 Hoption.Candle = candle.ParseOption(l);
4179 Hoption.Color = 0;
4180 }
4181
4182 l = strstr(chopt,"VIOLIN");
4183 if (l) {
4185 Hoption.Candle = candle.ParseOption(l);
4186 Hoption.Color = 0;
4187 }
4188
4189 l = strstr(chopt,"LEGO");
4190 if (l) {
4191 Hoption.Color = 0;
4192 Hoption.Lego = 1; memcpy(l," ",4);
4193 if (l[4] == '1') { Hoption.Lego = 11; l[4] = ' '; }
4194 if (l[4] == '2') { Hoption.Lego = 12; l[4] = ' '; }
4195 if (l[4] == '3') { Hoption.Lego = 13; l[4] = ' '; }
4196 if (l[4] == '4') { Hoption.Lego = 14; l[4] = ' '; }
4197 if (l[4] == '9') { Hoption.Lego = 19; l[4] = ' '; }
4198 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4199 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4200 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4201 }
4202
4203 l = strstr(chopt,"SURF");
4204 if (l) {
4205 Hoption.Color = 0;
4206 Hoption.Surf = 1; memcpy(l," ",4);
4207 if (l[4] == '1') { Hoption.Surf = 11; l[4] = ' '; }
4208 if (l[4] == '2') { Hoption.Surf = 12; l[4] = ' '; }
4209 if (l[4] == '3') { Hoption.Surf = 13; l[4] = ' '; }
4210 if (l[4] == '4') { Hoption.Surf = 14; l[4] = ' '; }
4211 if (l[4] == '5') { Hoption.Surf = 15; l[4] = ' '; }
4212 if (l[4] == '6') { Hoption.Surf = 16; l[4] = ' '; }
4213 if (l[4] == '7') { Hoption.Surf = 17; l[4] = ' '; }
4214 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4215 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4216 }
4217
4218 l = strstr(chopt,"TF3");
4219 if (l) {
4220 memcpy(l," ",3);
4221 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4222 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4223 }
4224
4225 l = strstr(chopt,"ISO");
4226 if (l) {
4227 memcpy(l," ",3);
4228 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4229 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4230 Hoption.Color = 0;
4231 }
4232
4233 l = strstr(chopt,"LIST"); if (l) { Hoption.List = 1; memcpy(l," ",4);}
4234
4235 l = strstr(chopt,"CONT");
4236 if (l) {
4237 memcpy(l," ",4);
4238 if (hdim>1) {
4239 Hoption.Color = 0;
4240 Hoption.Contour = 1;
4241 if (l[4] == '1') { Hoption.Contour = 11; l[4] = ' '; }
4242 if (l[4] == '2') { Hoption.Contour = 12; l[4] = ' '; }
4243 if (l[4] == '3') { Hoption.Contour = 13; l[4] = ' '; }
4244 if (l[4] == '4') { Hoption.Contour = 14; l[4] = ' '; }
4245 if (l[4] == '5') { Hoption.Contour = 15; l[4] = ' '; }
4246 } else {
4247 Hoption.Hist = 1;
4248 }
4249 }
4250 l = strstr(chopt,"HBAR");
4251 if (l) {
4252 Hoption.Hist = 0;
4253 Hoption.Bar = 20; memcpy(l," ",4);
4254 if (l[4] == '1') { Hoption.Bar = 21; l[4] = ' '; }
4255 if (l[4] == '2') { Hoption.Bar = 22; l[4] = ' '; }
4256 if (l[4] == '3') { Hoption.Bar = 23; l[4] = ' '; }
4257 if (l[4] == '4') { Hoption.Bar = 24; l[4] = ' '; }
4258 }
4259 l = strstr(chopt,"BAR");
4260 if (l) {
4261 Hoption.Hist = 0;
4262 Hoption.Bar = 10; memcpy(l," ",3);
4263 if (l[3] == '1') { Hoption.Bar = 11; l[3] = ' '; }
4264 if (l[3] == '2') { Hoption.Bar = 12; l[3] = ' '; }
4265 if (l[3] == '3') { Hoption.Bar = 13; l[3] = ' '; }
4266 if (l[3] == '4') { Hoption.Bar = 14; l[3] = ' '; }
4267 }
4268
4269 l = strstr(chopt,"ARR" );
4270 if (l) {
4271 memcpy(l," ", 3);
4272 if (hdim>1) {
4273 Hoption.Arrow = 1;
4274 Hoption.Color = 0;
4275 l = strstr(chopt,"COL"); if (l) { Hoption.Arrow = 2; memcpy(l," ",3); }
4276 l = strstr(chopt,"Z"); if (l) { Hoption.Zscale = 1; memcpy(l," ",1); }
4277 } else {
4278 Hoption.Hist = 1;
4279 }
4280 }
4281 l = strstr(chopt,"BOX" );
4282 if (l) {
4283 memcpy(l," ", 3);
4284 if (hdim>1) {
4285 Hoption.Color = 0;
4286 Hoption.Box = 1;
4287 if (l[3] == '1') { Hoption.Box = 11; l[3] = ' '; }
4288 if (l[3] == '2') { Hoption.Box = 12; l[3] = ' '; }
4289 if (l[3] == '3') { Hoption.Box = 13; l[3] = ' '; }
4290 } else {
4291 Hoption.Hist = 1;
4292 }
4293 }
4294 l = strstr(chopt,"TEXT");
4295 if (l) {
4296 Int_t angle;
4297 if (sscanf(&l[4],"%d",&angle) > 0) {
4298 if (angle < 0) angle=0;
4299 if (angle > 90) angle=90;
4300 Hoption.Text = 1000+angle;
4301 } else {
4302 Hoption.Text = 1;
4303 }
4304 memcpy(l," ", 4);
4305 l = strstr(chopt,"N");
4306 if (l && fH->InheritsFrom(TH2Poly::Class())) Hoption.Text = 3000 + (Hoption.Text != 1 ? Hoption.Text : 0);
4307 Hoption.Color = 0;
4308 }
4309 l = strstr(chopt,"COLZ");
4310 if (l) {
4311 memcpy(l," ",4);
4312 if (hdim > 1) {
4314 Hoption.Color = 1;
4315 Hoption.Zscale = 1;
4316 if (l[4] == '2') { Hoption.Color = 3; l[4] = ' '; }
4317 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4318 l = strstr(chopt,"1"); if (l) { Hoption.Color = 2; memcpy(l," ",1); }
4319 } else {
4320 Hoption.Hist = 1;
4321 }
4322 }
4323 l = strstr(chopt,"COL" );
4324 if (l) {
4325 memcpy(l," ", 3);
4326 if (hdim > 1) {
4328 Hoption.Color = 1;
4329 if (l[3] == '2') { Hoption.Color = 3; l[3] = ' '; }
4330 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4331 l = strstr(chopt,"1"); if (l) { Hoption.Color = 2; memcpy(l," ",1); }
4332 } else {
4333 Hoption.Hist = 1;
4334 }
4335 }
4336 l = strstr(chopt,"FUNC"); if (l) { Hoption.Func = 2; memcpy(l," ",4); Hoption.Hist = 0; }
4337 l = strstr(chopt,"HIST"); if (l) { Hoption.Hist = 2; memcpy(l," ",4); Hoption.Func = 0; Hoption.Error = 0;}
4338 l = strstr(chopt,"AXIS"); if (l) { Hoption.Axis = 1; memcpy(l," ",4); }
4339 l = strstr(chopt,"AXIG"); if (l) { Hoption.Axis = 2; memcpy(l," ",4); }
4340 l = strstr(chopt,"SCAT"); if (l) { Hoption.Scat = 1; memcpy(l," ",4); }
4341 l = strstr(chopt,"POLN"); if (l) { Hoption.System = kPOLAR; Hoption.Polar = 3; memcpy(l," ",4); }
4342 l = strstr(chopt,"POLF"); if (l) { Hoption.System = kPOLAR; Hoption.Polar = 2; memcpy(l," ",4); }
4343 l = strstr(chopt,"POL"); if (l) { Hoption.System = kPOLAR; Hoption.Polar = 1; memcpy(l," ",3); }
4344 l = strstr(chopt,"CYL"); if (l) { Hoption.System = kCYLINDRICAL; memcpy(l," ",3); }
4345 l = strstr(chopt,"SPH"); if (l) { Hoption.System = kSPHERICAL; memcpy(l," ",3); }
4346 l = strstr(chopt,"PSR"); if (l) { Hoption.System = kRAPIDITY; memcpy(l," ",3); }
4347
4348 l = strstr(chopt,"TRI");
4349 if (l) {
4350 if (!explicitColor) Hoption.Color = 0;
4351 Hoption.Tri = 1; memcpy(l," ",3);
4352 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4353 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4354 l = strstr(chopt,"ERR"); if (l) memcpy(l," ",3);
4355 }
4356
4357 l = strstr(chopt,"AITOFF");
4358 if (l) {
4359 Hoption.Proj = 1; memcpy(l," ",6); //Aitoff projection
4360 }
4361 l = strstr(chopt,"MERCATOR");
4362 if (l) {
4363 Hoption.Proj = 2; memcpy(l," ",8); //Mercator projection
4364 }
4365 l = strstr(chopt,"SINUSOIDAL");
4366 if (l) {
4367 Hoption.Proj = 3; memcpy(l," ",10); //Sinusoidal projection
4368 }
4369 l = strstr(chopt,"PARABOLIC");
4370 if (l) {
4371 Hoption.Proj = 4; memcpy(l," ",9); //Parabolic projection
4372 }
4373 l = strstr(chopt,"MOLLWEIDE");
4374 if (l) {
4375 Hoption.Proj = 5; memcpy(l," ",9); //Mollweide projection
4376 }
4377 if (Hoption.Proj > 0) {
4378 if (!explicitColor) Hoption.Color = 0;
4379 Hoption.Contour = 14;
4380 }
4381
4382 if (strstr(chopt,"A")) Hoption.Axis = -1;
4383 if (strstr(chopt,"B")) Hoption.Bar = 1;
4384 if (strstr(chopt,"C") && !strstr(chopt,"CJUST")) { Hoption.Curve =1; Hoption.Hist = -1;}
4385 if (strstr(chopt,"F")) Hoption.Fill =1;
4386 if (strstr(chopt,"][")) {Hoption.Off =1; Hoption.Hist =1;}
4387 if (strstr(chopt,"F2")) Hoption.Fill =2;
4388 if (strstr(chopt,"L")) { Hoption.Line =1; Hoption.Hist = -1;}
4389 if (strstr(chopt,"P")) { Hoption.Mark =1; Hoption.Hist = -1;}
4390 if (strstr(chopt,"Z")) Hoption.Zscale =1;
4391 if (strstr(chopt,"*")) Hoption.Star =1;
4392 if (strstr(chopt,"H")) Hoption.Hist =2;
4393 if (strstr(chopt,"P0")) Hoption.Mark =10;
4394
4395 if (fH->InheritsFrom(TH2Poly::Class())) {
4397 }
4398
4399 if (strstr(chopt,"E")) {
4400 if (hdim == 1) {
4401 Hoption.Error = 1;
4402 if (strstr(chopt,"E1")) Hoption.Error = 11;
4403 if (strstr(chopt,"E2")) Hoption.Error = 12;
4404 if (strstr(chopt,"E3")) Hoption.Error = 13;
4405 if (strstr(chopt,"E4")) Hoption.Error = 14;
4406 if (strstr(chopt,"E5")) Hoption.Error = 15;
4407 if (strstr(chopt,"E6")) Hoption.Error = 16;
4408 if (strstr(chopt,"E0")) Hoption.Error += 40;
4409 if (strstr(chopt,"X0")) {
4410 if (Hoption.Error == 1) Hoption.Error += 20;
4411 Hoption.Error += 10;
4412 }
4414 Hoption.Text += 2000;
4415 Hoption.Error = 0;
4416 }
4417 } else {
4418 if (Hoption.Error == 0) {
4419 Hoption.Error = 100;
4420 if (!explicitColor) Hoption.Color = 0;
4421 }
4422 if (Hoption.Text) {
4423 Hoption.Text += 2000;
4424 Hoption.Error = 0;
4425 }
4426 }
4427 }
4428
4429 if (Hoption.Surf == 15) {
4431 Hoption.Surf = 13;
4432 Warning("MakeChopt","option SURF5 is not supported in Cartesian and Polar modes");
4433 }
4434 }
4435
4436 // Copy options from current style
4437 Hoption.Logx = gPad->GetLogx();
4438 Hoption.Logy = gPad->GetLogy();
4439 Hoption.Logz = gPad->GetLogz();
4440
4441 // Check options incompatibilities
4442 if (Hoption.Bar == 1) Hoption.Hist = -1;
4443 return 1;
4444}
4445
4446////////////////////////////////////////////////////////////////////////////////
4447/// Decode string `choptin` and fill Graphical cuts structure.
4448
4450{
4451
4452 fNcuts = 0;
4453 char *left = (char*)strchr(choptin,'[');
4454 if (!left) return 0;
4455 char *right = (char*)strchr(choptin,']');
4456 if (!right) return 0;
4457 Int_t nch = right-left;
4458 if (nch < 2) return 0;
4459 char *cuts = left+1;
4460 *right = 0;
4461 char *comma, *minus;
4462 Int_t i;
4463 while (true) {
4464 comma = strchr(cuts,',');
4465 if (comma) *comma = 0;
4466 minus = strchr(cuts,'-');
4467 if (minus) cuts = minus+1;
4468 while (*cuts == ' ') cuts++;
4469 Int_t nc = strlen(cuts);
4470 while (cuts[nc-1] == ' ') {cuts[nc-1] = 0; nc--;}
4471 TIter next(gROOT->GetListOfSpecials());
4472 TCutG *cut=nullptr;
4473 TObject *obj;
4474 while ((obj = next())) {
4475 if (!obj->InheritsFrom(TCutG::Class())) continue;
4476 if (strcmp(obj->GetName(),cuts)) continue;
4477 cut = (TCutG*)obj;
4478 break;
4479 }
4480 if (cut) {
4481 fCuts[fNcuts] = cut;
4482 fCutsOpt[fNcuts] = 1;
4483 if (minus) fCutsOpt[fNcuts] = -1;
4484 fNcuts++;
4485 }
4486 if (!comma) break;
4487 cuts = comma+1;
4488 }
4489 for (i=0;i<=nch;i++) left[i] = ' ';
4490 return fNcuts;
4491}
4492
4493////////////////////////////////////////////////////////////////////////////////
4494/// [Control routine to paint any kind of histograms](\ref HP00)
4495
4497{
4498
4499 if (fH->GetBuffer()) fH->BufferEmpty(-1);
4500
4501 //For iOS: put the histogram on the top of stack of pickable objects.
4503
4504 gPad->SetVertical(kTRUE);
4505
4507 gCurrentHist = fH;
4508 TH1 *hsave = fH;
4510
4511 if (!MakeChopt(option)) return; //check options and fill Hoption structure
4512
4513 // Paint using TSpectrum2Painter
4514 if (Hoption.Spec) {
4515 if (!TableInit()) return;
4516 if (!TClass::GetClass("TSpectrum2Painter")) gSystem->Load("libSpectrumPainter");
4517 gROOT->ProcessLineFast(TString::Format("TSpectrum2Painter::PaintSpectrum((TH2F*)0x%zx,\"%s\",%d)",
4518 (size_t)fH, option, Hoption.Spec).Data());
4519 return;
4520 }
4521
4522 // Deflate the labels in case of alphanumeric labels
4526
4527 if (Hoption.Pie) {
4528 if (fH->GetDimension() == 1) {
4529 if (!fPie)
4530 fPie = std::make_unique<TPie>(fH);
4531 fPie->Paint(option);
4532 } else {
4533 Error("Paint", "Option PIE is for 1D histograms only");
4534 }
4535 return;
4536 } else {
4537 fPie.reset();
4538 }
4539
4540 fXbuf.resize(kNMAX);
4541 fYbuf.resize(kNMAX);
4542 if (fH->GetDimension() > 2) {
4543 PaintH3(option);
4545 if (Hoption.Func) {
4550 Hoption = hoptsave;
4551 Hparam = hparsave;
4552 }
4554 fXbuf.clear();
4555 fYbuf.clear();
4556 return;
4557 }
4558 TView *view = gPad->GetView();
4559 if (view) {
4560 if (!Hoption.Lego && !Hoption.Surf && !Hoption.Tri) {
4561 delete view;
4562 gPad->SetView(nullptr);
4563 }
4564 }
4565 if (fH->GetDimension() > 1 || Hoption.Lego || Hoption.Surf) {
4566 // In case of 1D histogram, Z axis becomes Y axis.
4567 Int_t logysav=0, logzsav=0;
4568 if (fH->GetDimension() == 1) {
4571 Hoption.Logz = 0;
4572 if (Hoption.Logy) {
4573 Hoption.Logz = 1;
4574 Hoption.Logy = 0;
4575 }
4576 }
4578 if (Hoption.Func) {
4583 Hoption = hoptsave;
4584 Hparam = hparsave;
4585 }
4588 fXbuf.clear();
4589 fYbuf.clear();
4590 if (fH->GetDimension() == 1) {
4593 }
4594 return;
4595 }
4596
4597 if (Hoption.Bar >= 20) {
4599 fXbuf.clear();
4600 fYbuf.clear();
4601 return;
4602 }
4603
4604 gPad->RangeAxisChanged(); //emit RangeAxisChanged() signal to sync axes
4605 // fill Hparam structure with histo parameters
4606 if (!PaintInit()) {
4607 fXbuf.clear();
4608 fYbuf.clear();
4609 return;
4610 }
4611
4612 // Picture surround (if new page) and page number (if requested).
4613 // Histogram surround (if not option "Same").
4614 PaintFrame();
4615
4616 // Paint histogram axis only
4617 Bool_t gridx = gPad->GetGridx();
4618 Bool_t gridy = gPad->GetGridy();
4619 if (Hoption.Axis > 0) {
4620 if (Hoption.Axis > 1) PaintAxis(kTRUE); //axis with grid
4621 else {
4622 if (gridx) gPad->SetGridx(0);
4623 if (gridy) gPad->SetGridy(0);
4625 if (gridx) gPad->SetGridx(1);
4626 if (gridy) gPad->SetGridy(1);
4627 }
4628 if ((Hoption.Same%10) ==1) Hoption.Same += 1;
4629 goto paintstat;
4630 }
4631 if (gridx || gridy) PaintAxis(kTRUE); // Draw the grid only
4632
4633 // test for options BAR or HBAR
4634 if (Hoption.Bar >= 10) {
4636 }
4637
4638 // do not draw histogram if error bars required
4639 if (!Hoption.Error) {
4640 if (Hoption.Hist && Hoption.Bar<10) PaintHist(option);
4641 }
4642
4643 // test for error bars or option E
4644 if (Hoption.Error) {
4646 if (Hoption.Hist == 2) PaintHist(option);
4647 }
4648
4650
4651 // test for associated function
4652 if (Hoption.Func) {
4657 Hoption = hoptsave;
4658 Hparam = hparsave;
4659 }
4660
4661 if (gridx) gPad->SetGridx(0);
4662 if (gridy) gPad->SetGridy(0);
4664 if (gridx) gPad->SetGridx(1);
4665 if (gridy) gPad->SetGridy(1);
4666
4667 PaintTitle(); // Draw histogram title
4668
4669 // Draw box with histogram statistics and/or fit parameters
4670paintstat:
4671 if ((Hoption.Same%10) != 1 && !fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
4672 TIter next(fFunctions);
4673 TObject *obj = nullptr;
4674 while ((obj = next())) {
4675 if (obj->InheritsFrom(TF1::Class())) break;
4676 obj = nullptr;
4677 }
4678
4679 //Stat is painted twice (first, it will be in canvas' list of primitives),
4680 //second, it will be here, this is not required on iOS.
4681 //Condition is ALWAYS true on a platform different from iOS.
4682 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode())
4683 PaintStat(gStyle->GetOptStat(),(TF1*)obj);
4684 }
4687 fXbuf.clear();
4688 fYbuf.clear();
4689}
4690
4691////////////////////////////////////////////////////////////////////////////////
4692/// [Control function to draw a table as an arrow plot](\ref HP12)
4693
4695{
4697 Double_t dx, dy, x1, x2, y1, y2, xc, yc, dxn, dyn;
4700 Double_t xrg = gPad->GetUxmin();
4701 Double_t yrg = gPad->GetUymin();
4702 Double_t xln = gPad->GetUxmax() - xrg;
4703 Double_t yln = gPad->GetUymax() - yrg;
4704 Double_t cx = (xln/Double_t(ncx))/2.;
4705 Double_t cy = (yln/Double_t(ncy))/2.;
4706 Double_t dn = 1.E-30;
4707
4708 auto arrow = new TArrow();
4709 arrow->SetAngle(30);
4710 arrow->SetFillStyle(1001);
4711 arrow->SetFillColor(fH->GetLineColor());
4712 arrow->SetLineColor(fH->GetLineColor());
4713 arrow->SetLineWidth(fH->GetLineWidth());
4714
4715 // Initialize the levels on the Z axis
4716 Int_t ncolors=0, ndivz=0;
4717 Double_t scale=0.;
4718 if (Hoption.Arrow>1) {
4720 Int_t ndiv = fH->GetContour();
4721 if (ndiv == 0 ) {
4722 ndiv = gStyle->GetNumberContours();
4723 fH->SetContour(ndiv);
4724 }
4725 ndivz = TMath::Abs(ndiv);
4726 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
4728 }
4729
4730 for (Int_t id=1;id<=2;id++) {
4731 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
4734 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
4735 xk = fXaxis->GetBinLowEdge(i);
4736 xstep = fXaxis->GetBinWidth(i);
4737 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
4738 if (i == Hparam.xfirst) {
4739 dx = fH->GetBinContent(i+1, j) - fH->GetBinContent(i, j);
4740 } else if (i == Hparam.xlast) {
4741 dx = fH->GetBinContent(i, j) - fH->GetBinContent(i-1, j);
4742 } else {
4743 dx = 0.5*(fH->GetBinContent(i+1, j) - fH->GetBinContent(i-1, j));
4744 }
4745 if (j == Hparam.yfirst) {
4746 dy = fH->GetBinContent(i, j+1) - fH->GetBinContent(i, j);
4747 } else if (j == Hparam.ylast) {
4748 dy = fH->GetBinContent(i, j) - fH->GetBinContent(i, j-1);
4749 } else {
4750 dy = 0.5*(fH->GetBinContent(i, j+1) - fH->GetBinContent(i, j-1));
4751 }
4752 if (id == 1) {
4755 } else if (id == 2) {
4756 xc = xrg + xln*(Double_t(i - Hparam.xfirst+1)-0.5)/Double_t(ncx);
4757 dxn = cx*dx/dn;
4758 x1 = xc - dxn;
4759 x2 = xc + dxn;
4760 yc = yrg + yln*(Double_t(j - Hparam.yfirst+1)-0.5)/Double_t(ncy);
4761 dyn = cy*dy/dn;
4762 y1 = yc - dyn;
4763 y2 = yc + dyn;
4764 if (Hoption.Arrow>1) {
4765 int color = Int_t(0.01+(fH->GetBinContent(i, j)-fH->GetMinimum())*scale);
4766 Int_t theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
4767 if (theColor > ncolors-1) theColor = ncolors-1;
4768 arrow->SetFillColor(gStyle->GetColorPalette(theColor));
4769 arrow->SetLineColor(gStyle->GetColorPalette(theColor));
4770 }
4771 if (TMath::Abs(x2-x1) > 0. || TMath::Abs(y2-y1) > 0.) {
4772 arrow->PaintArrow(x1, y1, x2, y2, 0.015, "|>");
4773 } else {
4774 arrow->PaintArrow(x1, y1, x2, y2, 0.005, "|>");
4775 }
4776 }
4777 }
4778 }
4779 }
4780
4782}
4783
4784////////////////////////////////////////////////////////////////////////////////
4785/// Draw axis (2D case) of an histogram.
4786///
4787/// If `drawGridOnly` is `TRUE`, only the grid is painted (if needed). This allows
4788/// to draw the grid and the axis separately. In `THistPainter::Paint` this
4789/// feature is used to make sure that the grid is drawn in the background and
4790/// the axis tick marks in the foreground of the pad.
4791
4793{
4794
4795 //On iOS, grid should not be pickable and can not be highlighted.
4796 //Condition is never true on a platform different from iOS.
4797 if (drawGridOnly && (gPad->PadInHighlightMode() || gPad->PadInSelectionMode()))
4798 return;
4799
4800 if (Hoption.Axis == -1) return;
4801 if (Hoption.Same && Hoption.Axis <= 0) return;
4802
4803 // Repainting alphanumeric labels axis on a plot done with
4804 // the option HBAR (horizontal) needs some adjustments.
4805 TAxis *xaxis = nullptr;
4806 TAxis *yaxis = nullptr;
4807 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4808 if (fXaxis->GetLabels() || fYaxis->GetLabels()) { // One axis has alphanumeric labels
4809 TIter next(gPad->GetListOfPrimitives());
4810 TObject *obj;
4811 // Check if the first TH1 of THStack in the pad is drawn with the option HBAR
4812 while ((obj = next())) {
4813 if (!obj->InheritsFrom(TH1::Class()) &&
4814 !obj->InheritsFrom(THStack::Class())) continue;
4815 TString opt = obj->GetDrawOption();
4816 opt.ToLower();
4817 // if drawn with HBAR, the axis should be inverted and the pad set to horizontal
4818 if (strstr(opt,"hbar")) {
4819 gPad->SetVertical(kFALSE);
4820 xaxis = fXaxis;
4821 yaxis = fYaxis;
4822 if (!strcmp(xaxis->GetName(),"xaxis")) {
4823 fXaxis = yaxis;
4824 fYaxis = xaxis;
4825 }
4826 }
4827 break;
4828 }
4829 }
4830 }
4831
4832 static char chopt[10] = "";
4833 Double_t gridl = 0;
4834 Int_t ndiv, ndivx, ndivy, nx1, nx2, ndivsave;
4835 Int_t useHparam = 0;
4839
4840 Double_t axmin = gPad->GetUxmin();
4841 Double_t axmax = gPad->GetUxmax();
4842 Double_t aymin = gPad->GetUymin();
4843 Double_t aymax = gPad->GetUymax();
4844 char *cw = nullptr;
4845 TGaxis axis;
4846
4847 // In case of option 'cont4' or in case of option 'same' over a 'cont4 plot'
4848 // Hparam must be use for the axis limits.
4849 if (Hoption.Contour == 14) useHparam = 1;
4850 if (Hoption.Same) {
4851 TObject *obj;
4852 TIter next(gPad->GetListOfPrimitives());
4853 while ((obj=next())) {
4854 if (strstr(obj->GetDrawOption(),"cont4")) {
4855 useHparam = 1;
4856 break;
4857 }
4858 }
4859 }
4860
4861 // Paint X axis
4862
4863 //To make X-axis selectable on iOS device.
4864 if (gPad->PadInSelectionMode())
4865 gPad->PushSelectableObject(fXaxis);
4866
4867 //This condition is ALWAYS true, unless it works on iOS (can be false on iOS).
4868 if (gPad->PadInSelectionMode() || !gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && gPad->GetSelected() == fXaxis)) {
4870 if (ndivx > 1000) {
4871 nx2 = ndivx/100;
4872 nx1 = TMath::Max(1, ndivx%100);
4873 ndivx = 100*nx2 + Int_t(Float_t(nx1)*gPad->GetAbsWNDC());
4874 }
4875 axis.SetTextAngle(0);
4877
4878 chopt[0] = 0;
4879 strlcat(chopt, "SDH",10);
4880 if (ndivx < 0) strlcat(chopt, "N",10);
4881 if (gPad->GetGridx()) {
4882 gridl = (aymax-aymin)/(gPad->GetY2() - gPad->GetY1());
4883 strlcat(chopt, "W",10);
4884 }
4885
4886 // Define X-Axis limits
4887 if (Hoption.Logx) {
4888 strlcat(chopt, "G",10);
4889 ndiv = TMath::Abs(ndivx);
4890 if (useHparam) {
4893 } else {
4894 umin = TMath::Power(10,axmin);
4895 umax = TMath::Power(10,axmax);
4896 }
4897 } else {
4898 ndiv = TMath::Abs(ndivx);
4899 if (useHparam) {
4900 umin = Hparam.xmin;
4901 umax = Hparam.xmax;
4902 } else {
4903 umin = axmin;
4904 umax = axmax;
4905 }
4906 }
4907
4908 // Display axis as time
4909 if (fXaxis->GetTimeDisplay()) {
4910 strlcat(chopt,"t",10);
4911 if (strlen(fXaxis->GetTimeFormatOnly()) == 0) {
4913 }
4914 }
4915
4916 // The main X axis can be on the bottom or on the top of the pad
4918 if (xAxisPos == 1) {
4919 // Main X axis top
4920 xAxisYPos1 = aymax;
4921 xAxisYPos2 = aymin;
4922 } else {
4923 // Main X axis bottom
4924 xAxisYPos1 = aymin;
4925 xAxisYPos2 = aymax;
4926 }
4927
4928 // Paint the main X axis (always)
4929 uminsave = umin;
4930 umaxsave = umax;
4931 ndivsave = ndiv;
4932 axis.SetOption(chopt);
4933 if (xAxisPos) {
4934 strlcat(chopt, "-",10);
4935 gridl = -gridl;
4936 }
4937 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4938 axis.SetLabelSize(0.);
4939 axis.SetTitle("");
4940 }
4943 umin, umax, ndiv, chopt, gridl, drawGridOnly);
4944
4945 // Paint additional X axis (if needed)
4946 // On iOS, this additional X axis is neither pickable, nor highlighted.
4947 // Additional checks PadInSelectionMode etc. does not effect non-iOS platform.
4948 if (gPad->GetTickx() && !gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
4949 if (xAxisPos) {
4950 cw=strstr(chopt,"-");
4951 *cw='z';
4952 } else {
4953 strlcat(chopt, "-",10);
4954 }
4955 if (gPad->GetTickx() < 2) strlcat(chopt, "U",10);
4956 if ((cw=strstr(chopt,"W"))) *cw='z';
4957 axis.SetTitle("");
4961 }
4962 }//End of "if pad in selection mode etc".
4963
4964 // Paint Y axis
4965 //On iOS, Y axis must pushed into the stack of selectable objects.
4966 if (gPad->PadInSelectionMode())
4967 gPad->PushSelectableObject(fYaxis);
4968
4969 //This conditions is ALWAYS true on a platform, different from iOS (on iOS can be true, can be false).
4970 if (gPad->PadInSelectionMode() || !gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && gPad->GetSelected() == fYaxis)) {
4973
4974 chopt[0] = 0;
4975 strlcat(chopt, "SDH",10);
4976 if (ndivy < 0) strlcat(chopt, "N",10);
4977 if (gPad->GetGridy()) {
4978 gridl = (axmax-axmin)/(gPad->GetX2() - gPad->GetX1());
4979 strlcat(chopt, "W",10);
4980 }
4981
4982 // Define Y-Axis limits
4983 if (Hoption.Logy) {
4984 strlcat(chopt, "G",10);
4985 ndiv = TMath::Abs(ndivy);
4986 if (useHparam) {
4989 } else {
4990 umin = TMath::Power(10,aymin);
4991 umax = TMath::Power(10,aymax);
4992 }
4993 } else {
4994 ndiv = TMath::Abs(ndivy);
4995 if (useHparam) {
4996 umin = Hparam.ymin;
4997 umax = Hparam.ymax;
4998 } else {
4999 umin = aymin;
5000 umax = aymax;
5001 }
5002 }
5003
5004 // Display axis as time
5005 if (fYaxis->GetTimeDisplay()) {
5006 strlcat(chopt,"t",10);
5007 if (strlen(fYaxis->GetTimeFormatOnly()) == 0) {
5009 }
5010 }
5011
5012 // The main Y axis can be on the left or on the right of the pad
5014 if (yAxisPos == 1) {
5015 // Main Y axis left
5016 yAxisXPos1 = axmax;
5017 yAxisXPos2 = axmin;
5018 } else {
5019 // Main Y axis right
5020 yAxisXPos1 = axmin;
5021 yAxisXPos2 = axmax;
5022 }
5023
5024 // Paint the main Y axis (always)
5025 uminsave = umin;
5026 umaxsave = umax;
5027 ndivsave = ndiv;
5028 axis.SetOption(chopt);
5029 if (yAxisPos) {
5030 strlcat(chopt, "+L",10);
5031 gridl = -gridl;
5032 }
5033 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
5034 axis.SetLabelSize(0.);
5035 axis.SetTitle("");
5036 }
5039 umin, umax, ndiv, chopt, gridl, drawGridOnly);
5040
5041 // Paint the additional Y axis (if needed)
5042 // Additional checks for pad mode are required on iOS: this "second" axis is
5043 // neither pickable, nor highlighted. Additional checks have no effect on non-iOS platform.
5044 if (gPad->GetTicky() && !gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
5045 if (gPad->GetTicky() < 2) {
5046 strlcat(chopt, "U",10);
5048 } else {
5049 strlcat(chopt, "+L",10);
5050 }
5051 if ((cw=strstr(chopt,"W"))) *cw='z';
5052 axis.SetTitle("");
5056 }
5057 }//End of "if pad is in selection mode etc."
5058
5059 // Reset the axis if they have been inverted in case of option HBAR
5060 if (xaxis) {
5061 fXaxis = xaxis;
5062 fYaxis = yaxis;
5063 }
5064}
5065
5066////////////////////////////////////////////////////////////////////////////////
5067/// [Draw a bar-chart in a normal pad.](\ref HP10)
5068
5070{
5071
5072 Int_t bar = Hoption.Bar - 10;
5076 TBox box;
5078 if (hcolor == gPad->GetFrameFillColor()) ++hcolor;
5080 box.SetFillColor(hcolor);
5081 box.SetFillStyle(hstyle);
5082 box.SetLineStyle(fH->GetLineStyle());
5083 box.SetLineColor(fH->GetLineColor());
5084 box.SetLineWidth(fH->GetLineWidth());
5085 for (Int_t bin=fXaxis->GetFirst();bin<=fXaxis->GetLast();bin++) {
5086 y = fH->GetBinContent(bin);
5087 xmin = gPad->XtoPad(fXaxis->GetBinLowEdge(bin));
5088 xmax = gPad->XtoPad(fXaxis->GetBinUpEdge(bin));
5089 ymin = gPad->GetUymin();
5090 ymax = gPad->YtoPad(y);
5091 if (ymax < gPad->GetUymin()) continue;
5092 if (ymax > gPad->GetUymax()) ymax = gPad->GetUymax();
5093 if (ymin < gPad->GetUymin()) ymin = gPad->GetUymin();
5094 if (Hoption.MinimumZero && ymin < 0)
5095 ymin=TMath::Min(0.,gPad->GetUymax());
5096 w = (xmax-xmin)*width;
5097 xmin += offset*(xmax-xmin);
5098 xmax = xmin + w;
5099 if (bar < 1) {
5100 box.PaintBox(xmin,ymin,xmax,ymax);
5101 } else {
5102 umin = xmin + bar*(xmax-xmin)/10.;
5103 umax = xmax - bar*(xmax-xmin)/10.;
5104 box.SetFillColor(TColor::GetColorBright(hcolor)); //bright
5105 box.PaintBox(xmin,ymin,umin,ymax);
5106 box.SetFillColor(hcolor);
5107 box.PaintBox(umin,ymin,umax,ymax);
5108 box.SetFillColor(TColor::GetColorDark(hcolor)); //dark
5109 box.PaintBox(umax,ymin,xmax,ymax);
5110 }
5111 }
5112}
5113
5114////////////////////////////////////////////////////////////////////////////////
5115/// [Draw a bar char in a rotated pad (X vertical, Y horizontal)](\ref HP10)
5116
5118{
5119
5120 gPad->SetVertical(kFALSE);
5121
5122 PaintInitH();
5123
5124 TAxis *xaxis = fXaxis;
5125 TAxis *yaxis = fYaxis;
5126 if (!strcmp(xaxis->GetName(),"xaxis")) {
5127 fXaxis = yaxis;
5128 fYaxis = xaxis;
5129 }
5130
5131 PaintFrame();
5133
5134 Int_t bar = Hoption.Bar - 20;
5138 TBox box;
5140 if (hcolor == gPad->GetFrameFillColor()) ++hcolor;
5142 box.SetFillColor(hcolor);
5143 box.SetFillStyle(hstyle);
5144 box.SetLineStyle(fH->GetLineStyle());
5145 box.SetLineColor(fH->GetLineColor());
5146 box.SetLineWidth(fH->GetLineWidth());
5147 for (Int_t bin=fYaxis->GetFirst();bin<=fYaxis->GetLast();bin++) {
5148 ymin = gPad->YtoPad(fYaxis->GetBinLowEdge(bin));
5149 ymax = gPad->YtoPad(fYaxis->GetBinUpEdge(bin));
5150 xmin = gPad->GetUxmin();
5151 xmax = gPad->XtoPad(fH->GetBinContent(bin));
5152 if (xmax < gPad->GetUxmin()) continue;
5153 if (xmax > gPad->GetUxmax()) xmax = gPad->GetUxmax();
5154 if (xmin < gPad->GetUxmin()) xmin = gPad->GetUxmin();
5155 if (Hoption.MinimumZero && xmin < 0)
5156 xmin=TMath::Min(0.,gPad->GetUxmax());
5157 w = (ymax-ymin)*width;
5158 ymin += offset*(ymax-ymin);
5159 ymax = ymin + w;
5160 if (bar < 1) {
5161 box.PaintBox(xmin,ymin,xmax,ymax);
5162 } else {
5163 umin = ymin + bar*(ymax-ymin)/10.;
5164 umax = ymax - bar*(ymax-ymin)/10.;
5165 box.SetFillColor(TColor::GetColorDark(hcolor)); //dark
5166 box.PaintBox(xmin,ymin,xmax,umin);
5167 box.SetFillColor(hcolor);
5168 box.PaintBox(xmin,umin,xmax,umax);
5169 box.SetFillColor(TColor::GetColorBright(hcolor)); //bright
5170 box.PaintBox(xmin,umax,xmax,ymax);
5171 }
5172 }
5173
5174 PaintTitle();
5175
5176 // Draw box with histogram statistics and/or fit parameters
5177 if ((Hoption.Same%10) != 1 && !fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
5178 TIter next(fFunctions);
5179 TObject *obj = nullptr;
5180 while ((obj = next())) {
5181 if (obj->InheritsFrom(TF1::Class())) break;
5182 obj = nullptr;
5183 }
5184 PaintStat(gStyle->GetOptStat(),(TF1*)obj);
5185 }
5186
5187 fXaxis = xaxis;
5188 fYaxis = yaxis;
5189}
5190
5191////////////////////////////////////////////////////////////////////////////////
5192/// [Control function to draw a 2D histogram as a box plot](\ref HP13)
5193
5195{
5196
5199 if (fH->GetFillColor() == 0) fH->SetFillStyle(0);
5200 if (Hoption.Box == 11) fH->SetFillStyle(1001);
5201 fH->TAttLine::Modify();
5202 fH->TAttFill::Modify();
5203
5204 Double_t z, xk,xstep, yk, ystep, xcent, ycent, xlow, xup, ylow, yup;
5205 Double_t ux1 = gPad->PixeltoX(1);
5206 Double_t ux0 = gPad->PixeltoX(0);
5207 Double_t uy1 = gPad->PixeltoY(1);
5208 Double_t uy0 = gPad->PixeltoY(0);
5209 Double_t dxmin = 0.51*(gPad->PadtoX(ux1)-gPad->PadtoX(ux0));
5210 Double_t dymin = 0.51*(gPad->PadtoY(uy0)-gPad->PadtoY(uy1));
5211
5212 Double_t zmin = TMath::Max(fH->GetMinimum(),0.);
5215 Double_t zminlin = zmin, zmaxlin = zmax;
5216
5217 // In case of option SAME, zmin and zmax values are taken from the
5218 // first plotted 2D histogram.
5219 if (Hoption.Same > 0 && Hoption.Same < 10) {
5220 TH2 *h2;
5221 TIter next(gPad->GetListOfPrimitives());
5222 while ((h2 = (TH2 *)next())) {
5223 if (!h2->InheritsFrom(TH2::Class())) continue;
5224 zmin = TMath::Max(h2->GetMinimum(), 0.);
5225 zmax = TMath::Max(TMath::Abs(h2->GetMaximum()),
5226 TMath::Abs(h2->GetMinimum()));
5227 zminlin = zmin;
5228 zmaxlin = zmax;
5229 if (Hoption.Logz) {
5230 if (zmin <= 0) {
5231 zmin = TMath::Log10(zmax*0.001);
5232 } else {
5233 zmin = TMath::Log10(zmin);
5234 }
5235 zmax = TMath::Log10(zmax);
5236 }
5237 break;
5238 }
5239 } else {
5240 if (Hoption.Logz) {
5241 if (zmin > 0) {
5242 zmin = TMath::Log10(zmin);
5243 zmax = TMath::Log10(zmax);
5244 } else {
5245 return;
5246 }
5247 }
5248 }
5249
5250 Double_t zratio, dz = zmax - zmin;
5252 if (fH->GetMinimum()<0) kZminNeg = kTRUE;
5254
5255 // Define the dark and light colors the "button style" boxes.
5256 Color_t color = fH->GetFillColor();
5257 Color_t light=0, dark=0;
5258 if (Hoption.Box == 11) {
5260 dark = TColor::GetColorDark(color);
5261 }
5262
5263 // Loop over all the bins and draw the boxes
5264 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
5267 ycent = 0.5*ystep;
5268 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
5269 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
5270 xk = fXaxis->GetBinLowEdge(i);
5271 xstep = fXaxis->GetBinWidth(i);
5272 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
5273 xcent = 0.5*xstep;
5275 kZNeg = kFALSE;
5276
5277 if (TMath::Abs(z) < zminlin) continue; // Can be the case with ...
5278 if (TMath::Abs(z) > zmaxlin) z = zmaxlin; // ... option Same
5279 if (kZminNeg && z==0) continue; // Do not draw empty bins if case of histo with negative bins.
5280
5281 if (z < 0) {
5282 if (Hoption.Logz) continue;
5283 z = -z;
5284 kZNeg = kTRUE;
5285 }
5286 if (Hoption.Logz) {
5287 if (z != 0) z = TMath::Log10(z);
5288 else z = zmin;
5289 }
5290
5291 if (dz == 0) continue;
5292 zratio = TMath::Sqrt((z-zmin)/dz);
5293 if (zratio == 0) continue;
5294
5295 xup = xcent*zratio + xk + xcent;
5296 xlow = 2*(xk + xcent) - xup;
5297 if (xup-xlow < dxmin) xup = xlow+dxmin;
5298 if (Hoption.Logx) {
5299 if (xup > 0) xup = TMath::Log10(xup);
5300 else continue;
5301 if (xlow > 0) xlow = TMath::Log10(xlow);
5302 else continue;
5303 }
5304
5305 yup = ycent*zratio + yk + ycent;
5306 ylow = 2*(yk + ycent) - yup;
5307 if (yup-ylow < dymin) yup = ylow+dymin;
5308 if (Hoption.Logy) {
5309 if (yup > 0) yup = TMath::Log10(yup);
5310 else continue;
5311 if (ylow > 0) ylow = TMath::Log10(ylow);
5312 else continue;
5313 }
5314
5315 xlow = TMath::Max(xlow, gPad->GetUxmin());
5316 ylow = TMath::Max(ylow, gPad->GetUymin());
5317 xup = TMath::Min(xup , gPad->GetUxmax());
5318 yup = TMath::Min(yup , gPad->GetUymax());
5319
5320 if (xlow >= xup) continue;
5321 if (ylow >= yup) continue;
5322
5323 if (Hoption.Box == 1) {
5324 fH->SetFillColor(color);
5325 fH->TAttFill::Modify();
5326 gPad->PaintBox(xlow, ylow, xup, yup);
5327 if (kZNeg) {
5328 gPad->PaintLine(xlow, ylow, xup, yup);
5329 gPad->PaintLine(xlow, yup, xup, ylow);
5330 }
5331 } else if (Hoption.Box == 11) {
5332 // Draw the center of the box
5333 fH->SetFillColor(color);
5334 fH->TAttFill::Modify();
5335 gPad->PaintBox(xlow, ylow, xup, yup);
5336
5337 // Draw top&left part of the box
5338 Double_t x[7], y[7];
5339 Double_t bwidth = 0.1;
5340 x[0] = xlow; y[0] = ylow;
5341 x[1] = xlow + bwidth*(xup-xlow); y[1] = ylow + bwidth*(yup-ylow);
5342 x[2] = x[1]; y[2] = yup - bwidth*(yup-ylow);
5343 x[3] = xup - bwidth*(xup-xlow); y[3] = y[2];
5344 x[4] = xup; y[4] = yup;
5345 x[5] = xlow; y[5] = yup;
5346 x[6] = xlow; y[6] = ylow;
5347 if (kZNeg) fH->SetFillColor(dark);
5348 else fH->SetFillColor(light);
5349 fH->TAttFill::Modify();
5350 gPad->PaintFillArea(7, x, y);
5351
5352 // Draw bottom&right part of the box
5353 x[0] = xlow; y[0] = ylow;
5354 x[1] = xlow + bwidth*(xup-xlow); y[1] = ylow + bwidth*(yup-ylow);
5355 x[2] = xup - bwidth*(xup-xlow); y[2] = y[1];
5356 x[3] = x[2]; y[3] = yup - bwidth*(yup-ylow);
5357 x[4] = xup; y[4] = yup;
5358 x[5] = xup; y[5] = ylow;
5359 x[6] = xlow; y[6] = ylow;
5360 if (kZNeg) fH->SetFillColor(light);
5361 else fH->SetFillColor(dark);
5362 fH->TAttFill::Modify();
5363 gPad->PaintFillArea(7, x, y);
5364 }
5365 }
5366 }
5367
5371 fH->TAttFill::Modify();
5372}
5373
5374
5375
5376////////////////////////////////////////////////////////////////////////////////
5377/// [Control function to draw a 2D histogram as a candle (box) plot or violin plot](\ref HP14)
5378
5380{
5381 TH1D *hproj = nullptr;
5382 TH2D *h2 = (TH2D*)fH;
5383
5386 myCandle.SetMarkerColor(fH->GetLineColor());
5387 myCandle.SetLineColor(fH->GetLineColor());
5388 myCandle.SetLineWidth(fH->GetLineWidth());
5389 myCandle.SetFillColor(fH->GetFillColor());
5390 myCandle.SetFillStyle(fH->GetFillStyle());
5391 myCandle.SetMarkerSize(fH->GetMarkerSize());
5392 myCandle.SetMarkerStyle(fH->GetMarkerStyle());
5394
5395 Bool_t swapXY = myCandle.IsHorizontal();
5396 const Double_t standardCandleWidth = 0.66;
5397 const Double_t standardHistoWidth = 0.8;
5398
5399 double allMaxContent = 0, allMaxIntegral = 0;
5400 if (myCandle.IsViolinScaled())
5402
5403 if (!swapXY) { // Vertical candle
5404 //Determining the slice with the maximum integral - if necessary
5405 if (myCandle.IsCandleScaled())
5406 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast; i++) {
5407 hproj = h2->ProjectionY("_px", i, i);
5408 if (hproj->Integral() > allMaxIntegral) allMaxIntegral = hproj->Integral();
5409 }
5410 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast; i++) {
5412 Double_t binWidth = fXaxis->GetBinWidth(i);
5413 hproj = h2->ProjectionY("_px", i, i);
5414 if (hproj->GetEntries() != 0) {
5416 Double_t offset = fH->GetBarOffset()*binWidth;
5417 double myMaxContent = hproj->GetBinContent(hproj->GetMaximumBin());
5418 double myIntegral = hproj->Integral();
5420 if (candleWidth > 0.999 && candleWidth < 1.001) {
5423 }
5424 if (Hoption.Logz && myMaxContent > 0) {
5426 if (myCandle.IsViolinScaled() && myMaxContent > 0 && allMaxContent > 0)
5428 } else if (myCandle.IsViolinScaled() && (allMaxContent > 0))
5430 if (myCandle.IsCandleScaled() && (allMaxIntegral > 0))
5432
5433 myCandle.SetAxisPosition(binPosX+binWidth/2. + offset);
5434 myCandle.SetCandleWidth(candleWidth*binWidth);
5435 myCandle.SetHistoWidth(histoWidth*binWidth);
5436 myCandle.SetHistogram(hproj);
5437 myCandle.Paint();
5438 }
5439 }
5440 } else { // Horizontal candle
5441 //Determining the slice with the maximum integral - if necessary
5442 if (myCandle.IsCandleScaled())
5443 for (Int_t i=Hparam.yfirst; i<=Hparam.ylast; i++) {
5444 hproj = h2->ProjectionX("_py", i, i);
5445 if (hproj->Integral() > allMaxIntegral) allMaxIntegral = hproj->Integral();
5446 }
5447 for (Int_t i=Hparam.yfirst; i<=Hparam.ylast; i++) {
5449 Double_t binWidth = fYaxis->GetBinWidth(i);
5450 hproj = h2->ProjectionX("_py", i, i);
5451 if (hproj->GetEntries() != 0) {
5453 Double_t offset = fH->GetBarOffset()*binWidth;
5454 double myMaxContent = hproj->GetBinContent(hproj->GetMaximumBin());
5455 double myIntegral = hproj->Integral();
5457 if (candleWidth > 0.999 && candleWidth < 1.001) {
5460 }
5461 if (Hoption.Logz && myMaxContent > 0) {
5463 if (myCandle.IsViolinScaled() && myMaxContent > 0 && allMaxContent > 0)
5465 } else if (myCandle.IsViolinScaled() && (allMaxContent > 0))
5467 if (myCandle.IsCandleScaled() && (allMaxIntegral > 0))
5469
5470 myCandle.SetAxisPosition(binPosY+binWidth/2. + offset);
5471 myCandle.SetCandleWidth(candleWidth*binWidth);
5472 myCandle.SetHistoWidth(histoWidth*binWidth);
5473 myCandle.SetHistogram(hproj);
5474 myCandle.Paint();
5475 }
5476 }
5477 }
5478 delete hproj;
5479}
5480
5481
5482
5483////////////////////////////////////////////////////////////////////////////////
5484/// Returns the rendering regions for an axis to use in the COL2 option
5485///
5486/// The algorithm analyses the size of the axis compared to the size of
5487/// the rendering region. It figures out the boundaries to use for each color
5488/// of the rendering region. Only one axis is computed here.
5489///
5490/// This allows for a single computation of the boundaries before iterating
5491/// through all of the bins.
5492///
5493/// \param pAxis the axis to consider
5494/// \param nPixels the number of pixels to render axis into
5495/// \param isLog whether the axis is log scale
5496
5497std::vector<THistRenderingRegion>
5499{
5500 std::vector<THistRenderingRegion> regions;
5501
5502 enum STRATEGY { Bins, Pixels } strategy;
5503
5504 Int_t nBins = (pAxis->GetLast() - pAxis->GetFirst() + 1);
5505
5506 if (nBins >= nPixels) {
5507 // more bins than pixels... we should loop over pixels and sample
5508 strategy = Pixels;
5509 } else {
5510 // fewer bins than pixels... we should loop over bins
5511 strategy = Bins;
5512 }
5513
5514 if (isLog) {
5515
5516 Double_t xMin = pAxis->GetBinLowEdge(pAxis->GetFirst());
5517 Int_t binOffset=0;
5518 while (xMin <= 0 && ((pAxis->GetFirst()+binOffset) != pAxis->GetLast()) ) {
5519 binOffset++;
5520 xMin = pAxis->GetBinLowEdge(pAxis->GetFirst()+binOffset);
5521 }
5522 if (xMin <= 0) {
5523 // this should cause an error if we have
5524 return regions;
5525 }
5526 Double_t xMax = pAxis->GetBinUpEdge(pAxis->GetLast());
5527
5528 if (strategy == Bins) {
5529 // logarithmic plot. we find the pixel for the bin
5530 // pixel = eta * log10(V) - alpha
5531 // where eta = nPixels/(log10(Vmax)-log10(Vmin))
5532 // and alpha = nPixels*log10(Vmin)/(log10(Vmax)-log10(Vmin))
5533 // and V is axis value
5534 Double_t eta = (nPixels-1.0)/(TMath::Log10(xMax) - TMath::Log10(xMin));
5535 Double_t offset = -1.0 * eta * TMath::Log10(xMin);
5536
5537 for (Int_t bin=pAxis->GetFirst()+binOffset; bin<=pAxis->GetLast(); bin++) {
5538
5539 // linear plot. we simply need to find the appropriate bin
5540 // for the
5541 Double_t xLowValue = pAxis->GetBinLowEdge(bin);
5542 Double_t xUpValue = pAxis->GetBinUpEdge(bin);
5545 THistRenderingRegion region = {std::make_pair(xPx0, xPx1),
5546 std::make_pair(bin, bin+1)};
5547 regions.push_back(region);
5548 }
5549
5550 } else {
5551
5552 // loop over pixels
5553
5554 Double_t beta = (TMath::Log10(xMax) - TMath::Log10(xMin))/(nPixels-1.0);
5555
5556 for (Int_t pixelIndex=0; pixelIndex<(nPixels-1); pixelIndex++) {
5557 // linear plot
5558 Int_t binLow = pAxis->FindBin(xMin*TMath::Power(10.0, beta*pixelIndex));
5559 Int_t binHigh = pAxis->FindBin(xMin*TMath::Power(10.0, beta*(pixelIndex+1)));
5560 THistRenderingRegion region = { std::make_pair(pixelIndex, pixelIndex+1),
5561 std::make_pair(binLow, binHigh)};
5562 regions.push_back(region);
5563 }
5564 }
5565 } else {
5566 // standard linear plot
5567
5568 if (strategy == Bins) {
5569 // loop over bins
5570 for (Int_t bin=pAxis->GetFirst(); bin<=pAxis->GetLast(); bin++) {
5571
5572 // linear plot. we simply need to find the appropriate bin
5573 // for the
5574 Int_t xPx0 = ((bin - pAxis->GetFirst()) * nPixels)/nBins;
5575 Int_t xPx1 = xPx0 + nPixels/nBins;
5576
5577 // make sure we don't compute beyond our bounds
5578 if (xPx1>= nPixels) xPx1 = nPixels-1;
5579
5580 THistRenderingRegion region = {std::make_pair(xPx0, xPx1),
5581 std::make_pair(bin, bin+1)};
5582 regions.push_back(region);
5583 }
5584 } else {
5585 // loop over pixels
5587 // linear plot
5588 Int_t binLow = (nBins*pixelIndex)/nPixels + pAxis->GetFirst();
5589 Int_t binHigh = binLow + nBins/nPixels;
5590 THistRenderingRegion region = { std::make_pair(pixelIndex, pixelIndex+1),
5591 std::make_pair(binLow, binHigh)};
5592 regions.push_back(region);
5593 }
5594 }
5595 }
5596
5597 return regions;
5598}
5599
5600////////////////////////////////////////////////////////////////////////////////
5601/// [Rendering scheme for the COL2 and COLZ2 options] (\ref HP14)
5602
5604{
5605
5606 if (Hoption.System != kCARTESIAN) {
5607 Error("THistPainter::PaintColorLevelsFast(Option_t*)",
5608 "Only cartesian coordinates supported by 'COL2' option. Using 'COL' option instead.");
5609 PaintColorLevels(nullptr);
5610 return;
5611 }
5612
5613 Double_t z;
5614
5615 // Use existing max or min values. If either is already set
5616 // the appropriate value to use.
5617 Double_t zmin = fH->GetMinimumStored();
5618 Double_t zmax = fH->GetMaximumStored();
5619 Double_t originalZMin = zmin;
5620 Double_t originalZMax = zmax;
5621 if ((zmin == -1111) && (zmax == -1111)) {
5622 fH->GetMinimumAndMaximum(zmin, zmax);
5623 fH->SetMinimum(zmin);
5624 fH->SetMaximum(zmax);
5625 } else if (zmin == -1111) {
5626 zmin = fH->GetMinimum();
5627 fH->SetMinimum(zmin);
5628 } else if (zmax == -1111) {
5629 zmax = fH->GetMaximum();
5630 fH->SetMaximum(zmax);
5631 }
5632
5633 Double_t dz = zmax - zmin;
5634 if (dz <= 0) { // Histogram filled with a constant value
5635 zmax += 0.1*TMath::Abs(zmax);
5636 zmin -= 0.1*TMath::Abs(zmin);
5637 dz = zmax - zmin;
5638 }
5639
5640 if (Hoption.Logz) {
5641 if (zmin > 0) {
5642 zmin = TMath::Log10(zmin);
5643 zmax = TMath::Log10(zmax);
5644 dz = zmax - zmin;
5645 } else {
5646 Error("THistPainter::PaintColorLevelsFast(Option_t*)",
5647 "Cannot plot logz because bin content is less than 0.");
5648 return;
5649 }
5650 }
5651
5652 // Initialize the levels on the Z axis
5653 Int_t ndiv = fH->GetContour();
5654 if (ndiv == 0 ) {
5655 ndiv = gStyle->GetNumberContours();
5656 fH->SetContour(ndiv);
5657 }
5658 std::vector<Double_t> colorBounds(ndiv);
5659 std::vector<Double_t> contours(ndiv, 0);
5660 if (!fH->TestBit(TH1::kUserContour)) {
5661 fH->SetContour(ndiv);
5662 } else {
5663 fH->GetContour(contours.data());
5664 }
5665
5666 Double_t step = 1.0/ndiv;
5667 for (Int_t i=0; i<ndiv; ++i) {
5668 colorBounds[i] = step*i;
5669 }
5670
5671 auto pFrame = gPad->GetFrame();
5672 Int_t px0 = gPad->XtoPixel(pFrame->GetX1());
5673 Int_t px1 = gPad->XtoPixel(pFrame->GetX2());
5674 Int_t py0 = gPad->YtoPixel(pFrame->GetY1());
5675 Int_t py1 = gPad->YtoPixel(pFrame->GetY2());
5676 Int_t nXPixels = px1-px0;
5677 Int_t nYPixels = py0-py1; // y=0 is at the top of the screen
5678
5679 std::vector<Double_t> buffer(nXPixels*nYPixels, 0);
5680
5683 if (xRegions.empty() || yRegions.empty()) {
5684 Error("THistPainter::PaintColorLevelFast(Option_t*)",
5685 "Encountered error while computing rendering regions.");
5686 return;
5687 }
5688
5691 Double_t minValue = 1.;
5692 Double_t maxValue = 0.;
5693 for (auto& yRegion : yRegions) {
5694 for (auto& xRegion : xRegions ) {
5695
5696 const auto& xBinRange = xRegion.fBinRange;
5697 const auto& yBinRange = yRegion.fBinRange;
5698
5699 // sample the range
5700 z = fH->GetBinContent(xBinRange.second-1, yBinRange.second-1);
5701
5702 if (Hoption.Logz) {
5703 if (z > 0) z = TMath::Log10(z);
5704 else z = zmin;
5705 }
5706
5707 // obey the user's max and min values if they were set
5708 if (z > zmax) z = zmax;
5709 if (z < zmin) z = zmin;
5710
5712 // contours are absolute values
5713 auto index = TMath::BinarySearch(contours.size(), contours.data(), z);
5714 z = colorBounds[index];
5715 } else {
5716 Int_t index = 0;
5717 if (dz != 0) {
5718 index = 0.001 + ((z - zmin)/dz)*ndiv;
5719 }
5720
5721 if (index == static_cast<Int_t>(colorBounds.size())) {
5722 index--;
5723 }
5724
5725 // Do a little bookkeeping to use later for getting libAfterImage to produce
5726 // the correct colors
5727 if (index == 0) {
5728 minExists = kTRUE;
5729 } else if (index == static_cast<Int_t>(colorBounds.size()-1)) {
5730 maxExists = kTRUE;
5731 }
5732
5733 z = colorBounds[index];
5734
5735 if (z < minValue) {
5736 minValue = z;
5737 }
5738 if (z > maxValue) {
5739 maxValue = z;
5740 }
5741 }
5742
5743 // fill in the actual pixels
5744 const auto& xPixelRange = xRegion.fPixelRange;
5745 const auto& yPixelRange = yRegion.fPixelRange;
5746 for (Int_t xPx = xPixelRange.first; xPx <= xPixelRange.second; ++xPx) {
5747 for (Int_t yPx = yPixelRange.first; yPx <= yPixelRange.second; ++yPx) {
5749 buffer[pixel] = z;
5750 }
5751 }
5752 } // end px loop
5753 } // end py loop
5754
5755 // This is a bit of a hack to ensure that we span the entire color range and
5756 // don't screw up the colors for a sparse histogram. No one will notice that I set a
5757 // single pixel on the edge of the image to a different color. This is even more
5758 // true because the chosen pixels will be covered by the axis.
5759 if (minValue != maxValue) {
5760 if ( !minExists) {
5761 buffer.front() = 0;
5762 }
5763
5764 if ( !maxExists) {
5765 buffer[buffer.size()-nXPixels] = 0.95;
5766 }
5767 }
5768
5769 // Generate the TImage
5772 pImage->SetImageQuality(TAttImage::kImgBest);
5773 pImage->SetImage(buffer.data(), nXPixels, nYPixels, pPalette);
5774 delete pPalette;
5775
5776 auto pp = gPad->GetPainter();
5777 if (pp)
5778 pp->DrawImage(pImage, px0, py1);
5779
5780 delete pImage;
5781
5782 if (Hoption.Zscale)
5783 PaintPalette();
5784
5785 // Reset the maximum and minimum values to their original values
5786 // when this function was called. If we don't do this, an initial
5787 // value of -1111 will be replaced with the true max or min values.
5790}
5791
5792////////////////////////////////////////////////////////////////////////////////
5793/// [Control function to draw a 2D histogram as a color plot.](\ref HP14)
5794
5796{
5797 Double_t z, e, zc, xk, xstep, yk, ystep, xlow, xup, ylow, yup;
5798
5799 Double_t zmin = fH->GetMinimum();
5800 Double_t zmax = fH->GetMaximum();
5801
5802 Double_t dz = zmax - zmin;
5803 if (dz <= 0) { // Histogram filled with a constant value
5804 zmax += 0.1*TMath::Abs(zmax);
5805 zmin -= 0.1*TMath::Abs(zmin);
5806 dz = zmax - zmin;
5807 }
5808
5809 // In case of option SAME, zmin and zmax values are taken from the
5810 // first plotted 2D histogram.
5811 if (Hoption.Same > 0 && Hoption.Same < 10) {
5812 TH2 *h2;
5813 TIter next(gPad->GetListOfPrimitives());
5814 while ((h2 = (TH2 *)next())) {
5815 if (!h2->InheritsFrom(TH2::Class())) continue;
5816 zmin = h2->GetMinimum();
5817 zmax = h2->GetMaximum();
5818 fH->SetMinimum(zmin);
5819 fH->SetMaximum(zmax);
5820 if (Hoption.Logz) {
5821 if (zmin <= 0) {
5822 zmin = TMath::Log10(zmax*0.001);
5823 } else {
5824 zmin = TMath::Log10(zmin);
5825 }
5826 zmax = TMath::Log10(zmax);
5827 }
5828 dz = zmax - zmin;
5829 break;
5830 }
5831 } else {
5832 if (Hoption.Logz) {
5833 if (zmin > 0) {
5834 zmin = TMath::Log10(zmin);
5835 zmax = TMath::Log10(zmax);
5836 dz = zmax - zmin;
5837 } else {
5838 return;
5839 }
5840 }
5841 }
5842
5845 fH->SetFillStyle(1001);
5846 fH->TAttFill::Modify();
5847
5848 // Initialize the levels on the Z axis
5850 Int_t ndiv = fH->GetContour();
5851 if (ndiv == 0) {
5852 ndiv = gStyle->GetNumberContours();
5853 fH->SetContour(ndiv);
5854 }
5855 Int_t ndivz = TMath::Abs(ndiv);
5856 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
5857 Double_t scale = (dz ? ndivz / dz : 1.0);
5858
5859 Double_t xmin = gPad->GetUxmin();
5860 Double_t xmax = gPad->GetUxmax();
5861 Double_t ymin = gPad->GetUymin();
5862 Double_t ymax = gPad->GetUymax();
5863
5864 // range used for polar coordinates
5865 Double_t pxmin = xmin, pxmax = xmax, pymin = ymin, pymax = ymax, pkr = 0.5;
5866 if ((Hoption.System == kPOLAR) && (Hoption.Polar == 2)) {
5867 pxmin = fXaxis->GetXmin();
5868 pxmax = fXaxis->GetXmax();
5869 if (Hoption.Logx) {
5870 if (pxmax <= 0)
5871 return;
5873 if (pxmin <= 0)
5874 pxmin = pxmax - 5;
5875 else
5877 }
5878 pkr = 0.45; // makes fixed range more pretty
5879 pymin = fYaxis->GetXmin();
5880 pymax = fYaxis->GetXmax();
5881 if (Hoption.Logy) {
5882 if (pymax <= 0)
5883 return;
5885 if (pymin <= 0)
5886 pymin = pymax - 5;
5887 else
5889 } else if ((pymax > 0) && (pymin > 0)) {
5890 // force minimal radius to 0 to display natural polar graphics
5891 pymin = 0;
5892 }
5893 }
5894
5895 if ((Hoption.System == kPOLAR) && (Hoption.Polar == 3)) {
5896 // do not touch boundaries when draw without axis histogram
5897 if (!Hoption.Same)
5898 pkr = 0.45;
5899 // for natural coordinates force minimal radius to 0
5900 if (!Hoption.Logy && (pymax > 0))
5901 pymin = 0;
5902 }
5903
5904 Int_t color;
5905 TProfile2D* prof2d = dynamic_cast<TProfile2D*>(fH);
5906 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
5909 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
5910 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
5911 xk = fXaxis->GetBinLowEdge(i);
5912 xstep = fXaxis->GetBinWidth(i);
5913 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
5914 z = fH->GetBinContent(bin);
5915 e = fH->GetBinError(bin);
5916 // if fH is a profile histogram do not draw empty bins
5917 if (prof2d) {
5918 const Double_t binEntries = prof2d->GetBinEntries(bin);
5919 if (binEntries == 0)
5920 continue;
5921 } else {
5922 // don't draw the empty bins for non-profile histograms
5923 // with positive content
5924 if (z == 0 && e == 0) {
5925 if (zmin >= 0 || Hoption.Logz) continue;
5926 if (Hoption.Color == 2) continue;
5927 }
5928 }
5929
5930 if (Hoption.Logz)
5931 z = z > 0 ? TMath::Log10(z) : zmin;
5932 if (z < zmin && !Hoption.Zero)
5933 continue;
5934 xup = xk + xstep;
5935 xlow = xk;
5936 if (Hoption.Logx) {
5937 if ((xup <= 0) || (xlow <= 0))
5938 continue;
5939 xup = TMath::Log10(xup);
5940 xlow = TMath::Log10(xlow);
5941 }
5942 yup = yk + ystep;
5943 ylow = yk;
5944 if (Hoption.Logy) {
5945 if ((yup <= 0) || (ylow <= 0))
5946 continue;
5947 yup = TMath::Log10(yup);
5948 ylow = TMath::Log10(ylow);
5949 }
5950 if ((xup < xmin) || (yup < ymin) || (xlow > xmax) || (ylow > ymax))
5951 continue;
5952 if (xlow < xmin)
5953 xlow = xmin;
5954 if (ylow < ymin)
5955 ylow = ymin;
5956 if (xup > xmax)
5957 xup = xmax;
5958 if (yup > ymax)
5959 yup = ymax;
5960
5962 zc = fH->GetContourLevelPad(0);
5963 if (z < zc) continue;
5964 color = -1;
5965 for (Int_t k=0; k<ndiv; k++) {
5966 zc = fH->GetContourLevelPad(k);
5967 if (z < zc) {
5968 continue;
5969 } else {
5970 color++;
5971 }
5972 }
5973 } else {
5974 color = Hoption.Zero ? Int_t(0.01+(std::max(z, zmin)-zmin)*scale) : Int_t(0.01+(z-zmin)*scale);
5975 }
5976
5977 Int_t theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
5978 if (theColor > ncolors-1)
5979 theColor = ncolors-1;
5981 if (Hoption.System != kPOLAR) {
5983 fH->TAttFill::Modify();
5984 gPad->PaintBox(xlow, ylow, xup, yup);
5985 } else {
5986 Double_t midx = (xmin + xmax) / 2;
5987 Double_t midy = (ymin + ymax) / 2;
5988 Double_t rx = xmax - xmin;
5989 Double_t ry = ymax - ymin;
5990 Double_t a1, a2;
5991
5992 if (Hoption.Polar == 3) {
5993 a1 = xlow / TMath::Pi() * 180;
5994 a2 = xup / TMath::Pi() * 180;
5995 } else {
5996 a1 = ((xlow - pxmin) / (pxmax - pxmin) - 0.5) * 360;
5997 a2 = ((xup - pxmin) / (pxmax - pxmin) - 0.5) * 360;
5998 }
5999 Double_t r1 = (ylow - pymin) / (pymax - pymin) * rx * pkr;
6000 Double_t r2 = (yup - pymin) / (pymax - pymin) * rx * pkr;
6001
6002 TCrown crown(midx, midy, r1, r2, a1, a2);
6003 crown.SetYXRatio(rx > 0 ? ry / rx : 1);
6004 crown.SetFillColor(fillColor);
6005 crown.SetLineColor(fH->GetLineColor());
6006 crown.SetLineWidth(fH->GetLineWidth());
6007 crown.SetLineStyle(fH->GetLineStyle());
6008 crown.Paint();
6009 }
6010 }
6011 }
6012
6014
6017 fH->TAttFill::Modify();
6018
6019}
6020
6021////////////////////////////////////////////////////////////////////////////////
6022/// [Control function to draw a 2D histogram as a contour plot.](\ref HP16)
6023
6025{
6026
6027 Int_t i, j, count, ncontour, icol, n, lj, m, ix, jx, ljfill;
6028 Int_t itars, mode, ir[4];
6029 Double_t xsave, ysave, thesave,phisave,x[4], y[4], zc[4];
6030
6031 if (Hoption.Contour == 14) {
6032 Hoption.Surf = 12;
6033 Hoption.Axis = 1;
6034 thesave = gPad->GetTheta();
6035 phisave = gPad->GetPhi();
6036 gPad->SetPhi(0.);
6037 gPad->SetTheta(90.);
6039 gPad->SetPhi(phisave);
6040 gPad->SetTheta(thesave);
6041 TView *view = gPad->GetView();
6042 if (view) view->SetBit(kCannotRotate); //tested in ExecuteEvent
6043 PaintAxis();
6044 return;
6045 }
6046
6047 if (Hoption.Same) {
6048 // If the contour is painted on a 3d plot, the contour lines are
6049 // paint in 3d too.
6050 TObject *obj;
6051 TIter next(gPad->GetListOfPrimitives());
6052 while ((obj=next())) {
6053 if (strstr(obj->GetDrawOption(),"surf") ||
6054 strstr(obj->GetDrawOption(),"lego") ||
6055 strstr(obj->GetDrawOption(),"tri")) {
6056 Hoption.Surf = 16;
6058 return;
6059 }
6060 }
6061 }
6062
6063 if (Hoption.Contour == 15) {
6064 TGraphDelaunay2D *dt = nullptr;
6065 TGraphDelaunay *dtOld = nullptr;
6067 dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
6068 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
6069 if (!dt && !dtOld) return;
6070 if (!fGraph2DPainter)
6071 fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
6072 fGraph2DPainter->Paint(option);
6073 return;
6074 }
6075
6076 gPad->SetBit(TGraph::kClipFrame);
6077
6078 std::vector<Double_t> levels(2*kMAXCONTOUR);
6079 std::vector<Double_t> xarr(2*kMAXCONTOUR);
6080 std::vector<Double_t> yarr(2*kMAXCONTOUR);
6081 std::vector<Int_t> itarr(2*kMAXCONTOUR);
6082
6083 Int_t npmax = 0;
6084 for (i=0;i<2*kMAXCONTOUR;i++) itarr[i] = 0;
6085
6086 ncontour = fH->GetContour();
6087 if (ncontour == 0) {
6090 }
6091 if (ncontour > kMAXCONTOUR) {
6092 Warning("PaintContour", "maximum number of contours is %d, asked for %d",
6095 }
6097
6098 for (i=0;i<ncontour;i++) levels[i] = fH->GetContourLevelPad(i);
6102 if (Hoption.Contour == 13) {
6103 fH->TAttLine::Modify();
6104 }
6105
6106 std::vector<std::unique_ptr<TPolyLine>> polys;
6107 TObjArray *contours = nullptr;
6108 TList *list = nullptr;
6109 TGraph *graph = nullptr;
6110 std::vector<Int_t> np;
6111 if (Hoption.Contour == 1 || (Hoption.List && (Hoption.Contour == 11 || Hoption.Contour == 12 || Hoption.Contour == 13))) {
6112 np.resize(ncontour);
6113 for (i=0;i<ncontour;i++)
6114 np[i] = 0;
6115 for (i=0;i<ncontour;i++)
6116 polys.emplace_back(std::make_unique<TPolyLine>(100));
6117 if (Hoption.List == 1) {
6118 contours = (TObjArray*)gROOT->GetListOfSpecials()->FindObject("contours");
6119 if (contours) {
6120 gROOT->GetListOfSpecials()->Remove(contours);
6121 count = contours->GetSize();
6122 for (i=0;i<count;i++) {
6123 list = (TList*)contours->At(i);
6124 if (list) list->Delete();
6125 }
6126 contours->Delete();
6127 delete contours;
6128 }
6130 contours->SetName("contours");
6131 gROOT->GetListOfSpecials()->Add(contours);
6132 for (i=0;i<ncontour;i++) {
6133 list = new TList();
6134 contours->Add(list);
6135 }
6136 }
6137 }
6141
6142 Int_t k,ipoly;
6143 for (j=Hparam.yfirst; j<Hparam.ylast; j++) {
6144 y[0] = fYaxis->GetBinCenter(j);
6145 y[1] = y[0];
6146 y[2] = fYaxis->GetBinCenter(j+1);
6147 y[3] = y[2];
6148 for (i=Hparam.xfirst; i<Hparam.xlast; i++) {
6149 zc[0] = fH->GetBinContent(i, j);
6150 zc[1] = fH->GetBinContent(i+1, j);
6151 zc[2] = fH->GetBinContent(i+1, j+1);
6152 zc[3] = fH->GetBinContent(i, j+1);
6153 if (!IsInside(fXaxis->GetBinCenter(i),fYaxis->GetBinCenter(j))) continue;
6154 if (Hoption.Logz) {
6155 if (zc[0] > 0) zc[0] = TMath::Log10(zc[0]);
6156 else zc[0] = Hparam.zmin;
6157 if (zc[1] > 0) zc[1] = TMath::Log10(zc[1]);
6158 else zc[1] = Hparam.zmin;
6159 if (zc[2] > 0) zc[2] = TMath::Log10(zc[2]);
6160 else zc[2] = Hparam.zmin;
6161 if (zc[3] > 0) zc[3] = TMath::Log10(zc[3]);
6162 else zc[3] = Hparam.zmin;
6163 }
6164 for (k=0;k<4;k++) {
6165 ir[k] = TMath::BinarySearch(ncontour, levels.data(), zc[k]);
6166 }
6167 if (ir[0] != ir[1] || ir[1] != ir[2] || ir[2] != ir[3] || ir[3] != ir[0]) {
6168 x[0] = fXaxis->GetBinCenter(i);
6169 x[3] = x[0];
6170 x[1] = fXaxis->GetBinCenter(i+1);
6171 x[2] = x[1];
6172 if (zc[0] <= zc[1]) n = 0; else n = 1;
6173 if (zc[2] <= zc[3]) m = 2; else m = 3;
6174 if (zc[n] > zc[m]) n = m;
6175 n++;
6176 lj=1;
6177 for (ix=1;ix<=4;ix++) {
6178 m = n%4 + 1;
6179 ljfill = PaintContourLine(zc[n-1],ir[n-1],x[n-1],y[n-1],zc[m-1],
6180 ir[m-1],x[m-1],y[m-1], xarr.data()+lj-1,yarr.data()+lj-1,itarr.data()+lj-1, levels.data());
6181 lj += 2*ljfill;
6182 n = m;
6183 }
6184
6185 if (zc[0] <= zc[1]) n = 0; else n = 1;
6186 if (zc[2] <= zc[3]) m = 2; else m = 3;
6187 if (zc[n] > zc[m]) n = m;
6188 n++;
6189 lj=2;
6190 for (ix=1;ix<=4;ix++) {
6191 if (n == 1) m = 4;
6192 else m = n-1;
6193 ljfill = PaintContourLine(zc[n-1],ir[n-1],x[n-1],y[n-1],zc[m-1],
6194 ir[m-1],x[m-1],y[m-1],xarr.data()+lj-1,yarr.data()+lj-1,itarr.data()+lj-1, levels.data());
6195 lj += 2*ljfill;
6196 n = m;
6197 }
6198
6199 // Re-order endpoints
6200
6201 count = 0;
6202 for (ix=1; ix<=lj-5; ix +=2) {
6203 //count = 0;
6204 while (itarr[ix-1] != itarr[ix]) {
6205 xsave = xarr[ix];
6206 ysave = yarr[ix];
6207 itars = itarr[ix];
6208 for (jx=ix; jx<=lj-5; jx +=2) {
6209 xarr[jx] = xarr[jx+2];
6210 yarr[jx] = yarr[jx+2];
6211 itarr[jx] = itarr[jx+2];
6212 }
6213 xarr[lj-3] = xsave;
6214 yarr[lj-3] = ysave;
6215 itarr[lj-3] = itars;
6216 if (count > 100) break;
6217 count++;
6218 }
6219 }
6220
6221 if (count > 100) continue;
6222 for (ix=1; ix<=lj-2; ix +=2) {
6223 theColor = Int_t((itarr[ix-1]+0.99)*Float_t(ncolors)/Float_t(ndivz));
6225 if (Hoption.Contour == 11) {
6227 }
6228 if (Hoption.Contour == 12) {
6229 mode = icol%5;
6230 if (mode == 0) mode = 5;
6232 }
6233 if (Hoption.Contour != 1) {
6234 fH->TAttLine::Modify();
6235 gPad->PaintPolyLine(2,xarr.data()+ix-1,yarr.data()+ix-1);
6236 if ((Hoption.Contour != 11 && Hoption.Contour != 12 && Hoption.Contour != 13) || !Hoption.List)
6237 continue;
6238 }
6239
6240 ipoly = itarr[ix-1];
6241 if (ipoly >=0 && ipoly <ncontour) {
6242 polys[ipoly]->SetPoint(np[ipoly] ,xarr[ix-1],yarr[ix-1]);
6243 polys[ipoly]->SetPoint(np[ipoly]+1,xarr[ix], yarr[ix]);
6244 np[ipoly] += 2;
6245 if (npmax < np[ipoly]) npmax = np[ipoly];
6246 }
6247 }
6248 } // end of if (ir[0]
6249 } //end of for (i
6250 } //end of for (j
6251
6253 std::vector<Double_t> xp, yp;
6255 Int_t istart;
6256 Int_t first = ncontour;
6257 std::vector<Int_t> polysort;
6259 if (Hoption.Contour != 1) {
6260 if (!Hoption.List || (Hoption.Contour != 11 && Hoption.Contour != 12 && Hoption.Contour != 13))
6261 goto theEND;
6262 }
6263
6264 //The 2 points line generated above are now sorted/merged to generate
6265 //a list of consecutive points.
6266 // If the option "List" has been specified, the list of points is saved
6267 // in the form of TGraph objects in the ROOT list of special objects.
6268 xmin = gPad->GetUxmin();
6269 ymin = gPad->GetUymin();
6270 xp.resize(2*npmax);
6271 yp.resize(2*npmax);
6272 polysort.resize(ncontour);
6273 //find first positive contour
6274 for (ipoly=0;ipoly<ncontour;ipoly++) {
6275 if (levels[ipoly] >= 0) {first = ipoly; break;}
6276 }
6277 //store negative contours from 0 to minimum, then all positive contours
6278 k = 0;
6279 for (ipoly=first-1;ipoly>=0;ipoly--) {polysort[k] = ipoly; k++;}
6280 for (ipoly=first;ipoly<ncontour;ipoly++) {polysort[k] = ipoly; k++;}
6281 // if Contour==1 we can now draw sorted contours, otherwise (11,12,13) just store
6282 contListNb = 0;
6283 if (Hoption.Contour == 1) fH->SetFillStyle(1001);
6284 for (k=0;k<ncontour;k++) {
6285 ipoly = polysort[k];
6286 if (Hoption.List) list = (TList*)contours->At(contListNb);
6287 contListNb++;
6288 if (np[ipoly] == 0)
6289 continue;
6290 Double_t *xx = polys[ipoly]->GetX();
6291 Double_t *yy = polys[ipoly]->GetY();
6292 istart = 0;
6293 while (true) {
6294 iminus = npmax;
6295 iplus = iminus+1;
6296 xp[iminus]= xx[istart]; yp[iminus] = yy[istart];
6297 xp[iplus] = xx[istart+1]; yp[iplus] = yy[istart+1];
6298 xx[istart] = xmin; yy[istart] = ymin;
6299 xx[istart+1] = xmin; yy[istart+1] = ymin;
6300 while (true) {
6301 nadd = 0;
6302 for (i=2;i<np[ipoly];i+=2) {
6303 if ((iplus < 2*npmax-1) && (xx[i] == xp[iplus]) && (yy[i] == yp[iplus])) {
6304 iplus++;
6305 xp[iplus] = xx[i+1]; yp[iplus] = yy[i+1];
6306 xx[i] = xmin; yy[i] = ymin;
6307 xx[i+1] = xmin; yy[i+1] = ymin;
6308 nadd++;
6309 }
6310 if ((iminus > 0) && (xx[i+1] == xp[iminus]) && (yy[i+1] == yp[iminus])) {
6311 iminus--;
6312 xp[iminus] = xx[i]; yp[iminus] = yy[i];
6313 xx[i] = xmin; yy[i] = ymin;
6314 xx[i+1] = xmin; yy[i+1] = ymin;
6315 nadd++;
6316 }
6317 }
6318 if (nadd == 0) break;
6319 }
6322 if (Hoption.Contour == 1) {
6323 if (ndivz > 1) fH->SetFillColor(icol);
6324 fH->TAttFill::Modify();
6325 gPad->PaintFillArea(iplus-iminus+1,xp.data()+iminus,yp.data()+iminus);
6326 }
6327 if (Hoption.List) {
6328 graph = new TGraph(iplus-iminus+1,xp.data()+iminus,yp.data()+iminus);
6329 if (Hoption.Contour == 1)
6330 graph->SetFillColor(icol);
6331 else if (Hoption.Contour == 11)
6332 graph->SetLineColor(icol);
6333 else if (Hoption.Contour == 12) {
6334 mode = icol%5;
6335 if (mode == 0) mode = 5;
6336 graph->SetLineStyle(mode);
6337 }
6338 graph->SetLineWidth(fH->GetLineWidth());
6339 list->Add(graph);
6340 }
6341 //check if more points are left
6342 istart = 0;
6343 for (i=2;i<np[ipoly];i+=2) {
6344 if (xx[i] != xmin && yy[i] != ymin) {
6345 istart = i;
6346 break;
6347 }
6348 }
6349 if (istart == 0) break;
6350 }
6351 }
6352
6353theEND:
6354 gPad->ResetBit(TGraph::kClipFrame);
6359}
6360
6361////////////////////////////////////////////////////////////////////////////////
6362/// Fill the matrix `xarr` and `yarr` for Contour Plot.
6363
6367{
6368
6369 Bool_t vert;
6371 Int_t n, i, icount;
6372
6373 if (x1 == x2) {
6374 vert = kTRUE;
6375 tlen = y2 - y1;
6376 } else {
6377 vert = kFALSE;
6378 tlen = x2 - x1;
6379 }
6380
6381 n = icont1 +1;
6382 tdif = elev2 - elev1;
6383 i = 0;
6384 icount = 0;
6385 while (n <= icont2 && i <= kMAXCONTOUR/2 -3) {
6386 //elev = fH->GetContourLevel(n);
6387 elev = levels[n];
6388 diff = elev - elev1;
6389 pdif = diff/tdif;
6390 xlen = tlen*pdif;
6391 if (vert) {
6392 if (Hoption.Logx)
6393 xarr[i] = TMath::Log10(x1);
6394 else
6395 xarr[i] = x1;
6396 if (Hoption.Logy)
6397 yarr[i] = TMath::Log10(y1 + xlen);
6398 else
6399 yarr[i] = y1 + xlen;
6400 } else {
6401 if (Hoption.Logx)
6402 xarr[i] = TMath::Log10(x1 + xlen);
6403 else
6404 xarr[i] = x1 + xlen;
6405 if (Hoption.Logy)
6406 yarr[i] = TMath::Log10(y1);
6407 else
6408 yarr[i] = y1;
6409 }
6410 itarr[i] = n;
6411 icount++;
6412 i +=2;
6413 n++;
6414 }
6415 return icount;
6416}
6417
6418////////////////////////////////////////////////////////////////////////////////
6419/// [Draw 1D histograms error bars.](\ref HP09)
6420
6422{
6423
6424 // On iOS, we do not highlight histogram, if it's not picked at the moment
6425 // (but part of histogram (axis or pavestat) was picked, that's why this code
6426 // is called at all. This conditional statement never executes on non-iOS platform.
6427 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH) return;
6428
6429 const Int_t kBASEMARKER=8;
6430 Double_t xp, yp, ex1, ex2, ey1, ey2;
6431 Double_t delta;
6433 Double_t xi1, xi2, xi3, xi4, yi1, yi2, yi3, yi4;
6435 Double_t logxmin = 0;
6436 Double_t logymin = 0;
6437 Double_t offset = 0.;
6438 Double_t width = 0.;
6439 Int_t i, k, npoints, first, last, fixbin;
6440 Int_t if1 = 0;
6441 Int_t if2 = 0;
6445 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};
6446 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};
6447
6448 std::vector<Double_t> xline, yline, xsegm, ysegm, xmarker, ymarker;
6450 if (Hoption.Error >= 40) {Hoption.Error -=40; option0 = 1;}
6451 if (Int_t(Hoption.Error/10) == 2) {optionEX0 = 1; Hoption.Error -= 10;}
6452 if (Hoption.Error == 31) {optionEX0 = 1; Hoption.Error = 1;}
6453 if (Hoption.Error == 11) option1 = 1;
6454 if (Hoption.Error == 12) option2 = 1;
6455 if (Hoption.Error == 13) option3 = 1;
6456 if (Hoption.Error == 14) {option4 = 1; option3 = 1;}
6457 if (Hoption.Error == 15) {optionI0 = 1; option3 = 1;}
6458 if (Hoption.Error == 16) {optionI0 = 1; option4 = 1; option3 = 1;}
6459 if (option2+option3 == 0) optionE = 1;
6460 if (Hoption.Error == 0) optionE = 0;
6461 if (fXaxis->GetXbins()->fN) fixbin = 0;
6462 else fixbin = 1;
6463
6464 offset = fH->GetBarOffset();
6465 width = fH->GetBarWidth();
6466
6468 if (optionEX0) {
6469 xerror = 0;
6470 } else {
6471 xerror = gStyle->GetErrorX();
6472 }
6474 if (errormarker == 1) symbolsize = 0.01;
6476 if (errormarker >= 20 && errormarker <= 49) {
6477 sbasex *= cxx[errormarker-20];
6478 sbasey *= cyy[errormarker-20];
6479 }
6480 // set the graphics attributes
6481
6482 fH->TAttLine::Modify();
6483 fH->TAttFill::Modify();
6484 fH->TAttMarker::Modify();
6485
6486 // set the first and last bin
6487
6488 Double_t factor = Hparam.factor;
6489 first = Hparam.xfirst;
6490 last = Hparam.xlast;
6491 npoints = last - first +1;
6492 xmin = gPad->GetUxmin();
6493 xmax = gPad->GetUxmax();
6494 ymin = gPad->GetUymin();
6495 ymax = gPad->GetUymax();
6496
6497 xsegm.reserve(1024);
6498 ysegm.reserve(1024);
6499 if (!xsegm.capacity() || !ysegm.capacity()) {
6500 Error("PaintErrors", "out of memory for lines painting");
6501 return;
6502 }
6503
6504 auto flush_segmentes = [&]() {
6505 if (xsegm.size() > 0) {
6506 gPad->PaintSegments(xsegm.size()/2, xsegm.data(), ysegm.data());
6507 xsegm.clear();
6508 ysegm.clear();
6509 }
6510 };
6511
6513 xsegm.emplace_back(x1);
6514 xsegm.emplace_back(x2);
6515 ysegm.emplace_back(y1);
6516 ysegm.emplace_back(y2);
6517 if (xsegm.size() == xsegm.capacity())
6519 };
6520
6521 auto flush_markers = [&]() {
6522 if (xmarker.size() > 0) {
6523 gPad->PaintPolyMarker(xmarker.size(), xmarker.data(), ymarker.data());
6524 xmarker.clear();
6525 ymarker.clear();
6526 }
6527 };
6528
6529 auto add_marker = [&](Double_t x, Double_t y) {
6530 if (xmarker.capacity() == 0) {
6531 xmarker.reserve(256);
6532 ymarker.reserve(256);
6533 }
6534
6535 xmarker.emplace_back(x);
6536 ymarker.emplace_back(y);
6537 if (xmarker.size() == xmarker.capacity()) {
6539 flush_markers();
6540 }
6541 };
6542
6543
6544 if (option3) {
6545 xline.resize(2*npoints);
6546 yline.resize(2*npoints);
6547 if ((npoints > 0) && (xline.empty() || yline.empty())) {
6548 Error("PaintErrors", "too many points, out of memory");
6549 return;
6550 }
6551 if1 = 1;
6552 if2 = 2*npoints;
6553 }
6554
6555 // compute the offset of the error bars due to the symbol size
6556 s2x = gPad->PixeltoX(Int_t(0.5*sbasex)) - gPad->PixeltoX(0);
6557 s2y =-gPad->PixeltoY(Int_t(0.5*sbasey)) + gPad->PixeltoY(0);
6558
6559 // compute size of the lines at the end of the error bars
6561 bxsize = gPad->PixeltoX(dxend) - gPad->PixeltoX(0);
6562 bysize =-gPad->PixeltoY(dxend) + gPad->PixeltoY(0);
6563
6564
6565 if (fixbin) {
6567 else xp = Hparam.xmin + 0.5*Hparam.xbinsize;
6568 } else {
6569 delta = fH->GetBinWidth(first);
6570 xp = fH->GetBinLowEdge(first) + 0.5*delta;
6571 }
6572
6573 // if errormarker = 0 or symbolsize = 0. no symbol is drawn
6576
6577 // ---------------------- Loop over the points---------------------
6578 for (k=first; k<=last; k++) {
6579
6580 // get the data
6581 // xp = X position of the current point
6582 // yp = Y position of the current point
6583 // ex1 = Low X error
6584 // ex2 = Up X error
6585 // ey1 = Low Y error
6586 // ey2 = Up Y error
6587 // (xi,yi) = Error bars coordinates
6588
6589 // apply offset on errors for bar histograms
6590 Double_t xminTmp = gPad->XtoPad(fXaxis->GetBinLowEdge(k));
6591 Double_t xmaxTmp = gPad->XtoPad(fXaxis->GetBinUpEdge(k));
6592 if (Hoption.Logx) {
6595 }
6598 xmaxTmp = xminTmp + w;
6599 xp = (xminTmp+xmaxTmp)/2.;
6600
6601 if (Hoption.Logx) {
6602 if (xp <= 0) goto L30;
6603 if (xp < logxmin) goto L30;
6604 if (xp > TMath::Power(10,xmax)) break;
6605 } else {
6606 if (xp < xmin) goto L30;
6607 if (xp > xmax) break;
6608 }
6609 yp = factor*fH->GetBinContent(k);
6610 if (optionI0 && yp==0) goto L30;
6611 if (fixbin) {
6613 } else {
6614 delta = fH->GetBinWidth(k);
6615 ex1 = xerror*delta;
6616 }
6617 if (fH->GetBinErrorOption() == TH1::kNormal) {
6618 ey1 = factor*fH->GetBinError(k);
6619 ey2 = ey1;
6620 } else {
6621 ey1 = factor*fH->GetBinErrorLow(k);
6622 ey2 = factor*fH->GetBinErrorUp(k);
6623 }
6624 ex2 = ex1;
6625
6626 xi4 = xp;
6627 xi3 = xp;
6628 xi2 = xp + ex2;
6629 xi1 = xp - ex1;
6630
6631 yi1 = yp;
6632 yi2 = yp;
6633 yi3 = yp - ey1;
6634 yi4 = yp + ey2;
6635
6636 // take the LOG if necessary
6637 if (Hoption.Logx) {
6642 }
6643 if (Hoption.Logy) {
6648 }
6649
6650 // test if error bars are not outside the limits
6651 // otherwise they are truncated
6652
6657
6658 // test if the marker is on the frame limits. If "Yes", the
6659 // marker will not be drawn and the error bars will be readjusted.
6660
6661 drawmarker = kTRUE;
6662 if (!option0 && !option3) {
6663 if (Hoption.Logy && yp < logymin) goto L30;
6664 if (yi1 < ymin || yi1 > ymax) goto L30;
6665 if (Hoption.Error != 0 && yp == 0 && ey1 <= 0) drawmarker = kFALSE;
6666 }
6668
6669 // draw the error rectangles
6670 if (option2) {
6671 if ((yi3 >= ymax) || (yi4 <= ymin))
6672 goto L30;
6673 gPad->PaintBox(xi1,yi3,xi2,yi4);
6674 }
6675
6676 // keep points for fill area drawing
6677 if (option3) {
6678 xline[if1-1] = xi3;
6679 xline[if2-1] = xi3;
6680 yline[if1-1] = yi4;
6681 yline[if2-1] = yi3;
6682 if1++;
6683 if2--;
6684 }
6685
6686 // draw the error bars
6687 if (Hoption.Logy && yp < logymin)
6689 if (optionE && drawmarker) {
6690 if ((yi3 < yi1 - s2y) && (yi3 < ymax))
6692 if ((yi1 + s2y < yi4) && (yi4 > ymin))
6694 // don't duplicate the horizontal line
6695 if (Hoption.Hist != 2) {
6697 if (xi1 < xi3 - s2x)
6699 if (xi3 + s2x < xi2)
6701 }
6702 }
6703 }
6704 if (optionE && !drawmarker && (ey1 != 0 || ey2 !=0)) {
6705 if ((yi3 < yi1) && (yi3 < ymax))
6707 if ((yi1 < yi4) && (yi4 > ymin))
6709 // don't duplicate the horizontal line
6710 if (Hoption.Hist != 2) {
6712 if (xi1 < xi3)
6714 if (xi3 < xi2)
6716 }
6717 }
6718 }
6719
6720 // draw line at the end of the error bars
6721
6722 if (option1 && drawmarker) {
6723
6729 if (xi1 < xi3-s2x)
6731 if (xi2 > xi3+s2x)
6733 }
6734 }
6735
6736 // draw the marker
6737
6738 if (drawmarker)
6739 add_marker(xi3, yi1);
6740
6741L30:
6742 if (fixbin) xp += Hparam.xbinsize;
6743 else {
6744 if (k < last) {
6745 delta = fH->GetBinWidth(k+1);
6746 xp = fH->GetBinLowEdge(k+1) + 0.5*delta;
6747 }
6748 }
6749 } //end of for loop
6750
6752
6753 flush_markers();
6754
6755
6756 // draw the filled area
6757
6758 if (option3) {
6759 TGraph graph;
6760 graph.SetLineStyle(fH->GetLineStyle());
6761 graph.SetLineColor(fH->GetLineColor());
6762 graph.SetLineWidth(fH->GetLineWidth());
6763 graph.SetFillStyle(fH->GetFillStyle());
6764 graph.SetFillColor(fH->GetFillColor());
6765 Int_t logx = gPad->GetLogx();
6766 Int_t logy = gPad->GetLogy();
6767 gPad->SetLogx(0);
6768 gPad->SetLogy(0);
6769
6770 // In some cases the number of points in the fill area is smaller than
6771 // 2*npoints. In such cases the array xline and yline must be arranged
6772 // before being plotted. The next loop does that.
6773 if (if2 > npoints) {
6774 for (i=1; i<if1; i++) {
6775 xline[if1-2+i] = xline[if2-1+i];
6776 yline[if1-2+i] = yline[if2-1+i];
6777 }
6778 npoints = if1-1;
6779 }
6780 if (option4) graph.PaintGraph(2*npoints,xline.data(),yline.data(),"FC");
6781 else graph.PaintGraph(2*npoints,xline.data(),yline.data(),"F");
6782 gPad->SetLogx(logx);
6783 gPad->SetLogy(logy);
6784 }
6785}
6786
6787////////////////////////////////////////////////////////////////////////////////
6788/// Draw 2D histograms errors.
6789
6791{
6792
6793 fH->TAttMarker::Modify();
6794 fH->TAttLine::Modify();
6795
6796 // Define the 3D view
6797 fXbuf[0] = Hparam.xmin;
6798 fYbuf[0] = Hparam.xmax;
6799 fXbuf[1] = Hparam.ymin;
6800 fYbuf[1] = Hparam.ymax;
6801 fXbuf[2] = Hparam.zmin;
6802 fYbuf[2] = Hparam.zmax*(1. + gStyle->GetHistTopMargin());
6803 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
6804 TView *view = gPad ? gPad->GetView() : nullptr;
6805 if (!view) {
6806 Error("Paint2DErrors", "no TView in current pad");
6807 return;
6808 }
6809 Double_t thedeg = 90 - gPad->GetTheta();
6810 Double_t phideg = -90 - gPad->GetPhi();
6811 Double_t psideg = view->GetPsi();
6812 Int_t irep;
6813 view->SetView(phideg, thedeg, psideg, irep);
6814
6815 // Set color/style for back box
6816 fLego->SetFillStyle(gPad->GetFrameFillStyle());
6817 fLego->SetFillColor(gPad->GetFrameFillColor());
6818 fLego->TAttFill::Modify();
6819 Int_t backcolor = gPad->GetFrameFillColor();
6820 if (Hoption.System != kCARTESIAN) backcolor = 0;
6821 view->PadRange(backcolor);
6822 fLego->SetFillStyle(fH->GetFillStyle());
6823 fLego->SetFillColor(fH->GetFillColor());
6824 fLego->TAttFill::Modify();
6825
6826 // Paint the Back Box if needed
6827 if (Hoption.BackBox && !Hoption.Same && !Hoption.Lego && !Hoption.Surf) {
6828 fLego->InitMoveScreen(-1.1,1.1);
6829 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
6831 fLego->BackBox(90);
6832 }
6833
6834 // Paint the Errors
6835 Double_t x, ex, x1, x2;
6836 Double_t y, ey, y1, y2;
6837 Double_t z, ez1, ez2, z1, z2;
6838 Double_t temp1[3],temp2[3];
6840 if (Hoption.Error == 110) {
6841 xyerror = 0;
6842 } else {
6844 }
6845
6847 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
6848 y = fYaxis->GetBinCenter(j);
6850 y1 = y-ey;
6851 y2 = y+ey;
6852 if (Hoption.Logy) {
6853 if (y > 0) y = TMath::Log10(y);
6854 else continue;
6855 if (y1 > 0) y1 = TMath::Log10(y1);
6856 else y1 = Hparam.ymin;
6857 if (y2 > 0) y2 = TMath::Log10(y2);
6858 else y2 = Hparam.ymin;
6859 }
6862 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
6863 xk = fXaxis->GetBinLowEdge(i);
6864 xstep = fXaxis->GetBinWidth(i);
6865 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
6866 Int_t bin = fH->GetBin(i,j);
6867 x = fXaxis->GetBinCenter(i);
6869 x1 = x-ex;
6870 x2 = x+ex;
6871 if (Hoption.Logx) {
6872 if (x > 0) x = TMath::Log10(x);
6873 else continue;
6874 if (x1 > 0) x1 = TMath::Log10(x1);
6875 else x1 = Hparam.xmin;
6876 if (x2 > 0) x2 = TMath::Log10(x2);
6877 else x2 = Hparam.xmin;
6878 }
6879 z = fH->GetBinContent(bin);
6880 if (fH->GetBinErrorOption() == TH1::kNormal) {
6881 ez1 = fH->GetBinError(bin);
6882 ez2 = ez1;
6883 }
6884 else {
6886 ez2 = fH->GetBinErrorUp(bin);
6887 }
6888 z1 = z - ez1;
6889 z2 = z + ez2;
6890 if (Hoption.Logz) {
6891 if (z > 0) z = TMath::Log10(z);
6892 else z = Hparam.zmin;
6893 if (z1 > 0) z1 = TMath::Log10(z1);
6894 else z1 = Hparam.zmin;
6895 if (z2 > 0) z2 = TMath::Log10(z2);
6896 else z2 = Hparam.zmin;
6897
6898 }
6899 if (z <= Hparam.zmin) continue;
6900 if (z > Hparam.zmax) z = Hparam.zmax;
6901
6902 temp1[0] = x1;
6903 temp1[1] = y;
6904 temp1[2] = z;
6905 temp2[0] = x2;
6906 temp2[1] = y;
6907 temp2[2] = z;
6908 gPad->PaintLine3D(temp1, temp2);
6909 temp1[0] = x;
6910 temp1[1] = y1;
6911 temp1[2] = z;
6912 temp2[0] = x;
6913 temp2[1] = y2;
6914 temp2[2] = z;
6915 gPad->PaintLine3D(temp1, temp2);
6916 temp1[0] = x;
6917 temp1[1] = y;
6918 temp1[2] = z1;
6919 temp2[0] = x;
6920 temp2[1] = y;
6921 temp2[2] = z2;
6922 gPad->PaintLine3D(temp1, temp2);
6923 temp1[0] = x;
6924 temp1[1] = y;
6925 temp1[2] = z;
6926 view->WCtoNDC(temp1, &temp2[0]);
6927 gPad->PaintPolyMarker(1, &temp2[0], &temp2[1]);
6928 }
6929 }
6930
6931 // Paint the Front Box if needed
6932 if (Hoption.FrontBox) {
6933 fLego->InitMoveScreen(-1.1,1.1);
6935 fLego->FrontBox(90);
6936 }
6937
6938 // Paint the Axis if needed
6939 if (!Hoption.Axis && !Hoption.Same && !Hoption.Lego && !Hoption.Surf) {
6940 TGaxis axis;
6941 PaintLegoAxis(&axis, 90);
6942 }
6943
6944 fLego.reset();
6945}
6946
6947////////////////////////////////////////////////////////////////////////////////
6948/// Calculate range and clear pad (canvas).
6949
6951{
6952
6953 if (Hoption.Same) return;
6954
6956
6957 if (Hoption.Lego || Hoption.Surf || Hoption.Tri ||
6958 Hoption.Contour == 14 || Hoption.Error >= 100) {
6959 TObject *frame = gPad->FindObject("TFrame");
6960 if (frame) gPad->Remove(frame);
6961 return;
6962 }
6963
6964 //The next statement is always executed on non-iOS platform,
6965 //on iOS depends on pad mode.
6966 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode())
6967 gPad->PaintPadFrame(Hparam.xmin,Hparam.ymin,Hparam.xmax,Hparam.ymax);
6968}
6969
6970////////////////////////////////////////////////////////////////////////////////
6971/// [Paint functions associated to an histogram.](\ref HP28")
6972
6974{
6975 auto lnk = fFunctions->FirstLink();
6976
6977 while (lnk) {
6978 auto obj = lnk->GetObject();
6980 if (obj->InheritsFrom(TF2::Class())) {
6981 if (!obj->TestBit(TF2::kNotDraw)) {
6982 if (Hoption.Lego || Hoption.Surf || Hoption.Error >= 100) {
6983 TF2 *f2 = (TF2*)obj;
6984 f2->SetMinimum(fH->GetMinimum());
6985 f2->SetMaximum(fH->GetMaximum());
6986 f2->SetRange(fH->GetXaxis()->GetXmin(), fH->GetYaxis()->GetXmin(), fH->GetXaxis()->GetXmax(), fH->GetYaxis()->GetXmax() );
6987 f2->Paint("surf same");
6988 } else {
6989 obj->Paint("cont3 same");
6990 }
6991 }
6992 } else if (obj->InheritsFrom(TF1::Class())) {
6993 if (!obj->TestBit(TF1::kNotDraw)) obj->Paint("lsame");
6994 } else {
6995 //Let's make this 'function' selectable on iOS device (for example, it can be TPaveStat).
6996 gPad->PushSelectableObject(obj);
6997
6998 //The next statement is ALWAYS executed on non-iOS platform, on iOS it depends on pad's mode
6999 //and picked object.
7000 if (!gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && obj == gPad->GetSelected()))
7001 obj->Paint(lnk->GetOption());
7002 }
7003 lnk = lnk->Next();
7004 }
7005}
7006
7007////////////////////////////////////////////////////////////////////////////////
7008/// [Control routine to draw 1D histograms](\ref HP01b)
7009
7011{
7012
7013 //On iOS: do not highlight hist, if part of it was selected.
7014 //Never executes on non-iOS platform.
7015 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
7016 return;
7017
7018 static char chopth[17];
7019
7021 Int_t i, j, first, last, nbins, fixbin;
7022 Double_t c1, yb;
7023 yb = 0;
7024
7025 strlcpy(chopth, " ",17);
7026
7029 Double_t baroffset = fH->GetBarOffset();
7030 Double_t barwidth = fH->GetBarWidth();
7033 gStyle->SetBarOffset(baroffset);
7034 gStyle->SetBarWidth(barwidth);
7035
7036 // Create "LIFE" structure to keep current histogram status
7037
7038 first = Hparam.xfirst;
7039 last = Hparam.xlast;
7040 nbins = last - first + 1;
7041
7042 std::vector<Double_t> keepx, keepy;
7043 if (fXaxis->GetXbins()->fN) fixbin = 0;
7044 else fixbin = 1;
7045 if (fixbin) keepx.resize(2);
7046 else keepx.resize(nbins+1);
7047 keepy.resize(nbins);
7048 Double_t logymin = 0;
7050
7051 // Loop on histogram bins
7052
7053 for (j=first; j<=last;j++) {
7055 if (TMath::Abs(ymax-ymin) > 0) {
7057 else yb = c1;
7058 }
7059 if (!Hoption.Line) {
7060 yb = TMath::Max(yb, ymin);
7061 yb = TMath::Min(yb, ymax);
7062 }
7063 keepy[j-first] = yb;
7064 }
7065
7066 // Draw histogram according to value of FillStyle and FillColor
7067
7068 if (fixbin) { keepx[0] = Hparam.xmin; keepx[1] = Hparam.xmax; }
7069 else {
7070 for (i=0; i<nbins; i++) keepx[i] = fXaxis->GetBinLowEdge(i+first);
7071 keepx[nbins] = fXaxis->GetBinUpEdge(nbins-1+first);
7072 }
7073
7074 // Prepare Fill area (systematic with option "Bar").
7075
7077 htype = oldhtype;
7078 if (Hoption.Bar) {
7079 if (htype == 0 || htype == 1000) htype = 1001;
7080 }
7081
7083
7084 // Code option for GrapHist
7085
7086 if (Hoption.Line) chopth[0] = 'L';
7087 if (Hoption.Star) chopth[1] = '*';
7088 if (Hoption.Mark) chopth[2] = 'P';
7089 if (Hoption.Mark == 10) chopth[3] = '0';
7091 if (Hoption.Curve) chopth[3] = 'C';
7092 if (Hoption.Hist > 0) chopth[4] = 'H';
7093 else if (Hoption.Bar) chopth[5] = 'B';
7094 if (Hoption.Logy) chopth[6] = '1';
7095 if (fH->GetFillColor() && htype) {
7096 if (Hoption.Hist > 0 || Hoption.Curve || Hoption.Line) {
7097 chopth[7] = 'F';
7098 }
7099 }
7100 }
7101 if (!fixbin && strlen(chopth)) {
7102 chopth[8] = 'N';
7103 }
7104
7105 if (Hoption.Fill == 2) chopth[13] = '2';
7106
7107 // Option LOGX
7108
7109 if (Hoption.Logx) {
7110 chopth[9] = 'G';
7111 chopth[10] = 'X';
7112 if (fixbin) {
7113 keepx[0] = TMath::Power(10,keepx[0]);
7114 keepx[1] = TMath::Power(10,keepx[1]);
7115 }
7116 }
7117
7118 if (Hoption.Off) {
7119 chopth[11] = ']';
7120 chopth[12] = '[';
7121 }
7122
7123 // Draw the histogram
7124
7125 TGraph graph;
7126 graph.SetLineWidth(lw);
7127 graph.SetLineStyle(fH->GetLineStyle());
7128 graph.SetLineColor(fH->GetLineColor());
7129 graph.SetFillStyle(htype);
7130 graph.SetFillColor(fH->GetFillColor());
7132 graph.SetMarkerSize(fH->GetMarkerSize());
7135
7136 graph.PaintGrapHist(nbins, keepx.data(), keepy.data() ,chopth);
7137
7140
7142}
7143
7144////////////////////////////////////////////////////////////////////////////////
7145/// [Control function to draw a 3D histograms.](\ref HP01d)
7146
7148{
7149
7150 TString cmd;
7151 TString opt = option;
7152 opt.ToLower();
7153 Int_t irep;
7154 Float_t NEntries = fH->GetEntries();
7155
7156 if (fCurrentF3 || strstr(opt,"tf3")) {
7157 PaintTF3();
7158 return;
7159 }
7160
7161 if (NEntries > 0) {
7162 if (Hoption.Box || Hoption.Lego || Hoption.Color) {
7163 if (Hoption.Box == 11 || Hoption.Lego == 11) {
7164 PaintH3Box(1);
7165 } else if (Hoption.Box == 12 || Hoption.Lego == 12 || Hoption.Color == 1) {
7166 PaintH3Box(2);
7167 } else if (Hoption.Box == 13 || Hoption.Lego == 13) {
7168 PaintH3Box(3);
7169 } else {
7171 }
7172 return;
7173 }
7174
7175 if (strstr(opt,"iso")) {
7176 PaintH3Iso();
7177 return;
7178 }
7179 }
7180
7181 TView *view = gPad ? gPad->GetView() : nullptr;
7182 if (!view) return;
7183
7184 if (strstr(opt,"fb")) Hoption.FrontBox = 0;
7185 if (strstr(opt,"bb")) Hoption.BackBox = 0;
7186
7187 Double_t thedeg = 90 - gPad->GetTheta();
7188 Double_t phideg = -90 - gPad->GetPhi();
7189 Double_t psideg = view->GetPsi();
7190 view->SetView(phideg, thedeg, psideg, irep);
7191
7192 if(NEntries > 0) { // Paint as 3D scatter plot
7193 cmd.Form("TPolyMarker3D::PaintH3((TH1 *)0x%zx,\"%s\");",(size_t)fH,option);
7194 gROOT->ProcessLine(cmd.Data());
7195 } else {
7196 TAxis* xAxis = fH->GetXaxis();
7197 TAxis* yAxis = fH->GetYaxis();
7198 TAxis* zAxis = fH->GetZaxis();
7199 Double_t xmin = xAxis->GetXmin();
7200 Double_t xmax = xAxis->GetXmax();
7201 Double_t ymin = yAxis->GetXmin();
7202 Double_t ymax = yAxis->GetXmax();
7203 Double_t zmin = zAxis->GetXmin();
7204 Double_t zmax = zAxis->GetXmax();
7205 view->SetRange(xmin, ymin, zmin, xmax, ymax, zmax); // Set the axis limits (Xmin, Ymin, Zmin, Xmax, Ymax, Zmax)
7206 }
7207
7208 if (Hoption.Same) return;
7209
7210 // Draw axis
7211 view->SetOutlineToCube();
7212 TSeqCollection *ol = view->GetOutline();
7213 if (ol && Hoption.BackBox && Hoption.FrontBox) ol->Paint(option);
7215
7216 if (!Hoption.Axis && !Hoption.Same) {
7217 TGaxis axis;
7218 PaintLegoAxis(&axis, 90);
7219 }
7220
7221 // Draw palette. In case of 4D plot with TTree::Draw() the palette should
7222 // be painted with the option colz.
7223 if (fH->GetDrawOption() && strstr(opt,"colz")) {
7224 Int_t ndiv = fH->GetContour();
7225 if (ndiv == 0 ) {
7226 ndiv = gStyle->GetNumberContours();
7227 fH->SetContour(ndiv);
7228 }
7229 PaintPalette();
7230 }
7231
7232 // Draw title
7233 PaintTitle();
7234
7235 //Draw stats and fit results
7236 TF1 *fit = nullptr;
7237 TIter next(fFunctions);
7238 while (auto obj = next()) {
7239 if (obj->InheritsFrom(TF1::Class())) {
7240 fit = (TF1*)obj;
7241 break;
7242 }
7243 }
7244 if ((Hoption.Same%10) != 1) {
7245 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7247 }
7248 }
7249
7250}
7251
7252////////////////////////////////////////////////////////////////////////////////
7253/// Compute histogram parameters used by the drawing routines.
7254
7256{
7257
7258 if (fH->GetDimension() > 1 || Hoption.Lego || Hoption.Surf) return 1;
7259
7260 Int_t i;
7261 static const char *where = "PaintInit";
7263 Int_t maximum = 0;
7264 Int_t minimum = 0;
7265 if (fH->GetMaximumStored() != -1111) maximum = 1;
7266 if (fH->GetMinimumStored() != -1111) minimum = 1;
7267
7268 // Compute X axis parameters
7269
7270 Int_t last = fXaxis->GetLast();
7271 Int_t first = fXaxis->GetFirst();
7274 Hparam.xlast = last;
7275 Hparam.xfirst = first;
7278
7279 // if log scale in X, replace xmin,max by the log
7280 if (Hoption.Logx) {
7281 if (Hparam.xmax<=0) {
7282 Error(where, "cannot set X axis to log scale");
7283 return 0;
7284 }
7285 if (Hparam.xlowedge <=0 ) {
7286 if (Hoption.Same) {
7287 TH1* h1 = nullptr;
7288 TObject *obj;
7289 TIter next(gPad->GetListOfPrimitives());
7290 while ((obj = (TObject *)next())) {
7291 if (obj->InheritsFrom(TH1::Class())) { h1 = (TH1*)(obj) ; break; }
7292 if (obj->InheritsFrom(THStack::Class())) { h1 = ((THStack*)(obj))->GetHistogram() ; break; }
7293 if (obj->InheritsFrom(TGraph::Class())) { h1 = ((TGraph*)(obj))->GetHistogram() ; break; }
7294 if (obj->InheritsFrom(TMultiGraph::Class())) { h1 = ((TMultiGraph*)(obj))->GetHistogram(); break; }
7295 if (obj->InheritsFrom(TGraph2D::Class())) { h1 = ((TGraph2D*)(obj))->GetHistogram(); break; }
7296 if (obj->InheritsFrom(TF1::Class())) { h1 = ((TF1*)(obj))->GetHistogram(); break; }
7297 }
7298 if (h1) {
7300 } else {
7301 Error(where, "undefined user's coordinates. Cannot use option SAME");
7302 return 0;
7303 }
7304 } else {
7305 for (i=first; i<=last; i++) {
7306 Double_t binLow = fXaxis->GetBinLowEdge(i);
7307 if (binLow>0) {
7308 Hparam.xlowedge = binLow;
7309 break;
7310 }
7311 if (binLow == 0 && fH->GetBinContent(i) !=0) {
7312 Hparam.xlowedge = fXaxis->GetBinUpEdge(i)*0.001;
7313 break;
7314 }
7315 }
7316 if (Hparam.xlowedge<=0) {
7317 Error(where, "cannot set X axis to log scale");
7318 return 0;
7319 }
7320 }
7322 }
7327 if (Hparam.xlast > last) Hparam.xlast = last;
7328 if (Hparam.xfirst < first) Hparam.xfirst = first;
7329 }
7330
7331 // Compute Y axis parameters
7332 Double_t bigp = TMath::Power(10,32);
7333 Double_t ymax = -bigp;
7334 Double_t ymin = bigp;
7335 Double_t c1, e1;
7336 Double_t xv[1];
7337 Double_t fval;
7338 TObject *f;
7339 TF1 *f1;
7340 Double_t allchan = 0;
7341 Int_t nonNullErrors = 0;
7342 TIter next(fFunctions);
7343 for (i=first; i<=last;i++) {
7344 c1 = fH->GetBinContent(i);
7345 if (std::isnan(c1) || std::isinf(c1))
7346 continue;
7348 if (Hoption.Logy) {
7349 if (c1 > 0) ymin = TMath::Min(ymin,c1);
7350 } else {
7352 }
7353 if (Hoption.Error) {
7355 e1 = fH->GetBinError(i);
7356 else
7357 e1 = fH->GetBinErrorUp(i);
7358 if (e1 > 0) nonNullErrors++;
7361 e1 = fH->GetBinErrorLow(i);
7362
7363 if (Hoption.Logy) {
7364 if (c1-e1>0.01*TMath::Abs(c1)) ymin = TMath::Min(ymin,c1-e1);
7365 } else {
7367 }
7368 }
7369 if (Hoption.Func) {
7370 xv[0] = fXaxis->GetBinCenter(i);
7371 while ((f = (TObject*) next())) {
7372 if (f->IsA() == TF1::Class()) {
7373 f1 = (TF1*)f;
7374 if (xv[0] < f1->GetXmin() || xv[0] > f1->GetXmax()) continue;
7375 fval = f1->Eval(xv[0],0,0);
7376 if (f1->GetMaximumStored() != -1111) fval = TMath::Min(f1->GetMaximumStored(), fval);
7378 if (Hoption.Logy) {
7379 if (c1 > 0 && fval > 0.3*c1) ymin = TMath::Min(ymin,fval);
7380 }
7381 }
7382 }
7383 next.Reset();
7384 }
7385 allchan += c1;
7386 }
7387 if (!nonNullErrors) {
7388 if (Hoption.Error) {
7389 if (!Hoption.Mark && !Hoption.Line && !Hoption.Star && !Hoption.Curve) Hoption.Hist = 2;
7390 Hoption.Error=0;
7391 }
7392 }
7393
7394
7395 // Take into account maximum , minimum
7396
7397 if (Hoption.Logy && ymin <= 0) {
7398 if (ymax >= 1) ymin = TMath::Max(.005,ymax*1e-10);
7399 else ymin = 0.001*ymax;
7400 }
7401
7402 Double_t xm = ymin;
7403 if (maximum) ymax = fH->GetMaximumStored();
7404 if (minimum) xm = fH->GetMinimumStored();
7405 if (Hoption.Logy && xm < 0) {
7406 Error(where, "log scale requested with a negative argument (%f)", xm);
7407 return 0;
7408 } else if (Hoption.Logy && xm>=0 && ymax==0) { // empty histogram in log scale
7409 ymin = 0.01;
7410 ymax = 10.;
7411 } else {
7412 ymin = xm;
7413 }
7414
7415 if (ymin >= ymax) {
7416 if (Hoption.Logy) {
7417 if (ymax > 0) ymin = 0.001*ymax;
7418 else {
7419 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", ymax);
7420 return 0;
7421 }
7422 }
7423 else {
7424 if (ymin > 0) {
7425 ymin = 0;
7426 ymax *= 2;
7427 } else if (ymin < 0) {
7428 ymax = 0;
7429 ymin *= 2;
7430 } else {
7431 ymin = 0;
7432 ymax = 1;
7433 }
7434 }
7435 }
7436
7437 // In some cases, mainly because of precision issues, ymin and ymax could almost equal.
7438 if (TMath::AreEqualRel(ymin,ymax,1E-15)) {
7439 ymin = ymin*(1-1E-14);
7440 ymax = ymax*(1+1E-14);
7441 }
7442
7443 // take into account normalization factor
7444 Hparam.allchan = allchan;
7445 Double_t factor = allchan;
7446 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
7447 if (allchan) factor /= allchan;
7448 if (factor == 0) factor = 1;
7449 Hparam.factor = factor;
7450 ymax = factor*ymax;
7451 ymin = factor*ymin;
7452 //just in case the norm factor is negative
7453 // this may happen with a positive norm factor and a negative integral !
7454 if (ymax < ymin) {
7455 Double_t temp = ymax;
7456 ymax = ymin;
7457 ymin = temp;
7458 }
7459
7460 // For log scales, histogram coordinates are LOG10(ymin) and
7461 // LOG10(ymax). Final adjustment (if not option "Same"
7462 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
7463 // Maximum and Minimum are not defined.
7464 if (Hoption.Logy) {
7465 if (ymin <=0 || ymax <=0) {
7466 Error(where, "Cannot set Y axis to log scale");
7467 return 0;
7468 }
7470 if (!minimum) ymin += TMath::Log10(0.5);
7472 if (!maximum) ymax += TMath::Log10(2*(0.9/0.95));
7473 if (!Hoption.Same) {
7474 Hparam.ymin = ymin;
7475 Hparam.ymax = ymax;
7476 }
7477 return 1;
7478 }
7479
7480 // final adjustment of ymin for linear scale.
7481 // if minimum is not set , then ymin is set to zero if >0
7482 // or to ymin - margin if <0.
7483 if (!minimum) {
7484 if (Hoption.MinimumZero) {
7485 if (ymin >= 0) ymin = 0;
7486 else ymin -= yMARGIN*(ymax-ymin);
7487 } else {
7489 if (ymin >= 0 && (ymin-dymin <= 0)) ymin = 0;
7490 else ymin -= dymin;
7491 }
7492 }
7493
7494 // final adjustment of YMAXI for linear scale (if not option "Same"):
7495 // decrease histogram height to MAX% of allowed height if HMAXIM
7496 // has not been called.
7497 if (!maximum) {
7498 ymax += yMARGIN*(ymax-ymin);
7499 }
7500
7501 Hparam.ymin = ymin;
7502 Hparam.ymax = ymax;
7503 return 1;
7504}
7505
7506////////////////////////////////////////////////////////////////////////////////
7507/// Compute histogram parameters used by the drawing routines for a rotated pad.
7508
7510{
7511
7512 static const char *where = "PaintInitH";
7514 Int_t maximum = 0;
7515 Int_t minimum = 0;
7516 if (fH->GetMaximumStored() != -1111) maximum = 1;
7517 if (fH->GetMinimumStored() != -1111) minimum = 1;
7518
7519 // Compute X axis parameters
7520
7521 Int_t last = fXaxis->GetLast();
7522 Int_t first = fXaxis->GetFirst();
7525 Hparam.xlast = last;
7526 Hparam.xfirst = first;
7529
7530 // if log scale in Y, replace ymin,max by the log
7531 if (Hoption.Logy) {
7532 if (Hparam.xlowedge <=0 ) {
7535 }
7536 if (Hparam.ymin <=0 || Hparam.ymax <=0) {
7537 Error(where, "cannot set Y axis to log scale");
7538 return 0;
7539 }
7544 if (Hparam.xlast > last) Hparam.xlast = last;
7545 }
7546
7547 // Compute Y axis parameters
7548 Double_t bigp = TMath::Power(10,32);
7549 Double_t xmax = -bigp;
7550 Double_t xmin = bigp;
7551 Double_t c1, e1;
7552 Double_t xv[1];
7553 Double_t fval;
7554 Int_t i;
7555 TObject *f;
7556 TF1 *f1;
7557 Double_t allchan = 0;
7558 TIter next(fFunctions);
7559 for (i=first; i<=last;i++) {
7560 c1 = fH->GetBinContent(i);
7563 if (Hoption.Error) {
7564 e1 = fH->GetBinError(i);
7567 }
7568 if (Hoption.Func) {
7569 xv[0] = fXaxis->GetBinCenter(i);
7570 while ((f = (TObject*) next())) {
7571 if (f->IsA() == TF1::Class()) {
7572 f1 = (TF1*)f;
7573 if (xv[0] < f1->GetXmin() || xv[0] > f1->GetXmax()) continue;
7574 fval = f1->Eval(xv[0],0,0);
7576 if (Hoption.Logy) {
7577 if (fval > 0.3*c1) xmin = TMath::Min(xmin,fval);
7578 }
7579 }
7580 }
7581 next.Reset();
7582 }
7583 allchan += c1;
7584 }
7585
7586 // Take into account maximum , minimum
7587
7588 if (Hoption.Logx && xmin <= 0) {
7589 if (xmax >= 1) xmin = TMath::Max(.5,xmax*1e-10);
7590 else xmin = 0.001*xmax;
7591 }
7592 Double_t xm = xmin;
7593 if (maximum) xmax = fH->GetMaximumStored();
7594 if (minimum) xm = fH->GetMinimumStored();
7595 if (Hoption.Logx && xm <= 0) {
7596 Error(where, "log scale requested with zero or negative argument (%f)", xm);
7597 return 0;
7598 }
7599 else xmin = xm;
7600 if (xmin >= xmax) {
7601 if (Hoption.Logx) {
7602 if (xmax > 0) xmin = 0.001*xmax;
7603 else {
7604 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", xmax);
7605 return 0;
7606 }
7607 }
7608 else {
7609 if (xmin > 0) {
7610 xmin = 0;
7611 xmax *= 2;
7612 } else if (xmin < 0) {
7613 xmax = 0;
7614 xmin *= 2;
7615 } else {
7616 xmin = 0;
7617 xmax = 1;
7618 }
7619 }
7620 }
7621
7622 // take into account normalization factor
7623 Hparam.allchan = allchan;
7624 Double_t factor = allchan;
7625 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
7626 if (allchan) factor /= allchan;
7627 if (factor == 0) factor = 1;
7628 Hparam.factor = factor;
7629 xmax = factor*xmax;
7630 xmin = factor*xmin;
7631
7632 // For log scales, histogram coordinates are LOG10(ymin) and
7633 // LOG10(ymax). Final adjustment (if not option "Same"
7634 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
7635 // Maximum and Minimum are not defined.
7636 if (Hoption.Logx) {
7637 if (xmin <=0 || xmax <=0) {
7638 Error(where, "Cannot set Y axis to log scale");
7639 return 0;
7640 }
7642 if (!minimum) xmin += TMath::Log10(0.5);
7644 if (!maximum) xmax += TMath::Log10(2*(0.9/0.95));
7645 if (!Hoption.Same) {
7646 Hparam.xmin = xmin;
7647 Hparam.xmax = xmax;
7648 }
7649 return 1;
7650 }
7651
7652 // final adjustment of ymin for linear scale.
7653 // if minimum is not set , then ymin is set to zero if >0
7654 // or to ymin - margin if <0.
7655 if (!minimum) {
7656 if (xmin >= 0) xmin = 0;
7657 else xmin -= yMARGIN*(xmax-xmin);
7658 }
7659
7660 // final adjustment of YMAXI for linear scale (if not option "Same"):
7661 // decrease histogram height to MAX% of allowed height if HMAXIM
7662 // has not been called.
7663 if (!maximum) {
7664 xmax += yMARGIN*(xmax-xmin);
7665 }
7666 Hparam.xmin = xmin;
7667 Hparam.xmax = xmax;
7668 return 1;
7669}
7670
7671////////////////////////////////////////////////////////////////////////////////
7672/// [Control function to draw a 3D histogram with boxes.](\ref HP25)
7673
7675{
7676 // Predefined box structure
7677 Double_t wxyz[8][3] = { {-1,-1,-1}, {1,-1,-1}, {1,1,-1}, {-1,1,-1},
7678 {-1,-1, 1}, {1,-1, 1}, {1,1, 1}, {-1,1, 1} };
7679 Int_t iface[6][4] = { {0,3,2,1}, {4,5,6,7},
7680 {0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7} };
7681
7682 // Define dimensions of world space
7683 TAxis *xaxis = fH->GetXaxis();
7684 TAxis *yaxis = fH->GetYaxis();
7685 TAxis *zaxis = fH->GetZaxis();
7686
7687 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7688 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7689 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7690 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7691 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7692 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7693
7694 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7695
7696 // Set view
7697 TView *view = gPad ? gPad->GetView() : nullptr;
7698 if (!view) {
7699 Error("PaintH3", "no TView in current pad");
7700 return;
7701 }
7702 Double_t thedeg = 90 - gPad->GetTheta();
7703 Double_t phideg = -90 - gPad->GetPhi();
7704 Double_t psideg = view->GetPsi();
7705 Int_t irep;
7706 view->SetView(phideg, thedeg, psideg, irep);
7707
7708 Int_t backcolor = gPad->GetFrameFillColor();
7709 view->PadRange(backcolor);
7710
7711 // Draw back surfaces of frame box
7712 fLego->InitMoveScreen(-1.1,1.1);
7713 if (Hoption.BackBox) {
7714 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
7716 fLego->BackBox(90);
7717 }
7718
7720
7721 // Define order of drawing
7722 Double_t *tnorm = view->GetTnorm();
7723 if (!tnorm) return;
7724 Int_t incrx = (tnorm[ 8] < 0.) ? -1 : +1;
7725 Int_t incry = (tnorm[ 9] < 0.) ? -1 : +1;
7726 Int_t incrz = (tnorm[10] < 0.) ? -1 : +1;
7727 Int_t ix1 = (incrx == +1) ? xaxis->GetFirst() : xaxis->GetLast();
7728 Int_t iy1 = (incry == +1) ? yaxis->GetFirst() : yaxis->GetLast();
7729 Int_t iz1 = (incrz == +1) ? zaxis->GetFirst() : zaxis->GetLast();
7730 Int_t ix2 = (incrx == +1) ? xaxis->GetLast() : xaxis->GetFirst();
7731 Int_t iy2 = (incry == +1) ? yaxis->GetLast() : yaxis->GetFirst();
7732 Int_t iz2 = (incrz == +1) ? zaxis->GetLast() : zaxis->GetFirst();
7733
7734 // Set graphic attributes (colour, style, etc.)
7739
7740 fH->SetFillStyle(1001);
7741 fH->TAttFill::Modify();
7742 fH->TAttLine::Modify();
7745
7746 // Create bin boxes and draw
7750
7751 Double_t pmin[3], pmax[3], sxyz[8][3];
7752 for (Int_t ix = ix1; ix !=ix2+incrx; ix += incrx) {
7753 pmin[0] = xaxis->GetBinLowEdge(ix);
7754 pmax[0] = xaxis->GetBinUpEdge(ix);
7755 for (Int_t iy = iy1; iy != iy2+incry; iy += incry) {
7756 pmin[1] = yaxis->GetBinLowEdge(iy);
7757 pmax[1] = yaxis->GetBinUpEdge(iy);
7758 for (Int_t iz = iz1; iz != iz2+incrz; iz += incrz) {
7759 pmin[2] = zaxis->GetBinLowEdge(iz);
7760 pmax[2] = zaxis->GetBinUpEdge(iz);
7761 Double_t w = fH->GetBinContent(fH->GetBin(ix,iy,iz));
7762 Bool_t neg = kFALSE;
7763 Int_t n = 5;
7764 if (w<0) {
7765 w = -w;
7766 neg = kTRUE;
7767 }
7768 if (w < wmin) continue;
7769 if (w > wmax) w = wmax;
7770 Double_t scale = (TMath::Power((w-wmin)/(wmax-wmin),1./3.))/2.;
7771 if (scale == 0) continue;
7772 for (Int_t i=0; i<3; ++i) {
7773 Double_t c = (pmax[i] + pmin[i])*0.5;
7774 Double_t d = (pmax[i] - pmin[i])*scale;
7775 for (Int_t k=0; k<8; ++k) { // set bin box vertices
7776 sxyz[k][i] = wxyz[k][i]*d + c;
7777 }
7778 }
7779 for (Int_t k=0; k<8; ++k) { // transform to normalized space
7780 view->WCtoNDC(&sxyz[k][0],&sxyz[k][0]);
7781 }
7782 Double_t x[8], y[8]; // draw bin box faces
7783 for (Int_t k=0; k<6; ++k) {
7784 for (Int_t i=0; i<4; ++i) {
7785 Int_t iv = iface[k][i];
7786 x[i] = sxyz[iv][0];
7787 y[i] = sxyz[iv][1];
7788 }
7789 x[4] = x[0] ; y[4] = y[0];
7790 if (neg) {
7791 x[5] = x[2] ; y[5] = y[2];
7792 x[6] = x[3] ; y[6] = y[3];
7793 x[7] = x[1] ; y[7] = y[1];
7794 n = 8;
7795 } else {
7796 n = 5;
7797 }
7798 Double_t z = (x[2]-x[0])*(y[3]-y[1]) - (y[2]-y[0])*(x[3]-x[1]);
7799 if (z <= 0.) continue;
7800 if (iopt == 2) {
7801 theColor = ncolors*((w-wmin)/(wmax-wmin)) -1;
7803 } else {
7804 if (k == 3 || k == 5) {
7806 } else if (k == 0 || k == 1) {
7808 } else {
7810 }
7811 }
7812 fH->TAttFill::Modify();
7813 gPad->PaintFillArea(4, x, y);
7814 if (iopt != 3)gPad->PaintPolyLine(n, x, y);
7815 }
7816 }
7817 }
7818 }
7819
7820 // Draw front surfaces of frame box
7821 if (Hoption.FrontBox) fLego->FrontBox(90);
7822
7823 // Draw axis and title
7824 if (!Hoption.Axis && !Hoption.Same) {
7825 TGaxis axis;
7826 PaintLegoAxis(&axis, 90);
7827 }
7828 PaintTitle();
7829
7830 // Draw palette. if needed.
7831 if (Hoption.Zscale) {
7832 Int_t ndiv = fH->GetContour();
7833 if (ndiv == 0 ) {
7834 ndiv = gStyle->GetNumberContours();
7835 fH->SetContour(ndiv);
7836 }
7837 PaintPalette();
7838 }
7839
7840 //Draw stats and fit results
7841 TF1 *fit = nullptr;
7842 TIter next(fFunctions);
7843 while (auto obj = next()) {
7844 if (obj->InheritsFrom(TF1::Class())) {
7845 fit = (TF1*)obj;
7846 break;
7847 }
7848 }
7849 if ((Hoption.Same%10) != 1) {
7850 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7852 }
7853 }
7854
7855 fLego.reset();
7856
7859 fH->TAttFill::Modify();
7860}
7861
7862////////////////////////////////////////////////////////////////////////////////
7863/// [Control function to draw a 3D histogram with boxes.](\ref HP25)
7864
7866{
7867 // Predefined box structure
7868 Double_t wxyz[8][3] = {
7869 {-1,-1,-1}, {1,-1,-1}, {1,1,-1}, {-1,1,-1}, // bottom vertices
7870 {-1,-1, 1}, {1,-1, 1}, {1,1, 1}, {-1,1, 1} // top vertices
7871 };
7872 Int_t iface[6][4] = {
7873 {0,3,2,1}, {4,5,6,7}, // bottom and top faces
7874 {0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7} // side faces
7875 };
7876 Double_t normal[6][3] = {
7877 {0,0,-1}, {0,0,1}, // Z-, Z+
7878 {0,-1,0}, {1,0,0}, {0,1,0}, {-1,0,0} // Y-, X+, Y+, X-
7879 };
7880
7881 // Define dimensions of world space
7882 TAxis *xaxis = fH->GetXaxis();
7883 TAxis *yaxis = fH->GetYaxis();
7884 TAxis *zaxis = fH->GetZaxis();
7885
7886 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7887 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7888 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7889 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7890 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7891 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7892
7893 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7894
7895 // Set view
7896 TView *view = gPad ? gPad->GetView() : nullptr;
7897 if (!view) {
7898 Error("PaintH3", "no TView in current pad");
7899 return;
7900 }
7901 Double_t thedeg = 90 - gPad->GetTheta();
7902 Double_t phideg = -90 - gPad->GetPhi();
7903 Double_t psideg = view->GetPsi();
7904 Int_t irep;
7905 view->SetView(phideg, thedeg, psideg, irep);
7906
7907 Int_t backcolor = gPad->GetFrameFillColor();
7908 view->PadRange(backcolor);
7909
7910 // Draw front surfaces of frame box
7911 if (Hoption.FrontBox) {
7912 fLego->InitMoveScreen(-1.1,1.1);
7914 }
7915
7916 // Initialize hidden line removal algorithm "raster screen"
7917 fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
7918
7919 // Define order of drawing
7920 Double_t *tnorm = view->GetTnorm();
7921 if (!tnorm) return;
7922 Int_t incrx = (tnorm[ 8] < 0.) ? +1 : -1;
7923 Int_t incry = (tnorm[ 9] < 0.) ? +1 : -1;
7924 Int_t incrz = (tnorm[10] < 0.) ? +1 : -1;
7925 Int_t ix1 = (incrx == +1) ? xaxis->GetFirst() : xaxis->GetLast();
7926 Int_t iy1 = (incry == +1) ? yaxis->GetFirst() : yaxis->GetLast();
7927 Int_t iz1 = (incrz == +1) ? zaxis->GetFirst() : zaxis->GetLast();
7928 Int_t ix2 = (incrx == +1) ? xaxis->GetLast() : xaxis->GetFirst();
7929 Int_t iy2 = (incry == +1) ? yaxis->GetLast() : yaxis->GetFirst();
7930 Int_t iz2 = (incrz == +1) ? zaxis->GetLast() : zaxis->GetFirst();
7931
7932 // Set line attributes (colour, style, etc.)
7933 fH->TAttLine::Modify();
7934
7935 // Create bin boxes and draw
7936 const Int_t NTMAX = 100;
7937 Double_t tt[NTMAX][2];
7941 Double_t pmin[3], pmax[3], sxyz[8][3], pp[4][2];
7942 for (Int_t ix = ix1; ix !=ix2+incrx; ix += incrx) {
7943 pmin[0] = xaxis->GetBinLowEdge(ix);
7944 pmax[0] = xaxis->GetBinUpEdge(ix);
7945 for (Int_t iy = iy1; iy != iy2+incry; iy += incry) {
7946 pmin[1] = yaxis->GetBinLowEdge(iy);
7947 pmax[1] = yaxis->GetBinUpEdge(iy);
7948 for (Int_t iz = iz1; iz != iz2+incrz; iz += incrz) {
7949 pmin[2] = zaxis->GetBinLowEdge(iz);
7950 pmax[2] = zaxis->GetBinUpEdge(iz);
7951 Double_t w = fH->GetBinContent(fH->GetBin(ix,iy,iz));
7952 Bool_t neg = kFALSE;
7953 if (w<0) {
7954 w = -w;
7955 neg = kTRUE;
7956 }
7957 if (w < wmin) continue;
7958 if (w > wmax) w = wmax;
7959 Double_t scale = (TMath::Power((w-wmin)/(wmax-wmin),1./3.))/2.;
7960 if (scale == 0) continue;
7961 for (Int_t i=0; i<3; ++i) {
7962 Double_t c = (pmax[i] + pmin[i])*0.5;
7963 Double_t d = (pmax[i] - pmin[i])*scale;
7964 for (Int_t k=0; k<8; ++k) { // set bin box vertices
7965 sxyz[k][i] = wxyz[k][i]*d + c;
7966 }
7967 }
7968 for (Int_t k=0; k<8; ++k) { // transform to normalized space
7969 view->WCtoNDC(&sxyz[k][0],&sxyz[k][0]);
7970 }
7971 for (Int_t k=0; k<6; ++k) { // draw box faces
7972 Double_t zn;
7973 view->FindNormal(normal[k][0], normal[k][1], normal[k][2], zn);
7974 if (zn <= 0) continue;
7975 for (Int_t i=0; i<4; ++i) {
7976 Int_t ip = iface[k][i];
7977 pp[i][0] = sxyz[ip][0];
7978 pp[i][1] = sxyz[ip][1];
7979 }
7980 for (Int_t i=0; i<4; ++i) {
7981 Int_t i1 = i;
7982 Int_t i2 = (i == 3) ? 0 : i + 1;
7983 Int_t nt;
7984 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7985 Double_t xdel = pp[i2][0] - pp[i1][0];
7986 Double_t ydel = pp[i2][1] - pp[i1][1];
7987 Double_t x[2], y[2];
7988 for (Int_t it = 0; it < nt; ++it) {
7989 x[0] = pp[i1][0] + xdel*tt[it][0];
7990 y[0] = pp[i1][1] + ydel*tt[it][0];
7991 x[1] = pp[i1][0] + xdel*tt[it][1];
7992 y[1] = pp[i1][1] + ydel*tt[it][1];
7993 gPad->PaintPolyLine(2, x, y);
7994 }
7995 }
7996 if (neg) {
7997 Int_t i1 = 0;
7998 Int_t i2 = 2;
7999 Int_t nt;
8000 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
8001 Double_t xdel = pp[i2][0] - pp[i1][0];
8002 Double_t ydel = pp[i2][1] - pp[i1][1];
8003 Double_t x[2], y[2];
8004 for (Int_t it = 0; it < nt; ++it) {
8005 x[0] = pp[i1][0] + xdel*tt[it][0];
8006 y[0] = pp[i1][1] + ydel*tt[it][0];
8007 x[1] = pp[i1][0] + xdel*tt[it][1];
8008 y[1] = pp[i1][1] + ydel*tt[it][1];
8009 gPad->PaintPolyLine(2, x, y);
8010 }
8011 i1 = 1;
8012 i2 = 3;
8013 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
8014 xdel = pp[i2][0] - pp[i1][0];
8015 ydel = pp[i2][1] - pp[i1][1];
8016 for (Int_t it = 0; it < nt; ++it) {
8017 x[0] = pp[i1][0] + xdel*tt[it][0];
8018 y[0] = pp[i1][1] + ydel*tt[it][0];
8019 x[1] = pp[i1][0] + xdel*tt[it][1];
8020 y[1] = pp[i1][1] + ydel*tt[it][1];
8021 gPad->PaintPolyLine(2, x, y);
8022 }
8023 }
8024 fLego->FillPolygonBorder(4, &pp[0][0]); // update raster screen
8025 }
8026 }
8027 }
8028 }
8029
8030 // Draw frame box
8031 if (Hoption.BackBox) {
8032 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
8034 fLego->BackBox(90);
8035 }
8036
8037 if (Hoption.FrontBox) fLego->FrontBox(90);
8038
8039 // Draw axis and title
8040 if (!Hoption.Axis && !Hoption.Same) {
8041 TGaxis axis;
8042 PaintLegoAxis(&axis, 90);
8043 }
8044 PaintTitle();
8045
8046 //Draw stats and fit results
8047 TF1 *fit = nullptr;
8048 TIter next(fFunctions);
8049 while (auto obj = next()) {
8050 if (obj->InheritsFrom(TF1::Class())) {
8051 fit = (TF1*)obj;
8052 break;
8053 }
8054 }
8055 if ((Hoption.Same%10) != 1) {
8056 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
8058 }
8059 }
8060
8061 fLego.reset();
8062}
8063
8064////////////////////////////////////////////////////////////////////////////////
8065/// [Control function to draw a 3D histogram with Iso Surfaces.](\ref HP25)
8066
8068{
8069
8070 const Double_t ydiff = 1;
8071 const Double_t yligh1 = 10;
8072 const Double_t qa = 0.15;
8073 const Double_t qd = 0.15;
8074 const Double_t qs = 0.8;
8076 Int_t i, irep;
8077 Int_t nbcol = 28;
8078 Int_t icol1 = 201;
8079 Int_t ic1 = icol1;
8080 Int_t ic2 = ic1+nbcol;
8081 Int_t ic3 = ic2+nbcol;
8082
8083 TAxis *xaxis = fH->GetXaxis();
8084 TAxis *yaxis = fH->GetYaxis();
8085 TAxis *zaxis = fH->GetZaxis();
8086
8087 Int_t nx = fH->GetNbinsX();
8088 Int_t ny = fH->GetNbinsY();
8089 Int_t nz = fH->GetNbinsZ();
8090
8091 std::vector<Double_t> x(nx);
8092 std::vector<Double_t> y(ny);
8093 std::vector<Double_t> z(nz);
8094
8095 for (i=0; i<nx; i++) x[i] = xaxis->GetBinCenter(i+1);
8096 for (i=0; i<ny; i++) y[i] = yaxis->GetBinCenter(i+1);
8097 for (i=0; i<nz; i++) z[i] = zaxis->GetBinCenter(i+1);
8098
8099 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
8100 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
8101 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
8102 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
8103 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
8104 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
8105
8106 Double_t s[3];
8107 s[0] = fH->GetSumOfWeights()/(fH->GetNbinsX()*fH->GetNbinsY()*fH->GetNbinsZ());
8108 s[1] = 0.5*s[0];
8109 s[2] = 1.5*s[0];
8110
8111 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
8112
8113 TView *view = gPad ? gPad->GetView() : nullptr;
8114 if (!view) {
8115 Error("PaintH3Iso", "no TView in current pad");
8116 return;
8117 }
8118 Double_t thedeg = 90 - gPad->GetTheta();
8119 Double_t phideg = -90 - gPad->GetPhi();
8120 Double_t psideg = view->GetPsi();
8121 view->SetView(phideg, thedeg, psideg, irep);
8122
8123 Int_t backcolor = gPad->GetFrameFillColor();
8124 if (Hoption.System != kCARTESIAN) backcolor = 0;
8125 view->PadRange(backcolor);
8126
8127 Double_t dcol = 0.5/Double_t(nbcol);
8128 TColor *colref = gROOT->GetColor(fH->GetFillColor());
8129 if (!colref) {
8130 return;
8131 }
8132 Float_t r, g, b, hue, light, satur;
8133 colref->GetRGB(r,g,b);
8135 TColor *acol;
8136 for (Int_t col=0;col<nbcol;col++) {
8137 acol = gROOT->GetColor(col+icol1);
8138 TColor::HLStoRGB(hue, .4+col*dcol, satur, r, g, b);
8139 if (acol) acol->SetRGB(r, g, b);
8140 }
8141
8142 fLego->InitMoveScreen(-1.1,1.1);
8143
8144 if (Hoption.BackBox) {
8145 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
8147 fLego->BackBox(90);
8148 }
8149
8150 fLego->LightSource(0, ydiff, 0, 0, 0, irep);
8151 fLego->LightSource(1, yligh1, 1, 1, 1, irep);
8152 fLego->SurfaceProperty(qa, qd, qs, 1, irep);
8153 fmin = ydiff*qa;
8154 fmax = ydiff*qa + (yligh1+0.1)*(qd+qs);
8155 fLego->SetIsoSurfaceParameters(fmin, fmax, nbcol, ic1, ic2, ic3);
8156
8157 fLego->IsoSurface(1, s, nx, ny, nz, x.data(), y.data(), z.data(), "BF");
8158
8159 if (Hoption.FrontBox) {
8160 fLego->InitMoveScreen(-1.1,1.1);
8162 fLego->FrontBox(90);
8163 }
8164 if (!Hoption.Axis && !Hoption.Same) {
8165 TGaxis axis;
8166 PaintLegoAxis(&axis, 90);
8167 }
8168
8169 PaintTitle();
8170
8171 //Draw stats and fit results
8172 TF1 *fit = nullptr;
8173 TIter next(fFunctions);
8174 while (auto obj = next()) {
8175 if (obj->InheritsFrom(TF1::Class())) {
8176 fit = (TF1*)obj;
8177 break;
8178 }
8179 }
8180 if ((Hoption.Same%10) != 1) {
8181 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
8183 }
8184 }
8185
8186 fLego.reset();
8187}
8188
8189////////////////////////////////////////////////////////////////////////////////
8190/// [Control function to draw a 2D histogram as a lego plot.](\ref HP17)
8191
8193{
8194
8195 Int_t raster = 1;
8196 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
8197 Int_t nx = Hparam.xlast - Hparam.xfirst + 1;
8198 Int_t ny = Hparam.ylast - Hparam.yfirst + 1;
8199 Double_t zmin = Hparam.zmin;
8200 Double_t zmax = Hparam.zmax;
8205 Double_t dangle = 10*3.141592/180; //Delta angle for Rapidity option
8206 Double_t deltaz = TMath::Abs(zmin);
8207 if (deltaz == 0) deltaz = 1;
8208 if (zmin >= zmax) {
8209 zmin -= 0.5*deltaz;
8210 zmax += 0.5*deltaz;
8211 }
8212 Double_t z1c = zmin;
8213 Double_t z2c = zmin + (zmax-zmin)*(1+gStyle->GetHistTopMargin());
8214
8215 // Compute the lego limits and instantiate a lego object
8216 fXbuf[0] = -1;
8217 fYbuf[0] = 1;
8218 fXbuf[1] = -1;
8219 fYbuf[1] = 1;
8220 if (Hoption.System == kPOLAR) {
8221 fXbuf[2] = z1c;
8222 fYbuf[2] = z2c;
8223 } else if (Hoption.System == kCYLINDRICAL) {
8224 if (Hoption.Logy) {
8225 if (ylab1 > 0) fXbuf[2] = TMath::Log10(ylab1);
8226 else fXbuf[2] = 0;
8227 if (ylab2 > 0) fYbuf[2] = TMath::Log10(ylab2);
8228 else fYbuf[2] = 0;
8229 } else {
8230 fXbuf[2] = ylab1;
8231 fYbuf[2] = ylab2;
8232 }
8233 z1c = 0; z2c = 1;
8234 } else if (Hoption.System == kSPHERICAL) {
8235 fXbuf[2] = -1;
8236 fYbuf[2] = 1;
8237 z1c = 0; z2c = 1;
8238 } else if (Hoption.System == kRAPIDITY) {
8239 fXbuf[2] = -1/TMath::Tan(dangle);
8240 fYbuf[2] = 1/TMath::Tan(dangle);
8241 } else {
8242 fXbuf[0] = xlab1;
8243 fYbuf[0] = xlab2;
8244 fXbuf[1] = ylab1;
8245 fYbuf[1] = ylab2;
8246 fXbuf[2] = z1c;
8247 fYbuf[2] = z2c;
8248 raster = 0;
8249 }
8250
8251 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data(), Hoption.System);
8252
8253 Int_t nids = -1;
8254 TH1 * hid = nullptr;
8255 Color_t colormain = -1, colordark = -1;
8257
8258 // LEGO3 is like LEGO1 except that the black lines around each lego are not drawn.
8259 if (Hoption.Lego == 13) {
8260 Hoption.Lego = 11;
8261 fLego->SetMesh(0);
8262 }
8263 // LEGO4 is like LEGO1 except no shadows are drawn.
8264 if (Hoption.Lego == 14) {
8265 Hoption.Lego = 11;
8267 }
8268
8269 // Initialize the levels on the Z axis
8270 Int_t ndiv = fH->GetContour();
8271 if (ndiv == 0 ) {
8272 ndiv = gStyle->GetNumberContours();
8273 fH->SetContour(ndiv);
8274 }
8275 Int_t ndivz = TMath::Abs(ndiv);
8276 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
8277
8278 // Initialize colors
8279 if (!fStack) {
8280 fLego->SetEdgeAtt(fH->GetLineColor(),fH->GetLineStyle(),fH->GetLineWidth(),0);
8281 } else {
8282 for (Int_t id=0;id<=fStack->GetSize();id++) {
8283 hid = (TH1*)fStack->At((id==0)?id:id-1);
8284 fLego->SetEdgeAtt(hid->GetLineColor(),hid->GetLineStyle(),hid->GetLineWidth(),id);
8285 }
8286 }
8287
8288 if (Hoption.Lego == 11) {
8289 nids = 1;
8290 if (fStack) nids = fStack->GetSize();
8291 hid = fH;
8292 for (Int_t id=0;id<=nids;id++) {
8293 if (id > 0 && fStack) hid = (TH1*)fStack->At(id-1);
8294 colormain = hid->GetFillColor();
8295 if (colormain == 1) colormain = 17; //avoid drawing with black
8297 else colordark = colormain;
8298 fLego->SetColorMain(colormain,id);
8299 fLego->SetColorDark(colordark,id);
8300 if (id <= 1) fLego->SetColorMain(colormain,-1); // Set Bottom color
8301 if (id == nids) fLego->SetColorMain(colormain,99); // Set Top color
8302 }
8303 }
8304
8305 // Now ready to draw the lego plot
8306 Int_t irep = 0;
8307
8308 TView *view = gPad ? gPad->GetView() : nullptr;
8309 if (!view) {
8310 Error("PaintLego", "no TView in current pad");
8311 return;
8312 }
8313
8314 Double_t thedeg = 90 - gPad->GetTheta();
8315 Double_t phideg = -90 - gPad->GetPhi();
8316 Double_t psideg = view->GetPsi();
8317 view->SetView(phideg, thedeg, psideg, irep);
8318
8319 fLego->SetLineColor(kBlack); // zgrid color for lego1 & lego2
8320 fLego->SetFillStyle(fH->GetFillStyle());
8321
8322 // Set color/style for back box
8323 fLego->SetFillStyle(gPad->GetFrameFillStyle());
8324 fLego->SetFillColor(gPad->GetFrameFillColor());
8325 fLego->TAttFill::Modify();
8326
8327 Int_t backcolor = gPad->GetFrameFillColor();
8328 if (Hoption.System != kCARTESIAN) backcolor = 0;
8329 view->PadRange(backcolor);
8330
8331 fLego->SetFillStyle(fH->GetFillStyle());
8332 fLego->SetFillColor(fH->GetFillColor());
8333 fLego->TAttFill::Modify();
8334
8335 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
8336
8337 if (raster) fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
8338 else fLego->InitMoveScreen(-1.1,1.1);
8339
8340 if (Hoption.Lego == 19) {
8342 if (Hoption.BackBox) fLego->BackBox(90);
8343 if (Hoption.FrontBox) fLego->FrontBox(90);
8344 if (!Hoption.Axis) { TGaxis axis; PaintLegoAxis(&axis, 90); }
8345 return;
8346 }
8347
8348 if (Hoption.Lego == 11 || Hoption.Lego == 12) {
8351 fLego->BackBox(90);
8352 }
8353 }
8354
8355 if (Hoption.Lego == 12) DefineColorLevels(ndivz);
8356
8357 fLego->SetLegoFunction(&TPainter3dAlgorithms::LegoFunction);
8359 if (Hoption.Lego == 11) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode3);
8360 if (Hoption.Lego == 12) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode2);
8361 if (Hoption.System == kPOLAR) {
8362 if (Hoption.Lego == 1) fLego->LegoPolar(1,nx,ny,"FB");
8363 if (Hoption.Lego == 11) fLego->LegoPolar(1,nx,ny,"BF");
8364 if (Hoption.Lego == 12) fLego->LegoPolar(1,nx,ny,"BF");
8365 } else if (Hoption.System == kCYLINDRICAL) {
8366 if (Hoption.Lego == 1) fLego->LegoCylindrical(1,nx,ny,"FB");
8367 if (Hoption.Lego == 11) fLego->LegoCylindrical(1,nx,ny,"BF");
8368 if (Hoption.Lego == 12) fLego->LegoCylindrical(1,nx,ny,"BF");
8369 } else if (Hoption.System == kSPHERICAL) {
8370 if (Hoption.Lego == 1) fLego->LegoSpherical(0,1,nx,ny,"FB");
8371 if (Hoption.Lego == 11) fLego->LegoSpherical(0,1,nx,ny,"BF");
8372 if (Hoption.Lego == 12) fLego->LegoSpherical(0,1,nx,ny,"BF");
8373 } else if (Hoption.System == kRAPIDITY) {
8374 if (Hoption.Lego == 1) fLego->LegoSpherical(1,1,nx,ny,"FB");
8375 if (Hoption.Lego == 11) fLego->LegoSpherical(1,1,nx,ny,"BF");
8376 if (Hoption.Lego == 12) fLego->LegoSpherical(1,1,nx,ny,"BF");
8377 } else {
8378 if (Hoption.Lego == 1) {
8380 fLego->LegoCartesian(90,nx,ny,"FB");}
8381 if (Hoption.Lego == 11) fLego->LegoCartesian(90,nx,ny,"BF");
8382 if (Hoption.Lego == 12) fLego->LegoCartesian(90,nx,ny,"BF");
8383 }
8384
8385 if (Hoption.Lego == 1 || Hoption.Lego == 11) {
8388 fLego->BackBox(90);
8389 }
8390 }
8391 if (Hoption.System == kCARTESIAN) {
8392 fLego->InitMoveScreen(-1.1,1.1);
8394 if (Hoption.FrontBox) fLego->FrontBox(90);
8395 }
8396 if (!Hoption.Axis && !Hoption.Same) {
8397 TGaxis axis;
8398 PaintLegoAxis(&axis, 90);
8399 }
8401 fLego.reset();
8402}
8403
8404////////////////////////////////////////////////////////////////////////////////
8405/// Draw the axis for legos and surface plots.
8406
8408{
8409
8410 static Double_t epsil = 0.001;
8411
8414 Double_t r[24] /* was [3][8] */;
8415 Int_t ndivx, ndivy, ndivz, i;
8416 Double_t x1[3], x2[3], y1[3], y2[3], z1[3], z2[3], av[24] /* was [3][8] */;
8417 static char chopax[8], chopay[8], chopaz[8];
8418 Int_t ix1, ix2, iy1, iy2, iz1, iz2;
8419 Double_t rad;
8420
8421 TView *view = gPad ? gPad->GetView() : nullptr;
8422 if (!view) {
8423 Error("PaintLegoAxis", "no TView in current pad");
8424 return;
8425 }
8426
8427 // In polar coordinates, draw a short line going from the external circle
8428 // corresponding to r = 1 up to r = 1.1
8429 if (Hoption.System == kPOLAR) {
8430 r[0] = 1;
8431 r[1] = 0;
8432 r[2] = 0;
8433 view->WCtoNDC(r, x1);
8434 r[0] = 1.1;
8435 r[1] = 0;
8436 r[2] = 0;
8437 view->WCtoNDC(r, x2);
8438 gPad->PaintLine(x1[0],x1[1],x2[0],x2[1]);
8439 return;
8440 }
8441
8442 if (Hoption.System != kCARTESIAN) return;
8443
8444 rad = TMath::ATan(1.) * 4. /180.;
8445 cosa = TMath::Cos(ang*rad);
8446 sina = TMath::Sin(ang*rad);
8447
8448 view->AxisVertex(ang, av, ix1, ix2, iy1, iy2, iz1, iz2);
8449 for (i = 1; i <= 8; ++i) {
8450 r[i*3 - 3] = av[i*3 - 3] + av[i*3 - 2]*cosa;
8451 r[i*3 - 2] = av[i*3 - 2]*sina;
8452 r[i*3 - 1] = av[i*3 - 1];
8453 }
8454
8455 view->WCtoNDC(&r[ix1*3 - 3], x1);
8456 view->WCtoNDC(&r[ix2*3 - 3], x2);
8457 view->WCtoNDC(&r[iy1*3 - 3], y1);
8458 view->WCtoNDC(&r[iy2*3 - 3], y2);
8459 view->WCtoNDC(&r[iz1*3 - 3], z1);
8460 view->WCtoNDC(&r[iz2*3 - 3], z2);
8461
8462 view->SetAxisNDC(x1, x2, y1, y2, z1, z2);
8463
8464 Double_t *rmin = view->GetRmin();
8465 Double_t *rmax = view->GetRmax();
8466 if (!rmin || !rmax) return;
8467
8468 // Initialize the axis options
8469 if (x1[0] > x2[0]) strlcpy(chopax, "SDH=+",8);
8470 else strlcpy(chopax, "SDH=-",8);
8471 if (y1[0] > y2[0]) strlcpy(chopay, "SDH=+",8);
8472 else strlcpy(chopay, "SDH=-",8);
8473 if (z2[1] > z1[1]) strlcpy(chopaz, "SDH=+",8);
8474 else strlcpy(chopaz, "SDH=-",8);
8475
8476 // Option LOG is required ?
8477 if (Hoption.Logx) strlcat(chopax,"G",8);
8478 if (Hoption.Logy) strlcat(chopay,"G",8);
8479 if (Hoption.Logz) strlcat(chopaz,"G",8);
8480
8481 // Initialize the number of divisions. If the
8482 // number of divisions is negative, option 'N' is required.
8486 if (ndivx < 0) {
8488 strlcat(chopax, "N",8);
8489 }
8490 if (ndivy < 0) {
8492 strlcat(chopay, "N",8);
8493 }
8494 if (ndivz < 0) {
8496 strlcat(chopaz, "N",8);
8497 }
8498
8499 // Set Axis attributes.
8500 // The variable SCALE rescales the VSIZ
8501 // in order to have the same label size for all angles.
8502
8503 axis->SetLineWidth(1);
8504
8505 // X axis drawing
8506 if (TMath::Abs(x1[0] - x2[0]) >= epsil || TMath::Abs(x1[1] - x2[1]) > epsil) {
8509 if (Hoption.Logx && !fH->InheritsFrom(TH3::Class())) {
8510 bmin = TMath::Power(10, rmin[0]);
8511 bmax = TMath::Power(10, rmax[0]);
8512 } else {
8513 bmin = rmin[0];
8514 bmax = rmax[0];
8515 }
8516 // Option time display is required ?
8517 if (fXaxis->GetTimeDisplay()) {
8518 strlcat(chopax,"t",8);
8519 if (strlen(fXaxis->GetTimeFormatOnly()) == 0) {
8521 } else {
8523 }
8524 }
8525 axis->SetOption(chopax);
8526 axis->PaintAxis(x1[0], x1[1], x2[0], x2[1], bmin, bmax, ndivx, chopax);
8527 }
8528
8529 // Y axis drawing
8530 if (TMath::Abs(y1[0] - y2[0]) >= epsil || TMath::Abs(y1[1] - y2[1]) > epsil) {
8533 if (fYaxis->GetTitleOffset() == 0) axis->SetTitleOffset(1.5);
8534
8535 if (fH->GetDimension() < 2) {
8536 strlcpy(chopay, "V=+UN",8);
8537 ndivy = 0;
8538 }
8539 if (TMath::Abs(y1[0] - y2[0]) < epsil) {
8540 y2[0] = y1[0];
8541 }
8542 if (Hoption.Logy && !fH->InheritsFrom(TH3::Class())) {
8543 bmin = TMath::Power(10, rmin[1]);
8544 bmax = TMath::Power(10, rmax[1]);
8545 } else {
8546 bmin = rmin[1];
8547 bmax = rmax[1];
8548 }
8549 // Option time display is required ?
8550 if (fYaxis->GetTimeDisplay()) {
8551 strlcat(chopay,"t",8);
8552 if (strlen(fYaxis->GetTimeFormatOnly()) == 0) {
8554 } else {
8556 }
8557 }
8558 axis->SetOption(chopay);
8559 axis->PaintAxis(y1[0], y1[1], y2[0], y2[1], bmin, bmax, ndivy, chopay);
8560 }
8561
8562 // Z axis drawing
8563 if (TMath::Abs(z1[0] - z2[0]) >= 100*epsil || TMath::Abs(z1[1] - z2[1]) > 100*epsil) {
8565 if (Hoption.Logz && !fH->InheritsFrom(TH3::Class())) {
8566 bmin = TMath::Power(10, rmin[2]);
8567 bmax = TMath::Power(10, rmax[2]);
8568 } else {
8569 bmin = rmin[2];
8570 bmax = rmax[2];
8571 }
8572 // Option time display is required ?
8573 if (fZaxis->GetTimeDisplay()) {
8574 strlcat(chopaz,"t",8);
8575 if (strlen(fZaxis->GetTimeFormatOnly()) == 0) {
8577 } else {
8579 }
8580 }
8581 axis->SetOption(chopaz);
8583 if (ztit.Index(";")>0) {
8584 ztit.Remove(ztit.Index(";"),ztit.Length());
8585 axis->SetTitle(ztit.Data());
8586 }
8587 axis->PaintAxis(z1[0], z1[1], z2[0], z2[1], bmin, bmax, ndivz, chopaz);
8588 }
8589
8590 //fH->SetLineStyle(1); /// otherwise fEdgeStyle[i] gets overwritten!
8591}
8592
8593////////////////////////////////////////////////////////////////////////////////
8594/// [Paint the color palette on the right side of the pad.](\ref HP22)
8595
8597{
8599 TView *view = gPad ? gPad->GetView() : nullptr;
8600 if (palette) {
8601 if (view) {
8602 if (!palette->TestBit(TPaletteAxis::kHasView)) {
8604 delete palette; palette = nullptr;
8605 }
8606 } else {
8607 if (palette->TestBit(TPaletteAxis::kHasView)) {
8609 delete palette; palette = nullptr;
8610 }
8611 }
8612 // make sure the histogram member of the palette is setup correctly. It may not be after a Clone()
8613 if (palette && !palette->GetHistogram()) palette->SetHistogram(fH);
8614 }
8615
8616 if (!palette) {
8617 Double_t xup = gPad->GetUxmax();
8618 Double_t x2 = gPad->PadtoX(gPad->GetX2());
8619 Double_t ymin = gPad->PadtoY(gPad->GetUymin());
8620 Double_t ymax = gPad->PadtoY(gPad->GetUymax());
8621 Double_t xr = 0.05*(gPad->GetX2() - gPad->GetX1());
8622 Double_t xmin = gPad->PadtoX(xup +0.1*xr);
8623 Double_t xmax = gPad->PadtoX(xup + xr);
8624 if (xmax > x2) xmax = gPad->PadtoX(gPad->GetX2()-0.01*xr);
8627 palette->Paint();
8628 }
8629}
8630
8631////////////////////////////////////////////////////////////////////////////////
8632/// [Control function to draw a 2D histogram as a scatter plot.](\ref HP11)
8633
8635{
8636
8637 fH->TAttMarker::Modify();
8638
8639 Int_t k, marker;
8640 Double_t dz, z, xk,xstep, yk, ystep;
8641 Double_t scale = 1;
8643 Double_t zmax = fH->GetMaximum();
8644 Double_t zmin = fH->GetMinimum();
8645 if (zmin == 0 && zmax == 0) return;
8646 if (zmin == zmax) {
8647 zmax += 0.1*TMath::Abs(zmax);
8648 zmin -= 0.1*TMath::Abs(zmin);
8649 }
8651 if (Hoption.Logz) {
8652 if (zmin > 0) zmin = TMath::Log10(zmin);
8653 else zmin = 0;
8654 if (zmax > 0) zmax = TMath::Log10(zmax);
8655 else zmax = 0;
8656 if (zmin == 0 && zmax == 0) return;
8657 dz = zmax - zmin;
8658 scale = 100/dz;
8659 if (ncells > 10000) scale /= 5;
8660 ltest = kTRUE;
8661 } else {
8662 dz = zmax - zmin;
8663 if (dz >= kNMAX || zmax < 1) {
8664 scale = (kNMAX-1)/dz;
8665 if (ncells > 10000) scale /= 5;
8666 ltest = kTRUE;
8667 }
8668 }
8669 if (fH->GetMinimumStored() == -1111) {
8671 if (Hoption.MinimumZero) {
8672 if (zmin >= 0) zmin = 0;
8673 else zmin -= yMARGIN*(zmax-zmin);
8674 } else {
8675 Double_t dzmin = yMARGIN*(zmax-zmin);
8676 if (zmin >= 0 && (zmin-dzmin <= 0)) zmin = 0;
8677 else zmin -= dzmin;
8678 }
8679 }
8680
8681 TString opt = option;
8682 opt.ToLower();
8683 if (opt.Contains("scat=")) {
8684 char optscat[100];
8685 strlcpy(optscat,opt.Data(),100);
8686 char *oscat = strstr(optscat,"scat=");
8687 char *blank = strstr(oscat," "); if (blank) *blank = 0;
8688 sscanf(oscat+5,"%lg",&scale);
8689 }
8690 // use an independent instance of a random generator
8691 // instead of gRandom to avoid conflicts and
8692 // to get same random numbers when drawing the same histogram
8694 marker=0;
8695 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
8698 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
8699 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
8700 xk = fXaxis->GetBinLowEdge(i);
8701 xstep = fXaxis->GetBinWidth(i);
8702 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
8703 z = fH->GetBinContent(bin);
8704 if (z < zmin) z = zmin;
8705 if (z > zmax) z = zmax;
8706 if (Hoption.Logz) {
8707 if (z > 0) z = TMath::Log10(z) - zmin;
8708 } else {
8709 z -= zmin;
8710 }
8711 if (z <= 0) continue;
8712 k = Int_t(z*scale);
8713 if (ltest) k++;
8714 if (k > 0) {
8715 for (Int_t loop=0; loop<k; loop++) {
8716 if (k+marker >= kNMAX) {
8717 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
8718 marker=0;
8719 }
8720 fXbuf[marker] = (random.Rndm()*xstep) + xk;
8721 fYbuf[marker] = (random.Rndm()*ystep) + yk;
8722 if (Hoption.Logx) {
8723 if (fXbuf[marker] > 0) fXbuf[marker] = TMath::Log10(fXbuf[marker]);
8724 else break;
8725 }
8726 if (Hoption.Logy) {
8727 if (fYbuf[marker] > 0) fYbuf[marker] = TMath::Log10(fYbuf[marker]);
8728 else break;
8729 }
8730 if (fXbuf[marker] < gPad->GetUxmin()) break;
8731 if (fYbuf[marker] < gPad->GetUymin()) break;
8732 if (fXbuf[marker] > gPad->GetUxmax()) break;
8733 if (fYbuf[marker] > gPad->GetUymax()) break;
8734 marker++;
8735 }
8736 }
8737 }
8738 }
8739 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
8740
8742}
8743
8744////////////////////////////////////////////////////////////////////////////////
8745/// Static function to paint special objects like vectors and matrices.
8746/// This function is called via `gROOT->ProcessLine` to paint these objects
8747/// without having a direct dependency of the graphics or histogramming
8748/// system.
8749
8751{
8752
8753 if (!obj) return;
8754 TDirectory::TContext ctx{nullptr}; // No self-registration to directories
8755
8756 if (obj->InheritsFrom(TMatrixFBase::Class())) {
8757 // case TMatrixF
8758 TH2F *R__TMatrixFBase = new TH2F((TMatrixFBase &)*obj);
8759 R__TMatrixFBase->SetBit(kCanDelete);
8760 R__TMatrixFBase->Draw(option);
8761
8762 } else if (obj->InheritsFrom(TMatrixDBase::Class())) {
8763 // case TMatrixD
8764 TH2D *R__TMatrixDBase = new TH2D((TMatrixDBase &)*obj);
8765 R__TMatrixDBase->SetBit(kCanDelete);
8766 R__TMatrixDBase->Draw(option);
8767
8768 } else if (obj->InheritsFrom(TVectorF::Class())) {
8769 //case TVectorF
8770 TH1F *R__TVectorF = new TH1F((TVectorF &)*obj);
8771 R__TVectorF->SetBit(kCanDelete);
8772 R__TVectorF->Draw(option);
8773
8774 } else if (obj->InheritsFrom(TVectorD::Class())) {
8775 //case TVectorD
8776 TH1D *R__TVectorD = new TH1D((TVectorD &)*obj);
8777 R__TVectorD->SetBit(kCanDelete);
8778 R__TVectorD->Draw(option);
8779 }
8780}
8781
8782////////////////////////////////////////////////////////////////////////////////
8783/// [Draw the statistics box for 1D and profile histograms.](\ref HP07)
8784
8786{
8787 TString tt, tf;
8788 Int_t dofit;
8789 TPaveStats *stats = nullptr;
8790 TIter next(fFunctions);
8791 while (auto obj = next()) {
8792 if (obj->InheritsFrom(TPaveStats::Class())) {
8793 stats = (TPaveStats*)obj;
8794 break;
8795 }
8796 }
8797
8798 if (stats && dostat) {
8799 dofit = stats->GetOptFit();
8800 dostat = stats->GetOptStat();
8801 } else {
8802 dofit = gStyle->GetOptFit();
8803 }
8804 if (!dofit) fit = nullptr;
8805 if (dofit == 1) dofit = 111;
8806 if (dostat == 1) dostat = 1111;
8807 Int_t print_name = dostat%10;
8808 Int_t print_entries = (dostat/10)%10;
8809 Int_t print_mean = (dostat/100)%10;
8810 Int_t print_stddev = (dostat/1000)%10;
8811 Int_t print_under = (dostat/10000)%10;
8812 Int_t print_over = (dostat/100000)%10;
8813 Int_t print_integral= (dostat/1000000)%10;
8814 Int_t print_skew = (dostat/10000000)%10;
8815 Int_t print_kurt = (dostat/100000000)%10;
8819 Int_t print_fval = dofit%10;
8820 Int_t print_ferrors = (dofit/10)%10;
8821 Int_t print_fchi2 = (dofit/100)%10;
8822 Int_t print_fprob = (dofit/1000)%10;
8824 if (fit) {
8825 if (print_fval < 2) nlinesf += fit->GetNumberFreeParameters();
8826 else nlinesf += fit->GetNpar();
8827 }
8829
8830 // Pavetext with statistics
8831 Bool_t done = kFALSE;
8832 if (!dostat && !fit) {
8833 if (stats) { fFunctions->Remove(stats); delete stats;}
8834 return;
8835 }
8837 if (fit) statw = 1.8*gStyle->GetStatW();
8839 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
8840 stath = 0.25*(nlines+nlinesf)*gStyle->GetStatH();
8841 }
8842 if (stats) {
8843 stats->Clear();
8844 done = kTRUE;
8845 } else {
8846 stats = new TPaveStats(
8849 gStyle->GetStatX(),
8850 gStyle->GetStatY(),"brNDC");
8851
8852 stats->SetParent(fH);
8853 stats->SetOptFit(dofit);
8854 stats->SetOptStat(dostat);
8855 stats->SetFillColor(gStyle->GetStatColor());
8856 stats->SetFillStyle(gStyle->GetStatStyle());
8858 stats->SetTextFont(gStyle->GetStatFont());
8859 if (gStyle->GetStatFont()%10 > 2)
8861 stats->SetFitFormat(gStyle->GetFitFormat());
8863 stats->SetName("stats");
8864
8866 stats->SetTextAlign(12);
8867 stats->SetBit(kCanDelete);
8868 stats->SetBit(kMustCleanup);
8869 }
8870 if (print_name) stats->AddText(fH->GetName());
8871 if (print_entries) {
8872 if (fH->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(fH->GetEntries()+0.5));
8873 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(fH->GetEntries()));
8874 stats->AddText(tt.Data());
8875 }
8876 if (print_mean) {
8877 if (print_mean == 1) {
8878 tf.Form("%s = %s%s",gStringMean.Data(),"%",stats->GetStatFormat());
8879 tt.Form(tf.Data(),fH->GetMean(1));
8880 } else {
8881 tf.Form("%s = %s%s #pm %s%s",gStringMean.Data(),"%",stats->GetStatFormat()
8882 ,"%",stats->GetStatFormat());
8883 tt.Form(tf.Data(),fH->GetMean(1),fH->GetMeanError(1));
8884 }
8885 stats->AddText(tt.Data());
8887 if (print_mean == 1) {
8888 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
8889 tt.Form(tf.Data(),fH->GetMean(2));
8890 } else {
8891 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
8892 ,"%",stats->GetStatFormat());
8893 tt.Form(tf.Data(),fH->GetMean(2),fH->GetMeanError(2));
8894 }
8895 stats->AddText(tt.Data());
8896 }
8897 }
8898 if (print_stddev) {
8899 if (print_stddev == 1) {
8900 tf.Form("%s = %s%s",gStringStdDev.Data(),"%",stats->GetStatFormat());
8901 tt.Form(tf.Data(),fH->GetStdDev(1));
8902 } else {
8903 tf.Form("%s = %s%s #pm %s%s",gStringStdDev.Data(),"%",stats->GetStatFormat()
8904 ,"%",stats->GetStatFormat());
8905 tt.Form(tf.Data(),fH->GetStdDev(1),fH->GetStdDevError(1));
8906 }
8907 stats->AddText(tt.Data());
8909 if (print_stddev == 1) {
8910 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
8911 tt.Form(tf.Data(),fH->GetStdDev(2));
8912 } else {
8913 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
8914 ,"%",stats->GetStatFormat());
8915 tt.Form(tf.Data(),fH->GetStdDev(2),fH->GetStdDevError(2));
8916 }
8917 stats->AddText(tt.Data());
8918 }
8919 }
8920 if (print_under) {
8921 tf.Form("%s = %s%s",gStringUnderflow.Data(),"%",stats->GetStatFormat());
8922 tt.Form(tf.Data(),fH->GetBinContent(0));
8923 stats->AddText(tt.Data());
8924 }
8925 if (print_over) {
8926 tf.Form("%s = %s%s",gStringOverflow.Data(),"%",stats->GetStatFormat());
8927 tt.Form(tf.Data(),fH->GetBinContent(fXaxis->GetNbins()+1));
8928 stats->AddText(tt.Data());
8929 }
8930 if (print_integral) {
8931 if (print_integral == 1) {
8932 tf.Form("%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
8933 tt.Form(tf.Data(),fH->Integral());
8934 } else {
8935 tf.Form("%s = %s%s",gStringIntegralBinWidth.Data(),"%",stats->GetStatFormat());
8936 tt.Form(tf.Data(),fH->Integral("width"));
8937 }
8938 stats->AddText(tt.Data());
8939 }
8940 if (print_skew) {
8941 if (print_skew == 1) {
8942 tf.Form("%s = %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat());
8943 tt.Form(tf.Data(),fH->GetSkewness(1));
8944 } else {
8945 tf.Form("%s = %s%s #pm %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat()
8946 ,"%",stats->GetStatFormat());
8947 tt.Form(tf.Data(),fH->GetSkewness(1),fH->GetSkewness(11));
8948 }
8949 stats->AddText(tt.Data());
8950 }
8951 if (print_kurt) {
8952 if (print_kurt == 1) {
8953 tf.Form("%s = %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat());
8954 tt.Form(tf.Data(),fH->GetKurtosis(1));
8955 } else {
8956 tf.Form("%s = %s%s #pm %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat()
8957 ,"%",stats->GetStatFormat());
8958 tt.Form(tf.Data(),fH->GetKurtosis(1),fH->GetKurtosis(11));
8959 }
8960 stats->AddText(tt.Data());
8961 }
8962
8963 // Draw Fit parameters
8964 if (fit) {
8965 Int_t ndf = fit->GetNDF();
8966 tf.Form("#chi^{2} / ndf = %s%s / %d","%",stats->GetFitFormat(),ndf);
8967 tt.Form(tf.Data(),fit->GetChisquare());
8968 if (print_fchi2) stats->AddText(tt.Data());
8969 if (print_fprob) {
8970 tf.Form("Prob = %s%s","%",stats->GetFitFormat());
8971 tt.Form(tf.Data(),TMath::Prob(fit->GetChisquare(),ndf));
8972 stats->AddText(tt.Data());
8973 }
8974 if (print_fval || print_ferrors) {
8976 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
8977 fit->GetParLimits(ipar,parmin,parmax);
8979 if (print_ferrors) {
8980 tf.Form("%-8s = %s%s #pm %s ", fit->GetParName(ipar), "%",stats->GetFitFormat(),
8981 GetBestFormat(fit->GetParameter(ipar), fit->GetParError(ipar), stats->GetFitFormat()));
8982 tt.Form(tf.Data(),fit->GetParameter(ipar)
8983 ,fit->GetParError(ipar));
8984 } else {
8985 tf.Form("%-8s = %s%s ",fit->GetParName(ipar), "%",stats->GetFitFormat());
8986 tt.Form(tf.Data(),fit->GetParameter(ipar));
8987 }
8988 stats->AddText(tt.Data());
8989 }
8990 }
8991 }
8992
8993 if (!done) fFunctions->Add(stats);
8994 stats->Paint(stats->GetOption());
8995}
8996
8997////////////////////////////////////////////////////////////////////////////////
8998/// [Draw the statistics box for 2D histograms.](\ref HP07)
8999
9001{
9002
9003 if (fH->GetDimension() != 2) return;
9004 TH2 *h2 = (TH2*)fH;
9005
9006 TString tt, tf;
9007 Int_t dofit;
9008 TPaveStats *stats = nullptr;
9009 TIter next(fFunctions);
9010 while (auto obj = next()) {
9011 if (obj->InheritsFrom(TPaveStats::Class())) {
9012 stats = (TPaveStats*)obj;
9013 break;
9014 }
9015 }
9016 if (stats && dostat) {
9017 dofit = stats->GetOptFit();
9018 dostat = stats->GetOptStat();
9019 } else {
9020 dofit = gStyle->GetOptFit();
9021 }
9022 if (dostat == 1) dostat = 1111;
9023 Int_t print_name = dostat%10;
9024 Int_t print_entries = (dostat/10)%10;
9025 Int_t print_mean = (dostat/100)%10;
9026 Int_t print_stddev = (dostat/1000)%10;
9027 Int_t print_under = (dostat/10000)%10;
9028 Int_t print_over = (dostat/100000)%10;
9029 Int_t print_integral= (dostat/1000000)%10;
9030 Int_t print_skew = (dostat/10000000)%10;
9031 Int_t print_kurt = (dostat/100000000)%10;
9033 if (print_under || print_over) nlines += 3;
9034
9035 // Pavetext with statistics
9036 if (!gStyle->GetOptFit()) fit = nullptr;
9037 Bool_t done = kFALSE;
9038 if (!dostat && !fit) {
9039 if (stats) { fFunctions->Remove(stats); delete stats;}
9040 return;
9041 }
9043 if (fit) statw = 1.8*gStyle->GetStatW();
9045 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
9046 stath = 0.25*nlines*gStyle->GetStatH();
9047 }
9048 if (fit) stath += gStyle->GetStatH();
9049 if (stats) {
9050 stats->Clear();
9051 done = kTRUE;
9052 } else {
9053 stats = new TPaveStats(
9056 gStyle->GetStatX(),
9057 gStyle->GetStatY(),"brNDC");
9058
9059 stats->SetParent(fH);
9060 stats->SetOptFit(dofit);
9061 stats->SetOptStat(dostat);
9062 stats->SetFillColor(gStyle->GetStatColor());
9063 stats->SetFillStyle(gStyle->GetStatStyle());
9065 stats->SetName("stats");
9066
9068 stats->SetTextAlign(12);
9069 stats->SetTextFont(gStyle->GetStatFont());
9070 if (gStyle->GetStatFont()%10 > 2)
9072 stats->SetFitFormat(gStyle->GetFitFormat());
9074 stats->SetBit(kCanDelete);
9075 stats->SetBit(kMustCleanup);
9076 }
9077 if (print_name) stats->AddText(h2->GetName());
9078 if (print_entries) {
9079 if (h2->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(h2->GetEntries()+0.5));
9080 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(h2->GetEntries()));
9081 stats->AddText(tt.Data());
9082 }
9083 if (print_mean) {
9084 if (print_mean == 1) {
9085 tf.Form("%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
9086 tt.Form(tf.Data(),h2->GetMean(1));
9087 stats->AddText(tt.Data());
9088 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
9089 tt.Form(tf.Data(),h2->GetMean(2));
9090 stats->AddText(tt.Data());
9091 } else {
9092 tf.Form("%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
9093 ,"%",stats->GetStatFormat());
9094 tt.Form(tf.Data(),h2->GetMean(1),h2->GetMeanError(1));
9095 stats->AddText(tt.Data());
9096 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
9097 ,"%",stats->GetStatFormat());
9098 tt.Form(tf.Data(),h2->GetMean(2),h2->GetMeanError(2));
9099 stats->AddText(tt.Data());
9100 }
9101 }
9102 if (print_stddev) {
9103 if (print_stddev == 1) {
9104 tf.Form("%s = %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat());
9105 tt.Form(tf.Data(),h2->GetStdDev(1));
9106 stats->AddText(tt.Data());
9107 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
9108 tt.Form(tf.Data(),h2->GetStdDev(2));
9109 stats->AddText(tt.Data());
9110 } else {
9111 tf.Form("%s = %s%s #pm %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat()
9112 ,"%",stats->GetStatFormat());
9113 tt.Form(tf.Data(),h2->GetStdDev(1),h2->GetStdDevError(1));
9114 stats->AddText(tt.Data());
9115 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
9116 ,"%",stats->GetStatFormat());
9117 tt.Form(tf.Data(),h2->GetStdDev(2),h2->GetStdDevError(2));
9118 stats->AddText(tt.Data());
9119 }
9120 }
9121 if (print_integral) {
9122 tf.Form("%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
9123 tt.Form(tf.Data(),fH->Integral());
9124 stats->AddText(tt.Data());
9125 }
9126 if (print_skew) {
9127 if (print_skew == 1) {
9128 tf.Form("%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
9129 tt.Form(tf.Data(),h2->GetSkewness(1));
9130 stats->AddText(tt.Data());
9131 tf.Form("%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
9132 tt.Form(tf.Data(),h2->GetSkewness(2));
9133 stats->AddText(tt.Data());
9134 } else {
9135 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
9136 ,"%",stats->GetStatFormat());
9137 tt.Form(tf.Data(),h2->GetSkewness(1),h2->GetSkewness(11));
9138 stats->AddText(tt.Data());
9139 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
9140 ,"%",stats->GetStatFormat());
9141 tt.Form(tf.Data(),h2->GetSkewness(2),h2->GetSkewness(12));
9142 stats->AddText(tt.Data());
9143 }
9144 }
9145 if (print_kurt) {
9146 if (print_kurt == 1) {
9147 tf.Form("%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
9148 tt.Form(tf.Data(),h2->GetKurtosis(1));
9149 stats->AddText(tt.Data());
9150 tf.Form("%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
9151 tt.Form(tf.Data(),h2->GetKurtosis(2));
9152 stats->AddText(tt.Data());
9153 } else {
9154 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
9155 ,"%",stats->GetStatFormat());
9156 tt.Form(tf.Data(),h2->GetKurtosis(1),h2->GetKurtosis(11));
9157 stats->AddText(tt.Data());
9158 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
9159 ,"%",stats->GetStatFormat());
9160 tt.Form(tf.Data(),h2->GetKurtosis(2),h2->GetKurtosis(12));
9161 stats->AddText(tt.Data());
9162 }
9163 }
9164 if (print_under || print_over) {
9165 //get 3*3 under/overflows for 2d hist
9166 Double_t unov[9];
9167
9168 Int_t cellsX = h2->GetXaxis()->GetNbins() + 1;
9169 Int_t cellsY = h2->GetYaxis()->GetNbins() + 1;
9170 Int_t firstX = std::max(1, h2->GetXaxis()->GetFirst());
9171 Int_t firstY = std::max(1, h2->GetYaxis()->GetFirst());
9172 Int_t lastX = std::min(h2->GetXaxis()->GetLast(), h2->GetXaxis()->GetNbins());
9173 Int_t lastY = std::min(h2->GetYaxis()->GetLast(), h2->GetYaxis()->GetNbins());
9174
9175 unov[0] = h2->Integral( 0, firstX-1, lastY+1, cellsY );
9176 unov[1] = h2->Integral(firstX , lastX , lastY+1, cellsY );
9177 unov[2] = h2->Integral(lastX+1, cellsX , lastY+1, cellsY );
9178 unov[3] = h2->Integral( 0, firstX-1, firstY , lastY );
9179 unov[4] = h2->Integral(firstX , lastX , firstY , lastY );
9180 unov[5] = h2->Integral(lastX+1, cellsX , firstY , lastY );
9181 unov[6] = h2->Integral( 0, firstX-1, 0, firstY-1);
9182 unov[7] = h2->Integral(firstX, lastX, 0, firstY-1);
9183 unov[8] = h2->Integral(lastX+1, cellsX , 0, firstY-1);
9184
9185 tt.Form("%g|%g|%g\n", unov[0], unov[1], unov[2]);
9186 stats->AddText(tt.Data());
9187 tt.Form("%g|%g|%g\n", unov[3], unov[4], unov[5]);
9188 stats->AddText(tt.Data());
9189 tt.Form("%g|%g|%g\n", unov[6], unov[7], unov[8]);
9190 stats->AddText(tt.Data());
9191 }
9192
9193 // Draw Fit parameters
9194 if (fit) {
9195 Int_t ndf = fit->GetNDF();
9196 tt.Form("#chi^{2} / ndf = %6.4g / %d",fit->GetChisquare(),ndf);
9197 stats->AddText(tt.Data());
9198 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
9199 tt.Form("%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
9200 ,fit->GetParameter(ipar)
9201 ,fit->GetParError(ipar));
9202 stats->AddText(tt.Data());
9203 }
9204 }
9205
9206 if (!done) fFunctions->Add(stats);
9207 stats->Paint(stats->GetOption());
9208}
9209
9210////////////////////////////////////////////////////////////////////////////////
9211/// [Draw the statistics box for 3D histograms.](\ref HP07)
9212
9214{
9215
9216 if (fH->GetDimension() != 3) return;
9217 TH3 *h3 = (TH3*)fH;
9218
9219 TString tt, tf;
9220 Int_t dofit;
9221 TPaveStats *stats = nullptr;
9222 TIter next(fFunctions);
9223 while (auto obj = next()) {
9224 if (obj->InheritsFrom(TPaveStats::Class())) {
9225 stats = (TPaveStats*)obj;
9226 break;
9227 }
9228 }
9229 if (stats && dostat) {
9230 dofit = stats->GetOptFit();
9231 dostat = stats->GetOptStat();
9232 } else {
9233 dofit = gStyle->GetOptFit();
9234 }
9235 if (dostat == 1) dostat = 1111;
9236 Int_t print_name = dostat%10;
9237 Int_t print_entries = (dostat/10)%10;
9238 Int_t print_mean = (dostat/100)%10;
9239 Int_t print_stddev = (dostat/1000)%10;
9240 Int_t print_under = (dostat/10000)%10;
9241 Int_t print_over = (dostat/100000)%10;
9242 Int_t print_integral= (dostat/1000000)%10;
9243 Int_t print_skew = (dostat/10000000)%10;
9244 Int_t print_kurt = (dostat/100000000)%10;
9246 if (print_under || print_over) nlines += 3;
9247
9248 // Pavetext with statistics
9249 if (!gStyle->GetOptFit()) fit = nullptr;
9250 Bool_t done = kFALSE;
9251 if (!dostat && !fit) {
9252 if (stats) { fFunctions->Remove(stats); delete stats;}
9253 return;
9254 }
9256 if (fit) statw = 1.8*gStyle->GetStatW();
9258 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
9259 stath = 0.25*nlines*gStyle->GetStatH();
9260 }
9261 if (fit) stath += gStyle->GetStatH();
9262 if (stats) {
9263 stats->Clear();
9264 done = kTRUE;
9265 } else {
9266 stats = new TPaveStats(
9269 gStyle->GetStatX(),
9270 gStyle->GetStatY(),"brNDC");
9271
9272 stats->SetParent(fH);
9273 stats->SetOptFit(dofit);
9274 stats->SetOptStat(dostat);
9275 stats->SetFillColor(gStyle->GetStatColor());
9276 stats->SetFillStyle(gStyle->GetStatStyle());
9278 stats->SetName("stats");
9279
9281 stats->SetTextAlign(12);
9282 stats->SetTextFont(gStyle->GetStatFont());
9283 stats->SetFitFormat(gStyle->GetFitFormat());
9285 stats->SetBit(kCanDelete);
9286 stats->SetBit(kMustCleanup);
9287 }
9288 if (print_name) stats->AddText(h3->GetName());
9289 if (print_entries) {
9290 if (h3->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(h3->GetEntries()+0.5));
9291 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(h3->GetEntries()+0.5));
9292 stats->AddText(tt.Data());
9293 }
9294 if (print_mean) {
9295 if (print_mean == 1) {
9296 tf.Form("%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
9297 tt.Form(tf.Data(),h3->GetMean(1));
9298 stats->AddText(tt.Data());
9299 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
9300 tt.Form(tf.Data(),h3->GetMean(2));
9301 stats->AddText(tt.Data());
9302 tf.Form("%s = %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat());
9303 tt.Form(tf.Data(),h3->GetMean(3));
9304 stats->AddText(tt.Data());
9305 } else {
9306 tf.Form("%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
9307 ,"%",stats->GetStatFormat());
9308 tt.Form(tf.Data(),h3->GetMean(1),h3->GetMeanError(1));
9309 stats->AddText(tt.Data());
9310 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
9311 ,"%",stats->GetStatFormat());
9312 tt.Form(tf.Data(),h3->GetMean(2),h3->GetMeanError(2));
9313 stats->AddText(tt.Data());
9314 tf.Form("%s = %s%s #pm %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat()
9315 ,"%",stats->GetStatFormat());
9316 tt.Form(tf.Data(),h3->GetMean(3),h3->GetMeanError(3));
9317 stats->AddText(tt.Data());
9318 }
9319 }
9320 if (print_stddev) {
9321 if (print_stddev == 1) {
9322 tf.Form("%s = %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat());
9323 tt.Form(tf.Data(),h3->GetStdDev(1));
9324 stats->AddText(tt.Data());
9325 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
9326 tt.Form(tf.Data(),h3->GetStdDev(2));
9327 stats->AddText(tt.Data());
9328 tf.Form("%s = %s%s",gStringStdDevZ.Data(),"%",stats->GetStatFormat());
9329 tt.Form(tf.Data(),h3->GetStdDev(3));
9330 stats->AddText(tt.Data());
9331 } else {
9332 tf.Form("%s = %s%s #pm %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat()
9333 ,"%",stats->GetStatFormat());
9334 tt.Form(tf.Data(),h3->GetStdDev(1),h3->GetStdDevError(1));
9335 stats->AddText(tt.Data());
9336 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
9337 ,"%",stats->GetStatFormat());
9338 tt.Form(tf.Data(),h3->GetStdDev(2),h3->GetStdDevError(2));
9339 stats->AddText(tt.Data());
9340 tf.Form("%s = %s%s #pm %s%s",gStringStdDevZ.Data(),"%",stats->GetStatFormat()
9341 ,"%",stats->GetStatFormat());
9342 tt.Form(tf.Data(),h3->GetStdDev(3),h3->GetStdDevError(3));
9343 stats->AddText(tt.Data());
9344 }
9345 }
9346 if (print_integral) {
9347 tt.Form("%s = %6.4g",gStringIntegral.Data(),h3->Integral());
9348 stats->AddText(tt.Data());
9349 }
9350 if (print_skew) {
9351 if (print_skew == 1) {
9352 tf.Form("%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
9353 tt.Form(tf.Data(),h3->GetSkewness(1));
9354 stats->AddText(tt.Data());
9355 tf.Form("%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
9356 tt.Form(tf.Data(),h3->GetSkewness(2));
9357 stats->AddText(tt.Data());
9358 tf.Form("%s = %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat());
9359 tt.Form(tf.Data(),h3->GetSkewness(3));
9360 stats->AddText(tt.Data());
9361 } else {
9362 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
9363 ,"%",stats->GetStatFormat());
9364 tt.Form(tf.Data(),h3->GetSkewness(1),h3->GetSkewness(11));
9365 stats->AddText(tt.Data());
9366 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
9367 ,"%",stats->GetStatFormat());
9368 tt.Form(tf.Data(),h3->GetSkewness(2),h3->GetSkewness(12));
9369 stats->AddText(tt.Data());
9370 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat()
9371 ,"%",stats->GetStatFormat());
9372 tt.Form(tf.Data(),h3->GetSkewness(3),h3->GetSkewness(13));
9373 stats->AddText(tt.Data());
9374 }
9375 }
9376 if (print_kurt) {
9377 if (print_kurt == 1) {
9378 tf.Form("%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
9379 tt.Form(tf.Data(),h3->GetKurtosis(1));
9380 stats->AddText(tt.Data());
9381 tf.Form("%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
9382 tt.Form(tf.Data(),h3->GetKurtosis(2));
9383 stats->AddText(tt.Data());
9384 tf.Form("%s = %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat());
9385 tt.Form(tf.Data(),h3->GetKurtosis(3));
9386 stats->AddText(tt.Data());
9387 } else {
9388 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
9389 ,"%",stats->GetStatFormat());
9390 tt.Form(tf.Data(),h3->GetKurtosis(1),h3->GetKurtosis(11));
9391 stats->AddText(tt.Data());
9392 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
9393 ,"%",stats->GetStatFormat());
9394 tt.Form(tf.Data(),h3->GetKurtosis(2),h3->GetKurtosis(12));
9395 stats->AddText(tt.Data());
9396 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat()
9397 ,"%",stats->GetStatFormat());
9398 tt.Form(tf.Data(),h3->GetKurtosis(3),h3->GetKurtosis(13));
9399 stats->AddText(tt.Data());
9400 }
9401 }
9402 if (print_under || print_over) {
9403 // no underflow - overflow printing for a 3D histogram
9404 // one would need a 3D table
9405 }
9406
9407 // Draw Fit parameters
9408 if (fit) {
9409 Int_t ndf = fit->GetNDF();
9410 tt.Form("#chi^{2} / ndf = %6.4g / %d",fit->GetChisquare(),ndf);
9411 stats->AddText(tt.Data());
9412 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
9413 tt.Form("%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
9414 ,fit->GetParameter(ipar)
9415 ,fit->GetParError(ipar));
9416 stats->AddText(tt.Data());
9417 }
9418 }
9419
9420 if (!done) fFunctions->Add(stats);
9421 stats->Paint(stats->GetOption());
9422}
9423
9424////////////////////////////////////////////////////////////////////////////////
9425/// [Control function to draw a 2D histogram as a surface plot.](\ref HP18)
9426
9428{
9429
9430 const Double_t ydiff = 1;
9431 const Double_t yligh1 = 10;
9432 const Double_t qa = 0.15;
9433 const Double_t qd = 0.15;
9434 const Double_t qs = 0.8;
9436 Int_t raster = 0;
9437 Int_t irep = 0;
9438
9439 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
9442 Double_t zmin = Hparam.zmin;
9443 Double_t zmax = Hparam.zmax;
9448 Double_t dangle = 10*3.141592/180; //Delta angle for Rapidity option
9449 Double_t deltaz = TMath::Abs(zmin);
9450 if (deltaz == 0) deltaz = 1;
9451 if (zmin >= zmax) {
9452 zmin -= 0.5*deltaz;
9453 zmax += 0.5*deltaz;
9454 }
9455 Double_t z1c = zmin;
9456 Double_t z2c = zmin + (zmax-zmin)*(1+gStyle->GetHistTopMargin());
9457 // Compute the lego limits and instantiate a lego object
9458 fXbuf[0] = -1;
9459 fYbuf[0] = 1;
9460 fXbuf[1] = -1;
9461 fYbuf[1] = 1;
9462 if (Hoption.System >= kPOLAR && (Hoption.Surf == 1 || Hoption.Surf == 13)) raster = 1;
9463 if (Hoption.System == kPOLAR) {
9464 fXbuf[2] = z1c;
9465 fYbuf[2] = z2c;
9466 } else if (Hoption.System == kCYLINDRICAL) {
9467 if (Hoption.Logy) {
9468 if (ylab1 > 0) fXbuf[2] = TMath::Log10(ylab1);
9469 else fXbuf[2] = 0;
9470 if (ylab2 > 0) fYbuf[2] = TMath::Log10(ylab2);
9471 else fYbuf[2] = 0;
9472 } else {
9473 fXbuf[2] = ylab1;
9474 fYbuf[2] = ylab2;
9475 }
9476 z1c = 0; z2c = 1;
9477 } else if (Hoption.System == kSPHERICAL) {
9478 fXbuf[2] = -1;
9479 fYbuf[2] = 1;
9480 z1c = 0; z2c = 1;
9481 } else if (Hoption.System == kRAPIDITY) {
9482 fXbuf[2] = -1/TMath::Tan(dangle);
9483 fYbuf[2] = 1/TMath::Tan(dangle);
9484 } else {
9485 fXbuf[0] = xlab1;
9486 fYbuf[0] = xlab2;
9487 fXbuf[1] = ylab1;
9488 fYbuf[1] = ylab2;
9489 fXbuf[2] = z1c;
9490 fYbuf[2] = z2c;
9491 }
9492
9493 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data(), Hoption.System);
9494 fLego->SetEdgeAtt(fH->GetLineColor(),fH->GetLineStyle(),fH->GetLineWidth(),0);
9495 fLego->SetFillColor(fH->GetFillColor());
9496
9497 // Initialize the levels on the Z axis
9498 Int_t ndiv = fH->GetContour();
9499 if (ndiv == 0 ) {
9500 ndiv = gStyle->GetNumberContours();
9501 fH->SetContour(ndiv);
9502 }
9503 Int_t ndivz = TMath::Abs(ndiv);
9504 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
9505
9506 if (Hoption.Surf == 13 || Hoption.Surf == 15) fLego->SetMesh(3);
9507 if (Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) fLego->SetMesh(0);
9508
9509 // Close the surface in case of non cartesian coordinates.
9510
9511 if (Hoption.System != kCARTESIAN) {nx++; ny++;}
9512
9513 // Now ready to draw the surface plot
9514
9515 TView *view = gPad ? gPad->GetView() : nullptr;
9516 if (!view) {
9517 Error("PaintSurface", "no TView in current pad");
9518 return;
9519 }
9520
9521 Double_t thedeg = 90 - gPad->GetTheta();
9522 Double_t phideg = -90 - gPad->GetPhi();
9523 Double_t psideg = view->GetPsi();
9524 view->SetView(phideg, thedeg, psideg, irep);
9525
9526 // Set color/style for back box
9527 if (Hoption.Same) {
9528 fLego->SetFillStyle(0);
9529 fLego->SetFillColor(1);
9530 } else {
9531 fLego->SetFillStyle(gPad->GetFrameFillStyle());
9532 fLego->SetFillColor(gPad->GetFrameFillColor());
9533 }
9534 fLego->TAttFill::Modify();
9535
9536 Int_t backcolor = gPad->GetFrameFillColor();
9537 if (Hoption.System != kCARTESIAN) backcolor = 0;
9538 view->PadRange(backcolor);
9539
9540 fLego->SetFillStyle(fH->GetFillStyle());
9541 fLego->SetFillColor(fH->GetFillColor());
9542 fLego->TAttFill::Modify();
9543
9544 // Draw the filled contour on top
9546
9548 if (Hoption.Surf == 13 || Hoption.Surf == 15) {
9550 Hoption.Surf = 23;
9551 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9553 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"BF");
9554 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9555 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9556 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9557 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"BF");
9559 fLego->SetMesh(1);
9560 }
9561
9562 if (raster) fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
9563 else fLego->InitMoveScreen(-1.1,1.1);
9564
9565 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) {
9566 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9569 fLego->BackBox(90);
9570 }
9571 }
9572
9573 // Gouraud Shading surface
9574 if (Hoption.Surf == 14) {
9575 // Set light sources
9576 fLego->LightSource(0, ydiff, 0,0,0,irep);
9577 fLego->LightSource(1, yligh1 ,1,1,1,irep);
9578 fLego->SurfaceProperty(qa, qd, qs, 1, irep);
9579 fmin = ydiff*qa;
9580 fmax = fmin + (yligh1+0.1)*(qd+qs);
9581 Int_t nbcol = 28;
9582 icol1 = 201;
9583 Double_t dcol = 0.5/Double_t(nbcol);
9584 TColor *colref = gROOT->GetColor(fH->GetFillColor());
9585 if (!colref) return;
9587 colref->GetRGB(r,g,b);
9589 TColor *acol;
9590 for (Int_t col=0;col<nbcol;col++) {
9591 acol = gROOT->GetColor(col+icol1);
9593 if (acol) acol->SetRGB(r,g,b);
9594 }
9595 fLego->Spectrum(nbcol, fmin, fmax, icol1, 1, irep);
9596 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::GouraudFunction);
9598 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"BF");
9599 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9600 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9601 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9602 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"BF");
9603 } else if (Hoption.Surf == 15) {
9604 // The surface is not drawn in this case.
9605 } else {
9606 // Draw the surface
9607 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 16 || Hoption.Surf == 17) {
9609 } else {
9610 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9611 }
9612 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9613 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceRaster1);
9614 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode2);
9615 if (Hoption.System == kPOLAR) {
9616 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfacePolar(1,nx,ny,"FB");
9617 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfacePolar(1,nx,ny,"BF");
9618 } else if (Hoption.System == kCYLINDRICAL) {
9619 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceCylindrical(1,nx,ny,"FB");
9620 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9621 } else if (Hoption.System == kSPHERICAL) {
9622 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceSpherical(0,1,nx,ny,"FB");
9623 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9624 } else if (Hoption.System == kRAPIDITY) {
9625 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceSpherical(1,1,nx,ny,"FB");
9626 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9627 } else {
9628 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove1);
9629 if (Hoption.Surf == 16) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove3);
9630 if (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16) fLego->SurfaceCartesian(90,nx,ny,"FB");
9631 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCartesian(90,nx,ny,"BF");
9632 }
9633 }
9634
9635 // Paint the line contour on top for option SURF7
9636 if (Hoption.Surf == 17) {
9637 fLego->InitMoveScreen(-1.1,1.1);
9638 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9639 Hoption.Surf = 23;
9640 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9642 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"FB");
9643 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"FB");
9644 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"FB");
9645 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"FB");
9646 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"FB");
9647 }
9648
9649 if ((!Hoption.Same) &&
9650 (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16)) {
9653 fLego->BackBox(90);
9654 }
9655 }
9656 if (Hoption.System == kCARTESIAN) {
9657 fLego->InitMoveScreen(-1.1,1.1);
9659 if (Hoption.FrontBox) fLego->FrontBox(90);
9660 }
9661 if (!Hoption.Axis && !Hoption.Same) {
9662 TGaxis axis;
9663 PaintLegoAxis(&axis, 90);
9664 }
9665
9667
9668 fLego.reset();
9669}
9670
9671////////////////////////////////////////////////////////////////////////////////
9672/// Control function to draw a table using Delaunay triangles.
9673
9675{
9676
9677 TGraphDelaunay2D *dt = nullptr;
9678 TGraphDelaunay *dtOld = nullptr;
9679
9680 // Check if fH contains a TGraphDelaunay2D
9682 dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
9683 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
9684 if (!dt && !dtOld) return;
9685
9686 // If needed, create a TGraph2DPainter
9687 if (!fGraph2DPainter)
9688 fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
9689
9690 // Define the 3D view
9691 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
9692 if (Hoption.Same) {
9693 TView *viewsame = gPad ? gPad->GetView() : nullptr;
9694 if (!viewsame) {
9695 Error("PaintTriangles", "no TView in current pad, do not use option SAME");
9696 return;
9697 }
9698 Double_t *rmin = viewsame->GetRmin();
9699 Double_t *rmax = viewsame->GetRmax();
9700 if (!rmin || !rmax) return;
9701 fXbuf[0] = rmin[0];
9702 fYbuf[0] = rmax[0];
9703 fXbuf[1] = rmin[1];
9704 fYbuf[1] = rmax[1];
9705 fXbuf[2] = rmin[2];
9706 fYbuf[2] = rmax[2];
9707 fH->SetMaximum(rmax[2]);
9708 fH->SetMinimum(rmin[2]);
9709 fH->GetXaxis()->SetRangeUser(rmin[0],rmax[0]);
9710 fH->GetYaxis()->SetRangeUser(rmin[1],rmax[1]);
9711 } else {
9712 fXbuf[0] = Hparam.xmin;
9713 fYbuf[0] = Hparam.xmax;
9714 fXbuf[1] = Hparam.ymin;
9715 fYbuf[1] = Hparam.ymax;
9716 fXbuf[2] = Hparam.zmin;
9717 fYbuf[2] = Hparam.zmax;
9718 }
9719
9720 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
9721 TView *view = gPad ? gPad->GetView() : nullptr;
9722 if (!view) {
9723 Error("PaintTriangles", "no TView in current pad");
9724 return;
9725 }
9726 Double_t thedeg = 90 - gPad->GetTheta();
9727 Double_t phideg = -90 - gPad->GetPhi();
9728 Double_t psideg = view->GetPsi();
9729 Int_t irep;
9730 view->SetView(phideg, thedeg, psideg, irep);
9731
9732 // Set color/style for back box
9733 fLego->SetFillStyle(gPad->GetFrameFillStyle());
9734 fLego->SetFillColor(gPad->GetFrameFillColor());
9735 fLego->TAttFill::Modify();
9736 Int_t backcolor = gPad->GetFrameFillColor();
9737 if (Hoption.System != kCARTESIAN) backcolor = 0;
9738 view->PadRange(backcolor);
9739 fLego->SetFillStyle(fH->GetFillStyle());
9740 fLego->SetFillColor(fH->GetFillColor());
9741 fLego->TAttFill::Modify();
9742
9743 // Paint the Back Box if needed
9744 if (Hoption.BackBox && !Hoption.Same) {
9745 fLego->InitMoveScreen(-1.1,1.1);
9746 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9748 fLego->BackBox(90);
9749 }
9750
9751 // Paint the triangles
9752 fGraph2DPainter->Paint(option);
9753
9754 // Paint the Front Box if needed
9755 if (Hoption.FrontBox) {
9756 fLego->InitMoveScreen(-1.1,1.1);
9758 fLego->FrontBox(90);
9759 }
9760
9761 // Paint the Axis if needed
9762 if (!Hoption.Axis && !Hoption.Same) {
9763 TGaxis axis;
9764 PaintLegoAxis(&axis, 90);
9765 }
9766
9768
9769 fLego.reset();
9770}
9771
9772////////////////////////////////////////////////////////////////////////////////
9773/// Define the color levels used to paint legos, surfaces etc..
9774
9776{
9777
9778 Int_t i, irep;
9779
9780 // Initialize the color levels
9781 if (ndivz >= 100) {
9782 Warning("PaintSurface", "too many color levels, %d >= 100, reset to 99", ndivz);
9783 ndivz = 99;
9784 }
9785 std::vector<Double_t> funlevel(ndivz+1);
9786 std::vector<Int_t> colorlevel(ndivz+1);
9789 for (i = 0; i < ndivz; ++i) {
9791 theColor = Int_t((i+0.99)*Float_t(ncolors)/Float_t(ndivz));
9793 }
9795 fLego->ColorFunction(ndivz, funlevel.data(), colorlevel.data(), irep);
9796}
9797
9798////////////////////////////////////////////////////////////////////////////////
9799/// [Control function to draw 2D/3D histograms (tables).](\ref HP01c)
9800
9802{
9803
9804 // Fill Hparam structure with histo parameters
9805 if (!TableInit()) return;
9806
9807 // Draw histogram frame
9808 PaintFrame();
9809
9810 // If palette option not specified, delete a possible existing palette
9811 if (!Hoption.Zscale) {
9812 TObject *palette = fFunctions->FindObject("palette");
9813 if (palette) { fFunctions->Remove(palette); delete palette;}
9814 }
9815
9816 // Do not draw the histogram. Only the attached functions will be drawn.
9817 if (Hoption.Func == 2) {
9818 if (Hoption.Zscale) {
9819 Int_t ndiv = fH->GetContour();
9820 if (ndiv == 0 ) {
9821 ndiv = gStyle->GetNumberContours();
9822 fH->SetContour(ndiv);
9823 }
9824 PaintPalette();
9825 }
9826
9827 // Draw the histogram according to the option
9828 } else {
9829 if (fH->InheritsFrom(TH2Poly::Class()) && Hoption.Axis<=0) {
9830 if (Hoption.Fill) PaintTH2PolyBins("f");
9834 if (Hoption.Line) PaintTH2PolyBins("l");
9835 if (Hoption.Mark) PaintTH2PolyBins("P");
9836 } else if (Hoption.Axis<=0) {
9840 if (Hoption.Color) {
9843 }
9846 if (Hoption.Error >= 100) Paint2DErrors(option);
9848 }
9852 }
9853
9854 // Draw histogram title
9855 PaintTitle();
9856
9857 // Draw the axes
9858 if (!Hoption.Lego && !Hoption.Surf &&
9859 !Hoption.Tri && !(Hoption.Error >= 100)) PaintAxis(kFALSE);
9860
9861 TF1 *fit = nullptr;
9862 TIter next(fFunctions);
9863 while (auto obj = next()) {
9864 if (obj->InheritsFrom(TF1::Class())) {
9865 fit = (TF1*)obj;
9866 break;
9867 }
9868 }
9869 if ((Hoption.Same%10) != 1) {
9870 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
9871 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
9872 //ALWAYS executed on non-iOS platform.
9873 //On iOS, depends on mode.
9875 }
9876 }
9877 }
9878}
9879
9880////////////////////////////////////////////////////////////////////////////////
9881/// Control function to draw a TH2Poly bins' contours.
9882///
9883/// - option = "F" draw the bins as filled areas.
9884/// - option = "L" draw the bins as line.
9885/// - option = "P" draw the bins as markers.
9886
9888{
9889
9890 //Do not highlight the histogram, if its part was picked.
9891 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH) return;
9892
9893 TString opt = option;
9894 opt.ToLower();
9895 Bool_t line = kFALSE;
9896 Bool_t fill = kFALSE;
9897 Bool_t mark = kFALSE;
9898 if (opt.Contains("l")) line = kTRUE;
9899 if (opt.Contains("f")) fill = kTRUE;
9900 if (opt.Contains("p")) mark = kTRUE;
9901
9902 TH2PolyBin *b;
9903 Double_t z;
9904
9905 TIter next(((TH2Poly*)fH)->GetBins());
9906 TObject *obj, *poly;
9907
9908 while ((obj=next())) {
9909 b = (TH2PolyBin*)obj;
9910 z = b->GetContent();
9911 if (z==0 && Hoption.Zero) continue; // Do not draw empty bins in case of option "COL0 L"
9912 poly = b->GetPolygon();
9913
9914 // Paint the TGraph bins.
9915 if (poly->IsA() == TGraph::Class()) {
9916 TGraph *g = (TGraph*)poly;
9917 g->TAttLine::Modify();
9918 g->TAttMarker::Modify();
9919 g->TAttFill::Modify();
9920 if (line) {
9921 Int_t fs = g->GetFillStyle();
9923 g->SetFillStyle(0);
9925 g->Paint("F");
9927 g->SetFillStyle(fs);
9928 }
9929 if (fill) g->Paint("F");
9930 if (mark) g->Paint("P");
9931 }
9932
9933 // Paint the TMultiGraph bins.
9934 if (poly->IsA() == TMultiGraph::Class()) {
9936 TList *gl = mg->GetListOfGraphs();
9937 if (!gl) return;
9938 TGraph *g;
9939 TIter nextg(gl);
9940 while ((g = (TGraph*) nextg())) {
9941 g->TAttLine::Modify();
9942 g->TAttMarker::Modify();
9943 g->TAttFill::Modify();
9944 if (line) {
9945 Int_t fs = g->GetFillStyle();
9947 g->SetFillStyle(0);
9949 g->Paint("F");
9951 g->SetFillStyle(fs);
9952 }
9953 if (fill) g->Paint("F");
9954 if (mark) g->Paint("P");
9955 }
9956 }
9957 }
9958}
9959
9960////////////////////////////////////////////////////////////////////////////////
9961/// [Control function to draw a TH2Poly as a color plot.](\ref HP20a)
9962
9964{
9965
9966 //Do not highlight the histogram, if its part was picked.
9967 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
9968 return;
9969
9970 Int_t ncolors, color, theColor;
9971 Double_t z, zc;
9972 Double_t zmin = fH->GetMinimum();
9973 Double_t zmax = fH->GetMaximum();
9974 if (Hoption.Logz) {
9975 if (zmax > 0) {
9976 if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
9977 zmin = TMath::Log10(zmin);
9978 zmax = TMath::Log10(zmax);
9979 } else {
9980 return;
9981 }
9982 }
9983 Double_t dz = zmax - zmin;
9984
9985 // Initialize the levels on the Z axis
9987 Int_t ndiv = fH->GetContour();
9988 if (ndiv == 0 ) {
9989 ndiv = gStyle->GetNumberContours();
9990 fH->SetContour(ndiv);
9991 }
9992 Int_t ndivz = TMath::Abs(ndiv);
9993 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
9995
9996 TIter next(((TH2Poly*)fH)->GetBins());
9997
9998 while (auto obj = next()) {
9999 TH2PolyBin *b = (TH2PolyBin*)obj;
10000 TObject *poly = b->GetPolygon();
10001
10002 z = b->GetContent();
10003 if (z==0 && Hoption.Zero) continue;
10004 if (Hoption.Logz) {
10005 if (z > 0) z = TMath::Log10(z);
10006 else z = zmin;
10007 }
10008 if (z < zmin) continue;
10009
10010 // Define the bin color.
10012 zc = fH->GetContourLevelPad(0);
10013 if (z < zc) continue;
10014 color = -1;
10015 for (Int_t k=0; k<ndiv; k++) {
10016 zc = fH->GetContourLevelPad(k);
10017 if (z < zc) {
10018 continue;
10019 } else {
10020 color++;
10021 }
10022 }
10023 } else {
10024 color = Int_t(0.01+(z-zmin)*scale);
10025 }
10026 theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
10027 if (theColor > ncolors-1) theColor = ncolors-1;
10028
10030
10031 // Paint the TGraph bins.
10032 if (poly->IsA() == TGraph::Class()) {
10033 TGraph *g = (TGraph*)poly;
10034 auto origin = g->GetFillColor();
10035 g->SetFillColor(rootColor);
10036 g->TAttFill::Modify();
10037 g->Paint("F");
10038 g->SetFillColor(origin);
10039 }
10040
10041 // Paint the TMultiGraph bins.
10042 if (poly->IsA() == TMultiGraph::Class()) {
10045 while (auto g = (TGraph*) nextg()) {
10046 auto origin = g->GetFillColor();
10047 g->SetFillColor(rootColor);
10048 g->TAttFill::Modify();
10049 g->Paint("F");
10050 g->SetFillColor(origin);
10051 }
10052 }
10053 }
10055}
10056
10057////////////////////////////////////////////////////////////////////////////////
10058/// [Control function to draw a TH2Poly as a scatter plot.](\ref HP20a)
10059
10061{
10062
10063 //Do not highlight the histogram, if its part was selected.
10064 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
10065 return;
10066
10067 Int_t k, loop, marker=0;
10068 Double_t z, xk,xstep, yk, ystep, xp, yp;
10069 Double_t scale = 1;
10070 Double_t zmin = fH->GetMinimum();
10071 Double_t zmax = fH->GetMaximum();
10072 if (Hoption.Logz) {
10073 if (zmax > 0) {
10074 if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
10075 zmin = TMath::Log10(zmin);
10076 zmax = TMath::Log10(zmax);
10077 } else {
10078 return;
10079 }
10080 }
10081 Double_t dz = zmax - zmin;
10082 scale = (kNMAX-1)/dz;
10083
10084
10085 // use an independent instance of a random generator
10086 // instead of gRandom to avoid conflicts and
10087 // to get same random numbers when drawing the same histogram
10089
10090 TH2PolyBin *b;
10091
10092 TIter next(((TH2Poly*)fH)->GetBins());
10093 TObject *obj, *poly;
10094
10095 Double_t maxarea = 0, a;
10096 while ((obj=next())) {
10097 b = (TH2PolyBin*)obj;
10098 a = b->GetArea();
10099 if (a>maxarea) maxarea = a;
10100 }
10101
10102 next.Reset();
10103
10104 while ((obj=next())) {
10105 b = (TH2PolyBin*)obj;
10106 poly = b->GetPolygon();
10107 z = b->GetContent();
10108 if (z < zmin) z = zmin;
10109 if (z > zmax) z = zmax;
10110 if (Hoption.Logz) {
10111 if (z > 0) z = TMath::Log10(z) - zmin;
10112 } else {
10113 z -= zmin;
10114 }
10115 k = Int_t((z*scale)*(b->GetArea()/maxarea));
10116 xk = b->GetXMin();
10117 yk = b->GetYMin();
10118 xstep = b->GetXMax()-xk;
10119 ystep = b->GetYMax()-yk;
10120
10121 // Paint the TGraph bins.
10122 if (poly->IsA() == TGraph::Class()) {
10123 TGraph *g = (TGraph*)poly;
10124 if (k <= 0 || z <= 0) continue;
10125 loop = 0;
10126 while (loop<k) {
10127 if (k+marker >= kNMAX) {
10128 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10129 marker=0;
10130 }
10131 xp = (random.Rndm()*xstep) + xk;
10132 yp = (random.Rndm()*ystep) + yk;
10133 if (g->IsInside(xp,yp)) {
10134 fXbuf[marker] = xp;
10135 fYbuf[marker] = yp;
10136 marker++;
10137 loop++;
10138 }
10139 }
10140 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10141 }
10142
10143 // Paint the TMultiGraph bins.
10144 if (poly->IsA() == TMultiGraph::Class()) {
10146 TList *gl = mg->GetListOfGraphs();
10147 if (!gl) return;
10148 if (k <= 0 || z <= 0) continue;
10149 loop = 0;
10150 while (loop<k) {
10151 if (k+marker >= kNMAX) {
10152 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10153 marker=0;
10154 }
10155 xp = (random.Rndm()*xstep) + xk;
10156 yp = (random.Rndm()*ystep) + yk;
10157 if (mg->IsInside(xp,yp)) {
10158 fXbuf[marker] = xp;
10159 fYbuf[marker] = yp;
10160 marker++;
10161 loop++;
10162 }
10163 }
10164 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10165 }
10166 }
10167 PaintTH2PolyBins("l");
10168}
10169
10170////////////////////////////////////////////////////////////////////////////////
10171/// [Control function to draw a TH2Poly as a text plot.](\ref HP20a)
10172
10174{
10175
10176 TLatex text;
10177 text.SetTextFont(gStyle->GetTextFont());
10178 text.SetTextColor(fH->GetMarkerColor());
10179 text.SetTextSize(0.02*fH->GetMarkerSize());
10180
10181 Double_t x, y, z, e, angle = 0;
10182 TString tt, tf;
10183 tf.Form("%s%s","%",gStyle->GetPaintTextFormat());
10184 if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
10185 Int_t opt = (Int_t)Hoption.Text/1000;
10186
10187 text.SetTextAlign(22);
10188 if (Hoption.Text == 1) angle = 0;
10189 text.SetTextAngle(angle);
10190 text.TAttText::Modify();
10191
10192 TH2PolyBin *b;
10193
10194 TIter next(((TH2Poly*)fH)->GetBins());
10195 TObject *obj, *p;
10196
10197 while ((obj=next())) {
10198 b = (TH2PolyBin*)obj;
10199 p = b->GetPolygon();
10200 x = (b->GetXMin()+b->GetXMax())/2;
10201 if (Hoption.Logx) {
10202 if (x > 0) x = TMath::Log10(x);
10203 else continue;
10204 }
10205 y = (b->GetYMin()+b->GetYMax())/2;
10206 if (Hoption.Logy) {
10207 if (y > 0) y = TMath::Log10(y);
10208 else continue;
10209 }
10210 z = b->GetContent();
10211 if (z < fH->GetMinimum() || (z == 0 && !Hoption.MinimumZero)) continue;
10212 if (opt==2) {
10213 e = fH->GetBinError(b->GetBinNumber());
10214 tf.Form("#splitline{%s%s}{#pm %s%s}",
10216 "%",gStyle->GetPaintTextFormat());
10217 tt.Form(tf.Data(),z,e);
10218 } else {
10219 tt.Form(tf.Data(),z);
10220 }
10221 if (opt==3) text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),p->GetName());
10222 else text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),tt.Data());
10223 }
10224
10225 PaintTH2PolyBins("l");
10226}
10227
10228////////////////////////////////////////////////////////////////////////////////
10229/// [Control function to draw a 1D/2D histograms with the bin values.](\ref HP15)
10230
10232{
10233
10234 TLatex text;
10235 text.SetTextFont(((int)gStyle->GetTextFont()/10)*10+2); // font precision must be 2
10236 text.SetTextColor(fH->GetMarkerColor());
10237 text.SetTextSize(0.02*fH->GetMarkerSize());
10238
10239 Double_t x, y, z, e, angle = 0;
10240 TString tt, tf;
10241 tf.Form("%s%s","%",gStyle->GetPaintTextFormat());
10242 if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
10243
10244 // 1D histograms
10245 if (fH->GetDimension() == 1) {
10247 Double_t yt;
10248 TProfile *hp = (TProfile*)fH;
10249 if (Hoption.Text>2000 && fH->InheritsFrom(TProfile::Class())) {
10250 Hoption.Text = Hoption.Text-2000;
10251 getentries = kTRUE;
10252 }
10253 if (Hoption.Text == 1) angle = 90;
10254 text.SetTextAlign(11);
10255 if (angle == 90) text.SetTextAlign(12);
10256 if (angle == 0) text.SetTextAlign(21);
10257 text.TAttText::Modify();
10258 Double_t dt = 0.02*(gPad->GetY2()-gPad->GetY1());
10259 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10260 if (Hoption.Bar) {
10261 x = fH->GetXaxis()->GetBinLowEdge(i)+
10262 fH->GetXaxis()->GetBinWidth(i)*
10263 (fH->GetBarOffset()+0.5*fH->GetBarWidth());
10264 } else {
10265 x = fH->GetXaxis()->GetBinCenter(i);
10266 }
10267 y = fH->GetBinContent(i);
10268 yt = y;
10269 if (Hoption.MinimumZero && y<0) y = 0;
10270 if (getentries) yt = hp->GetBinEntries(i);
10271 if (yt == 0.) continue;
10272 tt.Form(tf.Data(),yt);
10273 if (Hoption.Logx) {
10274 if (x > 0) x = TMath::Log10(x);
10275 else continue;
10276 }
10277 if (Hoption.Logy) {
10278 if (y > 0) y = TMath::Log10(y);
10279 else continue;
10280 }
10281 if (y >= gPad->GetY2()) continue;
10282 if (y <= gPad->GetY1()) continue;
10283 text.PaintLatex(x,y+0.2*dt,angle,0.02*fH->GetMarkerSize(),tt.Data());
10284 }
10285
10286 // 2D histograms
10287 } else {
10288 Double_t zmin = Hparam.zmin;
10289 if (Hoption.Logz) zmin = TMath::Power(10,Hparam.zmin);
10290
10291 text.SetTextAlign(22);
10292 if (Hoption.Text == 1) angle = 0;
10293 text.SetTextAngle(angle);
10294 text.TAttText::Modify();
10295 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
10296 y = fYaxis->GetBinCenter(j);
10297 if (Hoption.Logy) {
10298 if (y > 0) y = TMath::Log10(y);
10299 else continue;
10300 }
10301 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10302 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
10303 x = fXaxis->GetBinCenter(i);
10304 if (Hoption.Logx) {
10305 if (x > 0) x = TMath::Log10(x);
10306 else continue;
10307 }
10308 if (!IsInside(x,y)) continue;
10309 z = fH->GetBinContent(bin);
10310 if (z < zmin || (z == 0 && !Hoption.MinimumZero)) continue;
10311 if (Hoption.Text>2000) {
10312 e = fH->GetBinError(bin);
10313 tf.Form("#splitline{%s%s}{#pm %s%s}",
10315 "%",gStyle->GetPaintTextFormat());
10316 tt.Form(tf.Data(),z,e);
10317 } else {
10318 tt.Form(tf.Data(),z);
10319 }
10320 text.PaintLatex(x,y+fH->GetBarOffset()*fYaxis->GetBinWidth(j),
10321 angle,0.02*fH->GetMarkerSize(),tt.Data());
10322 }
10323 }
10324 }
10325}
10326
10327////////////////////////////////////////////////////////////////////////////////
10328/// [Control function to draw a 3D implicit functions.](\ref HP27)
10329
10331{
10332
10333 Int_t irep;
10334
10335 TAxis *xaxis = fH->GetXaxis();
10336 TAxis *yaxis = fH->GetYaxis();
10337 TAxis *zaxis = fH->GetZaxis();
10338
10339 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
10340 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
10341 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
10342 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
10343 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
10344 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
10345
10346 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
10347
10348 TView *view = gPad ? gPad->GetView() : nullptr;
10349 if (!view) {
10350 Error("PaintTF3", "no TView in current pad");
10351 return;
10352 }
10353 Double_t thedeg = 90 - gPad->GetTheta();
10354 Double_t phideg = -90 - gPad->GetPhi();
10355 Double_t psideg = view->GetPsi();
10356 view->SetView(phideg, thedeg, psideg, irep);
10357
10358 fLego->InitMoveScreen(-1.1,1.1);
10359
10360 if (Hoption.BackBox) {
10361 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
10363 fLego->BackBox(90);
10364 }
10365
10367
10368 fLego->ImplicitFunction(fCurrentF3, fXbuf.data(), fYbuf.data(), fH->GetNbinsX(),
10369 fH->GetNbinsY(),
10370 fH->GetNbinsZ(), "BF");
10371
10372 if (Hoption.FrontBox) {
10373 fLego->InitMoveScreen(-1.1,1.1);
10375 fLego->FrontBox(90);
10376 }
10377 if (!Hoption.Axis && !Hoption.Same) {
10378 TGaxis axis;
10379 PaintLegoAxis(&axis, 90);
10380 }
10381
10382 PaintTitle();
10383
10384 fLego.reset();
10385}
10386
10387/////////////////////////////////////////////////////////////new TGaxis///////////////////
10388/// Draw the histogram title
10389///
10390/// The title is drawn according to the title alignment returned by
10391/// `GetTitleAlign()`. It is a 2 digits integer): hv
10392///
10393/// where `h` is the horizontal alignment and `v` is the
10394/// vertical alignment.
10395///
10396/// - `h` can get the values 1 2 3 for left, center, and right
10397/// - `v` can get the values 1 2 3 for bottom, middle and top
10398///
10399/// for instance the default alignment is: 13 (left top)
10400
10402{
10403 // probably best place for calls PaintHighlightBin
10404 // calls after paint histo (1D or 2D) and before paint title and stats
10405 if (!gPad->GetView()) PaintHighlightBin();
10406
10407 if (Hoption.Same) return;
10408 if (fH->TestBit(TH1::kNoTitle)) return;
10409 Int_t nt = strlen(fH->GetTitle());
10410 TPaveText *title = nullptr;
10411 TObject *obj;
10412 TIter next(gPad->GetListOfPrimitives());
10413 while ((obj = next())) {
10414 if (!obj->InheritsFrom(TPaveText::Class())) continue;
10415 title = (TPaveText*)obj;
10416 if (strcmp(title->GetName(),"title")) {title = nullptr; continue;}
10417 break;
10418 }
10419 if (nt == 0 || gStyle->GetOptTitle() <= 0) {
10420 if (title) delete title;
10421 return;
10422 }
10425
10426 if (ht <= 0) {
10427 if (gStyle->GetTitleFont("")%10 == 3) {
10428 Double_t hw = (Double_t) TMath::Max(gPad->GetPadWidth(), gPad->GetPadHeight());
10429 if (hw > 0)
10430 ht = 1.1 * (gStyle->GetTitleSize("")/hw);
10431 } else {
10432 ht = 1.1*gStyle->GetTitleFontSize();
10433 }
10434 }
10435 if (ht <= 0) ht = 0.05;
10436 if (wt <= 0) {
10437 TLatex l;
10438 l.SetTextSize(ht);
10439 l.SetTitle(fH->GetTitle());
10440 // adjustment in case the title has several lines (#splitline)
10441 ht = TMath::Max(ht, 1.2*l.GetYsize()/(gPad->GetY2() - gPad->GetY1()));
10442 Double_t wndc = l.GetXsize()/(gPad->GetX2() - gPad->GetX1());
10443 wt = TMath::Min(0.7, 0.02+wndc);
10444 }
10445 if (title) {
10446 TText *t0 = (TText*)title->GetLine(0);
10447 if (t0) {
10448 if (!strcmp(t0->GetTitle(),fH->GetTitle())) return;
10449 t0->SetTitle(fH->GetTitle());
10450 if (wt > 0) title->SetX2NDC(title->GetX1NDC()+wt);
10451 }
10452 return;
10453 }
10454
10456 if (talh < 1) talh = 1; else if (talh > 3) talh = 3;
10458 if (talv < 1) talv = 1; else if (talv > 3) talv = 3;
10460 xpos = gStyle->GetTitleX();
10461 ypos = gStyle->GetTitleY();
10462 if (talh == 2) xpos = xpos-wt/2.;
10463 if (talh == 3) xpos = xpos-wt;
10464 if (talv == 2) ypos = ypos+ht/2.;
10465 if (talv == 1) ypos = ypos+ht;
10466
10467 TPaveText *ptitle = new TPaveText(xpos, ypos-ht, xpos+wt, ypos,"blNDC");
10468
10469 // box with the histogram title
10470 ptitle->SetFillColor(gStyle->GetTitleFillColor());
10471 ptitle->SetFillStyle(gStyle->GetTitleStyle());
10472 ptitle->SetName("title");
10473 ptitle->SetBorderSize(gStyle->GetTitleBorderSize());
10474 ptitle->SetTextColor(gStyle->GetTitleTextColor());
10475 ptitle->SetTextFont(gStyle->GetTitleFont(""));
10476 if (gStyle->GetTitleFont("")%10 > 2)
10477 ptitle->SetTextSize(gStyle->GetTitleFontSize());
10478 ptitle->AddText(fH->GetTitle());
10479 ptitle->SetBit(kCanDelete);
10480 ptitle->Draw();
10481 ptitle->Paint("blNDC");
10482
10483 if(!gPad->IsEditable()) delete ptitle;
10484}
10485
10486////////////////////////////////////////////////////////////////////////////////
10487/// Process message `mess`.
10488
10489void THistPainter::ProcessMessage(const char *mess, const TObject *obj)
10490{
10491 if (!strcmp(mess,"SetF3")) {
10492 fCurrentF3 = (TF3 *)obj;
10493 }
10494}
10495
10496////////////////////////////////////////////////////////////////////////////////
10497/// Static function.
10498///
10499/// Convert Right Ascension, Declination to X,Y using an AITOFF projection.
10500/// This procedure can be used to create an all-sky map in Galactic
10501/// coordinates with an equal-area Aitoff projection. Output map
10502/// coordinates are zero longitude centered.
10503/// Also called Hammer-Aitoff projection (first presented by Ernst von Hammer in 1892)
10504///
10505/// source: GMT
10506///
10507/// code from Ernst-Jan Buis
10508
10510{
10511
10512 Double_t x, y;
10513
10515 Double_t delta = b*TMath::DegToRad();
10516 Double_t r2 = TMath::Sqrt(2.);
10517 Double_t f = 2*r2/TMath::Pi();
10518 Double_t cdec = TMath::Cos(delta);
10521 y = TMath::Sin(delta)*r2/denom;
10522 x *= TMath::RadToDeg()/f;
10523 y *= TMath::RadToDeg()/f;
10524 // x *= -1.; // for a skymap swap left<->right
10525 Al = x;
10526 Ab = y;
10527
10528 return 0;
10529}
10530
10531////////////////////////////////////////////////////////////////////////////////
10532/// Static function
10533///
10534/// Probably the most famous of the various map projections, the Mercator projection
10535/// takes its name from Mercator who presented it in 1569. It is a cylindrical, conformal projection
10536/// with no distortion along the equator.
10537/// The Mercator projection has been used extensively for world maps in which the distortion towards
10538/// the polar regions grows rather large, thus incorrectly giving the impression that, for example,
10539/// Greenland is larger than South America. In reality, the latter is about eight times the size of
10540/// Greenland. Also, the Former Soviet Union looks much bigger than Africa or South America. One may wonder
10541/// whether this illusion has had any influence on U.S. foreign policy.' (Source: GMT)
10542/// code from Ernst-Jan Buis
10543
10545{
10546
10547 Al = l;
10549 Ab = TMath::Log(aid);
10550 return 0;
10551}
10552
10553////////////////////////////////////////////////////////////////////////////////
10554/// Static function code for sinusoidal projection
10555/// from Ernst-Jan Buis
10556/// Source https://en.wikipedia.org/wiki/Sinusoidal_projection
10557
10559{
10560
10561 Al = l*cos(b*TMath::DegToRad());
10562 Ab = b;
10563 return 0;
10564}
10565
10566////////////////////////////////////////////////////////////////////////////////
10567/// Static function code for parabolic projection
10568/// from Ernst-Jan Buis
10569
10571{
10572
10573 Al = l*(2.*TMath::Cos(2*b*TMath::DegToRad()/3) - 1);
10574 Ab = 180*TMath::Sin(b*TMath::DegToRad()/3);
10575 return 0;
10576}
10577
10578////////////////////////////////////////////////////////////////////////////////
10579/// Static function.
10580///
10581/// Convert Right Ascension, Declination to X,Y using an MOLLWEIDE projection.
10582/// This procedure can be used to create an all-sky map in Galactic
10583/// coordinates with an equal-area Mollweide projection. Output map
10584/// coordinates are zero longitude centered.
10585/// It is also known as the Babinet projection, homalographic projection, homolographic projection, and elliptical projection.
10586/// Source: https://en.wikipedia.org/wiki/Mollweide_projection
10587///
10588/// code from Marco Meyer-Conde
10589
10591{
10592
10593 Double_t theta0 = b * TMath::DegToRad(), theta = theta0;
10594
10595 for (int i = 0; i < 100; i++) {
10596 Double_t num = 2 * theta + TMath::Sin(2 * theta) - TMath::Pi() * TMath::Sin(theta0);
10597 Double_t den = 4 * TMath::Power(TMath::Cos(theta), 2);
10598
10599 if (den < 1e-20) {
10600 theta = theta0;
10601 break;
10602 }
10603
10604 theta -= num / den;
10605
10606 if (TMath::Abs(num / den) < 1e-4) break;
10607 }
10608
10609 Al = l * TMath::Cos(theta);
10610 Ab = 90 * TMath::Sin(theta);
10611
10612 return 0;
10613}
10614
10615////////////////////////////////////////////////////////////////////////////////
10616/// Recompute the histogram range following graphics operations.
10617
10619{
10620
10621 if (Hoption.Same) return;
10622
10623 // Compute x,y range
10625 xmax = Hparam.xmax,
10626 ymin = Hparam.ymin,
10627 ymax = Hparam.ymax,
10628 xscale = 1;
10629
10630 std::function<Int_t(Double_t,Double_t,Double_t&,Double_t&)> func;
10631
10632 if (Hoption.Proj == 1) {
10633 func = ProjectAitoff2xy;
10634 xscale = 0.9999;
10635 } else if (Hoption.Proj == 2) {
10636 if (Hparam.ymin <= -90 || Hparam.ymax >= 90) {
10637 Warning("Mercator Projection", "Latitude out of range %f or %f", Hparam.ymin, Hparam.ymax);
10638 Hoption.Proj = 0;
10639 } else {
10642 }
10643 } else if (Hoption.Proj == 3) {
10644 func = ProjectSinusoidal2xy;
10645 } else if (Hoption.Proj == 4) {
10646 func = ProjectParabolic2xy;
10647 } else if (Hoption.Proj == 5) {
10648 func = ProjectMollweide2xy;
10649 }
10650
10651 if (func) {
10653
10657 func(Hparam.xmax, Hparam.ymin, xmax, ymin);
10658
10659 if (xmin > xmin_aid) xmin = xmin_aid;
10660 if (ymin > ymin_aid) ymin = ymin_aid;
10661 if (xmax < xmax_aid) xmax = xmax_aid;
10662 if (ymax < ymax_aid) ymax = ymax_aid;
10663 if (Hparam.ymin < 0 && Hparam.ymax > 0) {
10664 // there is an 'equator', check its range in the plot..
10665 func(Hparam.xmin*xscale, 0, xmin_aid, ymin_aid);
10666 func(Hparam.xmax*xscale, 0, xmax_aid, ymin_aid);
10667 if (xmin > xmin_aid) xmin = xmin_aid;
10668 if (xmax < xmax_aid) xmax = xmax_aid;
10669 }
10670 if (Hparam.xmin < 0 && Hparam.xmax > 0) {
10671 func(0, Hparam.ymin, xmin_aid, ymin_aid);
10672 func(0, Hparam.ymax, xmax_aid, ymax_aid);
10673 if (ymin > ymin_aid) ymin = ymin_aid;
10674 if (ymax < ymax_aid) ymax = ymax_aid;
10675 }
10676 }
10677
10678 Hparam.xmin = xmin;
10679 Hparam.xmax = xmax;
10680 Hparam.ymin = ymin;
10681 Hparam.ymax = ymax;
10682
10683 Double_t dx = xmax-xmin;
10684 Double_t dy = ymax-ymin;
10685 Double_t dxr = dx/(1 - gPad->GetLeftMargin() - gPad->GetRightMargin());
10686 Double_t dyr = dy/(1 - gPad->GetBottomMargin() - gPad->GetTopMargin());
10687
10688 // Range() could change the size of the pad pixmap and therefore should
10689 // be called before the other paint routines
10690 gPad->Range(xmin - dxr*gPad->GetLeftMargin(),
10691 ymin - dyr*gPad->GetBottomMargin(),
10692 xmax + dxr*gPad->GetRightMargin(),
10693 ymax + dyr*gPad->GetTopMargin());
10694 gPad->RangeAxis(xmin, ymin, xmax, ymax);
10695}
10696
10697////////////////////////////////////////////////////////////////////////////////
10698/// Set current histogram to `h`
10699
10701{
10702
10703 if (h == nullptr) return;
10704 fH = h;
10705 fXaxis = h->GetXaxis();
10706 fYaxis = h->GetYaxis();
10707 fZaxis = h->GetZaxis();
10709}
10710
10711////////////////////////////////////////////////////////////////////////////////
10712/// Initialize various options to draw 2D histograms.
10713
10715{
10716
10717 static const char *where = "TableInit";
10718
10719 Int_t first, last;
10721 Double_t zmin, zmax;
10722 Int_t maximum = 0;
10723 Int_t minimum = 0;
10724 if (fH->GetMaximumStored() != -1111) maximum = 1;
10725 if (fH->GetMinimumStored() != -1111) minimum = 1;
10726
10727 // ----------------- Compute X axis parameters
10728 first = fXaxis->GetFirst();
10729 last = fXaxis->GetLast();
10730 Hparam.xlast = last;
10731 Hparam.xfirst = first;
10736
10737 // if log scale in X, replace xmin,max by the log
10738 if (Hoption.Logx) {
10739 // find the first edge of a bin that is > 0
10740 if (Hparam.xlowedge <=0 ) {
10743 }
10744 if (Hparam.xmin <=0 || Hparam.xmax <=0) {
10745 Error(where, "cannot set X axis to log scale");
10746 return 0;
10747 }
10749 if (Hparam.xfirst < first) Hparam.xfirst = first;
10751 if (Hparam.xlast > last) Hparam.xlast = last;
10754 }
10755
10756 // ----------------- Compute Y axis parameters
10757 first = fYaxis->GetFirst();
10758 last = fYaxis->GetLast();
10759 Hparam.ylast = last;
10760 Hparam.yfirst = first;
10763 if (!Hparam.ybinsize) Hparam.ybinsize = 1;
10766
10767 // if log scale in Y, replace ymin,max by the log
10768 if (Hoption.Logy) {
10769 if (Hparam.ylowedge <=0 ) {
10772 }
10773 if (Hparam.ymin <=0 || Hparam.ymax <=0) {
10774 Error(where, "cannot set Y axis to log scale");
10775 return 0;
10776 }
10778 if (Hparam.yfirst < first) Hparam.yfirst = first;
10780 if (Hparam.ylast > last) Hparam.ylast = last;
10783 }
10784
10785
10786 // ----------------- Compute Z axis parameters
10787 Double_t bigp = TMath::Power(10,32);
10788 zmax = -bigp;
10789 zmin = bigp;
10790 Double_t c1, e1;
10791 Double_t allchan = 0;
10792 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
10793 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10794 c1 = fH->GetBinContent(i,j);
10795 zmax = TMath::Max(zmax,c1);
10796 if (Hoption.Error) {
10797 e1 = fH->GetBinError(i,j);
10798 zmax = TMath::Max(zmax,c1+e1);
10799 }
10800 zmin = TMath::Min(zmin,c1);
10801 allchan += c1;
10802 }
10803 }
10804
10805 // Take into account maximum , minimum
10806
10807 if (maximum) zmax = fH->GetMaximumStored();
10808 if (minimum) zmin = fH->GetMinimumStored();
10809 if (Hoption.Logz && zmax < 0) {
10810 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10811 return 0;
10812 } else if (Hoption.Logz && zmin>=0 && zmax==0) { // empty histogram in log scale
10813 zmin = 0.01;
10814 zmax = 10.;
10815 }
10816 if (zmin >= zmax) {
10817 if (Hoption.Logz) {
10818 if (zmax > 0) zmin = 0.001*zmax;
10819 else {
10820 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10821 return 0;
10822 }
10823 }
10824 }
10825
10826 // take into account normalization factor
10827 Hparam.allchan = allchan;
10828 Double_t factor = allchan;
10829 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
10830 if (allchan) factor /= allchan;
10831 if (factor == 0) factor = 1;
10832 Hparam.factor = factor;
10833 zmax = factor*zmax;
10834 zmin = factor*zmin;
10835 c1 = zmax;
10836 if (TMath::Abs(zmin) > TMath::Abs(c1)) c1 = zmin;
10837
10838 // For log scales, histogram coordinates are log10(ymin) and
10839 // log10(ymax). Final adjustment (if not option "Same")
10840 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
10841 // Maximum and Minimum are not defined.
10842 if (Hoption.Logz) {
10843 if (zmin <= 0) {
10844 zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
10845 fH->SetMinimum(zmin);
10846 }
10847 zmin = TMath::Log10(zmin);
10848 if (!minimum) zmin += TMath::Log10(0.5);
10849 zmax = TMath::Log10(zmax);
10850 if (!maximum) zmax += TMath::Log10(2*(0.9/0.95));
10851 goto LZMIN;
10852 }
10853
10854 // final adjustment of YMAXI for linear scale (if not option "Same"):
10855 // decrease histogram height to MAX% of allowed height if HMAXIM
10856 // has not been called.
10857 // MAX% is the value in percent which has been set in HPLSET
10858 // (default is 90%).
10859 if (!maximum) {
10860 zmax += yMARGIN*(zmax-zmin);
10861 }
10862
10863 // final adjustment of ymin for linear scale.
10864 // if minimum is not set , then ymin is set to zero if >0
10865 // or to ymin - yMARGIN if <0.
10866 if (!minimum) {
10867 if (Hoption.MinimumZero) {
10868 if (zmin >= 0) zmin = 0;
10869 else zmin -= yMARGIN*(zmax-zmin);
10870 } else {
10871 Double_t dzmin = yMARGIN*(zmax-zmin);
10872 if (zmin >= 0 && (zmin-dzmin <= 0)) zmin = 0;
10873 else zmin -= dzmin;
10874 }
10875 }
10876
10877LZMIN:
10878 Hparam.zmin = zmin;
10879 Hparam.zmax = zmax;
10880
10881 // Set bar offset and width
10884
10885 return 1;
10886}
10887
10888////////////////////////////////////////////////////////////////////////////////
10889/// This function returns the best format to print the error value (e)
10890/// knowing the parameter value (v) and the format (f) used to print it.
10891
10893{
10894
10895 static TString ef;
10896 TString tf, tv;
10897
10898 // print v with the format f in tv.
10899 tf.Form("%s%s","%",f);
10900 tv.Form(tf.Data(),v);
10901
10902 // Analyse tv.
10903 int ie = tv.Index("e");
10904 int iE = tv.Index("E");
10905 int id = tv.Index(".");
10906
10907 // v has been printed with the exponent notation.
10908 // There is 2 cases, the exponent is positive or negative
10909 if (ie >= 0 || iE >= 0) {
10910 if (tv.Index("+") >= 0) {
10911 if (e < 1) {
10912 ef.Form("%s.1f","%");
10913 } else {
10914 if (ie >= 0) {
10915 ef.Form("%s.%de","%",ie-id-1);
10916 } else {
10917 ef.Form("%s.%dE","%",iE-id-1);
10918 }
10919 }
10920 } else {
10921 if (ie >= 0) {
10922 ef.Form("%s.%de","%",ie-id-1);
10923 } else {
10924 ef.Form("%s.%dE","%",iE-id-1);
10925 }
10926 }
10927
10928 // There is not '.' in tv. e will be printed with one decimal digit.
10929 } else if (id < 0) {
10930 ef.Form("%s.1f","%");
10931
10932 // There is a '.' in tv and no exponent notation. e's decimal part will
10933 // have the same number of digits as v's one.
10934 } else {
10935 ef.Form("%s.%df","%",tv.Length()-id-1);
10936 }
10937
10938 return ef.Data();
10939}
10940
10941////////////////////////////////////////////////////////////////////////////////
10942/// Set projection.
10943
10945{
10946 if (fShowProjection2) {
10947 auto name2 = TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2);
10948 auto c2 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name2.Data()));
10949 if (c2) c2->Close();
10950 fShowProjection2 = 0;
10951 }
10952 if (fShowProjection) {
10953 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10954 auto c1 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name1.Data()));
10955 if (c1) c1->Close();
10956 fShowProjection = 0;
10957 }
10958
10959 if (nbins <= 0) return;
10960
10961 TString opt = option;
10962 opt.ToLower();
10963 Int_t projection = 0;
10964 if (opt.Contains("x")) projection = 1;
10965 if (opt.Contains("y")) projection = 2;
10966 if (opt.Contains("z")) projection = 3;
10967 if (opt.Contains("xy")) projection = 4;
10968 if (opt.Contains("yx")) projection = 5;
10969 if (opt.Contains("xz")) projection = 6;
10970 if (opt.Contains("zx")) projection = 7;
10971 if (opt.Contains("yz")) projection = 8;
10972 if (opt.Contains("zy")) projection = 9;
10973 if (projection < 4) fShowOption = option+1;
10974 else fShowOption = option+2;
10976 fShowProjection2 = 0;
10977 gROOT->MakeDefCanvas();
10978 gPad->SetName(TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection).Data());
10979 gPad->SetGrid();
10980}
10981
10983{
10984 if (fShowProjection2) {
10985 auto name2 = TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2);
10986 auto c2 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name2.Data()));
10987 if (c2) c2->Close();
10988 fShowProjection2 = 0;
10989 }
10990 if (fShowProjection) {
10991 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10992 auto c1 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name1.Data()));
10993 if (c1) c1->Close();
10994 fShowProjection = 0;
10995 }
10996
10997 if ((nbinsX <= 0) || (nbinsY <= 0)) return;
10998
10999
11000 TString opt = option;
11001 opt.ToLower();
11002 Int_t projection = 0;
11003 if (opt.Contains("x")) projection = 1;
11004 if (opt.Contains("y")) projection = 2;
11005 if (opt.Contains("z")) projection = 3;
11006 if (opt.Contains("xy")) projection = 4;
11007 if (opt.Contains("yx")) projection = 5;
11008 if (opt.Contains("xz")) projection = 6;
11009 if (opt.Contains("zx")) projection = 7;
11010 if (opt.Contains("yz")) projection = 8;
11011 if (opt.Contains("zy")) projection = 9;
11012 if (projection < 4) fShowOption = option+1;
11013 else fShowOption = option+2;
11016 gROOT->MakeDefCanvas();
11017 gPad->SetName(TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection).Data());
11018 gPad->SetGrid();
11019 gROOT->MakeDefCanvas();
11020 gPad->SetName(TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2).Data());
11021 gPad->SetGrid();
11022}
11023
11024
11025////////////////////////////////////////////////////////////////////////////////
11026/// Show projection onto X.
11027
11029{
11030
11032 gPad->SetDoubleBuffer(0); // turn off double buffer mode
11033 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
11034
11035 // Erase old position and draw a line at current position
11036 static int pyold1 = 0;
11037 static int pyold2 = 0;
11038 float uxmin = gPad->GetUxmin();
11039 float uxmax = gPad->GetUxmax();
11040 int pxmin = gPad->XtoAbsPixel(uxmin);
11041 int pxmax = gPad->XtoAbsPixel(uxmax);
11042 Float_t upy = gPad->AbsPixeltoY(py);
11043 Float_t y = gPad->PadtoY(upy);
11044 Int_t biny1 = fH->GetYaxis()->FindBin(y);
11046 Int_t py1 = gPad->YtoAbsPixel(gPad->GetLogy() ? TMath::Log10(fH->GetYaxis()->GetBinLowEdge(biny1)) : fH->GetYaxis()->GetBinLowEdge(biny1));
11047 Int_t py2 = gPad->YtoAbsPixel(gPad->GetLogy() ? TMath::Log10(fH->GetYaxis()->GetBinUpEdge(biny2)) : fH->GetYaxis()->GetBinUpEdge(biny2));
11048
11050 gVirtualX->DrawBox(pxmin,py1,pxmax,py2,TVirtualX::kFilled);
11051 pyold1 = py1;
11052 pyold2 = py2;
11053
11054 // Create or set the new canvas proj x
11056 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
11057 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(name1.Data());
11058 if (c) {
11059 c->Clear();
11060 } else {
11061 fShowProjection = 0;
11062 fShowProjection2 = 0;
11063 pyold1 = 0;
11064 pyold2 = 0;
11065 return;
11066 }
11067 c->cd();
11068 c->SetLogy(ctxt.GetSaved()->GetLogz());
11069 c->SetLogx(ctxt.GetSaved()->GetLogx());
11070
11071 // Draw slice corresponding to mouse position
11072 TString prjName = TString::Format("slice_px_of_%s",fH->GetName());
11073 TH1D *hp = ((TH2*)fH)->ProjectionX(prjName, biny1, biny2);
11074 if (hp) {
11075 hp->SetFillColor(38);
11076 // apply a patch from Oliver Freyermuth to set the title in the projection
11077 // using the range of the projected Y values
11078 if (biny1 == biny2) {
11081 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11083 if (fH->GetYaxis()->GetLabels() != nullptr) {
11084 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf] %s", biny1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetYaxis()->GetBinLabel(biny1)));
11085 } else {
11086 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf]", biny1, valuePrecision, valueFrom, valuePrecision, valueTo));
11087 }
11088 } else {
11091 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11092 // biny1 is used here to get equal precision no matter how large the binrange is,
11093 // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
11095 if (fH->GetYaxis()->GetLabels() != nullptr) {
11096 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)));
11097 } else {
11098 hp->SetTitle(TString::Format("ProjectionX of biny=[%d,%d] [y=%.*lf..%.*lf]", biny1, biny2, valuePrecision, valueFrom, valuePrecision, valueTo));
11099 }
11100 }
11101 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11102 hp->SetYTitle(((TH2*)fH)->GetZaxis()->GetTitle() ? ((TH2*)fH)->GetZaxis()->GetTitle() : "Number of Entries");
11103 hp->Draw();
11104 c->Update();
11105 }
11106}
11107
11108////////////////////////////////////////////////////////////////////////////////
11109/// Show projection onto Y.
11110
11112{
11113
11115 if (fShowProjection2)
11117 gPad->SetDoubleBuffer(0); // turn off double buffer mode
11118 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
11119
11120 // Erase old position and draw a line at current position
11121 static int pxold1 = 0;
11122 static int pxold2 = 0;
11123 float uymin = gPad->GetUymin();
11124 float uymax = gPad->GetUymax();
11125 int pymin = gPad->YtoAbsPixel(uymin);
11126 int pymax = gPad->YtoAbsPixel(uymax);
11127 Float_t upx = gPad->AbsPixeltoX(px);
11128 Float_t x = gPad->PadtoX(upx);
11129 Int_t binx1 = fH->GetXaxis()->FindBin(x);
11131 Int_t px1 = gPad->XtoAbsPixel(gPad->GetLogx() ? TMath::Log10(fH->GetXaxis()->GetBinLowEdge(binx1)) : fH->GetXaxis()->GetBinLowEdge(binx1));
11132 Int_t px2 = gPad->XtoAbsPixel(gPad->GetLogx() ? TMath::Log10(fH->GetXaxis()->GetBinUpEdge(binx2)) : fH->GetXaxis()->GetBinUpEdge(binx2));
11133
11135 gVirtualX->DrawBox(px1,pymin,px2,pymax,TVirtualX::kFilled);
11136 pxold1 = px1;
11137 pxold2 = px2;
11138
11139 // Create or set the new canvas proj y
11141
11142 TString name2 = fShowProjection2 ? TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2)
11143 : TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
11144
11145 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(name2.Data());
11146 if (c) {
11147 c->Clear();
11148 } else {
11149 fShowProjection = 0;
11150 fShowProjection2 = 0;
11151 pxold1 = 0;
11152 pxold2 = 0;
11153 return;
11154 }
11155 c->cd();
11156 c->SetLogy(ctxt.GetSaved()->GetLogz());
11157 c->SetLogx(ctxt.GetSaved()->GetLogy());
11158
11159 // Draw slice corresponding to mouse position
11160 TString prjName = TString::Format("slice_py_of_%s",fH->GetName());
11161 TH1D *hp = ((TH2*)fH)->ProjectionY(prjName, binx1, binx2);
11162 if (hp) {
11163 hp->SetFillColor(38);
11164 // apply a patch from Oliver Freyermuth to set the title in the projection
11165 // using the range of the projected X values
11166 if (binx1 == binx2) {
11169 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11171 if (fH->GetXaxis()->GetLabels() != nullptr) {
11172 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf] [%s]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetXaxis()->GetBinLabel(binx1)));
11173 } else {
11174 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo));
11175 }
11176 } else {
11179 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11180 // binx1 is used here to get equal precision no matter how large the binrange is,
11181 // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
11183 if (fH->GetXaxis()->GetLabels() != nullptr) {
11184 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)));
11185 } else {
11186 hp->SetTitle(TString::Format("ProjectionY of binx=[%d,%d] [x=%.*lf..%.*lf]", binx1, binx2, valuePrecision, valueFrom, valuePrecision, valueTo));
11187 }
11188 }
11189 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11190 hp->SetYTitle(((TH2*)fH)->GetZaxis()->GetTitle() ? ((TH2*)fH)->GetZaxis()->GetTitle() : "Number of Entries");
11191 hp->Draw(fShowProjection2 ? "hbar" : "");
11192 c->Update();
11193 }
11194}
11195
11196////////////////////////////////////////////////////////////////////////////////
11197/// Show projection (specified by `fShowProjection`) of a `TH3`.
11198/// The drawing option for the projection is in `fShowOption`.
11199///
11200/// First implementation; R.Brun
11201///
11202/// Full implementation: Tim Tran (timtran@jlab.org) April 2006
11203
11205{
11206
11207 Int_t nbins=(Int_t)fShowProjection/100; //decode nbins
11208 if (fH->GetDimension() < 3) {
11209 if (fShowProjection2 % 100 == 1) {
11210 ShowProjectionY(px, py);
11211 }
11212 if (fShowProjection % 100 == 1) {
11213 ShowProjectionX(px, py);
11214 return;
11215 }
11216 if (fShowProjection % 100 == 2) {
11217 ShowProjectionY(px, py);
11218 return;
11219 }
11220 }
11221
11222 gPad->SetDoubleBuffer(0); // turn off double buffer mode
11223 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
11224
11225 // Erase old position and draw a line at current position
11226 TView *view = gPad->GetView();
11227 if (!view) return;
11228 TH3 *h3 = (TH3*)fH;
11229 TAxis *xaxis = h3->GetXaxis();
11230 TAxis *yaxis = h3->GetYaxis();
11231 TAxis *zaxis = h3->GetZaxis();
11232 Double_t u[3],xx[3];
11233
11234 static TPoint line1[2];//store end points of a line, initialised 0 by default
11235 static TPoint line2[2];// second line when slice thickness > 1 bin thickness
11236 static TPoint line3[2];
11237 static TPoint line4[2];
11238 static TPoint endface1[5];
11239 static TPoint endface2[5];
11240 static TPoint rect1[5];//store vertices of the polyline (rectangle), initialsed 0 by default
11241 static TPoint rect2[5];// second rectangle when slice thickness > 1 bin thickness
11242
11243 Double_t uxmin = gPad->GetUxmin();
11244 Double_t uxmax = gPad->GetUxmax();
11245 Double_t uymin = gPad->GetUymin();
11246 Double_t uymax = gPad->GetUymax();
11247
11248 int pxmin = gPad->XtoAbsPixel(uxmin);
11249 int pxmax = gPad->XtoAbsPixel(uxmax);
11250 if (pxmin==pxmax) return;
11251 int pymin = gPad->YtoAbsPixel(uymin);
11252 int pymax = gPad->YtoAbsPixel(uymax);
11253 if (pymin==pymax) return;
11256 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(TString::Format("c_%zx_projection_%d",
11257 (size_t)fH, fShowProjection).Data());
11258 if (!c) {
11259 fShowProjection = 0;
11260 return;
11261 }
11262
11264
11265 switch ((Int_t)fShowProjection%100) {
11266 case 1:
11267 // "x"
11268 {
11269 Int_t firstY = yaxis->GetFirst();
11270 Int_t lastY = yaxis->GetLast();
11272 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11273 yaxis->SetRange(biny,biny2);
11274 Int_t firstZ = zaxis->GetFirst();
11275 Int_t lastZ = zaxis->GetLast();
11277 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11278 zaxis->SetRange(binz,binz2);
11279 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11280 if (nbins>1 && line1[0].GetX()) {
11281 gVirtualX->DrawPolyLine(2,line2);
11282 gVirtualX->DrawPolyLine(2,line3);
11283 gVirtualX->DrawPolyLine(2,line4);
11284 gVirtualX->DrawPolyLine(5,endface1);
11285 gVirtualX->DrawPolyLine(5,endface2);
11286 }
11287 xx[0] = xaxis->GetXmin();
11288 xx[2] = zaxis->GetBinCenter(binz);
11289 xx[1] = yaxis->GetBinCenter(biny);
11290 view->WCtoNDC(xx,u);
11291 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11292 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11293 xx[0] = xaxis->GetXmax();
11294 view->WCtoNDC(xx,u);
11295 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11296 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11297 gVirtualX->DrawPolyLine(2,line1);
11298 if (nbins>1) {
11299 xx[0] = xaxis->GetXmin();
11300 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11301 xx[1] = yaxis->GetBinCenter(biny);
11302 view->WCtoNDC(xx,u);
11303 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11304 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11305 xx[0] = xaxis->GetXmax();
11306 view->WCtoNDC(xx,u);
11307 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11308 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11309
11310 xx[0] = xaxis->GetXmin();
11311 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11312 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11313 view->WCtoNDC(xx,u);
11314 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11315 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11316 xx[0] = xaxis->GetXmax();
11317 view->WCtoNDC(xx,u);
11318 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11319 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11320
11321 xx[0] = xaxis->GetXmin();
11322 xx[2] = zaxis->GetBinCenter(binz);
11323 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11324 view->WCtoNDC(xx,u);
11325 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11326 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11327 xx[0] = xaxis->GetXmax();
11328 view->WCtoNDC(xx,u);
11329 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11330 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11331
11332 endface1[0].SetX(line1[0].GetX());
11333 endface1[0].SetY(line1[0].GetY());
11334 endface1[1].SetX(line2[0].GetX());
11335 endface1[1].SetY(line2[0].GetY());
11336 endface1[2].SetX(line3[0].GetX());
11337 endface1[2].SetY(line3[0].GetY());
11338 endface1[3].SetX(line4[0].GetX());
11339 endface1[3].SetY(line4[0].GetY());
11340 endface1[4].SetX(line1[0].GetX());
11341 endface1[4].SetY(line1[0].GetY());
11342
11343 endface2[0].SetX(line1[1].GetX());
11344 endface2[0].SetY(line1[1].GetY());
11345 endface2[1].SetX(line2[1].GetX());
11346 endface2[1].SetY(line2[1].GetY());
11347 endface2[2].SetX(line3[1].GetX());
11348 endface2[2].SetY(line3[1].GetY());
11349 endface2[3].SetX(line4[1].GetX());
11350 endface2[3].SetY(line4[1].GetY());
11351 endface2[4].SetX(line1[1].GetX());
11352 endface2[4].SetY(line1[1].GetY());
11353
11354 gVirtualX->DrawPolyLine(2,line2);
11355 gVirtualX->DrawPolyLine(2,line3);
11356 gVirtualX->DrawPolyLine(2,line4);
11357 gVirtualX->DrawPolyLine(5,endface1);
11358 gVirtualX->DrawPolyLine(5,endface2);
11359 }
11360 c->Clear();
11361 c->cd();
11362 TH1 *hp = h3->Project3D("x");
11363 yaxis->SetRange(firstY,lastY);
11364 zaxis->SetRange(firstZ,lastZ);
11365 if (hp) {
11366 hp->SetFillColor(38);
11367 if (nbins == 1)
11368 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny),
11369 binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
11370 else {
11371 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),
11372 binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
11373 }
11374 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11375 hp->SetYTitle("Number of Entries");
11376 hp->Draw(fShowOption.Data());
11377 }
11378 }
11379 break;
11380
11381 case 2:
11382 // "y"
11383 {
11384 Int_t firstX = xaxis->GetFirst();
11385 Int_t lastX = xaxis->GetLast();
11387 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11388 xaxis->SetRange(binx,binx2);
11389 Int_t firstZ = zaxis->GetFirst();
11390 Int_t lastZ = zaxis->GetLast();
11392 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11393 zaxis->SetRange(binz,binz2);
11394 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11395 if (nbins>1 && line1[0].GetX()) {
11396 gVirtualX->DrawPolyLine(2,line2);
11397 gVirtualX->DrawPolyLine(2,line3);
11398 gVirtualX->DrawPolyLine(2,line4);
11399 gVirtualX->DrawPolyLine(5,endface1);
11400 gVirtualX->DrawPolyLine(5,endface2);
11401 }
11402 xx[0]=xaxis->GetBinCenter(binx);
11403 xx[2] = zaxis->GetBinCenter(binz);
11404 xx[1] = yaxis->GetXmin();
11405 view->WCtoNDC(xx,u);
11406 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11407 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11408 xx[1] = yaxis->GetXmax();
11409 view->WCtoNDC(xx,u);
11410 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11411 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11412 gVirtualX->DrawPolyLine(2,line1);
11413 if (nbins>1) {
11414 xx[1] = yaxis->GetXmin();
11415 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11416 xx[0] = xaxis->GetBinCenter(binx);
11417 view->WCtoNDC(xx,u);
11418 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11419 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11420 xx[1] = yaxis->GetXmax();
11421 view->WCtoNDC(xx,u);
11422 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11423 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11424
11425 xx[1] = yaxis->GetXmin();
11426 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11427 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11428 view->WCtoNDC(xx,u);
11429 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11430 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11431 xx[1] = yaxis->GetXmax();
11432 view->WCtoNDC(xx,u);
11433 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11434 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11435
11436 xx[1] = yaxis->GetXmin();
11437 xx[2] = zaxis->GetBinCenter(binz);
11438 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11439 view->WCtoNDC(xx,u);
11440 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11441 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11442 xx[1] = yaxis->GetXmax();
11443 view->WCtoNDC(xx,u);
11444 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11445 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11446
11447 endface1[0].SetX(line1[0].GetX());
11448 endface1[0].SetY(line1[0].GetY());
11449 endface1[1].SetX(line2[0].GetX());
11450 endface1[1].SetY(line2[0].GetY());
11451 endface1[2].SetX(line3[0].GetX());
11452 endface1[2].SetY(line3[0].GetY());
11453 endface1[3].SetX(line4[0].GetX());
11454 endface1[3].SetY(line4[0].GetY());
11455 endface1[4].SetX(line1[0].GetX());
11456 endface1[4].SetY(line1[0].GetY());
11457
11458 endface2[0].SetX(line1[1].GetX());
11459 endface2[0].SetY(line1[1].GetY());
11460 endface2[1].SetX(line2[1].GetX());
11461 endface2[1].SetY(line2[1].GetY());
11462 endface2[2].SetX(line3[1].GetX());
11463 endface2[2].SetY(line3[1].GetY());
11464 endface2[3].SetX(line4[1].GetX());
11465 endface2[3].SetY(line4[1].GetY());
11466 endface2[4].SetX(line1[1].GetX());
11467 endface2[4].SetY(line1[1].GetY());
11468
11469 gVirtualX->DrawPolyLine(2,line2);
11470 gVirtualX->DrawPolyLine(2,line3);
11471 gVirtualX->DrawPolyLine(2,line4);
11472 gVirtualX->DrawPolyLine(5,endface1);
11473 gVirtualX->DrawPolyLine(5,endface2);
11474 }
11475 c->Clear();
11476 c->cd();
11477 TH1 *hp = h3->Project3D("y");
11478 xaxis->SetRange(firstX,lastX);
11479 zaxis->SetRange(firstZ,lastZ);
11480 if (hp) {
11481 hp->SetFillColor(38);
11482 if (nbins == 1)
11483 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
11484 binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
11485 else
11486 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),
11487 binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
11488 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11489 hp->SetYTitle("Number of Entries");
11490 hp->Draw(fShowOption.Data());
11491 }
11492 }
11493 break;
11494
11495 case 3:
11496 // "z"
11497 {
11498 Int_t firstX = xaxis->GetFirst();
11499 Int_t lastX = xaxis->GetLast();
11501 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11502 xaxis->SetRange(binx,binx2);
11503 Int_t firstY = yaxis->GetFirst();
11504 Int_t lastY = yaxis->GetLast();
11506 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11507 yaxis->SetRange(biny,biny2);
11508 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11509 if (nbins>1 && line1[0].GetX()) {
11510 gVirtualX->DrawPolyLine(2,line2);
11511 gVirtualX->DrawPolyLine(2,line3);
11512 gVirtualX->DrawPolyLine(2,line4);
11513 gVirtualX->DrawPolyLine(5,endface1);
11514 gVirtualX->DrawPolyLine(5,endface2);
11515 }
11516 xx[0] = xaxis->GetBinCenter(binx);
11517 xx[1] = yaxis->GetBinCenter(biny);
11518 xx[2] = zaxis->GetXmin();
11519 view->WCtoNDC(xx,u);
11520 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11521 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11522 xx[2] = zaxis->GetXmax();
11523 view->WCtoNDC(xx,u);
11524 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11525 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11526 gVirtualX->DrawPolyLine(2,line1);
11527 if (nbins>1) {
11528 xx[2] = zaxis->GetXmin();
11529 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11530 xx[0] = xaxis->GetBinCenter(binx);
11531 view->WCtoNDC(xx,u);
11532 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11533 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11534 xx[2] = zaxis->GetXmax();
11535 view->WCtoNDC(xx,u);
11536 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11537 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11538
11539 xx[2] = zaxis->GetXmin();
11540 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11541 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11542 view->WCtoNDC(xx,u);
11543 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11544 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11545 xx[2] = zaxis->GetXmax();
11546 view->WCtoNDC(xx,u);
11547 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11548 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11549
11550 xx[2] = zaxis->GetXmin();
11551 xx[1] = yaxis->GetBinCenter(biny);
11552 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11553 view->WCtoNDC(xx,u);
11554 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11555 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11556 xx[2] = zaxis->GetXmax();
11557 view->WCtoNDC(xx,u);
11558 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11559 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11560
11561 endface1[0].SetX(line1[0].GetX());
11562 endface1[0].SetY(line1[0].GetY());
11563 endface1[1].SetX(line2[0].GetX());
11564 endface1[1].SetY(line2[0].GetY());
11565 endface1[2].SetX(line3[0].GetX());
11566 endface1[2].SetY(line3[0].GetY());
11567 endface1[3].SetX(line4[0].GetX());
11568 endface1[3].SetY(line4[0].GetY());
11569 endface1[4].SetX(line1[0].GetX());
11570 endface1[4].SetY(line1[0].GetY());
11571
11572 endface2[0].SetX(line1[1].GetX());
11573 endface2[0].SetY(line1[1].GetY());
11574 endface2[1].SetX(line2[1].GetX());
11575 endface2[1].SetY(line2[1].GetY());
11576 endface2[2].SetX(line3[1].GetX());
11577 endface2[2].SetY(line3[1].GetY());
11578 endface2[3].SetX(line4[1].GetX());
11579 endface2[3].SetY(line4[1].GetY());
11580 endface2[4].SetX(line1[1].GetX());
11581 endface2[4].SetY(line1[1].GetY());
11582
11583 gVirtualX->DrawPolyLine(2,line2);
11584 gVirtualX->DrawPolyLine(2,line3);
11585 gVirtualX->DrawPolyLine(2,line4);
11586 gVirtualX->DrawPolyLine(5,endface1);
11587 gVirtualX->DrawPolyLine(5,endface2);
11588 }
11589 c->Clear();
11590 c->cd();
11591 TH1 *hp = h3->Project3D("z");
11592 xaxis->SetRange(firstX,lastX);
11593 yaxis->SetRange(firstY,lastY);
11594 if (hp) {
11595 hp->SetFillColor(38);
11596 if (nbins == 1)
11597 hp->SetTitle(TString::Format("ProjectionZ of binx=%d [x=%.1f..%.1f] biny=%d [y=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
11598 biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny)));
11599 else
11600 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),
11601 biny, biny2, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny2) ) );
11602 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11603 hp->SetYTitle("Number of Entries");
11604 hp->Draw(fShowOption.Data());
11605 }
11606 }
11607 break;
11608
11609 case 4:
11610 // "xy"
11611 {
11612 Int_t first = zaxis->GetFirst();
11613 Int_t last = zaxis->GetLast();
11614 Int_t binz = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11615 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11616 zaxis->SetRange(binz,binz2);
11617 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11618 if (nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11619 xx[0] = xaxis->GetXmin();
11620 xx[1] = yaxis->GetXmax();
11621 xx[2] = zaxis->GetBinCenter(binz);
11622 view->WCtoNDC(xx,u);
11623 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11624 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11625 rect1[4].SetX(rect1[0].GetX());
11626 rect1[4].SetY(rect1[0].GetY());
11627 xx[0] = xaxis->GetXmax();
11628 view->WCtoNDC(xx,u);
11629 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11630 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11631 xx[1] = yaxis->GetXmin();
11632 view->WCtoNDC(xx,u);
11633 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11634 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11635 xx[0] = xaxis->GetXmin();
11636 view->WCtoNDC(xx,u);
11637 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11638 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11639 gVirtualX->DrawPolyLine(5,rect1);
11640 if (nbins>1) {
11641 xx[0] = xaxis->GetXmin();
11642 xx[1] = yaxis->GetXmax();
11643 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11644 view->WCtoNDC(xx,u);
11645 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11646 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11647 rect2[4].SetX(rect2[0].GetX());
11648 rect2[4].SetY(rect2[0].GetY());
11649 xx[0] = xaxis->GetXmax();
11650 view->WCtoNDC(xx,u);
11651 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11652 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11653 xx[1] = yaxis->GetXmin();
11654 view->WCtoNDC(xx,u);
11655 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11656 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11657 xx[0] = xaxis->GetXmin();
11658 view->WCtoNDC(xx,u);
11659 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11660 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11661 gVirtualX->DrawPolyLine(5,rect2);
11662 }
11663
11664 c->Clear();
11665 c->cd();
11666 TH2 *hp = (TH2*)h3->Project3D("xy");
11667 zaxis->SetRange(first,last);
11668 if (hp) {
11669 hp->SetFillColor(38);
11670 if (nbins==1)hp->SetTitle(TString::Format("ProjectionXY of binz=%d [z=%.1f..%.f]", binz,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz)));
11671 else hp->SetTitle(TString::Format("ProjectionXY, binz=[%d,%d] [z=%.1f..%.1f]", binz,binz2,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz2)));
11672 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11673 hp->SetYTitle(fH->GetXaxis()->GetTitle());
11674 hp->SetZTitle("Number of Entries");
11675 hp->Draw(fShowOption.Data());
11676 }
11677 }
11678 break;
11679
11680 case 5:
11681 // "yx"
11682 {
11683 Int_t first = zaxis->GetFirst();
11684 Int_t last = zaxis->GetLast();
11685 Int_t binz = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11686 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11687 zaxis->SetRange(binz,binz2);
11688 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11689 if (nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11690 xx[0] = xaxis->GetXmin();
11691 xx[1] = yaxis->GetXmax();
11692 xx[2] = zaxis->GetBinCenter(binz);
11693 view->WCtoNDC(xx,u);
11694 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11695 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11696 rect1[4].SetX(rect1[0].GetX());
11697 rect1[4].SetY(rect1[0].GetY());
11698 xx[0] = xaxis->GetXmax();
11699 view->WCtoNDC(xx,u);
11700 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11701 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11702 xx[1] = yaxis->GetXmin();
11703 view->WCtoNDC(xx,u);
11704 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11705 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11706 xx[0] = xaxis->GetXmin();
11707 view->WCtoNDC(xx,u);
11708 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11709 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11710 gVirtualX->DrawPolyLine(5,rect1);
11711 if (nbins>1) {
11712 xx[0] = xaxis->GetXmin();
11713 xx[1] = yaxis->GetXmax();
11714 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11715 view->WCtoNDC(xx,u);
11716 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11717 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11718 rect2[4].SetX(rect2[0].GetX());
11719 rect2[4].SetY(rect2[0].GetY());
11720 xx[0] = xaxis->GetXmax();
11721 view->WCtoNDC(xx,u);
11722 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11723 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11724 xx[1] = yaxis->GetXmin();
11725 view->WCtoNDC(xx,u);
11726 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11727 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11728 xx[0] = xaxis->GetXmin();
11729 view->WCtoNDC(xx,u);
11730 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11731 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11732 gVirtualX->DrawPolyLine(5,rect2);
11733 }
11734 c->Clear();
11735 c->cd();
11736 TH2 *hp = (TH2*)h3->Project3D("yx");
11737 zaxis->SetRange(first,last);
11738 if (hp) {
11739 hp->SetFillColor(38);
11740 if (nbins==1)hp->SetTitle(TString::Format("ProjectionYX of binz=%d [z=%.1f..%.f]", binz,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz)));
11741 else hp->SetTitle(TString::Format("ProjectionYX, binz=[%d,%d] [z=%.1f..%.1f]", binz,binz2,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz2)));
11742 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11743 hp->SetYTitle(fH->GetYaxis()->GetTitle());
11744 hp->SetZTitle("Number of Entries");
11745 hp->Draw(fShowOption.Data());
11746 }
11747 }
11748 break;
11749
11750 case 6:
11751 // "xz"
11752 {
11753 Int_t first = yaxis->GetFirst();
11754 Int_t last = yaxis->GetLast();
11755 Int_t biny = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11756 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11757 yaxis->SetRange(biny,biny2);
11758 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11759 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11760 xx[0] = xaxis->GetXmin();
11761 xx[2] = zaxis->GetXmax();
11762 xx[1] = yaxis->GetBinCenter(biny);
11763 view->WCtoNDC(xx,u);
11764 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11765 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11766 rect1[4].SetX(rect1[0].GetX());
11767 rect1[4].SetY(rect1[0].GetY());
11768 xx[0] = xaxis->GetXmax();
11769 view->WCtoNDC(xx,u);
11770 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11771 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11772 xx[2] = zaxis->GetXmin();
11773 view->WCtoNDC(xx,u);
11774 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11775 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11776 xx[0] = xaxis->GetXmin();
11777 view->WCtoNDC(xx,u);
11778 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11779 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11780 gVirtualX->DrawPolyLine(5,rect1);
11781 if (nbins>1) {
11782 xx[0] = xaxis->GetXmin();
11783 xx[2] = zaxis->GetXmax();
11784 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11785 view->WCtoNDC(xx,u);
11786 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11787 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11788 rect2[4].SetX(rect2[0].GetX());
11789 rect2[4].SetY(rect2[0].GetY());
11790 xx[0] = xaxis->GetXmax();
11791 view->WCtoNDC(xx,u);
11792 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11793 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11794 xx[2] = zaxis->GetXmin();
11795 view->WCtoNDC(xx,u);
11796 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11797 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11798 xx[0] = xaxis->GetXmin();
11799 view->WCtoNDC(xx,u);
11800 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11801 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11802 gVirtualX->DrawPolyLine(5,rect2);
11803 }
11804 c->Clear();
11805 c->cd();
11806 TH2 *hp = (TH2*)h3->Project3D("xz");
11807 yaxis->SetRange(first,last);
11808 if (hp) {
11809 hp->SetFillColor(38);
11810 if (nbins==1)hp->SetTitle(TString::Format("ProjectionXZ of biny=%d [y=%.1f..%.f]", biny,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny)));
11811 else hp->SetTitle(TString::Format("ProjectionXZ, biny=[%d,%d] [y=%.1f..%.1f]", biny,biny2,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny2)));
11812 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11813 hp->SetYTitle(fH->GetXaxis()->GetTitle());
11814 hp->SetZTitle("Number of Entries");
11815 hp->Draw(fShowOption.Data());
11816 }
11817 }
11818 break;
11819
11820 case 7:
11821 // "zx"
11822 {
11823 Int_t first = yaxis->GetFirst();
11824 Int_t last = yaxis->GetLast();
11825 Int_t biny = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11826 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11827 yaxis->SetRange(biny,biny2);
11828 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11829 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11830 xx[0] = xaxis->GetXmin();
11831 xx[2] = zaxis->GetXmax();
11832 xx[1] = yaxis->GetBinCenter(biny);
11833 view->WCtoNDC(xx,u);
11834 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11835 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11836 rect1[4].SetX(rect1[0].GetX());
11837 rect1[4].SetY(rect1[0].GetY());
11838 xx[0] = xaxis->GetXmax();
11839 view->WCtoNDC(xx,u);
11840 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11841 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11842 xx[2] = zaxis->GetXmin();
11843 view->WCtoNDC(xx,u);
11844 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11845 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11846 xx[0] = xaxis->GetXmin();
11847 view->WCtoNDC(xx,u);
11848 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11849 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11850 gVirtualX->DrawPolyLine(5,rect1);
11851 if (nbins>1) {
11852 xx[0] = xaxis->GetXmin();
11853 xx[2] = zaxis->GetXmax();
11854 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11855 view->WCtoNDC(xx,u);
11856 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11857 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11858 rect2[4].SetX(rect2[0].GetX());
11859 rect2[4].SetY(rect2[0].GetY());
11860 xx[0] = xaxis->GetXmax();
11861 view->WCtoNDC(xx,u);
11862 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11863 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11864 xx[2] = zaxis->GetXmin();
11865 view->WCtoNDC(xx,u);
11866 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11867 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11868 xx[0] = xaxis->GetXmin();
11869 view->WCtoNDC(xx,u);
11870 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11871 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11872 gVirtualX->DrawPolyLine(5,rect2);
11873 }
11874 c->Clear();
11875 c->cd();
11876 TH2 *hp = (TH2*)h3->Project3D("zx");
11877 yaxis->SetRange(first,last);
11878 if (hp) {
11879 hp->SetFillColor(38);
11880 if (nbins==1)hp->SetTitle(TString::Format("ProjectionZX of biny=%d [y=%.1f..%.f]", biny,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny)));
11881 else hp->SetTitle(TString::Format("ProjectionZX, biny=[%d,%d] [y=%.1f..%.1f]", biny,biny2,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny2)));
11882 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11883 hp->SetYTitle(fH->GetZaxis()->GetTitle());
11884 hp->SetZTitle("Number of Entries");
11885 hp->Draw(fShowOption.Data());
11886 }
11887 }
11888 break;
11889
11890 case 8:
11891 // "yz"
11892 {
11893 Int_t first = xaxis->GetFirst();
11894 Int_t last = xaxis->GetLast();
11895 Int_t binx = first + Int_t((last-first)*(px-pxmin)/(pxmax-pxmin));
11896 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11897 xaxis->SetRange(binx,binx2);
11898 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11899 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11900 xx[2] = zaxis->GetXmin();
11901 xx[1] = yaxis->GetXmax();
11902 xx[0] = xaxis->GetBinCenter(binx);
11903 view->WCtoNDC(xx,u);
11904 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11905 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11906 rect1[4].SetX(rect1[0].GetX());
11907 rect1[4].SetY(rect1[0].GetY());
11908 xx[2] = zaxis->GetXmax();
11909 view->WCtoNDC(xx,u);
11910 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11911 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11912 xx[1] = yaxis->GetXmin();
11913 view->WCtoNDC(xx,u);
11914 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11915 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11916 xx[2] = zaxis->GetXmin();
11917 view->WCtoNDC(xx,u);
11918 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11919 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11920 gVirtualX->DrawPolyLine(5,rect1);
11921 if (nbins>1) {
11922 xx[2] = zaxis->GetXmin();
11923 xx[1] = yaxis->GetXmax();
11924 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11925 view->WCtoNDC(xx,u);
11926 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11927 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11928 rect2[4].SetX(rect2[0].GetX());
11929 rect2[4].SetY(rect2[0].GetY());
11930 xx[2] = zaxis->GetXmax();
11931 view->WCtoNDC(xx,u);
11932 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11933 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11934 xx[1] = yaxis->GetXmin();
11935 view->WCtoNDC(xx,u);
11936 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11937 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11938 xx[2] = zaxis->GetXmin();
11939 view->WCtoNDC(xx,u);
11940 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11941 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11942 gVirtualX->DrawPolyLine(5,rect2);
11943 }
11944 c->Clear();
11945 c->cd();
11946 TH2 *hp = (TH2*)h3->Project3D("yz");
11947 xaxis->SetRange(first,last);
11948 if (hp) {
11949 hp->SetFillColor(38);
11950 if (nbins==1)hp->SetTitle(TString::Format("ProjectionYZ of binx=%d [x=%.1f..%.f]", binx,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx)));
11951 else hp->SetTitle(TString::Format("ProjectionYZ, binx=[%d,%d] [x=%.1f..%.1f]", binx,binx2,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx2)));
11952 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11953 hp->SetYTitle(fH->GetYaxis()->GetTitle());
11954 hp->SetZTitle("Number of Entries");
11955 hp->Draw(fShowOption.Data());
11956 }
11957 }
11958 break;
11959
11960 case 9:
11961 // "zy"
11962 {
11963 Int_t first = xaxis->GetFirst();
11964 Int_t last = xaxis->GetLast();
11965 Int_t binx = first + Int_t((last-first)*(px-pxmin)/(pxmax-pxmin));
11966 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11967 xaxis->SetRange(binx,binx2);
11968 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11969 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11970 xx[2] = zaxis->GetXmin();
11971 xx[1] = yaxis->GetXmax();
11972 xx[0] = xaxis->GetBinCenter(binx);
11973 view->WCtoNDC(xx,u);
11974 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11975 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11976 rect1[4].SetX(rect1[0].GetX());
11977 rect1[4].SetY(rect1[0].GetY());
11978 xx[2] = zaxis->GetXmax();
11979 view->WCtoNDC(xx,u);
11980 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11981 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11982 xx[1] = yaxis->GetXmin();
11983 view->WCtoNDC(xx,u);
11984 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11985 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11986 xx[2] = zaxis->GetXmin();
11987 view->WCtoNDC(xx,u);
11988 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11989 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11990 gVirtualX->DrawPolyLine(5,rect1);
11991 if (nbins>1) {
11992 xx[2] = zaxis->GetXmin();
11993 xx[1] = yaxis->GetXmax();
11994 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11995 view->WCtoNDC(xx,u);
11996 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11997 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11998 rect2[4].SetX(rect2[0].GetX());
11999 rect2[4].SetY(rect2[0].GetY());
12000 xx[2] = zaxis->GetXmax();
12001 view->WCtoNDC(xx,u);
12002 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
12003 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
12004 xx[1] = yaxis->GetXmin();
12005 view->WCtoNDC(xx,u);
12006 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
12007 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
12008 xx[2] = zaxis->GetXmin();
12009 view->WCtoNDC(xx,u);
12010 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
12011 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
12012 gVirtualX->DrawPolyLine(5,rect2);
12013 }
12014 c->Clear();
12015 c->cd();
12016 TH2 *hp = (TH2*)h3->Project3D("zy");
12017 xaxis->SetRange(first,last);
12018 if (hp) {
12019 hp->SetFillColor(38);
12020 if (nbins==1)hp->SetTitle(TString::Format("ProjectionZY of binx=%d [x=%.1f..%.f]", binx,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx)));
12021 else hp->SetTitle(TString::Format("ProjectionZY, binx=[%d,%d] [x=%.1f..%.1f]", binx,binx2,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx2)));
12022 hp->SetXTitle(fH->GetYaxis()->GetTitle());
12023 hp->SetYTitle(fH->GetZaxis()->GetTitle());
12024 hp->SetZTitle("Number of Entries");
12025 hp->Draw(fShowOption.Data());
12026 }
12027 }
12028 break;
12029 }
12030 c->Update();
12031}
@ kMouseMotion
Definition Buttons.h:23
@ kWheelUp
Definition Buttons.h:18
@ kButton1Motion
Definition Buttons.h:20
@ kButton1Up
Definition Buttons.h:19
@ kWheelDown
Definition Buttons.h:18
@ kButton1Down
Definition Buttons.h:17
@ kButton1Locate
Definition Buttons.h:22
@ kArrowVer
Definition GuiTypes.h:375
@ kPointer
Definition GuiTypes.h:376
#define d(i)
Definition RSha256.hxx:102
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
#define c(i)
Definition RSha256.hxx:101
#define g(i)
Definition RSha256.hxx:105
#define a(i)
Definition RSha256.hxx:99
#define h(i)
Definition RSha256.hxx:106
#define e(i)
Definition RSha256.hxx:103
cudaEvent_t event
short Style_t
Style number (short)
Definition RtypesCore.h:97
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:60
short Color_t
Color number (short)
Definition RtypesCore.h:100
unsigned int UInt_t
Unsigned integer 4 bytes (unsigned int)
Definition RtypesCore.h:61
short Width_t
Line width (short)
Definition RtypesCore.h:99
float Float_t
Float 4 bytes (float)
Definition RtypesCore.h:72
short Short_t
Signed Short integer 2 bytes (short)
Definition RtypesCore.h:54
constexpr Bool_t kFALSE
Definition RtypesCore.h:109
double Double_t
Double 8 bytes.
Definition RtypesCore.h:74
constexpr Bool_t kTRUE
Definition RtypesCore.h:108
const char Option_t
Option string (const char)
Definition RtypesCore.h:81
#define BIT(n)
Definition Rtypes.h:90
@ kBlack
Definition Rtypes.h:65
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
R__EXTERN TEnv * gEnv
Definition TEnv.h:126
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t option
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void pixel
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t wmin
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t np
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize id
Option_t Option_t TPoint TPoint const char x2
Option_t Option_t TPoint TPoint const char x1
Option_t Option_t TPoint TPoint angle
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void xpos
Option_t Option_t TPoint TPoint const char mode
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char backcolor
Option_t Option_t TPoint TPoint const char y2
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void ypos
Option_t Option_t width
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize fs
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t wmax
Option_t Option_t TPoint TPoint const char text
Option_t Option_t TPoint TPoint const char y1
R__EXTERN TH1 * gCurrentHist
R__EXTERN Hoption_t Hoption
float xmin
int ncx
float ymin
int ncy
float xmax
float ymax
static TString gStringStdDevZ
static TString gStringStdDevX
static TString gStringIntegralBinWidth
const UInt_t kCannotRotate
static TString gStringStdDev
const Int_t kNMAX
Hparam_t Hparam
const Int_t kMAXCONTOUR
static TString gStringOverflow
static TString gStringUnderflow
static TString gStringSkewnessY
static TString gStringMean
static TString gStringKurtosis
Hoption_t Hoption
static TString gStringMeanX
static TString gStringEntries
static TString gStringIntegral
static TString gStringKurtosisY
static TString gStringStdDevY
static TString gStringMeanY
static TString gStringSkewnessX
static TString gStringKurtosisX
static std::unique_ptr< TBox > gXHighlightBox
static std::unique_ptr< TBox > gYHighlightBox
static TString gStringSkewnessZ
TH1 * gCurrentHist
static TString gStringMeanZ
static TString gStringSkewness
static TString gStringKurtosisZ
const Int_t kMaxCuts
const Int_t kCYLINDRICAL
const Int_t kSPHERICAL
const Int_t kRAPIDITY
#define gROOT
Definition TROOT.h:417
R__EXTERN TStyle * gStyle
Definition TStyle.h:442
R__EXTERN TSystem * gSystem
Definition TSystem.h:582
const Int_t kCARTESIAN
Definition TView3D.cxx:32
const Int_t kPOLAR
Definition TView3D.cxx:33
#define gPad
#define gVirtualX
Definition TVirtualX.h:379
Draw all kinds of Arrows.
Definition TArrow.h:29
virtual Int_t GetNdivisions() const
Definition TAttAxis.h:37
virtual Float_t GetLabelOffset() const
Definition TAttAxis.h:41
virtual Float_t GetLabelSize() const
Definition TAttAxis.h:42
virtual Float_t GetTickLength() const
Definition TAttAxis.h:46
virtual Float_t GetTitleOffset() const
Definition TAttAxis.h:44
virtual Color_t GetFillColor() const
Return the fill area color.
Definition TAttFill.h:32
virtual Style_t GetFillStyle() const
Return the fill area style.
Definition TAttFill.h:33
virtual void SetFillColor(Color_t fcolor)
Set the fill area color.
Definition TAttFill.h:40
virtual void SetFillStyle(Style_t fstyle)
Set the fill area style.
Definition TAttFill.h:42
virtual Color_t GetLineColor() const
Return the line color.
Definition TAttLine.h:36
virtual void SetLineStyle(Style_t lstyle)
Set the line style.
Definition TAttLine.h:46
virtual Width_t GetLineWidth() const
Return the line width.
Definition TAttLine.h:38
virtual void SetLineWidth(Width_t lwidth)
Set the line width.
Definition TAttLine.h:47
virtual void SetLineColor(Color_t lcolor)
Set the line color.
Definition TAttLine.h:44
virtual Style_t GetLineStyle() const
Return the line style.
Definition TAttLine.h:37
virtual Style_t GetMarkerStyle() const
Return the marker style.
Definition TAttMarker.h:35
virtual Color_t GetMarkerColor() const
Return the marker color.
Definition TAttMarker.h:34
virtual Size_t GetMarkerSize() const
Return the marker size.
Definition TAttMarker.h:36
virtual void SetMarkerStyle(Style_t mstyle=1)
Set the marker style.
virtual void SetMarkerSize(Size_t msize=1)
Set the marker size.
virtual void SetMarkerColor(Color_t mcolor=1)
Set the marker color.
static Style_t GetMarkerStyleBase(Style_t style)
Internal helper function that returns the corresponding marker style with line width 1 for the given ...
virtual void SetTextAlign(Short_t align=11)
Set the text alignment.
Definition TAttText.h:48
virtual Font_t GetTextFont() const
Return the text font.
Definition TAttText.h:38
virtual void SetTextAngle(Float_t tangle=0)
Set the text angle.
Definition TAttText.h:49
virtual void SetTextColor(Color_t tcolor=1)
Set the text color.
Definition TAttText.h:50
virtual void SetTextFont(Font_t tfont=62)
Set the text font.
Definition TAttText.h:52
virtual void SetTextSize(Float_t tsize=1)
Set the text size.
Definition TAttText.h:53
Class to manage histogram axis.
Definition TAxis.h:32
virtual Bool_t GetTimeDisplay() const
Definition TAxis.h:133
Bool_t IsAlphanumeric() const
Definition TAxis.h:90
const char * GetTitle() const override
Returns title of object.
Definition TAxis.h:137
virtual Double_t GetBinCenter(Int_t bin) const
Return center of bin.
Definition TAxis.cxx:482
Bool_t CanExtend() const
Definition TAxis.h:88
const TArrayD * GetXbins() const
Definition TAxis.h:138
Double_t GetXmax() const
Definition TAxis.h:142
@ kAxisRange
Definition TAxis.h:66
const char * GetBinLabel(Int_t bin) const
Return label for bin.
Definition TAxis.cxx:444
virtual Int_t FindBin(Double_t x)
Find bin number corresponding to abscissa x.
Definition TAxis.cxx:293
virtual Double_t GetBinLowEdge(Int_t bin) const
Return low edge of bin.
Definition TAxis.cxx:522
virtual Int_t FindFixBin(Double_t x) const
Find bin number corresponding to abscissa x
Definition TAxis.cxx:422
const char * ChooseTimeFormat(Double_t axislength=0)
Choose a reasonable time format from the coordinates in the active pad and the number of divisions in...
Definition TAxis.cxx:127
Int_t GetLast() const
Return last bin on the axis i.e.
Definition TAxis.cxx:473
virtual const char * GetTimeFormatOnly() const
Return only the time format from the string fTimeFormat.
Definition TAxis.cxx:604
Double_t GetXmin() const
Definition TAxis.h:141
Int_t GetNbins() const
Definition TAxis.h:127
virtual void SetRangeUser(Double_t ufirst, Double_t ulast)
Set the viewing range for the axis from ufirst to ulast (in user coordinates, that is,...
Definition TAxis.cxx:1090
virtual const char * GetTimeFormat() const
Definition TAxis.h:134
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width.
Definition TAxis.cxx:546
virtual Double_t GetBinUpEdge(Int_t bin) const
Return up edge of bin.
Definition TAxis.cxx:532
Int_t GetFirst() const
Return first bin on the axis i.e.
Definition TAxis.cxx:462
THashList * GetLabels() const
Definition TAxis.h:123
Create a Box.
Definition TBox.h:22
The candle plot painter class.
Definition TCandle.h:27
CandleOption
Definition TCandle.h:30
static Bool_t SupportAlpha()
Static function returning "true" if transparency is supported.
Definition TCanvas.cxx:2490
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition TClass.cxx:2999
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
The color creation and management class.
Definition TColor.h:22
static void RGBtoHLS(Float_t r, Float_t g, Float_t b, Float_t &h, Float_t &l, Float_t &s)
Definition TColor.h:83
static Int_t GetColor(const char *hexcolor)
Static method returning color number for color specified by hex color string of form: "#rrggbb",...
Definition TColor.cxx:1939
static Int_t GetColorBright(Int_t color)
Static function: Returns the bright color number corresponding to n If the TColor object does not exi...
Definition TColor.cxx:2108
static Int_t GetColorDark(Int_t color)
Static function: Returns the dark color number corresponding to n If the TColor object does not exist...
Definition TColor.cxx:2151
static void HLStoRGB(Float_t h, Float_t l, Float_t s, Float_t &r, Float_t &g, Float_t &b)
Definition TColor.h:78
To draw a Crown.
Definition TCrown.h:19
Graphical cut class.
Definition TCutG.h:20
static TClass * Class()
TDirectory::TContext keeps track and restore the current directory.
Definition TDirectory.h:89
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition TEnv.cxx:511
1-Dim function class
Definition TF1.h:182
virtual Double_t GetXmax() const
Definition TF1.h:525
virtual Int_t GetNDF() const
Return the number of degrees of freedom in the fit the fNDF parameter has been previously computed du...
Definition TF1.cxx:1940
virtual void GetParLimits(Int_t ipar, Double_t &parmin, Double_t &parmax) const
Return limits for parameter ipar.
Definition TF1.cxx:1991
virtual Double_t GetParError(Int_t ipar) const
Return value of parameter number ipar.
Definition TF1.cxx:1981
static TClass * Class()
Double_t GetChisquare() const
Return the Chisquare after fitting. See ROOT::Fit::FitResult::Chi2()
Definition TF1.h:409
virtual void SetMaximum(Double_t maximum=-1111)
Set the maximum value along Y for this function In case the function is already drawn,...
Definition TF1.cxx:3450
virtual Double_t GetMaximumStored() const
Definition TF1.h:438
virtual Int_t GetNpar() const
Definition TF1.h:446
virtual Int_t GetNumberFreeParameters() const
Return the number of free parameters.
Definition TF1.cxx:1951
@ kNotDraw
Definition TF1.h:297
virtual void SetMinimum(Double_t minimum=-1111)
Set the minimum value along Y for this function In case the function is already drawn,...
Definition TF1.cxx:3463
virtual const char * GetParName(Int_t ipar) const
Definition TF1.h:494
virtual Double_t Eval(Double_t x, Double_t y=0, Double_t z=0, Double_t t=0) const
Evaluate this function.
Definition TF1.cxx:1447
virtual Double_t GetXmin() const
Definition TF1.h:521
virtual Double_t GetParameter(Int_t ipar) const
Definition TF1.h:477
A 2-Dim function with parameters.
Definition TF2.h:29
void Paint(Option_t *option="") override
Paint this 2-D function with its current attributes.
Definition TF2.cxx:806
void SetRange(Double_t xmin, Double_t xmax) override
Initialize the upper and lower bounds to draw the function.
Definition TF2.h:133
static TClass * Class()
TF3 defines a 3D Function with Parameters.
Definition TF3.h:28
The axis painter class.
Definition TGaxis.h:26
void SetTimeFormat(const char *tformat)
Change the format used for time plotting.
Definition TGaxis.cxx:2937
virtual void PaintAxis(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax, Double_t &wmin, Double_t &wmax, Int_t &ndiv, Option_t *chopt="", Double_t gridlength=0, Bool_t drawGridOnly=kFALSE)
Control function to draw an axis.
Definition TGaxis.cxx:1006
void SetTitleOffset(Float_t titleoffset=1)
Definition TGaxis.h:130
virtual void SetTitle(const char *title="")
Change the title of the axis.
Definition TGaxis.cxx:2910
void SetLabelOffset(Float_t labeloffset)
Definition TGaxis.h:108
virtual void ImportAxisAttributes(TAxis *axis)
Internal method to import TAxis attributes to this TGaxis.
Definition TGaxis.cxx:953
void SetTickSize(Float_t ticksize)
Definition TGaxis.h:124
void SetLabelSize(Float_t labelsize)
Definition TGaxis.h:109
void SetOption(Option_t *option="")
To set axis options.
Definition TGaxis.cxx:2902
Graphics object made of three arrays X, Y and Z with the same number of points each.
Definition TGraph2D.h:41
static TClass * Class()
TGraphDelaunay2D generates a Delaunay triangulation of a TGraph2D.
TGraphDelaunay generates a Delaunay triangulation of a TGraph2D.
A TGraph is an object made of two arrays X and Y with npoints each.
Definition TGraph.h:41
static TClass * Class()
@ kClipFrame
Clip to the frame boundary.
Definition TGraph.h:75
void PaintGraph(Int_t npoints, const Double_t *x, const Double_t *y, Option_t *chopt)
Draw the (x,y) as a graph.
Definition TGraph.cxx:2015
void PaintGrapHist(Int_t npoints, const Double_t *x, const Double_t *y, Option_t *chopt)
Draw the (x,y) as a histogram.
Definition TGraph.cxx:2024
1-D histogram with a double per channel (see TH1 documentation)
Definition TH1.h:926
1-D histogram with a float per channel (see TH1 documentation)
Definition TH1.h:878
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:109
TAxis * GetZaxis()
Definition TH1.h:573
virtual EBinErrorOpt GetBinErrorOption() const
Definition TH1.h:517
virtual Float_t GetBarWidth() const
Definition TH1.h:501
virtual Double_t GetMinimumStored() const
Definition TH1.h:537
virtual Float_t GetBarOffset() const
Definition TH1.h:500
static TClass * Class()
virtual Double_t GetStdDev(Int_t axis=1) const
Returns the Standard Deviation (Sigma).
Definition TH1.cxx:7816
virtual Int_t GetNbinsY() const
Definition TH1.h:542
virtual Double_t GetBinError(Int_t bin) const
Return value of error associated to bin number bin.
Definition TH1.cxx:9293
virtual Int_t GetNbinsZ() const
Definition TH1.h:543
virtual Double_t GetNormFactor() const
Definition TH1.h:545
virtual Double_t GetMean(Int_t axis=1) const
For axis = 1,2 or 3 returns the mean value of the histogram along X,Y or Z axis.
Definition TH1.cxx:7744
virtual Double_t GetSkewness(Int_t axis=1) const
Definition TH1.cxx:7880
virtual Double_t GetContourLevelPad(Int_t level) const
Return the value of contour number "level" in Pad coordinates.
Definition TH1.cxx:8669
virtual Int_t GetDimension() const
Definition TH1.h:527
@ kNoTitle
Don't draw the histogram title.
Definition TH1.h:408
@ kUserContour
User specified contour levels.
Definition TH1.h:404
@ kNoStats
Don't draw stats box.
Definition TH1.h:403
TAxis * GetXaxis()
Definition TH1.h:571
virtual Double_t GetSumOfWeights() const
Return the sum of weights across all bins excluding under/overflows.
Definition TH1.h:559
virtual Int_t GetBin(Int_t binx, Int_t biny=0, Int_t binz=0) const
Return Global bin number corresponding to binx,y,z.
Definition TH1.cxx:5137
virtual Double_t GetMaximum(Double_t maxval=FLT_MAX) const
Return maximum value smaller than maxval of bins in the range, unless the value has been overridden b...
Definition TH1.cxx:8778
virtual Int_t GetNbinsX() const
Definition TH1.h:541
virtual void SetMaximum(Double_t maximum=-1111)
Definition TH1.h:652
TAxis * GetYaxis()
Definition TH1.h:572
virtual Double_t GetBinErrorLow(Int_t bin) const
Return lower error associated to bin number bin.
Definition TH1.cxx:9309
virtual void SetMinimum(Double_t minimum=-1111)
Definition TH1.h:653
virtual Double_t Integral(Option_t *option="") const
Return integral of bin contents.
Definition TH1.cxx:8170
virtual void SetBinContent(Int_t bin, Double_t content)
Set bin content see convention for numbering bins in TH1::GetBin In case the bin number is greater th...
Definition TH1.cxx:9452
virtual Double_t GetBinLowEdge(Int_t bin) const
Return bin lower edge for 1D histogram.
Definition TH1.cxx:9382
virtual Double_t GetEntries() const
Return the current number of entries.
Definition TH1.cxx:4574
TList * GetListOfFunctions() const
Definition TH1.h:488
virtual Double_t GetMeanError(Int_t axis=1) const
Return standard error of mean of this histogram along the X axis.
Definition TH1.cxx:7784
virtual Double_t GetMaximumStored() const
Definition TH1.h:533
virtual void GetMinimumAndMaximum(Double_t &min, Double_t &max) const
Retrieve the minimum and maximum values in the histogram.
Definition TH1.cxx:8964
virtual Int_t GetMaximumBin() const
Return location of bin with maximum value in the range.
Definition TH1.cxx:8810
@ kNormal
Errors with Normal (Wald) approximation: errorUp=errorLow= sqrt(N)
Definition TH1.h:115
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition TH1.cxx:5239
virtual Int_t GetContour(Double_t *levels=nullptr)
Return contour values into array levels if pointer levels is non zero.
Definition TH1.cxx:8640
const Double_t * GetBuffer() const
Definition TH1.h:483
virtual Bool_t IsHighlight() const
Definition TH1.h:585
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width for 1D histogram.
Definition TH1.cxx:9393
virtual void SetContour(Int_t nlevels, const Double_t *levels=nullptr)
Set the number and values of contour levels.
Definition TH1.cxx:8716
virtual Double_t GetBinErrorUp(Int_t bin) const
Return upper error associated to bin number bin.
Definition TH1.cxx:9340
virtual Int_t GetSumw2N() const
Definition TH1.h:562
virtual Double_t GetStdDevError(Int_t axis=1) const
Return error of standard deviation estimation for Normal distribution.
Definition TH1.cxx:7864
virtual Double_t GetMinimum(Double_t minval=-FLT_MAX) const
Return minimum value larger than minval of bins in the range, unless the value has been overridden by...
Definition TH1.cxx:8868
virtual void LabelsDeflate(Option_t *axis="X")
Reduce the number of bins for the axis passed in the option to the number of bins having a label.
Definition TH1.cxx:5423
virtual Int_t BufferEmpty(Int_t action=0)
Fill histogram with all entries in the buffer.
Definition TH1.cxx:1445
virtual Double_t GetKurtosis(Int_t axis=1) const
Definition TH1.cxx:7953
2-D histogram with a double per channel (see TH1 documentation)
Definition TH2.h:400
2-D histogram with a float per channel (see TH1 documentation)
Definition TH2.h:345
Helper class to represent a bin in the TH2Poly histogram.
Definition TH2Poly.h:25
2D Histogram with Polygonal Bins
Definition TH2Poly.h:66
static TClass * Class()
Service class for 2-D histogram classes.
Definition TH2.h:30
TH1D * ProjectionY(const char *name="_py", Int_t firstxbin=0, Int_t lastxbin=-1, Option_t *option="") const
Project a 2-D histogram into a 1-D histogram along Y (integration along X).
Definition TH2.cxx:2444
TH1D * ProjectionX(const char *name="_px", Int_t firstybin=0, Int_t lastybin=-1, Option_t *option="") const
Project a 2-D histogram into a 1-D histogram along X (integration along Y).
Definition TH2.cxx:2401
Double_t GetBinContent(Int_t binx, Int_t biny) const override
Definition TH2.h:97
static TClass * Class()
Double_t Integral(Option_t *option="") const override
Return integral of bin contents.
Definition TH2.cxx:1293
The 3-D histogram classes derived from the 1-D histogram classes.
Definition TH3.h:45
static TClass * Class()
The Histogram stack class.
Definition THStack.h:40
static TClass * Class()
The histogram painter class.
static Int_t ProjectSinusoidal2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function code for sinusoidal projection from Ernst-Jan Buis Source https://en....
void Paint(Option_t *option="") override
Control routine to paint any kind of histograms
TAxis * fYaxis
Pointer to Y axis.
std::unique_ptr< TPainter3dAlgorithms > fLego
Pointer to a TPainter3dAlgorithms object.
std::vector< Double_t > fXbuf
X buffer coordinates.
Int_t fXHighlightBin
X highlight bin.
TF3 * fCurrentF3
Current TF3 function.
virtual void PaintErrors(Option_t *option)
Draw 1D histograms error bars.
~THistPainter() override
destructor.
Int_t fShowProjection2
True if a second projection must be drawn (when calling SetShowProjectionXY on a TH2)
virtual void PaintTF3()
Control function to draw a 3D implicit functions.
virtual Int_t TableInit()
Initialize various options to draw 2D histograms.
virtual void PaintTH2PolyScatterPlot(Option_t *option)
Control function to draw a TH2Poly as a scatter plot.
static Int_t ProjectMollweide2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
static Int_t ProjectAitoff2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
virtual void PaintText(Option_t *option)
Control function to draw a 1D/2D histograms with the bin values.
Int_t DistancetoPrimitive(Int_t px, Int_t py) override
Compute the distance from the point px,py to a line.
virtual void PaintAxis(Bool_t drawGridOnly=kFALSE)
Draw axis (2D case) of an histogram.
virtual void PaintColorLevelsFast(Option_t *option)
[Rendering scheme for the COL2 and COLZ2 options] (HP14)
virtual Int_t PaintInit()
Compute histogram parameters used by the drawing routines.
virtual void Paint2DErrors(Option_t *option)
Draw 2D histograms errors.
Int_t fYHighlightBin
Y highlight bin.
virtual void PaintCandlePlot(Option_t *option)
Control function to draw a 2D histogram as a candle (box) plot or violin plot
virtual void PaintScatterPlot(Option_t *option)
Control function to draw a 2D histogram as a scatter plot.
void SetShowProjectionXY(const char *option, Int_t nbinsY, Int_t nbinsX) override
virtual void PaintLego(Option_t *option)
Control function to draw a 2D histogram as a lego plot.
virtual void PaintH3(Option_t *option="")
Control function to draw a 3D histograms.
Int_t fNcuts
Number of graphical cuts.
TString fShowOption
Option to draw the projection.
virtual void PaintHighlightBin(Option_t *option="")
Paint highlight bin as TBox object.
virtual void PaintTH2PolyBins(Option_t *option)
Control function to draw a TH2Poly bins' contours.
virtual Int_t PaintContourLine(Double_t elev1, Int_t icont1, Double_t x1, Double_t y1, Double_t elev2, Int_t icont2, Double_t x2, Double_t y2, Double_t *xarr, Double_t *yarr, Int_t *itarr, Double_t *levels)
Fill the matrix xarr and yarr for Contour Plot.
Int_t fShowProjection
True if a projection must be drawn.
virtual void PaintLegoAxis(TGaxis *axis, Double_t ang)
Draw the axis for legos and surface plots.
virtual void PaintTriangles(Option_t *option)
Control function to draw a table using Delaunay triangles.
virtual void HighlightBin(Int_t px, Int_t py)
Check on highlight bin.
virtual void PaintH3Box(Int_t iopt)
Control function to draw a 3D histogram with boxes.
Int_t MakeCuts(char *cutsopt) override
Decode string choptin and fill Graphical cuts structure.
TList * fFunctions
Pointer to histogram list of functions.
void DrawPanel() override
Display a panel with all histogram drawing options.
std::unique_ptr< TPie > fPie
Pointer to a TPie in case of option PIE.
static void PaintSpecialObjects(const TObject *obj, Option_t *option)
Static function to paint special objects like vectors and matrices.
virtual void PaintTitle()
new TGaxis/////////////////// Draw the histogram title
virtual void PaintTH2PolyColorLevels(Option_t *option)
Control function to draw a TH2Poly as a color plot.
virtual std::vector< THistRenderingRegion > ComputeRenderingRegions(TAxis *pAxis, Int_t nPixels, bool isLog)
Returns the rendering regions for an axis to use in the COL2 option.
virtual void ShowProjectionX(Int_t px, Int_t py)
Show projection onto X.
virtual void PaintPalette()
Paint the color palette on the right side of the pad.
TAxis * fXaxis
Pointer to X axis.
virtual void PaintStat2(Int_t dostat, TF1 *fit)
Draw the statistics box for 2D histograms.
virtual void PaintArrows(Option_t *option)
Control function to draw a table as an arrow plot
virtual void RecalculateRange()
Recompute the histogram range following graphics operations.
void PaintStat(Int_t dostat, TF1 *fit) override
Draw the statistics box for 1D and profile histograms.
static Int_t ProjectParabolic2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function code for parabolic projection from Ernst-Jan Buis.
std::unique_ptr< TGraph2DPainter > fGraph2DPainter
Pointer to a TGraph2DPainter object.
virtual void PaintBarH(Option_t *option)
Draw a bar char in a rotated pad (X vertical, Y horizontal)
virtual void PaintStat3(Int_t dostat, TF1 *fit)
Draw the statistics box for 3D histograms.
virtual void PaintSurface(Option_t *option)
Control function to draw a 2D histogram as a surface plot.
TList * fStack
Pointer to stack of histograms (if any)
THistPainter()
Default constructor.
TH1 * fH
Pointer to histogram to paint.
virtual void PaintTH2PolyText(Option_t *option)
Control function to draw a TH2Poly as a text plot.
virtual void ShowProjection3(Int_t px, Int_t py)
Show projection (specified by fShowProjection) of a TH3.
TAxis * fZaxis
Pointer to Z axis.
void SetHistogram(TH1 *h) override
Set current histogram to h
virtual void PaintFunction(Option_t *option)
[Paint functions associated to an histogram.](HP28")
virtual void PaintBar(Option_t *option)
Draw a bar-chart in a normal pad.
static Int_t ProjectMercator2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
virtual void PaintBoxes(Option_t *option)
Control function to draw a 2D histogram as a box plot
virtual Int_t MakeChopt(Option_t *option)
Decode string choptin and fill Hoption structure.
char * GetObjectInfo(Int_t px, Int_t py) const override
Display the histogram info (bin number, contents, integral up to bin corresponding to cursor position...
TList * GetContourList(Double_t contour) const override
Get a contour (as a list of TGraphs) using the Delaunay triangulation.
void ProcessMessage(const char *mess, const TObject *obj) override
Process message mess.
void SetShowProjection(const char *option, Int_t nbins) override
Set projection.
virtual void ShowProjectionY(Int_t px, Int_t py)
Show projection onto Y.
static const char * GetBestFormat(Double_t v, Double_t e, const char *f)
This function returns the best format to print the error value (e) knowing the parameter value (v) an...
virtual void PaintContour(Option_t *option)
Control function to draw a 2D histogram as a contour plot.
TCutG * fCuts[kMaxCuts]
Pointers to graphical cuts.
virtual void PaintTable(Option_t *option)
Control function to draw 2D/3D histograms (tables).
void ExecuteEvent(Int_t event, Int_t px, Int_t py) override
Execute the actions corresponding to event.
virtual Int_t PaintInitH()
Compute histogram parameters used by the drawing routines for a rotated pad.
virtual void PaintFrame()
Calculate range and clear pad (canvas).
Int_t fCutsOpt[kMaxCuts]
Sign of each cut.
virtual void PaintH3Iso()
Control function to draw a 3D histogram with Iso Surfaces.
std::vector< Double_t > fYbuf
Y buffer coordinates.
virtual void PaintH3BoxRaster()
Control function to draw a 3D histogram with boxes.
virtual void PaintHist(Option_t *option)
Control routine to draw 1D histograms
void SetHighlight() override
Set highlight (enable/disable) mode for fH.
virtual void DefineColorLevels(Int_t ndivz)
Define the color levels used to paint legos, surfaces etc..
TString fObjectInfo
virtual void PaintColorLevels(Option_t *option)
Control function to draw a 2D histogram as a color plot.
Bool_t IsInside(Int_t x, Int_t y) override
Return kTRUE if the cell ix, iy is inside one of the graphical cuts.
A class to define a conversion from pixel values to pixel color.
Definition TAttImage.h:33
static TImagePalette * CreateCOLPalette(Int_t nContours)
Factory method to creates an image palette for histogram plotting.
An abstract interface to image processing library.
Definition TImage.h:29
static TImage * Create()
Create an image.
Definition TImage.cxx:34
void Reset()
To draw Mathematical Formula.
Definition TLatex.h:20
A doubly linked list.
Definition TList.h:38
TObject * FindObject(const char *name) const override
Find an object in this list using its name.
Definition TList.cxx:708
void Add(TObject *obj) override
Definition TList.h:81
TObject * Remove(TObject *obj) override
Remove object from the list.
Definition TList.cxx:952
TObject * First() const override
Return the first object in the list. Returns 0 when list is empty.
Definition TList.cxx:789
virtual TObjLink * FirstLink() const
Definition TList.h:107
TObject * At(Int_t idx) const override
Returns the object at position idx. Returns 0 if idx is out of range.
Definition TList.cxx:487
void AddFirst(TObject *obj) override
Add object at the beginning of the list.
Definition TList.cxx:97
TMatrixTBase.
static TClass * Class()
A TMultiGraph is a collection of TGraph (or derived) objects.
Definition TMultiGraph.h:34
TList * GetListOfGraphs() const
Definition TMultiGraph.h:70
static TClass * Class()
virtual Int_t IsInside(Double_t x, Double_t y) const
Return 1 if the point (x,y) is inside one of the graphs 0 otherwise.
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:50
An array of TObjects.
Definition TObjArray.h:31
Mother of all ROOT objects.
Definition TObject.h:42
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:461
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:204
virtual Option_t * GetDrawOption() const
Get option used by the graphics system to draw this object.
Definition TObject.cxx:444
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1082
virtual TObject * FindObject(const char *name) const
Must be redefined in derived classes.
Definition TObject.cxx:424
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:886
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:548
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1096
virtual const char * GetTitle() const
Returns title of object.
Definition TObject.cxx:506
void ResetBit(UInt_t f)
Definition TObject.h:203
@ kCannotPick
if object in a pad cannot be picked
Definition TObject.h:76
@ kCanDelete
if object in a list can be deleted
Definition TObject.h:71
@ kMustCleanup
if object destructor must call RecursiveRemove()
Definition TObject.h:73
void DrawFaceMove3(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 3rd variant for "MOVING SCREEN" algorithm (draw level lines only)
void DrawLevelLines(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw level lines without hidden line removal.
void SurfaceFunction(Int_t ia, Int_t ib, Double_t *f, Double_t *t)
Service function for Surfaces.
void DrawFaceMode1(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *t)
Draw face - 1st variant (2 colors: 1st for external surface, 2nd for internal)
void GouraudFunction(Int_t ia, Int_t ib, Double_t *f, Double_t *t)
Find part of surface with luminosity in the corners.
void DrawFaceMove1(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 1st variant for "MOVING SCREEN" algorithm (draw face with level lines)
void DrawFaceRaster2(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 2nd variant for "RASTER SCREEN" algorithm (draw face for stacked lego plot)
void LegoFunction(Int_t ia, Int_t ib, Int_t &nv, Double_t *ab, Double_t *vv, Double_t *t)
Service function for Legos.
void DrawFaceMove2(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 2nd variant for "MOVING SCREEN" algorithm (draw face for stacked lego plot)
void DrawFaceRaster1(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 1st variant for "RASTER SCREEN" algorithm (draw face with level lines)
void DrawFaceMode3(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *t)
Draw face - 3rd option (draw face for stacked lego plot)
void DrawFaceMode2(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *t)
Draw face - 2nd option (fill in correspondence with function levels)
The palette painting class.
The histogram statistics painter class.
Definition TPaveStats.h:18
Int_t GetOptStat() const
Return the stat option.
virtual void SetStatFormat(const char *format="6.4g")
Change (i.e. set) the format for printing statistics.
void SetOptStat(Int_t stat=1)
Set the stat option.
virtual const char * GetFitFormat() const
Definition TPaveStats.h:35
virtual void SetFitFormat(const char *format="5.4g")
Change (i.e. set) the format for printing fit parameters in statistics box.
Int_t GetOptFit() const
Return the fit option.
void SetParent(TObject *obj) override
Definition TPaveStats.h:53
void SetOptFit(Int_t fit=1)
Set the fit option.
virtual const char * GetStatFormat() const
Definition TPaveStats.h:36
void Paint(Option_t *option="") override
Paint the pave stat.
static TClass * Class()
A Pave (see TPave) with text, lines or/and boxes inside.
Definition TPaveText.h:21
virtual TText * AddText(Double_t x1, Double_t y1, const char *label)
Add a new Text line to this pavetext at given coordinates.
static TClass * Class()
void Clear(Option_t *option="") override
Clear all lines in this pavetext.
virtual TText * GetLine(Int_t number) const
Get Pointer to line number in this pavetext.
const char * GetName() const override
Returns name of object.
Definition TPave.h:58
virtual void SetName(const char *name="")
Definition TPave.h:81
virtual void SetBorderSize(Int_t bordersize=4)
Sets the border size of the TPave box and shadow.
Definition TPave.h:79
Option_t * GetOption() const override
Definition TPave.h:59
Double_t GetX1NDC() const
Definition TPave.h:61
virtual void SetX2NDC(Double_t x2)
Definition TPave.h:85
void SetX(SCoord_t x)
Definition TPoint.h:48
void SetY(SCoord_t y)
Definition TPoint.h:49
Profile2D histograms are used to display the mean value of Z and its error for each cell in X,...
Definition TProfile2D.h:27
static TClass * Class()
Profile Histogram.
Definition TProfile.h:32
static TClass * Class()
Random number generator class based on the maximally equidistributed combined Tausworthe generator by...
Definition TRandom2.h:27
Sequenceable collection abstract base class.
Basic string class.
Definition TString.h:137
void ToLower()
Change string to lower-case.
Definition TString.cxx:1190
const char * Data() const
Definition TString.h:385
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2460
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2438
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:642
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:661
Int_t GetOptStat() const
Definition TStyle.h:247
Color_t GetStatTextColor() const
Definition TStyle.h:260
Float_t GetTitleX() const
Definition TStyle.h:282
Int_t GetOptTitle() const
Definition TStyle.h:248
Float_t GetStatFontSize() const
Definition TStyle.h:263
Float_t GetBarOffset() const
Definition TStyle.h:184
Float_t GetStatX() const
Definition TStyle.h:266
Float_t GetTitleSize(Option_t *axis="X") const
Return title size.
Definition TStyle.cxx:1241
Float_t GetTitleY() const
Definition TStyle.h:283
Style_t GetTitleFont(Option_t *axis="X") const
Return title font.
Definition TStyle.cxx:1217
Bool_t GetHistMinimumZero() const
Definition TStyle.h:239
Float_t GetStatY() const
Definition TStyle.h:267
Color_t GetTitleFillColor() const
Definition TStyle.h:273
Style_t GetTitleStyle() const
Definition TStyle.h:275
Color_t GetStatColor() const
Definition TStyle.h:259
Float_t GetBarWidth() const
Definition TStyle.h:185
void SetDrawBorder(Int_t drawborder=1)
Definition TStyle.h:346
Float_t GetStatH() const
Definition TStyle.h:269
Width_t GetTitleBorderSize() const
Definition TStyle.h:277
Int_t GetColorPalette(Int_t i) const
Return color number i in current palette.
Definition TStyle.cxx:1102
Float_t GetErrorX() const
Definition TStyle.h:188
Double_t GetHistTopMargin() const
Definition TStyle.h:240
void SetBarOffset(Float_t baroff=0.5)
Definition TStyle.h:339
Float_t GetEndErrorSize() const
Definition TStyle.h:187
Int_t GetDrawBorder() const
Definition TStyle.h:186
Width_t GetStatBorderSize() const
Definition TStyle.h:261
Color_t GetTitleTextColor() const
Definition TStyle.h:274
void SetBarWidth(Float_t barwidth=0.5)
Definition TStyle.h:340
Float_t GetTitleH() const
Definition TStyle.h:285
Style_t GetStatStyle() const
Definition TStyle.h:264
Float_t GetStatW() const
Definition TStyle.h:268
const char * GetFitFormat() const
Definition TStyle.h:201
const char * GetStatFormat() const
Definition TStyle.h:265
Int_t GetNumberOfColors() const
Return number of colors in the color palette.
Definition TStyle.cxx:1176
Int_t GetOptFit() const
Definition TStyle.h:246
Int_t GetNumberContours() const
Definition TStyle.h:243
const char * GetPaintTextFormat() const
Definition TStyle.h:252
Style_t GetStatFont() const
Definition TStyle.h:262
Float_t GetTitleFontSize() const
Definition TStyle.h:276
Int_t GetTitleAlign() const
Definition TStyle.h:272
Float_t GetTitleW() const
Definition TStyle.h:284
virtual int Load(const char *module, const char *entry="", Bool_t system=kFALSE)
Load a shared library.
Definition TSystem.cxx:1872
Base class for several text objects.
Definition TText.h:22
TVectorT.
Definition TVectorT.h:29
static TClass * Class()
See TView3D.
Definition TView.h:25
virtual Double_t GetPsi()=0
virtual Double_t * GetRmax()=0
virtual void SetAxisNDC(const Double_t *x1, const Double_t *x2, const Double_t *y1, const Double_t *y2, const Double_t *z1, const Double_t *z2)=0
virtual Double_t * GetRmin()=0
virtual void WCtoNDC(const Float_t *pw, Float_t *pn)=0
virtual void SetOutlineToCube()=0
virtual Int_t GetDistancetoAxis(Int_t axis, Int_t px, Int_t py, Double_t &ratio)=0
virtual Double_t * GetTnorm()=0
virtual void ExecuteRotateView(Int_t event, Int_t px, Int_t py)=0
virtual TSeqCollection * GetOutline()=0
virtual void PadRange(Int_t rback)=0
virtual void SetRange(const Double_t *min, const Double_t *max)=0
virtual void FindNormal(Double_t x, Double_t y, Double_t z, Double_t &zn)=0
virtual void AxisVertex(Double_t ang, Double_t *av, Int_t &ix1, Int_t &ix2, Int_t &iy1, Int_t &iy2, Int_t &iz1, Int_t &iz2)=0
virtual void SetView(Double_t longitude, Double_t latitude, Double_t psi, Int_t &irep)=0
Abstract base class used by ROOT graphics editor.
static TVirtualPadEditor * GetPadEditor(Bool_t load=kTRUE)
Returns the pad editor dialog. Static method.
small helper class to store/restore gPad context in TPad methods
Definition TVirtualPad.h:61
TVirtualPad is an abstract base class for the Pad and Canvas classes.
Definition TVirtualPad.h:51
TLine * line
void box(Int_t pat, Double_t x1, Double_t y1, Double_t x2, Double_t y2)
Definition fillpatterns.C:1
Double_t y[n]
Definition legend1.C:17
return c1
Definition legend1.C:41
Double_t x[n]
Definition legend1.C:17
Double_t ey[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
Double_t ex[n]
Definition legend1.C:17
TH1F * h1
Definition legend1.C:5
TF1 * f1
Definition legend1.C:11
return c2
Definition legend2.C:14
Int_t Nint(T x)
Round to nearest integer. Rounds half integers to the nearest even integer.
Definition TMath.h:706
Short_t Max(Short_t a, Short_t b)
Returns the largest of a and b.
Definition TMathBase.h:249
Double_t Prob(Double_t chi2, Int_t ndf)
Computation of the probability for a certain Chi-squared (chi2) and number of degrees of freedom (ndf...
Definition TMath.cxx:637
Double_t ATan(Double_t)
Returns the principal value of the arc tangent of x, expressed in radians.
Definition TMath.h:653
constexpr Double_t PiOver2()
Definition TMath.h:54
Double_t Log(Double_t x)
Returns the natural logarithm of x.
Definition TMath.h:769
constexpr Double_t DegToRad()
Conversion from degree to radian: .
Definition TMath.h:82
Double_t Sqrt(Double_t x)
Returns the square root of x.
Definition TMath.h:675
LongDouble_t Power(LongDouble_t x, LongDouble_t y)
Returns x raised to the power y.
Definition TMath.h:734
Short_t Min(Short_t a, Short_t b)
Returns the smallest of a and b.
Definition TMathBase.h:197
Double_t Cos(Double_t)
Returns the cosine of an angle of x radians.
Definition TMath.h:607
constexpr Double_t Pi()
Definition TMath.h:40
Bool_t AreEqualRel(Double_t af, Double_t bf, Double_t relPrec)
Comparing floating points.
Definition TMath.h:429
Double_t Sin(Double_t)
Returns the sine of an angle of x radians.
Definition TMath.h:601
Double_t Tan(Double_t)
Returns the tangent of an angle of x radians.
Definition TMath.h:613
Long64_t BinarySearch(Long64_t n, const T *array, T value)
Binary search in an array of n values to locate value.
Definition TMathBase.h:329
constexpr Double_t RadToDeg()
Conversion from radian to degree: .
Definition TMath.h:75
Double_t Log10(Double_t x)
Returns the common (base-10) logarithm of x.
Definition TMath.h:775
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:122
Histograms' drawing options structure.
Definition Hoption.h: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