Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
THistPainter.cxx
Go to the documentation of this file.
1// @(#)root/histpainter:$Id$
2// Author: Rene Brun, Olivier Couet
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12#include <cstdlib>
13#include <cstring>
14#include <cstdio>
15#include <cctype>
16#include <iostream>
17
18#include "TROOT.h"
19#include "TSystem.h"
20#include "THistPainter.h"
21#include "TH2.h"
22#include "TH2Poly.h"
23#include "TH3.h"
24#include "TProfile.h"
25#include "TProfile2D.h"
26#include "THStack.h"
27#include "TF2.h"
28#include "TF3.h"
29#include "TCutG.h"
30#include "TMatrixDBase.h"
31#include "TMatrixFBase.h"
32#include "TVectorD.h"
33#include "TVectorF.h"
34#include "TCanvas.h"
35#include "TPad.h"
36#include "TPaveStats.h"
37#include "TFrame.h"
38#include "TLatex.h"
39#include "TPolyLine.h"
40#include "TPoints.h"
41#include "TStyle.h"
42#include "TGraph.h"
43#include "TMultiGraph.h"
44#include "TPie.h"
45#include "TGaxis.h"
46#include "TColor.h"
48#include "TGraph2D.h"
49#include "TGraph2DPainter.h"
50#include "TGraphDelaunay2D.h"
51#include "TView.h"
52#include "TMath.h"
53#include "TRandom2.h"
54#include "TObjArray.h"
55#include "Hoption.h"
56#include "Hparam.h"
57#include "TPluginManager.h"
58#include "TPaletteAxis.h"
59#include "TCrown.h"
60#include "TArrow.h"
61#include "TVirtualPadEditor.h"
62#include "TVirtualX.h"
63#include "TEnv.h"
64#include "TPoint.h"
65#include "TImage.h"
66#include "TCandle.h"
67#include "strlcpy.h"
68
69/*! \class THistPainter
70 \ingroup Histpainter
71 \brief The histogram painter class. Implements all histograms' drawing's options.
72
73- [Introduction](\ref HP00)
74- [Histograms' plotting options](\ref HP01)
75 - [Options supported for 1D and 2D histograms](\ref HP01a)
76 - [Options supported for 1D histograms](\ref HP01b)
77 - [Options supported for 2D histograms](\ref HP01c)
78 - [Options supported for 3D histograms](\ref HP01d)
79 - [Options supported for histograms' stacks (THStack)](\ref HP01e)
80- [Setting the Style](\ref HP02)
81- [Setting line, fill, marker, and text attributes](\ref HP03)
82- [Setting Tick marks on the histogram axis](\ref HP04)
83- [Giving titles to the X, Y and Z axis](\ref HP05)
84- [The option SAME](\ref HP060)
85 - [Limitations](\ref HP060a)
86- [Colors automatically picked in palette](\ref HP061)
87- [Superimposing two histograms with different scales in the same pad](\ref HP06)
88- [Statistics Display](\ref HP07)
89- [Fit Statistics](\ref HP08)
90- [The error bars options](\ref HP09)
91- [The bar chart option](\ref HP100)
92- [The BAR and HBAR options](\ref HP10)
93- [The SCATter plot option (legacy draw option)](\ref HP11)
94- [The ARRow option](\ref HP12)
95- [The BOX option](\ref HP13)
96- [The COLor option (default for 2D and 3D histograms)](\ref HP14)
97- [The CANDLE and VIOLIN options](\ref HP140)
98 - [The CANDLE option](\ref HP140a)
99 - [The VIOLIN option](\ref HP140b)
100- [The TEXT and TEXTnn Option](\ref HP15)
101- [The CONTour options](\ref HP16)
102 - [The LIST option](\ref HP16a)
103 - [The AITOFF, MERCATOR, SINUSOIDAL and PARABOLIC options](\ref HP16b)
104- [The LEGO options](\ref HP17)
105- [The SURFace options](\ref HP18)
106- [Cylindrical, Polar, Spherical and PseudoRapidity/Phi options](\ref HP19)
107- [Base line for bar-charts and lego plots](\ref HP20)
108- [TH2Poly Drawing](\ref HP20a)
109- [The SPEC option](\ref HP21)
110- [Option Z : Adding the color palette on the right side of the pad](\ref HP22)
111- [Setting the color palette](\ref HP23)
112- [Drawing a sub-range of a 2-D histogram; the [cutg] option](\ref HP24)
113- [Drawing options for 3D histograms](\ref HP25)
114- [Drawing option for histograms' stacks](\ref HP26)
115- [Drawing of 3D implicit functions](\ref HP27)
116- [Associated functions drawing](\ref HP28)
117- [Drawing using OpenGL](\ref HP29)
118 - [General information: plot types and supported options](\ref HP29a)
119 - [TH3 as color boxes](\ref HP290)
120 - [TH3 as boxes (spheres)](\ref HP29b)
121 - [TH3 as iso-surface(s)](\ref HP29c)
122 - [TF3 (implicit function)](\ref HP29d)
123 - [Parametric surfaces](\ref HP29e)
124 - [Interaction with the plots](\ref HP29f)
125 - [Selectable parts](\ref HP29g)
126 - [Rotation and zooming](\ref HP29h)
127 - [Panning](\ref HP29i)
128 - [Box cut](\ref HP29j)
129 - [Plot specific interactions (dynamic slicing etc.)](\ref HP29k)
130 - [Surface with option GLSURF](\ref HP29l)
131 - [TF3](\ref HP29m)
132 - [Box](\ref HP29n)
133 - [Iso](\ref HP29o)
134 - [Parametric plot](\ref HP29p)
135- [Highlight mode for histogram](\ref HP30)
136 - [Highlight mode and user function](\ref HP30a)
137
138
139\anchor HP00
140## Introduction
141
142
143Histograms are drawn via the `THistPainter` class. Each histogram has a
144pointer to its own painter (to be usable in a multithreaded program). When the
145canvas has to be redrawn, the `Paint` function of each objects in the
146pad is called. In case of histograms, `TH1::Paint` invokes directly
147`THistPainter::Paint`.
148
149To draw a histogram `h` it is enough to do:
150
151 h->Draw();
152
153`h` can be of any kind: 1D, 2D or 3D. To choose how the histogram will
154be drawn, the `Draw()` method can be invoked with an option. For instance
155to draw a 2D histogram as a lego plot it is enough to do:
156
157 h->Draw("lego");
158
159`THistPainter` offers many options to paint 1D, 2D and 3D histograms.
160
161When the `Draw()` method of a histogram is called for the first time
162(`TH1::Draw`), it creates a `THistPainter` object and saves a
163pointer to this "painter" as a data member of the histogram. The
164`THistPainter` class specializes in the drawing of histograms. It is
165separated from the histogram so that one can have histograms without the
166graphics overhead, for example in a batch program. Each histogram having its own
167painter (rather than a central singleton painter painting all histograms), allows
168two histograms to be drawn in two threads without overwriting the painter's
169values.
170
171When a displayed histogram is filled again, there is no need to call the
172`Draw()` method again; the image will be refreshed the next time the
173pad will be updated.
174
175A pad is updated after one of these three actions:
176
1771. a carriage control on the ROOT command line,
1782. a click inside the pad,
1793. a call to `TPad::Update`.
180
181
182By default a call to `TH1::Draw()` clears the pad of all objects
183before drawing the new image of the histogram. One can use the `SAME`
184option to leave the previous display intact and superimpose the new histogram.
185The same histogram can be drawn with different graphics options in different
186pads.
187
188When a displayed histogram is deleted, its image is automatically removed
189from the pad.
190
191To create a copy of the histogram when drawing it, one can use
192`TH1::DrawClone()`. This will clone the histogram and allow to change
193and delete the original one without affecting the clone.
194
195
196\anchor HP01
197### Histograms' plotting options
198
199
200Most options can be concatenated with or without spaces or commas, for example:
201
202 h->Draw("E1 SAME");
203
204The options are not case sensitive:
205
206 h->Draw("e1 same");
207
208
209The default drawing option can be set with `TH1::SetOption` and retrieve
210using `TH1::GetOption`:
211
212 root [0] h->Draw(); // Draw "h" using the standard histogram representation.
213 root [1] h->Draw("E"); // Draw "h" using error bars
214 root [3] h->SetOption("E"); // Change the default drawing option for "h"
215 root [4] h->Draw(); // Draw "h" using error bars
216 root [5] h->GetOption(); // Retrieve the default drawing option for "h"
217 (const Option_t* 0xa3ff948)"E"
218
219
220\anchor HP01a
221#### Options supported for 1D and 2D histograms
222
223| Option | Description |
224|----------|-------------------------------------------------------------------|
225| "E" | Draw error bars. |
226| "AXIS" | Draw only axis. |
227| "AXIG" | Draw only grid (if the grid is requested). |
228| \anchor OPTHIST "HIST" | When an histogram has errors it is visualized by default with error bars. To visualize it without errors use the option "HIST" together with the required option (eg "hist same c"). The "HIST" option can also be used to plot only the histogram and not the associated function(s). |
229| "FUNC" | When an histogram has a fitted function, this option allows to draw the fit result only. |
230| "SAME" | Superimpose on previous picture in the same pad. |
231| "SAMES" | Same as "SAME" and draw the statistics box|
232| "PFC" | Palette Fill Color: histogram's fill color is taken in the current palette. |
233| "PLC" | Palette Line Color: histogram's line color is taken in the current palette. |
234| "PMC" | Palette Marker Color: histogram's marker color is taken in the current palette. |
235| "LEGO" | Draw a lego plot with hidden line removal. |
236| "LEGO1" | Draw a lego plot with hidden surface removal. |
237| "LEGO2" | Draw a lego plot using colors to show the cell contents When the option "0" is used with any LEGO option, the empty bins are not drawn.|
238| "LEGO3" | Draw a lego plot with hidden surface removal, like LEGO1 but the border lines of each lego-bar are not drawn.|
239| "LEGO4" | Draw a lego plot with hidden surface removal, like LEGO1 but without the shadow effect on each lego-bar.|
240| "TEXT" | Draw bin contents as text (format set via `gStyle->SetPaintTextFormat`).|
241| "TEXTnn" | Draw bin contents as text at angle nn (0 < nn <= 90). |
242| "X+" | The X-axis is drawn on the top side of the plot. |
243| "Y+" | The Y-axis is drawn on the right side of the plot. |
244| "MIN0" | Set minimum value for the Y axis to 0, equivalent to gStyle->SetHistMinimumZero(). |
245
246
247\anchor HP01b
248#### Options supported for 1D histograms
249
250| Option | Description |
251|----------|-------------------------------------------------------------------|
252| " " | Default. |
253| "AH" | Draw histogram without axis. "A" can be combined with any drawing option. For instance, "AC" draws the histogram as a smooth Curve without axis.|
254| "][" | When this option is selected the first and last vertical lines of the histogram are not drawn.|
255| "B" | Bar chart option.|
256| "BAR" | Like option "B", but bars can be drawn with a 3D effect.|
257| "HBAR" | Like option "BAR", but bars are drawn horizontally.|
258| "C" | Draw a smooth Curve through the histogram bins.|
259| "E0" | Draw error bars. Markers are drawn for bins with 0 contents. Combined with E1 or E2 it avoids error bars clipping|
260| "E1" | Draw error bars with perpendicular lines at the edges.|
261| "E2" | Draw error bars with rectangles.|
262| "E3" | Draw a fill area through the end points of the vertical error bars.|
263| "E4" | Draw a smoothed filled area through the end points of the error bars.|
264| "E5" | Like E3 but ignore the bins with 0 contents.|
265| "E6" | Like E4 but ignore the bins with 0 contents.|
266| "X0" | When used with one of the "E" option, it suppress the error bar along X as `gStyle->SetErrorX(0)` would do.|
267| "L" | Draw a line through the bin contents.|
268| "P" | Draw current marker at each bin except empty bins.|
269| "P*" | Draw a star marker at each bin except empty bins.|
270| "P0" | Draw current marker at each bin including empty bins.|
271| "PIE" | Draw histogram as a Pie Chart.|
272| "*H" | Draw histogram with a * at each bin.|
273| "LF2" | Draw histogram like with option "L" but with a fill area. Note that "L" draws also a fill area if the hist fill color is set but the fill area corresponds to the histogram contour.|
274
275
276
277\anchor HP01c
278#### Options supported for 2D histograms
279
280| Option | Description |
281|--------------|------------------------------------------------------------------|
282| " " | Default (color plot).|
283| "ARR" | Arrow mode. Shows gradient between adjacent cells.|
284| "BOX" | A box is drawn for each cell with surface proportional to the content's absolute value. A negative content is marked with a X. |
285| "BOX1" | A button is drawn for each cell with surface proportional to content's absolute value. A sunken button is drawn for negative values a raised one for positive.|
286| "COL" | A box is drawn for each cell with a color scale varying with contents. All the none empty bins (bins with content and error equal to 0) are painted. Empty bins are not painted unless some bins have a negative content because in that case the null bins might be not empty. `TProfile2D` histograms are handled differently because, for this type of 2D histograms, it is possible to know if an empty bin has been filled or not. So even if all the bins' contents are positive some empty bins might be painted. And vice versa, if some bins have a negative content some empty bins might be not painted (default).|
287| "COL1" | Same as "COL" but in case of histogram with negative content the empty bins are not drawn.
288| "COLZ" | Same as "COL". In addition the color palette is also drawn.|
289| "COL2" | Alternative rendering algorithm to "COL". Can significantly improve rendering performance for large, non-sparse 2-D histograms.|
290| "COLZ2" | Same as "COL2". In addition the color palette is also drawn.|
291| "Z CJUST" | In combination with colored options "COL","CONT0" etc: Justify labels in the color palette at color boundaries. For more details see `TPaletteAxis`|
292| "CANDLE" | Draw a candle plot along X axis.|
293| "CANDLEX" | Same as "CANDLE".|
294| "CANDLEY" | Draw a candle plot along Y axis.|
295| "CANDLEXn" | Draw a candle plot along X axis. Different candle-styles with n from 1 to 6.|
296| "CANDLEYn" | Draw a candle plot along Y axis. Different candle-styles with n from 1 to 6.|
297| "VIOLIN" | Draw a violin plot along X axis.|
298| "VIOLINX" | Same as "VIOLIN".|
299| "VIOLINY" | Draw a violin plot along Y axis.|
300| "VIOLINXn" | Draw a violin plot along X axis. Different violin-styles with n being 1 or 2.|
301| "VIOLINYn" | Draw a violin plot along Y axis. Different violin-styles with n being 1 or 2.|
302| "CONT" | Draw a contour plot (same as CONT0).|
303| "CONT0" | Draw a contour plot using surface colors to distinguish contours.|
304| "CONT1" | Draw a contour plot using line styles to distinguish contours.|
305| "CONT2" | Draw a contour plot using the same line style for all contours.|
306| "CONT3" | Draw a contour plot using fill area colors.|
307| "CONT4" | Draw a contour plot using surface colors (SURF option at theta = 0).|
308| "LIST" | Generate a list of TGraph objects for each contour.|
309| "SAME0" | Same as "SAME" but do not use the z-axis range of the first plot. |
310| "SAMES0" | Same as "SAMES" but do not use the z-axis range of the first plot. |
311| "CYL" | Use Cylindrical coordinates. The X coordinate is mapped on the angle and the Y coordinate on the cylinder length.|
312| "POL" | Use Polar coordinates. The X coordinate is mapped on the angle and the Y coordinate on the radius.|
313| "SPH" | Use Spherical coordinates. The X coordinate is mapped on the latitude and the Y coordinate on the longitude.|
314| "PSR" | Use PseudoRapidity/Phi coordinates. The X coordinate is mapped on Phi.|
315| "SURF" | Draw a surface plot with hidden line removal.|
316| "SURF1" | Draw a surface plot with hidden surface removal.|
317| "SURF2" | Draw a surface plot using colors to show the cell contents.|
318| "SURF3" | Same as SURF with in addition a contour view drawn on the top.|
319| "SURF4" | Draw a surface using Gouraud shading.|
320| "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.|
321| "AITOFF" | Draw a contour via an AITOFF projection.|
322| "MERCATOR" | Draw a contour via an Mercator projection.|
323| "SINUSOIDAL" | Draw a contour via an Sinusoidal projection.|
324| "PARABOLIC" | Draw a contour via an Parabolic projection.|
325| "MOLLWEIDE" | Draw a contour via an Mollweide projection.|
326| "LEGO9" | Draw the 3D axis only. Mainly needed for internal use |
327| "FB" | With LEGO or SURFACE, suppress the Front-Box.|
328| "BB" | With LEGO or SURFACE, suppress the Back-Box.|
329| "A" | With LEGO or SURFACE, suppress the axis.|
330| "SCAT" | Draw a scatter-plot (legacy draw option).|
331| "[cutg]" | Draw only the sub-range selected by the TCutG named "cutg".|
332
333
334
335\anchor HP01d
336#### Options supported for 3D histograms
337
338| Option | Description |
339|----------|-------------------------------------------------------------------|
340| " " | Default (color plot).|
341| "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)`.|
342| "BOX" | Draw a for each cell with volume proportional to the content's absolute value. An hidden line removal algorithm is used|
343| "BOX1" | Same as BOX but an hidden surface removal algorithm is used|
344| "BOX2" | The boxes' colors are picked in the current palette according to the bins' contents|
345| "BOX2Z" | Same as "BOX2". In addition the color palette is also drawn.|
346| "BOX3" | Same as BOX1, but the border lines of each lego-bar are not drawn.|
347| "LEGO" | Same as `BOX`.|
348
349\anchor HP01e
350#### Options supported for histograms' stacks (`THStack`)
351
352| Option | Description |
353|------------|-----------------------------------------------------------------|
354| " " | Default, the histograms are drawn on top of each other (as lego plots for 2D histograms).|
355| "NOSTACK" | Histograms in the stack are all paint in the same pad as if the option `SAME` had been specified.|
356| "NOSTACKB" | Histograms are drawn next to each other as bar charts.|
357| "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.|
358| "PFC" | Palette Fill Color: stack's fill color is taken in the current palette. |
359| "PLC" | Palette Line Color: stack's line color is taken in the current palette. |
360| "PMC" | Palette Marker Color: stack's marker color is taken in the current palette. |
361
362
363
364\anchor HP02
365### Setting the Style
366
367
368Histograms use the current style (`gStyle`). When one changes the current
369style and would like to propagate the changes to the histogram,
370`TH1::UseCurrentStyle` should be called. Call `UseCurrentStyle` on
371each histogram is needed.
372
373To force all the histogram to use the current style use:
374
375 gROOT->ForceStyle();
376
377All the histograms read after this call will use the current style.
378
379
380\anchor HP03
381### Setting line, fill, marker, and text attributes
382
383
384The histogram classes inherit from the attribute classes:
385`TAttLine`, `TAttFill` and `TAttMarker`.
386See the description of these classes for the list of options.
387
388
389\anchor HP04
390### Setting Tick marks on the histogram axis
391
392
393The `TPad::SetTicks` method specifies the type of tick marks on the axis.
394If ` tx = gPad->GetTickx()` and `ty = gPad->GetTicky()` then:
395
396 tx = 1; tick marks on top side are drawn (inside)
397 tx = 2; tick marks and labels on top side are drawn
398 ty = 1; tick marks on right side are drawn (inside)
399 ty = 2; tick marks and labels on right side are drawn
400
401By default only the left Y axis and X bottom axis are drawn
402(`tx = ty = 0`)
403
404`TPad::SetTicks(tx,ty)` allows to set these options.
405See also The `TAxis` functions to set specific axis attributes.
406
407In case multiple color filled histograms are drawn on the same pad, the fill
408area may hide the axis tick marks. One can force a redraw of the axis over all
409the histograms by calling:
410
411 gPad->RedrawAxis();
412
413
414\anchor HP05
415### Giving titles to the X, Y and Z axis
416
417
418 h->GetXaxis()->SetTitle("X axis title");
419 h->GetYaxis()->SetTitle("Y axis title");
420
421The histogram title and the axis titles can be any `TLatex` string.
422The titles are part of the persistent histogram.
423
424
425\anchor HP060
426### The option "SAME"
427
428
429By default, when an histogram is drawn, the current pad is cleared before
430drawing. In order to keep the previous drawing and draw on top of it the
431option `SAME` should be use. The histogram drawn with the option
432`SAME` uses the coordinates system available in the current pad.
433
434This option can be used alone or combined with any valid drawing option but
435some combinations must be use with care.
436
437\anchor HP060a
438#### Limitations
439
440- It does not work when combined with the `LEGO` and `SURF` options unless the
441 histogram plotted with the option `SAME` has exactly the same
442 ranges on the X, Y and Z axis as the currently drawn histogram. To superimpose
443 lego plots [histograms' stacks](\ref HP26) should be used.
444
445
446\anchor HP061
447### Colors automatically picked in palette
448
449\since **ROOT version 6.09/01**
450
451When several histograms are painted in the same canvas thanks to the option "SAME"
452or via a `THStack` it might be useful to have an easy and automatic way to choose
453their color. The simplest way is to pick colors in the current active color
454palette. Palette coloring for histogram is activated thanks to the options `PFC`
455(Palette Fill Color), `PLC` (Palette Line Color) and `PMC` (Palette Marker Color).
456When one of these options is given to `TH1::Draw` the histogram get its color
457from the current color palette defined by `gStyle->SetPalette(...)`. The color
458is determined according to the number of objects having palette coloring in
459the current pad.
460
461Begin_Macro(source)
462../../../tutorials/hist/hist005_TH1_palettecolor.C
463End_Macro
464
465Begin_Macro(source)
466../../../tutorials/hist/hist027_THStack_palette_color.C
467End_Macro
468
469Begin_Macro(source)
470../../../tutorials/hist/hist025_THStack_2d_palette_color.C
471End_Macro
472
473\anchor HP06
474### Superimposing two histograms with different scales in the same pad
475
476
477The following example creates two histograms, the second histogram is the bins
478integral of the first one. It shows a procedure to draw the two histograms in
479the same pad and it draws the scale of the second histogram using a new vertical
480axis on the right side. See also the tutorial `transpad.C` for a variant
481of this example.
482
483Begin_Macro(source)
484{
485 auto c1 = new TCanvas("c1","c1",600,400);
486 // create/fill draw h1
487 gStyle->SetOptStat(kFALSE);
488 auto h1 = new TH1F("h1","Superimposing two histograms with different scales",100,-3,3);
489 Int_t i;
490 for (i=0;i<10000;i++) h1->Fill(gRandom->Gaus(0,1));
491 h1->Draw();
492 c1->Update();
493
494 // create hint1 filled with the bins integral of h1
495 auto hint1 = new TH1F("hint1","h1 bins integral",100,-3,3);
496 float sum = 0.f;
497 for (i=1;i<=100;i++) {
498 sum += h1->GetBinContent(i);
499 hint1->SetBinContent(i,sum);
500 }
501
502 // scale hint1 to the pad coordinates
503 float rightmax = 1.1*hint1->GetMaximum();
504 float scale = gPad->GetUymax()/rightmax;
505 hint1->SetLineColor(kRed);
506 hint1->Scale(scale);
507 hint1->Draw("same");
508
509 // draw an axis on the right side
510 auto axis = new TGaxis(gPad->GetUxmax(),gPad->GetUymin(),
511 gPad->GetUxmax(), gPad->GetUymax(),0,rightmax,510,"+L");
512 axis->SetLineColor(kRed);
513 axis->SetTextColor(kRed);
514 axis->Draw();
515}
516End_Macro
517
518
519\anchor HP07
520### Statistics Display
521
522
523The type of information shown in the histogram statistics box can be selected
524with:
525
526 gStyle->SetOptStat(mode);
527
528The `mode` has up to nine digits that can be set to on (1 or 2), off (0).
529
530 mode = ksiourmen (default = 000001111)
531 k = 1; kurtosis printed
532 k = 2; kurtosis and kurtosis error printed
533 s = 1; skewness printed
534 s = 2; skewness and skewness error printed
535 i = 1; integral of bins printed
536 i = 2; integral of bins with option "width" printed
537 o = 1; number of overflows printed
538 u = 1; number of underflows printed
539 r = 1; standard deviation printed
540 r = 2; standard deviation and standard deviation error printed
541 m = 1; mean value printed
542 m = 2; mean and mean error values printed
543 e = 1; number of entries printed
544 n = 1; name of histogram is printed
545
546For example:
547
548 gStyle->SetOptStat(11);
549
550displays only the name of histogram and the number of entries, whereas:
551
552 gStyle->SetOptStat(1101);
553
554displays the name of histogram, mean value and standard deviation.
555
556<b>WARNING 1:</b> never do:
557
558 gStyle->SetOptStat(0001111);
559
560but instead do:
561
562 gStyle->SetOptStat(1111);
563
564because `0001111` will be taken as an octal number!
565
566<b>WARNING 2:</b> for backward compatibility with older versions
567
568 gStyle->SetOptStat(1);
569
570is taken as:
571
572 gStyle->SetOptStat(1111)
573
574To print only the name of the histogram do:
575
576 gStyle->SetOptStat(1000000001);
577
578<b>NOTE</b> that in case of 2D histograms, when selecting only underflow
579(10000) or overflow (100000), the statistics box will show all combinations
580of underflow/overflows and not just one single number.
581
582The parameter mode can be any combination of the letters `kKsSiIourRmMen`
583
584 k : kurtosis printed
585 K : kurtosis and kurtosis error printed
586 s : skewness printed
587 S : skewness and skewness error printed
588 i : integral of bins printed
589 I : integral of bins with option "width" printed
590 o : number of overflows printed
591 u : number of underflows printed
592 r : standard deviation printed
593 R : standard deviation and standard deviation error printed
594 m : mean value printed
595 M : mean value mean error values printed
596 e : number of entries printed
597 n : name of histogram is printed
598
599For example, to print only name of histogram and number of entries do:
600
601 gStyle->SetOptStat("ne");
602
603To print only the name of the histogram do:
604
605 gStyle->SetOptStat("n");
606
607The default value is:
608
609 gStyle->SetOptStat("nemr");
610
611When a histogram is painted, a `TPaveStats` object is created and added
612to the list of functions of the histogram. If a `TPaveStats` object
613already exists in the histogram list of functions, the existing object is just
614updated with the current histogram parameters.
615
616Once a histogram is painted, the statistics box can be accessed using
617`h->FindObject("stats")`. In the command line it is enough to do:
618
619 Root > h->Draw()
620 Root > TPaveStats *st = (TPaveStats*)h->FindObject("stats")
621
622because after `h->Draw()` the histogram is automatically painted. But
623in a script file the painting should be forced using `gPad->Update()`
624in order to make sure the statistics box is created:
625
626 h->Draw();
627 gPad->Update();
628 TPaveStats *st = (TPaveStats*)h->FindObject("stats");
629
630Without `gPad->Update()` the line `h->FindObject("stats")` returns a null pointer.
631
632When a histogram is drawn with the option `SAME`, the statistics box
633is not drawn. To force the statistics box drawing with the option
634`SAME`, the option `SAMES` must be used.
635If the new statistics box hides the previous statistics box, one can change
636its position with these lines (`h` being the pointer to the histogram):
637
638 Root > TPaveStats *st = (TPaveStats*)h->FindObject("stats")
639 Root > st->SetX1NDC(newx1); //new x start position
640 Root > st->SetX2NDC(newx2); //new x end position
641
642To change the type of information for an histogram with an existing
643`TPaveStats` one should do:
644
645 st->SetOptStat(mode);
646
647Where `mode` has the same meaning than when calling `gStyle->SetOptStat(mode)`
648(see above).
649
650One can delete the statistics box for a histogram `TH1* h` with:
651
652 h->SetStats(0)
653
654and activate it again with:
655
656 h->SetStats(1).
657
658Labels used in the statistics box ("Mean", "Std Dev", ...) can be changed from
659`$ROOTSYS/etc/system.rootrc` or `.rootrc` (look for the string `Hist.Stats.`).
660
661
662\anchor HP08
663### Fit Statistics
664
665
666The type of information about fit parameters printed in the histogram statistics
667box can be selected via the parameter mode. The parameter mode can be
668`= pcev` (default `= 0111`)
669
670 p = 1; print Probability
671 c = 1; print Chisquare/Number of degrees of freedom
672 e = 1; print errors (if e=1, v must be 1)
673 v = 1; print name/values of parameters
674
675Example:
676
677 gStyle->SetOptFit(1011);
678
679print fit probability, parameter names/values and errors.
680
6811. When `v = 1` is specified, only the non-fixed parameters are shown.
6822. When `v = 2` all parameters are shown.
683
684Note: `gStyle->SetOptFit(1)` means "default value", so it is equivalent
685to `gStyle->SetOptFit(111)`
686
687
688\anchor HP09
689### The error bars options
690
691
692| Option | Description |
693|----------|-------------------------------------------------------------------|
694| "E" | Default. Shows only the error bars, not a marker.|
695| "E1" | Small lines are drawn at the end of the error bars.|
696| "E2" | Error rectangles are drawn.|
697| "E3" | A filled area is drawn through the end points of the vertical error bars.|
698| "E4" | A smoothed filled area is drawn through the end points of the vertical error bars.|
699| "E0" | Draw error bars. Markers are drawn for bins with 0 contents. Combined with E1 or E2 it avoids error bars clipping|
700| "E5" | Like E3 but ignore the bins with 0 contents.|
701| "E6" | Like E4 but ignore the bins with 0 contents.|
702| "X0" | When used with one of the "E" option, it suppress the error bar along X as `gStyle->SetErrorX(0)` would do.|
703
704Begin_Macro(source)
705{
706 auto c1 = new TCanvas("c1","c1",600,400);
707 auto he = new TH1F("he","Distribution drawn with error bars (option E1) ",100,-3,3);
708 for (int i=0; i<10000; i++) he->Fill(gRandom->Gaus(0,1));
709 gStyle->SetEndErrorSize(3);
710 gStyle->SetErrorX(1.);
711 he->SetMarkerStyle(20);
712 he->Draw("E1");
713}
714End_Macro
715
716The options "E3" and "E4" draw an error band through the end points of the
717vertical error bars. With "E4" the error band is smoothed. Because of the
718smoothing algorithm used some artefacts may appear at the end of the band
719like in the following example. In such cases "E3" should be used instead
720of "E4".
721
722Begin_Macro(source)
723{
724 auto ce4 = new TCanvas("ce4","ce4",600,400);
725 ce4->Divide(2,1);
726 auto he4 = new TH1F("he4","Distribution drawn with option E4",100,-3,3);
727 Int_t i;
728 for (i=0;i<10000;i++) he4->Fill(gRandom->Gaus(0,1));
729 he4->SetFillColor(kRed);
730 he4->GetXaxis()->SetRange(40,48);
731 ce4->cd(1);
732 he4->Draw("E4");
733 ce4->cd(2);
734 auto he3 = (TH1F*)he4->DrawClone("E3");
735 he3->SetTitle("Distribution drawn option E3");
736}
737End_Macro
738
7392D histograms can be drawn with error bars as shown is the following example:
740
741Begin_Macro(source)
742{
743 auto c2e = new TCanvas("c2e","c2e",600,400);
744 auto h2e = new TH2F("h2e","TH2 drawn with option E",40,-4,4,40,-20,20);
745 float px, py;
746 for (Int_t i = 0; i < 25000; i++) {
747 gRandom->Rannor(px,py);
748 h2e->Fill(px,5*py);
749 }
750 h2e->Draw("E");
751}
752End_Macro
753
754
755\anchor HP100
756### The bar chart option
757
758
759The option "B" allows to draw simple vertical bar charts.
760The bar width is controlled with `TH1::SetBarWidth()`,
761and the bar offset within the bin, with `TH1::SetBarOffset()`.
762These two settings are useful to draw several histograms on the
763same plot as shown in the following example:
764
765Begin_Macro(source)
766{
767 int i;
768 const Int_t nx = 8;
769 string os_X[nx] = {"8","32","128","512","2048","8192","32768","131072"};
770 float d_35_0[nx] = {0.75, -3.30, -0.92, 0.10, 0.08, -1.69, -1.29, -2.37};
771 float d_35_1[nx] = {1.01, -3.02, -0.65, 0.37, 0.34, -1.42, -1.02, -2.10};
772
773 auto cb = new TCanvas("cb","cb",600,400);
774 cb->SetGrid();
775
776 gStyle->SetHistMinimumZero();
777
778 auto h1b = new TH1F("h1b","Option B example",nx,0,nx);
779 h1b->SetFillColor(4);
780 h1b->SetBarWidth(0.4);
781 h1b->SetBarOffset(0.1);
782 h1b->SetStats(0);
783 h1b->SetMinimum(-5);
784 h1b->SetMaximum(5);
785
786 for (i=1; i<=nx; i++) {
787 h1b->SetBinContent(i, d_35_0[i-1]);
788 h1b->GetXaxis()->SetBinLabel(i,os_X[i-1].c_str());
789 }
790
791 h1b->Draw("b");
792
793 auto h2b = new TH1F("h2b","h2b",nx,0,nx);
794 h2b->SetFillColor(38);
795 h2b->SetBarWidth(0.4);
796 h2b->SetBarOffset(0.5);
797 h2b->SetStats(0);
798 for (i=1;i<=nx;i++) h2b->SetBinContent(i, d_35_1[i-1]);
799
800 h2b->Draw("b same");
801}
802End_Macro
803
804
805\anchor HP10
806### The "BAR" and "HBAR" options
807
808
809When the option `bar` or `hbar` is specified, a bar chart is drawn. A vertical
810bar-chart is drawn with the options `bar`, `bar0`, `bar1`, `bar2`, `bar3`, `bar4`.
811An horizontal bar-chart is drawn with the options `hbar`, `hbar0`, `hbar1`,
812`hbar2`, `hbar3`, `hbar4` (hist006_TH1_bar_charts.C).
813
814- The bar is filled with the histogram fill color.
815- The left side of the bar is drawn with a light fill color.
816- The right side of the bar is drawn with a dark fill color.
817- The percentage of the bar drawn with either the light or dark color is:
818 - 0% for option "(h)bar" or "(h)bar0"
819 - 10% for option "(h)bar1"
820 - 20% for option "(h)bar2"
821 - 30% for option "(h)bar3"
822 - 40% for option "(h)bar4"
823
824When an histogram has errors the option ["HIST"](\ref OPTHIST) together with the `(h)bar` option.
825
826Begin_Macro(source)
827../../../tutorials/hist/hist006_TH1_bar_charts.C
828End_Macro
829
830To control the bar width (default is the bin width) `TH1::SetBarWidth()`
831should be used.
832
833To control the bar offset (default is 0) `TH1::SetBarOffset()` should
834be used.
835
836These two parameters are useful when several histograms are plotted using
837the option `SAME`. They allow to plot the histograms next to each other.
838
839
840\anchor HP11
841### The SCATter plot option (legacy draw option)
842
843\attention
844Use of option `SCAT` has been deprecated. It was the default drawing option for 2D and
8453D histograms. The new default option is `COL` (heat-map).
846
847
848For each cell (i,j) a number of points proportional to the cell content is
849drawn. A maximum of `kNMAX` points per cell is drawn. If the maximum is above
850`kNMAX` contents are normalized to `kNMAX` (`kNMAX=2000`).
851If option is of the form `scat=ff`, (eg `scat=1.8`,
852`scat=1e-3`), then `ff` is used as a scale factor to compute the
853number of dots. `scat=1` is the default.
854
855By default the scatter plot is painted with a "dot marker" which not scalable
856(see the `TAttMarker` documentation). To change the marker size, a scalable marker
857type should be used. For instance a circle (marker style 20).
858
859Begin_Macro(source)
860{
861 auto c1 = new TCanvas("c1","c1",600,400);
862 auto hscat = new TH2F("hscat","Option SCATter example (default for 2D histograms) ",40,-4,4,40,-20,20);
863 float px, py;
864 for (Int_t i = 0; i < 25000; i++) {
865 gRandom->Rannor(px,py);
866 hscat->Fill(px,5*py);
867 hscat->Fill(3+0.5*px,2*py-10.);
868 }
869 hscat->Draw("scat=0.5"); // This a legacy draw option. Please consider using TScatter
870}
871End_Macro
872
873
874\anchor HP12
875### The ARRow option
876
877
878Shows gradient between adjacent cells. For each cell (i,j) an arrow is drawn
879The orientation of the arrow follows the cell gradient.
880
881Begin_Macro(source)
882{
883 auto c1 = new TCanvas("c1","c1",600,400);
884 auto harr = new TH2F("harr","Option ARRow example",20,-4,4,20,-20,20);
885 harr->SetLineColor(kRed);
886 float px, py;
887 for (Int_t i = 0; i < 25000; i++) {
888 gRandom->Rannor(px,py);
889 harr->Fill(px,5*py);
890 harr->Fill(3+0.5*px,2*py-10.,0.1);
891 }
892 harr->Draw("ARR");
893}
894End_Macro
895
896\since **ROOT version 6.17/01**
897
898The option `ARR` can be combined with the option `COL` or `COLZ`.
899
900Begin_Macro(source)
901{
902 auto c1 = new TCanvas("c1","c1",600,400);
903 auto harr = new TH2F("harr","Option ARR + COLZ example",20,-4,4,20,-20,20);
904 harr->SetStats(0);
905 float px, py;
906 for (Int_t i = 0; i < 25000; i++) {
907 gRandom->Rannor(px,py);
908 harr->Fill(px,5*py);
909 harr->Fill(3+0.5*px,2*py-10.,0.1);
910 }
911 harr->Draw("ARR COLZ");
912}
913End_Macro
914
915
916\anchor HP13
917### The BOX option
918
919
920For each cell (i,j) a box is drawn. The size (surface) of the box is
921proportional to the absolute value of the cell content.
922The cells with a negative content are drawn with a `X` on top of the box.
923
924Begin_Macro(source)
925{
926 auto c1 = new TCanvas("c1","c1",600,400);
927 auto hbox = new TH2F("hbox","Option BOX example",3,0,3,3,0,3);
928 hbox->SetFillColor(42);
929 hbox->Fill(0.5, 0.5, 1.);
930 hbox->Fill(0.5, 1.5, 4.);
931 hbox->Fill(0.5, 2.5, 3.);
932 hbox->Fill(1.5, 0.5, 2.);
933 hbox->Fill(1.5, 1.5, 12.);
934 hbox->Fill(1.5, 2.5, -6.);
935 hbox->Fill(2.5, 0.5, -4.);
936 hbox->Fill(2.5, 1.5, 6.);
937 hbox->Fill(2.5, 2.5, 0.5);
938 hbox->Draw("BOX");
939}
940End_Macro
941
942With option `BOX1` a button is drawn for each cell with surface
943proportional to content's absolute value. A sunken button is drawn for
944negative values a raised one for positive.
945
946Begin_Macro(source)
947{
948 auto c1 = new TCanvas("c1","c1",600,400);
949 auto hbox1 = new TH2F("hbox1","Option BOX1 example",3,0,3,3,0,3);
950 hbox1->SetFillColor(42);
951 hbox1->Fill(0.5, 0.5, 1.);
952 hbox1->Fill(0.5, 1.5, 4.);
953 hbox1->Fill(0.5, 2.5, 3.);
954 hbox1->Fill(1.5, 0.5, 2.);
955 hbox1->Fill(1.5, 1.5, 12.);
956 hbox1->Fill(1.5, 2.5, -6.);
957 hbox1->Fill(2.5, 0.5, -4.);
958 hbox1->Fill(2.5, 1.5, 6.);
959 hbox1->Fill(2.5, 2.5, 0.5);
960 hbox1->Draw("BOX1");
961}
962End_Macro
963
964When the option `SAME` (or "SAMES") is used with the option `BOX`,
965the boxes' sizes are computed taking the previous plots into account. The range
966along the Z axis is imposed by the first plot (the one without option
967`SAME`); therefore the order in which the plots are done is relevant.
968
969Begin_Macro(source)
970{
971 auto c1 = new TCanvas("c1","c1",600,400);
972 auto hb1 = new TH2F("hb1","Example of BOX plots with option SAME ",40,-3,3,40,-3,3);
973 auto hb2 = new TH2F("hb2","hb2",40,-3,3,40,-3,3);
974 auto hb3 = new TH2F("hb3","hb3",40,-3,3,40,-3,3);
975 auto hb4 = new TH2F("hb4","hb4",40,-3,3,40,-3,3);
976 for (Int_t i=0;i<1000;i++) {
977 double x,y;
978 gRandom->Rannor(x,y);
979 if (x>0 && y>0) hb1->Fill(x,y,4);
980 if (x<0 && y<0) hb2->Fill(x,y,3);
981 if (x>0 && y<0) hb3->Fill(x,y,2);
982 if (x<0 && y>0) hb4->Fill(x,y,1);
983 }
984 hb1->SetFillColor(1);
985 hb2->SetFillColor(2);
986 hb3->SetFillColor(3);
987 hb4->SetFillColor(4);
988 hb1->Draw("box");
989 hb2->Draw("box same");
990 hb3->Draw("box same");
991 hb4->Draw("box same");
992}
993End_Macro
994
995\since **ROOT version 6.17/01:**
996
997Sometimes the change of the range of the Z axis is unwanted, in which case, one
998can use `SAME0` (or `SAMES0`) option to opt out of this change.
999
1000Begin_Macro(source)
1001{
1002 auto h2 = new TH2F("h2"," ",10,0,10,10,20,30);
1003 auto hf = (TH2F*)h2->Clone("hf");
1004 h2->SetBit(TH1::kNoStats);
1005 hf->SetBit(TH1::kNoStats);
1006 h2->Fill(5,22);
1007 h2->Fill(5,23);
1008 h2->Fill(6,22);
1009 h2->Fill(6,23);
1010 hf->Fill(6,23);
1011 hf->Fill(6,23);
1012 hf->Fill(6,23);
1013 hf->Fill(6,23);
1014 hf->Fill(5,23);
1015
1016 auto hf_copy1 = hf->Clone("hf_copy1");
1017 TLatex lt;
1018
1019 auto cx = new TCanvas(); cx->Divide(2,1);
1020
1021 cx->cd(1);
1022 h2->Draw("box");
1023 hf->Draw("text colz same");
1024 lt.DrawLatexNDC(0.3,0.5,"SAME");
1025
1026 cx->cd(2);
1027 h2->Draw("box");
1028 hf_copy1->Draw("text colz same0");
1029 lt.DrawLatexNDC(0.3,0.5,"SAME0");
1030}
1031End_Macro
1032
1033
1034\anchor HP14
1035### The COLor option (default for 2D histograms)
1036
1037The magnitude of individual cell (i,j) is represented as a color picked in the current color palette.
1038This data visualization technique is often called a heat map (or heat-map).
1039
1040The color table used is defined in the current style.
1041
1042If the histogram's minimum and maximum are the same (flat histogram), the
1043mapping on colors is not possible, therefore nothing is painted. To paint a
1044flat histogram it is enough to set the histogram minimum
1045(`TH1::SetMinimum()`) different from the bins' content.
1046
1047The default number of color levels used to paint the cells is 20.
1048It can be changed with `TH1::SetContour()` or
1049`TStyle::SetNumberContours()`. The higher this number is, the smoother
1050is the color change between cells.
1051
1052The color palette in TStyle can be modified via `gStyle->SetPalette()`.
1053
1054All the non-empty bins are painted. Empty bins (bins with content and error equal to 0) are
1055not painted unless some bins have a negative content because in that case the null bins
1056might be not empty.
1057
1058`TProfile2D` histograms are handled differently because, for this type of 2D
1059histograms, it is possible to know if an empty bin has been filled or not. So even
1060if all the bins' contents are positive some empty bins might be painted. And vice versa,
1061if some bins have a negative content some empty bins might be not painted.
1062
1063Combined with the option `COL`, the option `Z` allows to
1064display the color palette defined by `gStyle->SetPalette()`.
1065
1066In the following example, the histogram has only positive bins; the empty
1067bins (containing 0) are not drawn.
1068
1069Begin_Macro(source)
1070{
1071 auto c1 = new TCanvas("c1","c1",600,400);
1072 auto hcol1 = new TH2F("hcol1","Option COLor example ",40,-4,4,40,-20,20);
1073 float px, py;
1074 for (Int_t i = 0; i < 25000; i++) {
1075 gRandom->Rannor(px,py);
1076 hcol1->Fill(px,5*py);
1077 }
1078 hcol1->Draw("COLZ");
1079}
1080End_Macro
1081
1082In the first plot of following example, the histogram has some negative bins;
1083the empty bins (containing 0) are drawn. In some cases one wants to not draw
1084empty bins (containing 0) of histograms having a negative minimum. The option
1085`1`, used to produce the second plot in the following picture, allows to do that.
1086
1087Begin_Macro(source)
1088{
1089 auto c1 = new TCanvas("c1","c1",600,600);
1090 c1->Divide(1,2);
1091 auto hcol23 = new TH2F("hcol23","Option COLZ example ",40,-4,4,40,-20,20);
1092 auto hcol24 = new TH2F("hcol24","Option COLZ1 example ",40,-4,4,40,-20,20);
1093 float px, py;
1094 for (Int_t i = 0; i < 25000; i++) {
1095 gRandom->Rannor(px,py);
1096 hcol23->Fill(px,5*py);
1097 hcol24->Fill(px,5*py);
1098 }
1099 hcol23->Fill(0.,0.,-200.);
1100 hcol24->Fill(0.,0.,-200.);
1101 c1->cd(1); hcol23->Draw("COLZ");
1102 c1->cd(2); hcol24->Draw("COLZ1");
1103}
1104End_Macro
1105
1106When the maximum of the histogram is set to a smaller value than the real maximum,
1107 the bins having a content between the new maximum and the real maximum are
1108painted with the color corresponding to the new maximum.
1109
1110When the minimum of the histogram is set to a greater value than the real minimum,
1111 the bins having a value between the real minimum and the new minimum are not drawn
1112 unless the option `0` is set.
1113
1114The following example illustrates the option `0` combined with the option `COL`.
1115
1116Begin_Macro(source)
1117{
1118 auto c1 = new TCanvas("c1","c1",600,600);
1119 c1->Divide(1,2);
1120 auto hcol21 = new TH2F("hcol21","Option COLZ",40,-4,4,40,-20,20);
1121 auto hcol22 = new TH2F("hcol22","Option COLZ0",40,-4,4,40,-20,20);
1122 float px, py;
1123 for (Int_t i = 0; i < 25000; i++) {
1124 gRandom->Rannor(px,py);
1125 hcol21->Fill(px,5*py);
1126 hcol22->Fill(px,5*py);
1127 }
1128 hcol21->SetBit(TH1::kNoStats);
1129 hcol22->SetBit(TH1::kNoStats);
1130 c1->cd(1); hcol21->Draw("COLZ");
1131 c1->cd(2); hcol22->Draw("COLZ0");
1132 hcol22->SetMaximum(100);
1133 hcol22->SetMinimum(40);
1134}
1135End_Macro
1136
1137\since **ROOT version 6.09/01:**
1138
1139When the option SAME (or "SAMES") is used with the option COL, the boxes' color
1140are computed taking the previous plots into account. The range along the Z axis
1141is imposed by the first plot (the one without option SAME); therefore the order
1142in which the plots are done is relevant. Same as [in the `BOX` option](\ref HP13), one can use
1143`SAME0` (or `SAMES0`) to opt out of this imposition.
1144
1145Begin_Macro(source)
1146{
1147 auto c = new TCanvas("c","Example of col plots with option SAME",200,10,700,500);
1148 auto h1 = new TH2F("h1","h1",40,-3,3,40,-3,3);
1149 auto h2 = new TH2F("h2","h2",40,-3,3,40,-3,3);
1150 auto h3 = new TH2F("h3","h3",40,-3,3,40,-3,3);
1151 auto h4 = new TH2F("h4","h4",40,-3,3,40,-3,3);
1152 h1->SetBit(TH1::kNoStats);
1153 for (Int_t i=0;i<5000;i++) {
1154 double x,y;
1155 gRandom->Rannor(x,y);
1156 if(x>0 && y>0) h1->Fill(x,y,4);
1157 if(x<0 && y<0) h2->Fill(x,y,3);
1158 if(x>0 && y<0) h3->Fill(x,y,2);
1159 if(x<0 && y>0) h4->Fill(x,y,1);
1160 }
1161 h1->Draw("colz");
1162 h2->Draw("col same");
1163 h3->Draw("col same");
1164 h4->Draw("col same");
1165}
1166End_Macro
1167
1168The option `COL` can be combined with the option `POL`:
1169
1170Begin_Macro(source)
1171{
1172 auto c1 = new TCanvas("c1","c1",600,400);
1173 auto hcol1 = new TH2F("hcol1","Option COLor combined with POL",40,-4,4,40,-4,4);
1174 float px, py;
1175 for (Int_t i = 0; i < 25000; i++) {
1176 gRandom->Rannor(px,py);
1177 hcol1->Fill(px,py);
1178 }
1179 hcol1->Draw("COLZPOL");
1180}
1181End_Macro
1182
1183\since **ROOT version 6.07/03:**
1184
1185A second rendering technique is also available with the COL2 and COLZ2 options.
1186
1187These options provide potential performance improvements compared to the standard
1188COL option. The performance comparison of the COL2 to the COL option depends on
1189the histogram and the size of the rendering region in the current pad. In general,
1190a small (approx. less than 100 bins per axis), sparsely populated TH2 will render
1191faster with the COL option.
1192
1193However, for larger histograms (approx. more than 100 bins per axis)
1194that are not sparse, the COL2 option will provide up to 20 times performance improvements.
1195For example, a 1000x1000 bin TH2 that is not sparse will render an order of magnitude
1196faster with the COL2 option.
1197
1198The COL2 option will also scale its performance based on the size of the
1199pixmap the histogram image is being rendered into. It also is much better optimized for
1200sessions where the user is forwarding X11 windows through an `ssh` connection.
1201
1202For the most part, the COL2 and COLZ2 options are a drop in replacement to the COL
1203and COLZ options. There is one major difference and that concerns the treatment of
1204bins with zero content. The COL2 and COLZ2 options color these bins the color of zero.
1205
1206COL2 option renders the histogram as a bitmap. Therefore it cannot be saved in vector
1207graphics file format like PostScript or PDF (an empty image will be generated). It can
1208be saved only in bitmap files like PNG format for instance.
1209
1210
1211\anchor HP140
1212### The CANDLE and VIOLIN options
1213
1214The mechanism behind Candle plots and Violin plots is very similar. Because of this they are
1215implemented in the same class TCandle. The keywords CANDLE or VIOLIN will initiate the drawing of
1216the corresponding plots. Followed by the keyword the user can select a plot direction (X or V for
1217vertical projections, or Y or H for horizontal projections) and/or predefined definitions
1218(1-6 for candles, 1-2 for violins). The order doesn't matter. Default is X and 1.
1219
1220Instead of using the predefined representations, the candle and violin parameters can be
1221changed individually. In that case the option have the following form:
1222
1223 CANDLEX(<option-string>)
1224 CANDLEY(<option-string>)
1225 VIOLINX(<option-string>)
1226 VIOLINY(<option-string>).
1227
1228All zeros at the beginning of `option-string` can be omitted.
1229
1230`option-string` consists eight values, defined as follow:
1231
1232 "CANDLEX(zhpawMmb)"
1233
1234Where:
1235
1236 - `b = 0`; no box drawn
1237 - `b = 1`; the box is drawn. As the candle-plot is also called a box-plot it
1238 makes sense in the very most cases to always draw the box
1239 - `b = 2`; draw a filled box with border
1240
1241 - `m = 0`; no median drawn
1242 - `m = 1`; median is drawn as a line
1243 - `m = 2`; median is drawn with errors (notches)
1244 - `m = 3`; median is drawn as a circle
1245
1246 - `M = 0`; no mean drawn
1247 - `M = 1`; mean is drawn as a dashed line
1248 - `M = 3`; mean is drawn as a circle
1249
1250 - `w = 0`; no whisker drawn
1251 - `w = 1`; whisker is drawn to end of distribution.
1252 - `w = 2`; whisker is drawn to max 1.5*iqr
1253
1254 - `a = 0`; no anchor drawn
1255 - `a = 1`; the anchors are drawn
1256
1257 - `p = 0`; no points drawn
1258 - `p = 1`; only outliers are drawn
1259 - `p = 2`; all datapoints are drawn
1260 - `p = 3`: all datapoints are drawn scattered
1261
1262 - `h = 0`; no histogram is drawn
1263 - `h = 1`; histogram at the left or bottom side is drawn
1264 - `h = 2`; histogram at the right or top side is drawn
1265 - `h = 3`; histogram at left and right or top and bottom (violin-style) is drawn
1266
1267 - `z = 0`; no zero indicator line is drawn
1268 - `z = 1`; zero indicator line is drawn.
1269
1270As one can see all individual options for both candle and violin plots can be accessed by this
1271mechanism. In deed the keywords CANDLE(<option-string>) and VIOLIN(<option-string>) have the same
1272meaning. So you can parametrise an option-string for a candle plot and use the keywords VIOLIN and
1273vice versa, if you wish.
1274
1275Using a logarithmic x- or y-axis is possible for candle and violin charts.
1276
1277\since **ROOT version 6.11/01**
1278
1279a logarithmic z-axis is possible, too but will only affect violin charts of course.
1280
1281\anchor HP140a
1282#### The CANDLE option
1283
1284<a href="http://en.wikipedia.org/wiki/Box_plot">A Candle plot</a> (also known as
1285a "box plot" or "whisker plot") was invented in 1977 by John Tukey. It is a convenient
1286way to describe graphically a data distribution (D) with only five numbers:
1287
1288 1. The minimum value of the distribution D (bottom or left whisker).
1289 2. The lower quartile (Q1): 25% of the data points in D are less than Q1 (bottom of the box).
1290 3. The median (M): 50% of the data points in D are less than M.
1291 4. The upper quartile (Q3): 75% of the data points in D are less than Q3 (top of the box).
1292 5. The maximum value of the distribution D (top or right whisker).
1293
1294In this implementation a TH2 is considered as a collection of TH1 along
1295X (option `CANDLE` or `CANDLEX`) or Y (option `CANDLEY`).
1296Each TH1 is represented as one candle.
1297
1298Begin_Macro(source)
1299../../../tutorials/hist/hist052_Graphics_candle_plot_whiskers.C
1300End_Macro
1301
1302The candle reduces the information coming from a whole distribution into few values.
1303Independently from the number of entries or the significance of the underlying distribution
1304a candle will always look like a candle. So candle plots should be used carefully in
1305particular with unknown distributions. The definition of a candle is based on
1306__unbinned data__. Here, candles are created from binned data. Because of this, the
1307deviation is connected to the bin width used. The calculation of the quantiles
1308normally done on unbinned data also. Because data are binned, this will
1309only work the best possible way within the resolution of one bin
1310
1311Because of all these facts one should take care that:
1312
1313 - there are enough points per candle
1314 - the bin width is small enough (more bins will increase the maximum
1315 available resolution of the quantiles although there will be some
1316 bins with no entries)
1317 - never make a candle-plot if the underlying distribution is double-distributed
1318 - only create candles of distributions that are more-or-less gaussian (the
1319 MPV should be not too far away from the mean).
1320
1321#### What a candle is made of
1322
1323\since **ROOT version 6.07/05**
1324
1325##### The box
1326The box displays the position of the inter-quantile-range of the underlying
1327distribution. The box contains 25% of the distribution below the median
1328and 25% of the distribution above the median. If the underlying distribution is large
1329enough and gaussian shaped the end-points of the box represent \f$ 0.6745\times\sigma \f$
1330(Where \f$ \sigma \f$ is the standard deviation of the gaussian). The width and
1331the position of the box can be modified by SetBarWidth() and SetBarOffset().
1332The +-25% quantiles are calculated by the GetQuantiles() methods.
1333
1334\since **ROOT version 6.11/01**
1335
1336Using the static function TCandle::SetBoxRange(double) the box definition will be
1337overwritten. E.g. using a box range of 0.68 will redefine the area of the lower box edge
1338to the upper box edge in order to cover 68% of the distribution illustrated by that candle.
1339The static function will affect all candle-charts in the running program.
1340Default is 0.5.
1341
1342Using the static function TCandle::SetScaledCandle(bool) the width of the box (and the
1343whole candle) can be influenced. Deactivated, the width is constant (to be set by
1344SetBarWidth() ). Activated, the width of the boxes will be scaled to each other based on the
1345amount of data in the corresponding candle, the maximum width can be influenced by
1346SetBarWidth(). The static function will affect all candle-charts in the running program.
1347Default is false. Scaling between multiple candle-charts (using "same" or THStack) is not
1348supported, yet
1349
1350##### The Median
1351For a sorted list of numbers, the median is the value in the middle of the list.
1352E.g. if a sorted list is made of five numbers "1,2,3,6,7" 3 will be the median
1353because it is in the middle of the list. If the number of entries is even the
1354average of the two values in the middle will be used. As histograms are binned
1355data, the situation is a bit more complex. The following example shows this:
1356
1357~~~ {.cpp}
1358void quantiles() {
1359 auto h = new TH1I("h","h",10,0,10);
1360 //h->Fill(3);
1361 //h->Fill(3);
1362 h->Fill(4);
1363 h->Draw();
1364 double p = 0.;
1365 double q = 0.;
1366 h->GetQuantiles(1,&q,&p);
1367
1368 cout << "Median is: " << q << std::endl;
1369}
1370~~~
1371
1372Here the bin-width is 1.0. If the two Fill(3) are commented out, as there are currently,
1373the example will return a calculated median of 4.5, because that's the bin center
1374of the bin in which the value 4.0 has been dropped. If the two Fill(3) are not
1375commented out, it will return 3.75, because the algorithm tries to evenly distribute
1376the individual values of a bin with bin content > 0. It means the sorted list
1377would be "3.25, 3.75, 4.5".
1378
1379The consequence is a median of 3.75. This shows how important it is to use a
1380small enough bin-width when using candle-plots on binned data.
1381If the distribution is large enough and gaussian shaped the median will be exactly
1382equal to the mean.
1383The median can be shown as a line or as a circle or not shown at all.
1384
1385In order to show the significance of the median notched candle plots apply a "notch" or
1386narrowing of the box around the median. The significance is defined by
1387\f$ 1.57\times\frac{iqr}{N} \f$ and will be represented as the size of the notch
1388(where iqr is the size of the box and N is the number of entries of the whole
1389distribution). Candle plots like these are usually called "notched candle plots".
1390
1391In case the significance of the median is greater that the size of the box, the
1392box will have an unnatural shape. Usually it means the chart has not enough data,
1393or that representing this uncertainty is not useful
1394
1395##### The Mean
1396The mean can be drawn as a dashed line or as a circle or not drawn at all.
1397The mean is the arithmetic average of the values in the distribution.
1398It is calculated using GetMean(). Because histograms are
1399binned data, the mean value can differ from a calculation on the raw-data.
1400If the distribution is large enough and gaussian shaped the mean will be
1401exactly the median.
1402
1403##### The Whiskers
1404The whiskers represent the part of the distribution not covered by the box.
1405The upper 25% and the lower 25% of the distribution are located within the whiskers.
1406Two representations are available.
1407
1408 - A simple one (using w=1) defining the lower whisker from the lowest data value
1409 to the bottom of the box, and the upper whisker from the top of the box to the
1410 highest data value. In this representation the whisker-lines are dashed.
1411 - A more complex one having a further restriction. The whiskers are still connected
1412 to the box but their length cannot exceed \f$ 1.5\times iqr \f$. So it might
1413 be that the outermost part of the underlying distribution will not be covered
1414 by the whiskers. Usually these missing parts will be represented by the outliers
1415 (see points). Of course the upper and the lower whisker may differ in length.
1416 In this representation the whiskers are drawn as solid lines.
1417
1418\since **ROOT version 6.11/01**
1419
1420Using the static function TCandle::SetWhiskerRange(double) the whisker definition w=1
1421will be overwritten. E.g. using a whisker-range of 0.95 and w=1 will redefine the area of
1422the lower whisker to the upper whisker in order to cover 95% of the distribution inside
1423that candle. The static function will affect all candle-charts in the running program.
1424Default is 1.
1425
1426If the distribution is large enough and gaussian shaped, the maximum length of
1427the whisker will be located at \f$ \pm 2.698 \sigma \f$ (when using the
14281.5*iqr-definition (w=2), where \f$ \sigma \f$ is the standard deviation
1429(see picture above). In that case 99.3% of the total distribution will be covered
1430by the box and the whiskers, whereas 0.7% are represented by the outliers.
1431
1432##### The Anchors
1433The anchors have no special meaning in terms of statistical calculation. They mark
1434the end of the whiskers and they have the width of the box. Both representation
1435with and without anchors are common.
1436
1437##### The Points
1438Depending on the configuration the points can have different meanings:
1439 - If p=1 the points represent the outliers. If they are shown, it means
1440 some parts of the underlying distribution are not covered by the whiskers.
1441 This can only occur when the whiskers are set to option w=2. Here the whiskers
1442 can have a maximum length of \f$ 1.5 \times iqr \f$. So any points outside the
1443 whiskers will be drawn as outliers. The outliers will be represented by crosses.
1444 - If p=2 all points in the distribution will be painted as crosses. This is
1445 useful for small datasets only (up to 10 or 20 points per candle).
1446 The outliers are shown along the candle. Because the underlying distribution
1447 is binned, is frequently occurs that a bin contains more than one value.
1448 Because of this the points will be randomly scattered within their bin along
1449 the candle axis. If the bin content for a bin is exactly 1 (usually
1450 this happens for the outliers) if will be drawn in the middle of the bin along
1451 the candle axis. As the maximum number of points per candle is limited by kNMax/2
1452 on very large datasets scaling will be performed automatically. In that case one
1453 would loose all outliers because they have usually a bin content of 1 (and a
1454 bin content between 0 and 1 after the scaling). Because of this all bin contents
1455 between 0 and 1 - after the scaling - will be forced to be 1.
1456 - As the drawing of all values on large datasets can lead to big amounts of crosses,
1457 one can show all values as a scatter plot instead by choosing p=3. The points will be
1458 drawn as dots and will be scattered within the width of the candle. The color
1459 of the points will be the color of the candle-chart.
1460
1461##### Other Options
1462Is is possible to combine all options of candle and violin plots with each other. E.g. a box-plot
1463with a histogram.
1464
1465#### How to use the candle-plots drawing option
1466
1467There are six predefined candle-plot representations:
1468
1469 - "CANDLEX1": Standard candle (whiskers cover the whole distribution)
1470 - "CANDLEX2": Standard candle with better whisker definition + outliers.
1471 It is a good compromise
1472 - "CANDLEX3": Like candle2 but with a mean as a circle.
1473 It is easier to distinguish mean and median
1474 - "CANDLEX4": Like candle3 but showing the uncertainty of the median as well
1475 (notched candle plots).
1476 For bigger datasets per candle
1477 - "CANDLEX5": Like candle2 but showing all data points.
1478 For very small datasets
1479 - "CANDLEX6": Like candle2 but showing all datapoints scattered.
1480 For huge datasets
1481
1482
1483The following picture shows how the six predefined representations look.
1484
1485Begin_Macro
1486{
1487 auto c1 = new TCanvas("c1","c1",700,800);
1488 c1->Divide(2,3);
1489 gStyle->SetOptStat(kFALSE);
1490
1491 auto hcandle = new TH2F("hcandle"," ",10,-4,4,40,-20,20);
1492 float px, py;
1493 for (Int_t i = 0; i < 15000; i++) {
1494 gRandom->Rannor(px,py);
1495 hcandle->Fill(px,5*py);
1496 }
1497 hcandle->SetMarkerSize(0.5);
1498
1499 TH2F *h2;
1500 for (Int_t i=1; i<7; i++) {
1501 c1->cd(i);
1502 h2 = (TH2F*)hcandle->DrawClone(Form("CANDLE%d",i));
1503 h2->SetTitle(Form("CANDLE%d",i));
1504 }
1505}
1506End_Macro
1507
1508
1509#### Example 1
1510Box and improved whisker, no mean, no median, no anchor no outliers
1511
1512 h1->Draw("CANDLEX(2001)");
1513
1514#### Example 2
1515A Candle-definition like "CANDLEX2" (New standard candle with better whisker definition + outliers)
1516
1517 h1->Draw("CANDLEX(112111)");
1518
1519#### Example 3
1520The following example shows how several candle plots can be super-imposed using
1521the option SAME. Note that the bar-width and bar-offset are active on candle plots.
1522Also the color, the line width, the size of the points and so on can be changed by the
1523standard attribute setting methods such as SetLineColor() SetLineWidth().
1524
1525Begin_Macro(source)
1526../../../tutorials/hist/hist049_Graphics_candle_plot.C
1527End_Macro
1528
1529\anchor HP140b
1530#### The VIOLIN option
1531
1532<a href="http://en.wikipedia.org/wiki/Violin_plot">A violin plot</a> is a candle plot
1533that also encodes the pdf information at each point.
1534
1535
1536Quartiles and mean are also represented at each point, with a marker
1537and two lines.
1538
1539In this implementation a TH2 is considered as a collection of TH1 along
1540X (option `VIOLIN` or `VIOLINX`) or Y (option `VIOLINY`).
1541
1542#### What a violin is made of
1543
1544\since **ROOT version 6.09/02**
1545
1546##### The histogram
1547The histogram is typically drawn to both directions with respect to the middle-line of the
1548corresponding bin. This can be achieved by using h=3. It is possible to draw a histogram only to
1549one side (h=1, or h=2).
1550The maximum number of bins in the histogram is limited to 500, if the number of bins in the used
1551histogram is higher it will be rebinned automatically. The maximum height of the histogram can
1552be modified by using SetBarWidth() and the position can be changed with SetBarOffset().
1553A solid fill style is recommended.
1554
1555\since **ROOT version 6.11/01**
1556
1557Using the static function TCandle::SetScaledViolin(bool) the height of the histogram or the
1558violin can be influenced. Activated, the height of the bins of the individual violins will be
1559scaled with respect to each other, the maximum height can be influenced by SetBarWidth().
1560Deactivated, the height of the bin with the maximum content of each individual violin is
1561set to a constant value using SetBarWidth(). The static function will affect all violin-charts
1562in the running program. Default is true. Scaling between multiple violin-charts
1563(using "same" or THStack) is not supported, yet.
1564
1565##### The zero indicator line
1566Typical for violin charts is a line in the background over the whole histogram indicating
1567the bins with zero entries. The zero indicator line can be activated with z=1. The line color
1568will always be the same as the fill-color of the histogram.
1569
1570##### The Mean
1571The Mean is illustrated with the same mechanism as used for candle plots. Usually a circle is used.
1572
1573##### Whiskers
1574The whiskers are illustrated by the same mechanism as used for candle plots. There is only one
1575difference. When using the simple whisker definition (w=1) and the zero indicator line (z=1), then
1576the whiskers will be forced to be solid (usually hashed)
1577
1578##### Points
1579The points are illustrated by the same mechanism as used for candle plots. E.g. VIOLIN2 uses
1580better whisker definition (w=2) and outliers (p=1).
1581
1582##### Other options
1583It is possible to combine all options of candle or violin plots with each other. E.g. a violin plot
1584including a box-plot.
1585
1586#### How to use the violin-plots drawing option
1587
1588There are two predefined violin-plot representations:
1589 - "VIOLINX1": Standard violin (histogram, mean, whisker over full distribution,
1590 zero indicator line)
1591 - "VIOLINX2": Line VIOLINX1 both with better whisker definition + outliers.
1592
1593A solid fill style is recommended for this plot (as opposed to a hollow or
1594hashed style).
1595
1596Begin_Macro(source)
1597{
1598 auto c1 = new TCanvas("c1","c1",600,400);
1599 Int_t nx(6), ny(40);
1600 double xmin(0.0), xmax(+6.0), ymin(0.0), ymax(+4.0);
1601 auto hviolin = new TH2F("hviolin", "Option VIOLIN example", nx, xmin, xmax, ny, ymin, ymax);
1602 TF1 f1("f1", "gaus", +0,0 +4.0);
1603 double x,y;
1604 for (Int_t iBin=1; iBin<hviolin->GetNbinsX(); ++iBin) {
1605 double xc = hviolin->GetXaxis()->GetBinCenter(iBin);
1606 f1.SetParameters(1, 2.0+TMath::Sin(1.0+xc), 0.2+0.1*(xc-xmin)/xmax);
1607 for(Int_t i=0; i<10000; ++i){
1608 x = xc;
1609 y = f1.GetRandom();
1610 hviolin->Fill(x, y);
1611 }
1612 }
1613 hviolin->SetFillColor(kGray);
1614 hviolin->SetMarkerStyle(20);
1615 hviolin->SetMarkerSize(0.5);
1616 hviolin->Draw("VIOLIN");
1617 c1->Update();
1618}
1619End_Macro
1620
1621The next example illustrates a time development of a certain value:
1622
1623Begin_Macro(source)
1624../../../tutorials/hist/hist047_Graphics_candle_decay.C
1625End_Macro
1626
1627
1628\anchor HP15
1629### The TEXT and TEXTnn Option
1630
1631
1632For each bin the content is printed. The text attributes are:
1633
1634- text font = current TStyle font (`gStyle->SetTextFont()`).
1635- text size = 0.02*padheight*markersize (if `h` is the histogram drawn
1636 with the option `TEXT` the marker size can be changed with
1637 `h->SetMarkerSize(markersize)`).
1638- text color = marker color.
1639
1640By default the format `g` is used. This format can be redefined
1641by calling `gStyle->SetPaintTextFormat()`.
1642
1643It is also possible to use `TEXTnn` in order to draw the text with
1644the angle `nn` (`0 < nn <= 90`).
1645
1646For 2D histograms the text is plotted in the center of each non empty cells.
1647It is possible to plot empty cells by calling `gStyle->SetHistMinimumZero()`
1648or providing MIN0 draw option. For 1D histogram the text is plotted at a y
1649position equal to the bin content.
1650
1651For 2D histograms when the option "E" (errors) is combined with the option
1652text ("TEXTE"), the error for each bin is also printed.
1653
1654Begin_Macro(source)
1655{
1656 auto c01 = new TCanvas("c01","c01",700,400);
1657 c01->Divide(2,1);
1658 auto htext1 = new TH1F("htext1","Option TEXT on 1D histograms ",10,-4,4);
1659 auto htext2 = new TH2F("htext2","Option TEXT on 2D histograms ",10,-4,4,10,-20,20);
1660 float px, py;
1661 for (Int_t i = 0; i < 25000; i++) {
1662 gRandom->Rannor(px,py);
1663 htext1->Fill(px,0.1);
1664 htext2->Fill(px,5*py,0.1);
1665 }
1666 gStyle->SetPaintTextFormat("4.1f m");
1667 htext2->SetMarkerSize(1.8);
1668 c01->cd(1);
1669 htext2->Draw("TEXT45");
1670 c01->cd(2);
1671 htext1->Draw();
1672 htext1->Draw("HIST TEXT0 SAME");
1673}
1674End_Macro
1675
1676\since **ROOT version 6.07/07:**
1677
1678In case several histograms are drawn on top ot each other (using option `SAME`),
1679the text can be shifted using `SetBarOffset()`. It specifies an offset for the
1680text position in each cell, in percentage of the bin width.
1681
1682Begin_Macro(source)
1683{
1684 auto c03 = new TCanvas("c03","c03",700,400);
1685 gStyle->SetOptStat(0);
1686 auto htext3 = new TH2F("htext3","Several 2D histograms drawn with option TEXT",10,-4,4,10,-20,20);
1687 auto htext4 = new TH2F("htext4","htext4",10,-4,4,10,-20,20);
1688 auto htext5 = new TH2F("htext5","htext5",10,-4,4,10,-20,20);
1689 float px, py;
1690 for (Int_t i = 0; i < 25000; i++) {
1691 gRandom->Rannor(px,py);
1692 htext3->Fill(4*px,20*py,0.1);
1693 htext4->Fill(4*px,20*py,0.5);
1694 htext5->Fill(4*px,20*py,1.0);
1695 }
1696 htext4->SetMarkerSize(1.8);
1697 htext5->SetMarkerSize(1.8);
1698 htext5->SetMarkerColor(kRed);
1699 htext4->SetBarOffset(0.2);
1700 htext5->SetBarOffset(-0.2);
1701 htext3->Draw("COL");
1702 htext4->Draw("TEXT SAME");
1703 htext5->Draw("TEXT SAME");
1704}
1705End_Macro
1706
1707In the case of profile histograms it is possible to print the number
1708of entries instead of the bin content. It is enough to combine the
1709option "E" (for entries) with the option "TEXT".
1710
1711Begin_Macro(source)
1712{
1713 auto c02 = new TCanvas("c02","c02",700,400);
1714 c02->Divide(2,1);
1715 gStyle->SetPaintTextFormat("g");
1716
1717 auto profile = new TProfile("profile","profile",10,0,10);
1718 profile->SetMarkerSize(2.2);
1719 profile->Fill(0.5,1);
1720 profile->Fill(1.5,2);
1721 profile->Fill(2.5,3);
1722 profile->Fill(3.5,4);
1723 profile->Fill(4.5,5);
1724 profile->Fill(5.5,5);
1725 profile->Fill(6.5,4);
1726 profile->Fill(7.5,3);
1727 profile->Fill(8.5,2);
1728 profile->Fill(9.5,1);
1729 c02->cd(1); profile->Draw("HIST TEXT0");
1730 c02->cd(2); profile->Draw("HIST TEXT0E");
1731}
1732End_Macro
1733
1734\anchor HP16
1735### The CONTour options
1736
1737
1738The following contour options are supported:
1739
1740| Option | Description |
1741|----------|-----------------------------------------------------------------------------|
1742| "CONT" | Draw a contour plot (same as CONT0). |
1743| "CONT0" | Draw a contour plot using surface colors to distinguish contours. |
1744| "CONT1" | Draw a contour plot using the line colors to distinguish contours. |
1745| "CONT2" | Draw a contour plot using the line styles (1 to 5) to distinguish contours. |
1746| "CONT3" | Draw a contour plot using the same line style for all contours. |
1747| "CONT4" | Draw a contour plot using surface colors (`SURF` option at theta = 0). |
1748
1749
1750The following example shows a 2D histogram plotted with the option
1751`CONTZ`. The option `CONT` draws a contour plot using surface
1752colors to distinguish contours. Combined with the option `CONT` (or
1753`CONT0`), the option `Z` allows to display the color palette
1754defined by `gStyle->SetPalette()`.
1755
1756Begin_Macro(source)
1757{
1758 auto c1 = new TCanvas("c1","c1",600,400);
1759 auto hcontz = new TH2F("hcontz","Option CONTZ example ",40,-4,4,40,-20,20);
1760 float px, py;
1761 for (Int_t i = 0; i < 25000; i++) {
1762 gRandom->Rannor(px,py);
1763 hcontz->Fill(px-1,5*py);
1764 hcontz->Fill(2+0.5*px,2*py-10.,0.1);
1765 }
1766 hcontz->Draw("CONTZ");
1767}
1768End_Macro
1769
1770The following example shows a 2D histogram plotted with the option
1771`CONT1Z`. The option `CONT1` draws a contour plot using the
1772line colors to distinguish contours. Combined with the option `CONT1`,
1773the option `Z` allows to display the color palette defined by
1774`gStyle->SetPalette()`.
1775
1776Begin_Macro(source)
1777{
1778 auto c1 = new TCanvas("c1","c1",600,400);
1779 auto hcont1 = new TH2F("hcont1","Option CONT1Z example ",40,-4,4,40,-20,20);
1780 float px, py;
1781 for (Int_t i = 0; i < 25000; i++) {
1782 gRandom->Rannor(px,py);
1783 hcont1->Fill(px-1,5*py);
1784 hcont1->Fill(2+0.5*px,2*py-10.,0.1);
1785 }
1786 hcont1->Draw("CONT1Z");
1787}
1788End_Macro
1789
1790The following example shows a 2D histogram plotted with the option
1791`CONT2`. The option `CONT2` draws a contour plot using the
1792line styles (1 to 5) to distinguish contours.
1793
1794Begin_Macro(source)
1795{
1796 auto c1 = new TCanvas("c1","c1",600,400);
1797 auto hcont2 = new TH2F("hcont2","Option CONT2 example ",40,-4,4,40,-20,20);
1798 float px, py;
1799 for (Int_t i = 0; i < 25000; i++) {
1800 gRandom->Rannor(px,py);
1801 hcont2->Fill(px-1,5*py);
1802 hcont2->Fill(2+0.5*px,2*py-10.,0.1);
1803 }
1804 hcont2->Draw("CONT2");
1805}
1806End_Macro
1807
1808The following example shows a 2D histogram plotted with the option
1809`CONT3`. The option `CONT3` draws contour plot using the same line style for
1810all contours.
1811
1812Begin_Macro(source)
1813{
1814 auto c1 = new TCanvas("c1","c1",600,400);
1815 auto hcont3 = new TH2F("hcont3","Option CONT3 example ",40,-4,4,40,-20,20);
1816 float px, py;
1817 for (Int_t i = 0; i < 25000; i++) {
1818 gRandom->Rannor(px,py);
1819 hcont3->Fill(px-1,5*py);
1820 hcont3->Fill(2+0.5*px,2*py-10.,0.1);
1821 }
1822 hcont3->SetLineStyle(kDotted);
1823 hcont3->Draw("CONT3");
1824}
1825End_Macro
1826
1827The following example shows a 2D histogram plotted with the option
1828`CONT4`. The option `CONT4` draws a contour plot using surface
1829colors to distinguish contours (`SURF` option at theta = 0). Combined
1830with the option `CONT` (or `CONT0`), the option `Z`
1831allows to display the color palette defined by `gStyle->SetPalette()`.
1832
1833Begin_Macro(source)
1834{
1835 auto c1 = new TCanvas("c1","c1",600,400);
1836 auto hcont4 = new TH2F("hcont4","Option CONT4Z example ",40,-4,4,40,-20,20);
1837 float px, py;
1838 for (Int_t i = 0; i < 25000; i++) {
1839 gRandom->Rannor(px,py);
1840 hcont4->Fill(px-1,5*py);
1841 hcont4->Fill(2+0.5*px,2*py-10.,0.1);
1842 }
1843 hcont4->Draw("CONT4Z");
1844}
1845End_Macro
1846
1847The default number of contour levels is 20 equidistant levels and can be changed
1848with `TH1::SetContour()` or `TStyle::SetNumberContours()`.
1849
1850\anchor HP16a
1851#### The LIST option
1852
1853When option `LIST` is specified together with option
1854`CONT`, the points used to draw the contours are saved in
1855`TGraph` objects:
1856
1857 h->Draw("CONT LIST");
1858 gPad->Update();
1859
1860The contour are saved in `TGraph` objects once the pad is painted.
1861Therefore to use this functionality in a macro, `gPad->Update()`
1862should be performed after the histogram drawing. Once the list is
1863built, the contours are accessible in the following way:
1864
1865 TObjArray *contours = (TObjArray*)gROOT->GetListOfSpecials()->FindObject("contours");
1866 Int_t ncontours = contours->GetSize();
1867 TList *list = (TList*)contours->At(i);
1868
1869Where `i` is a contour number, and list contains a list of
1870`TGraph` objects.
1871For one given contour, more than one disjoint polyline may be generated.
1872The number of TGraphs per contour is given by:
1873
1874 list->GetSize();
1875
1876To access the first graph in the list one should do:
1877
1878 TGraph *gr1 = (TGraph*)list->First();
1879
1880
1881The following example (hist102_TH2_contour_list.C) shows how to use this functionality.
1882
1883Begin_Macro(source)
1884../../../tutorials/hist/hist102_TH2_contour_list.C
1885End_Macro
1886
1887\anchor HP16b
1888#### The AITOFF, MERCATOR, SINUSOIDAL and PARABOLIC options
1889
1890The following options select the `CONT4` option and are useful for
1891sky maps or exposure maps (earth.C).
1892
1893| Option | Description |
1894|--------------|---------------------------------------------------------------|
1895| "AITOFF" | Draw a contour via an AITOFF projection.|
1896| "MERCATOR" | Draw a contour via an Mercator projection.|
1897| "SINUSOIDAL" | Draw a contour via an Sinusoidal projection.|
1898| "PARABOLIC" | Draw a contour via an Parabolic projection.|
1899
1900Begin_Macro(source)
1901../../../tutorials/visualisation/graphics/earth.C
1902End_Macro
1903
1904
1905\anchor HP17
1906### The LEGO options
1907
1908
1909In a lego plot the cell contents are drawn as 3-d boxes. The height of each box
1910is proportional to the cell content. The lego aspect is control with the
1911following options:
1912
1913| Option | Description |
1914|----------|-------------------------------------------------------------------|
1915| "LEGO" | Draw a lego plot using the hidden lines removal technique.|
1916| "LEGO1" | Draw a lego plot using the hidden surface removal technique.|
1917| "LEGO2" | Draw a lego plot using colors to show the cell contents.|
1918| "LEGO3" | Draw a lego plot with hidden surface removal, like LEGO1 but the border lines of each lego-bar are not drawn.|
1919| "LEGO4" | Draw a lego plot with hidden surface removal, like LEGO1 but without the shadow effect on each lego-bar.|
1920| "0" | When used with any LEGO option, the empty bins are not drawn.|
1921
1922
1923See the limitations with [the option "SAME"](\ref HP060a).
1924
1925Line attributes can be used in lego plots to change the edges' style.
1926
1927The following example shows a 2D histogram plotted with the option
1928`LEGO`. The option `LEGO` draws a lego plot using the hidden
1929lines removal technique.
1930
1931Begin_Macro(source)
1932{
1933 auto c2 = new TCanvas("c2","c2",600,400);
1934 auto hlego = new TH2F("hlego","Option LEGO example ",40,-4,4,40,-20,20);
1935 float px, py;
1936 for (Int_t i = 0; i < 25000; i++) {
1937 gRandom->Rannor(px,py);
1938 hlego->Fill(px-1,5*py);
1939 hlego->Fill(2+0.5*px,2*py-10.,0.1);
1940 }
1941 hlego->Draw("LEGO");
1942}
1943End_Macro
1944
1945The following example shows a 2D histogram plotted with the option
1946`LEGO1`. The option `LEGO1` draws a lego plot using the
1947hidden surface removal technique. Combined with any `LEGOn` option, the
1948option `0` allows to not drawn the empty bins.
1949
1950Begin_Macro(source)
1951{
1952 auto c2 = new TCanvas("c2","c2",600,400);
1953 auto hlego1 = new TH2F("hlego1","Option LEGO1 example (with option 0) ",40,-4,4,40,-20,20);
1954 float px, py;
1955 for (Int_t i = 0; i < 25000; i++) {
1956 gRandom->Rannor(px,py);
1957 hlego1->Fill(px-1,5*py);
1958 hlego1->Fill(2+0.5*px,2*py-10.,0.1);
1959 }
1960 hlego1->SetFillColor(kYellow);
1961 hlego1->Draw("LEGO1 0");
1962}
1963End_Macro
1964
1965The following example shows a 2D histogram plotted with the option
1966`LEGO3`. Like the option `LEGO1`, the option `LEGO3`
1967draws a lego plot using the hidden surface removal technique but doesn't draw
1968the border lines of each individual lego-bar. This is very useful for histograms
1969having many bins. With such histograms the option `LEGO1` gives a black
1970image because of the border lines. This option also works with stacked legos.
1971
1972Begin_Macro(source)
1973{
1974 auto c2 = new TCanvas("c2","c2",600,400);
1975 auto hlego3 = new TH2F("hlego3","Option LEGO3 example",40,-4,4,40,-20,20);
1976 float px, py;
1977 for (Int_t i = 0; i < 25000; i++) {
1978 gRandom->Rannor(px,py);
1979 hlego3->Fill(px-1,5*py);
1980 hlego3->Fill(2+0.5*px,2*py-10.,0.1);
1981 }
1982 hlego3->SetFillColor(kRed);
1983 hlego3->Draw("LEGO3");
1984}
1985End_Macro
1986
1987The following example shows a 2D histogram plotted with the option
1988`LEGO2`. The option `LEGO2` draws a lego plot using colors to
1989show the cell contents. Combined with the option `LEGO2`, the option
1990`Z` allows to display the color palette defined by
1991`gStyle->SetPalette()`.
1992
1993Begin_Macro(source)
1994{
1995 auto c2 = new TCanvas("c2","c2",600,400);
1996 auto hlego2 = new TH2F("hlego2","Option LEGO2Z example ",40,-4,4,40,-20,20);
1997 float px, py;
1998 for (Int_t i = 0; i < 25000; i++) {
1999 gRandom->Rannor(px,py);
2000 hlego2->Fill(px-1,5*py);
2001 hlego2->Fill(2+0.5*px,2*py-10.,0.1);
2002 }
2003 hlego2->Draw("LEGO2Z");
2004}
2005End_Macro
2006
2007
2008
2009\anchor HP18
2010### The "SURFace" options
2011
2012
2013In a surface plot, cell contents are represented as a mesh.
2014The height of the mesh is proportional to the cell content.
2015
2016| Option | Description |
2017|----------|-------------------------------------------------------------------|
2018| "SURF" | Draw a surface plot using the hidden line removal technique.|
2019| "SURF1" | Draw a surface plot using the hidden surface removal technique.|
2020| "SURF2" | Draw a surface plot using colors to show the cell contents.|
2021| "SURF3" | Same as `SURF` with an additional filled contour plot on top.|
2022| "SURF4" | Draw a surface using the Gouraud shading technique.|
2023| "SURF5" | Used with one of the options CYL, PSR and CYL this option allows to draw a filled contour plot.|
2024| "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.|
2025| "SURF7" | Same as `SURF2` with an additional line contour plot on top.|
2026
2027
2028
2029See the limitations with [the option "SAME"](\ref HP060a).
2030
2031The following example shows a 2D histogram plotted with the option
2032`SURF`. The option `SURF` draws a lego plot using the hidden
2033lines removal technique.
2034
2035Begin_Macro(source)
2036{
2037 auto c2 = new TCanvas("c2","c2",600,400);
2038 auto hsurf = new TH2F("hsurf","Option SURF example ",30,-4,4,30,-20,20);
2039 float px, py;
2040 for (Int_t i = 0; i < 25000; i++) {
2041 gRandom->Rannor(px,py);
2042 hsurf->Fill(px-1,5*py);
2043 hsurf->Fill(2+0.5*px,2*py-10.,0.1);
2044 }
2045 hsurf->Draw("SURF");
2046}
2047End_Macro
2048
2049The following example shows a 2D histogram plotted with the option
2050`SURF1`. The option `SURF1` draws a surface plot using the
2051hidden surface removal technique. Combined with the option `SURF1`,
2052the option `Z` allows to display the color palette defined by
2053`gStyle->SetPalette()`.
2054
2055Begin_Macro(source)
2056{
2057 auto c2 = new TCanvas("c2","c2",600,400);
2058 auto hsurf1 = new TH2F("hsurf1","Option SURF1 example ",30,-4,4,30,-20,20);
2059 float px, py;
2060 for (Int_t i = 0; i < 25000; i++) {
2061 gRandom->Rannor(px,py);
2062 hsurf1->Fill(px-1,5*py);
2063 hsurf1->Fill(2+0.5*px,2*py-10.,0.1);
2064 }
2065 hsurf1->Draw("SURF1");
2066}
2067End_Macro
2068
2069The following example shows a 2D histogram plotted with the option
2070`SURF2`. The option `SURF2` draws a surface plot using colors
2071to show the cell contents. Combined with the option `SURF2`, the option
2072`Z` allows to display the color palette defined by
2073`gStyle->SetPalette()`.
2074
2075Begin_Macro(source)
2076{
2077 auto c2 = new TCanvas("c2","c2",600,400);
2078 auto hsurf2 = new TH2F("hsurf2","Option SURF2 example ",30,-4,4,30,-20,20);
2079 float px, py;
2080 for (Int_t i = 0; i < 25000; i++) {
2081 gRandom->Rannor(px,py);
2082 hsurf2->Fill(px-1,5*py);
2083 hsurf2->Fill(2+0.5*px,2*py-10.,0.1);
2084 }
2085 hsurf2->Draw("SURF2");
2086}
2087End_Macro
2088
2089The following example shows a 2D histogram plotted with the option
2090`SURF3`. The option `SURF3` draws a surface plot using the
2091hidden line removal technique with, in addition, a filled contour view drawn on the
2092top. Combined with the option `SURF3`, the option `Z` allows
2093to display the color palette defined by `gStyle->SetPalette()`.
2094
2095Begin_Macro(source)
2096{
2097 auto c2 = new TCanvas("c2","c2",600,400);
2098 auto hsurf3 = new TH2F("hsurf3","Option SURF3 example ",30,-4,4,30,-20,20);
2099 float px, py;
2100 for (Int_t i = 0; i < 25000; i++) {
2101 gRandom->Rannor(px,py);
2102 hsurf3->Fill(px-1,5*py);
2103 hsurf3->Fill(2+0.5*px,2*py-10.,0.1);
2104 }
2105 hsurf3->Draw("SURF3");
2106}
2107End_Macro
2108
2109The following example shows a 2D histogram plotted with the option
2110`SURF4`. The option `SURF4` draws a surface using the Gouraud
2111shading technique.
2112
2113Begin_Macro(source)
2114{
2115 auto c2 = new TCanvas("c2","c2",600,400);
2116 auto hsurf4 = new TH2F("hsurf4","Option SURF4 example ",30,-4,4,30,-20,20);
2117 float px, py;
2118 for (Int_t i = 0; i < 25000; i++) {
2119 gRandom->Rannor(px,py);
2120 hsurf4->Fill(px-1,5*py);
2121 hsurf4->Fill(2+0.5*px,2*py-10.,0.1);
2122 }
2123 hsurf4->SetFillColor(kOrange);
2124 hsurf4->Draw("SURF4");
2125}
2126End_Macro
2127
2128The following example shows a 2D histogram plotted with the option
2129`SURF5 CYL`. Combined with the option `SURF5`, the option
2130`Z` allows to display the color palette defined by `gStyle->SetPalette()`.
2131
2132Begin_Macro(source)
2133{
2134 auto c2 = new TCanvas("c2","c2",600,400);
2135 auto hsurf5 = new TH2F("hsurf4","Option SURF5 example ",30,-4,4,30,-20,20);
2136 float px, py;
2137 for (Int_t i = 0; i < 25000; i++) {
2138 gRandom->Rannor(px,py);
2139 hsurf5->Fill(px-1,5*py);
2140 hsurf5->Fill(2+0.5*px,2*py-10.,0.1);
2141 }
2142 hsurf5->Draw("SURF5 CYL");
2143}
2144End_Macro
2145
2146The following example shows a 2D histogram plotted with the option
2147`SURF7`. The option `SURF7` draws a surface plot using the
2148hidden surfaces removal technique with, in addition, a line contour view drawn on the
2149top. Combined with the option `SURF7`, the option `Z` allows
2150to display the color palette defined by `gStyle->SetPalette()`.
2151
2152Begin_Macro(source)
2153{
2154 auto c2 = new TCanvas("c2","c2",600,400);
2155 auto hsurf7 = new TH2F("hsurf3","Option SURF7 example ",30,-4,4,30,-20,20);
2156 float px, py;
2157 for (Int_t i = 0; i < 25000; i++) {
2158 gRandom->Rannor(px,py);
2159 hsurf7->Fill(px-1,5*py);
2160 hsurf7->Fill(2+0.5*px,2*py-10.,0.1);
2161 }
2162 hsurf7->Draw("SURF7");
2163}
2164End_Macro
2165
2166As shown in the following example, when a contour plot is painted on top of a
2167surface plot using the option `SAME`, the contours appear in 3D on the
2168surface.
2169
2170Begin_Macro(source)
2171{
2172 auto c20=new TCanvas("c20","c20",600,400);
2173 int NBins = 50;
2174 double d = 2;
2175 auto hsc = new TH2F("hsc", "Surface and contour with option SAME ", NBins, -d, d, NBins, -d, d);
2176 for (int bx = 1; bx <= NBins; ++bx) {
2177 for (int by = 1; by <= NBins; ++by) {
2178 double x = hsc->GetXaxis()->GetBinCenter(bx);
2179 double y = hsc->GetYaxis()->GetBinCenter(by);
2180 hsc->SetBinContent(bx, by, exp(-x*x)*exp(-y*y));
2181 }
2182 }
2183 hsc->Draw("surf2");
2184 hsc->Draw("CONT1 SAME");
2185}
2186End_Macro
2187
2188
2189\anchor HP19
2190### Cylindrical, Polar, Spherical and PseudoRapidity/Phi options
2191
2192
2193Legos and surfaces plots are represented by default in Cartesian coordinates.
2194Combined with any `LEGOn` or `SURFn` options the following
2195options allow to draw a lego or a surface in other coordinates systems.
2196
2197| Option | Description |
2198|----------|-------------------------------------------------------------------|
2199| "CYL" | Use Cylindrical coordinates. The X coordinate is mapped on the angle and the Y coordinate on the cylinder length.|
2200| "POL" | Use Polar coordinates. The X coordinate is mapped on the angle and the Y coordinate on the radius.|
2201| "SPH" | Use Spherical coordinates. The X coordinate is mapped on the latitude and the Y coordinate on the longitude.|
2202| "PSR" | Use PseudoRapidity/Phi coordinates. The X coordinate is mapped on Phi.|
2203
2204
2205
2206<b>WARNING:</b> Axis are not drawn with these options.
2207
2208The following example shows the same histogram as a lego plot is the four
2209different coordinates systems.
2210
2211Begin_Macro(source)
2212{
2213 auto c3 = new TCanvas("c3","c3",600,400);
2214 c3->Divide(2,2);
2215 auto hlcc = new TH2F("hlcc","Cylindrical coordinates",20,-4,4,20,-20,20);
2216 float px, py;
2217 for (Int_t i = 0; i < 25000; i++) {
2218 gRandom->Rannor(px,py);
2219 hlcc->Fill(px-1,5*py);
2220 hlcc->Fill(2+0.5*px,2*py-10.,0.1);
2221 }
2222 hlcc->SetFillColor(kYellow);
2223 c3->cd(1); hlcc->Draw("LEGO1 CYL");
2224 c3->cd(2); auto hlpc = (TH2F*) hlcc->DrawClone("LEGO1 POL");
2225 hlpc->SetTitle("Polar coordinates");
2226 c3->cd(3); auto hlsc = (TH2F*) hlcc->DrawClone("LEGO1 SPH");
2227 hlsc->SetTitle("Spherical coordinates");
2228 c3->cd(4); auto hlprpc = (TH2F*) hlcc->DrawClone("LEGO1 PSR");
2229 hlprpc->SetTitle("PseudoRapidity/Phi coordinates");
2230}
2231End_Macro
2232
2233The following example shows the same histogram as a surface plot is the four different coordinates systems.
2234
2235Begin_Macro(source)
2236{
2237 auto c4 = new TCanvas("c4","c4",600,400);
2238 c4->Divide(2,2);
2239 auto hscc = new TH2F("hscc","Cylindrical coordinates",20,-4,4,20,-20,20);
2240 float px, py;
2241 for (Int_t i = 0; i < 25000; i++) {
2242 gRandom->Rannor(px,py);
2243 hscc->Fill(px-1,5*py);
2244 hscc->Fill(2+0.5*px,2*py-10.,0.1);
2245 }
2246 c4->cd(1); hscc->Draw("SURF1 CYL");
2247 c4->cd(2); auto hspc = (TH2F*) hscc->DrawClone("SURF1 POL");
2248 hspc->SetTitle("Polar coordinates");
2249 c4->cd(3); auto hssc = (TH2F*) hscc->DrawClone("SURF1 SPH");
2250 hssc->SetTitle("Spherical coordinates");
2251 c4->cd(4); auto hsprpc = (TH2F*) hscc->DrawClone("SURF1 PSR");
2252 hsprpc->SetTitle("PseudoRapidity/Phi coordinates");
2253}
2254End_Macro
2255
2256
2257\anchor HP20
2258### Base line for bar-charts and lego plots
2259
2260
2261By default the base line used to draw the boxes for bar-charts and lego plots is
2262the histogram minimum. It is possible to force this base line to be 0, using MIN0 draw
2263option or with the command:
2264
2265 gStyle->SetHistMinimumZero();
2266
2267Begin_Macro(source)
2268{
2269 auto c5 = new TCanvas("c5","c5",700,400);
2270 c5->Divide(2,1);
2271 auto hz1 = new TH1F("hz1","Bar-chart drawn from 0",20,-3,3);
2272 auto hz2 = new TH2F("hz2","Lego plot drawn from 0",20,-3,3,20,-3,3);
2273 Int_t i;
2274 double x,y;
2275 hz1->SetFillColor(kBlue);
2276 hz2->SetFillColor(kBlue);
2277 for (i=0;i<10000;i++) {
2278 x = gRandom->Gaus(0,1);
2279 y = gRandom->Gaus(0,1);
2280 if (x>0) {
2281 hz1->Fill(x,1);
2282 hz2->Fill(x,y,1);
2283 } else {
2284 hz1->Fill(x,-1);
2285 hz2->Fill(x,y,-2);
2286 }
2287 }
2288 c5->cd(1); hz1->Draw("bar2 min0");
2289 c5->cd(2); hz2->Draw("lego1 min0");
2290}
2291End_Macro
2292
2293This option also works for horizontal plots. The example given in the section
2294["The bar chart option"](\ref HP100) appears as follow:
2295
2296Begin_Macro(source)
2297{
2298 int i;
2299 const Int_t nx = 8;
2300 string os_X[nx] = {"8","32","128","512","2048","8192","32768","131072"};
2301 float d_35_0[nx] = {0.75, -3.30, -0.92, 0.10, 0.08, -1.69, -1.29, -2.37};
2302 float d_35_1[nx] = {1.01, -3.02, -0.65, 0.37, 0.34, -1.42, -1.02, -2.10};
2303
2304 auto cbh = new TCanvas("cbh","cbh",400,600);
2305 cbh->SetGrid();
2306
2307 auto h1bh = new TH1F("h1bh","Option HBAR centered on 0",nx,0,nx);
2308 h1bh->SetFillColor(4);
2309 h1bh->SetBarWidth(0.4);
2310 h1bh->SetBarOffset(0.1);
2311 h1bh->SetStats(0);
2312 h1bh->SetMinimum(-5);
2313 h1bh->SetMaximum(5);
2314
2315 for (i=1; i<=nx; i++) {
2316 h1bh->Fill(os_X[i-1].c_str(), d_35_0[i-1]);
2317 h1bh->GetXaxis()->SetBinLabel(i,os_X[i-1].c_str());
2318 }
2319
2320 h1bh->Draw("hbar min0");
2321
2322 auto h2bh = new TH1F("h2bh","h2bh",nx,0,nx);
2323 h2bh->SetFillColor(38);
2324 h2bh->SetBarWidth(0.4);
2325 h2bh->SetBarOffset(0.5);
2326 h2bh->SetStats(0);
2327 for (i=1;i<=nx;i++) h2bh->Fill(os_X[i-1].c_str(), d_35_1[i-1]);
2328
2329 h2bh->Draw("hbar min0 same");
2330}
2331End_Macro
2332
2333
2334\anchor HP20a
2335### TH2Poly Drawing
2336
2337
2338The following options are supported:
2339
2340| Option | Description |
2341|----------|-------------------------------------------------------------------|
2342| "SCAT" | Draw a scatter plot (legacy draw option).|
2343| "COL" | Draw a color plot. All the bins are painted even the empty bins (default).|
2344| "COLZ" | Same as "COL". In addition the color palette is also drawn.|
2345| "0" | When used with any COL options, the empty bins are not drawn.|
2346| "TEXT" | Draw bin contents as text (format set via `gStyle->SetPaintTextFormat`).|
2347| "TEXTN" | Draw bin names as text.|
2348| "TEXTnn" | Draw bin contents as text at angle nn (0 < nn <= 90).|
2349| "L" | Draw the bins boundaries as lines. The lines attributes are the TGraphs ones.|
2350| "P" | Draw the bins boundaries as markers. The markers attributes are the TGraphs ones.|
2351| "F" | Draw the bins boundaries as filled polygons. The filled polygons attributes are the TGraphs ones.|
2352
2353
2354
2355`TH2Poly` can be drawn as a color plot (option COL). `TH2Poly` bins can have any
2356shapes. The bins are defined as graphs. The following macro is a very simple
2357example showing how to book a TH2Poly and draw it.
2358
2359Begin_Macro(source)
2360{
2361 auto ch2p1 = new TCanvas("ch2p1","ch2p1",600,400);
2362 auto h2p = new TH2Poly();
2363 h2p->SetName("h2poly_name");
2364 h2p->SetTitle("h2poly_title");
2365 double px1[] = {0, 5, 6};
2366 double py1[] = {0, 0, 5};
2367 double px2[] = {0, -1, -1, 0};
2368 double py2[] = {0, 0, -1, 3};
2369 double px3[] = {4, 3, 0, 1, 2.4};
2370 double py3[] = {4, 3.7, 1, 3.7, 2.5};
2371 h2p->AddBin(3, px1, py1);
2372 h2p->AddBin(4, px2, py2);
2373 h2p->AddBin(5, px3, py3);
2374 h2p->Fill(0.1, 0.01, 3);
2375 h2p->Fill(-0.5, -0.5, 7);
2376 h2p->Fill(-0.7, -0.5, 1);
2377 h2p->Fill(1, 3, 1.5);
2378 double fx[] = {0.1, -0.5, -0.7, 1};
2379 double fy[] = {0.01, -0.5, -0.5, 3};
2380 double fw[] = {3, 1, 1, 1.5};
2381 h2p->FillN(4, fx, fy, fw);
2382 h2p->Draw("col");
2383}
2384End_Macro
2385
2386Rectangular bins are a frequent case. The special version of
2387the `AddBin` method allows to define them more easily like
2388shown in the following example (hist037_TH2Poly_boxes.C).
2389
2390Begin_Macro(source)
2391../../../tutorials/hist/hist037_TH2Poly_boxes.C
2392End_Macro
2393
2394One `TH2Poly` bin can be a list of polygons. Such bins are defined
2395by calling `AddBin` with a `TMultiGraph`. The following example
2396shows a such case:
2397
2398Begin_Macro(source)
2399{
2400 auto ch2p2 = new TCanvas("ch2p2","ch2p2",600,400);
2401
2402 Int_t i, bin;
2403 const Int_t nx = 48;
2404 const char *states [nx] = {
2405 "alabama", "arizona", "arkansas", "california",
2406 "colorado", "connecticut", "delaware", "florida",
2407 "georgia", "idaho", "illinois", "indiana",
2408 "iowa", "kansas", "kentucky", "louisiana",
2409 "maine", "maryland", "massachusetts", "michigan",
2410 "minnesota", "mississippi", "missouri", "montana",
2411 "nebraska", "nevada", "new_hampshire", "new_jersey",
2412 "new_mexico", "new_york", "north_carolina", "north_dakota",
2413 "ohio", "oklahoma", "oregon", "pennsylvania",
2414 "rhode_island", "south_carolina", "south_dakota", "tennessee",
2415 "texas", "utah", "vermont", "virginia",
2416 "washington", "west_virginia", "wisconsin", "wyoming"
2417 };
2418 Double_t pop[nx] = {
2419 4708708, 6595778, 2889450, 36961664, 5024748, 3518288, 885122, 18537969,
2420 9829211, 1545801, 12910409, 6423113, 3007856, 2818747, 4314113, 4492076,
2421 1318301, 5699478, 6593587, 9969727, 5266214, 2951996, 5987580, 974989,
2422 1796619, 2643085, 1324575, 8707739, 2009671, 19541453, 9380884, 646844,
2423 11542645, 3687050, 3825657, 12604767, 1053209, 4561242, 812383, 6296254,
2424 24782302, 2784572, 621760, 7882590, 6664195, 1819777, 5654774, 544270
2425 };
2426
2427 Double_t lon1 = -130;
2428 Double_t lon2 = -65;
2429 Double_t lat1 = 24;
2430 Double_t lat2 = 50;
2431 auto p = new TH2Poly("USA","USA Population",lon1,lon2,lat1,lat2);
2432
2433 TFile::SetCacheFileDir(".");
2434 auto f = TFile::Open("http://root.cern/files/usa.root", "CACHEREAD");
2435
2436 TMultiGraph *mg;
2437 TKey *key;
2438 TIter nextkey(gDirectory->GetListOfKeys());
2439 while ((key = (TKey*)nextkey())) {
2440 TObject *obj = key->ReadObj();
2441 if (obj->InheritsFrom("TMultiGraph")) {
2442 mg = (TMultiGraph*)obj;
2443 bin = p->AddBin(mg);
2444 }
2445 }
2446
2447 for (i=0; i<nx; i++) p->Fill(states[i], pop[i]);
2448
2449 gStyle->SetOptStat(11);
2450 p->Draw("COLZ L");
2451}
2452End_Macro
2453
2454`TH2Poly` histograms can also be plotted using the GL interface using
2455the option "GLLEGO".
2456
2457\since **ROOT version 6.09/01**
2458
2459In some cases it can be useful to not draw the empty bins. the option "0"
2460combined with the option "COL" et COLZ allows to do that.
2461
2462Begin_Macro(source)
2463{
2464 auto chc = new TCanvas("chc","chc",600,400);
2465
2466 auto hc = new TH2Poly();
2467 hc->Honeycomb(0,0,.1,25,25);
2468 hc->SetName("hc");
2469 hc->SetTitle("Option COLZ 0");
2470 TRandom ran;
2471 for (int i = 0; i<300; i++) hc->Fill(ran.Gaus(2.,1), ran.Gaus(2.,1));
2472 hc->Draw("colz 0");
2473}
2474End_Macro
2475
2476\anchor HP21
2477### The SPEC option
2478
2479
2480This option allows to use the `TSpectrum2Painter` tools. See the full
2481documentation in `TSpectrum2Painter::PaintSpectrum`.
2482
2483
2484\anchor HP22
2485### Option "Z" : Adding the color palette on the right side of the pad
2486
2487
2488When this option is specified, a color palette with an axis indicating the value
2489of the corresponding color is drawn on the right side of the picture. In case,
2490not enough space is left, one can increase the size of the right margin by
2491calling `TPad::SetRightMargin()`. The attributes used to display the
2492palette axis values are taken from the Z axis of the object. For example, to
2493set the labels size on the palette axis do:
2494
2495 hist->GetZaxis()->SetLabelSize().
2496
2497<b>WARNING:</b> The palette axis is always drawn vertically.
2498
2499
2500\anchor HP23
2501### Setting the color palette
2502
2503
2504To change the color palette `TStyle::SetPalette` should be used, eg:
2505
2506 gStyle->SetPalette(ncolors,colors);
2507
2508For example the option `COL` draws a 2D histogram with cells
2509represented by a box filled with a color index which is a function
2510of the cell content.
2511If the cell content is N, the color index used will be the color number
2512in `colors[N]`, etc. If the maximum cell content is greater than
2513`ncolors`, all cell contents are scaled to `ncolors`.
2514
2515If ` ncolors <= 0`, a default palette (see below) of 50 colors is
2516defined. This palette is recommended for pads, labels ...
2517
2518`if ncolors == 1 && colors == 0`, then a Pretty Palette with a
2519Spectrum Violet->Red is created with 50 colors. That's the default rain bow
2520palette.
2521
2522Other pre-defined palettes with 255 colors are available when `colors == 0`.
2523The following value of `ncolors` give access to:
2524
2525
2526 if ncolors = 51 and colors=0, a Deep Sea palette is used.
2527 if ncolors = 52 and colors=0, a Grey Scale palette is used.
2528 if ncolors = 53 and colors=0, a Dark Body Radiator palette is used.
2529 if ncolors = 54 and colors=0, a two-color hue palette palette is used.(dark blue through neutral gray to bright
2530yellow) if ncolors = 55 and colors=0, a Rain Bow palette is used. if ncolors = 56 and colors=0, an inverted Dark Body
2531Radiator palette is used.
2532
2533
2534If `ncolors > 0 && colors == 0`, the default palette is used with a maximum of ncolors.
2535
2536The default palette defines:
2537
2538- index 0 to 9 : shades of grey
2539- index 10 to 19 : shades of brown
2540- index 20 to 29 : shades of blue
2541- index 30 to 39 : shades of red
2542- index 40 to 49 : basic colors
2543
2544The color numbers specified in the palette can be viewed by selecting
2545the item `colors` in the `VIEW` menu of the canvas tool bar.
2546The red, green, and blue components of a color can be changed thanks to
2547`TColor::SetRGB()`.
2548
2549\since **ROOT version 6.19/01**
2550
2551As default labels and ticks are drawn by `TGAxis` at equidistant (lin or log)
2552points as controlled by SetNdivisions.
2553If option "CJUST" is given labels and ticks are justified at the
2554color boundaries defined by the contour levels.
2555For more details see `TPaletteAxis`
2556
2557\anchor HP24
2558### Drawing a sub-range of a 2D histogram; the [cutg] option
2559
2560
2561Using a `TCutG` object, it is possible to draw a sub-range of a 2D
2562histogram. One must create a graphical cut (mouse or C++) and specify the name
2563of the cut between `[]` in the `Draw()` option.
2564For example (fit2a.C), with a `TCutG` named `cutg`, one can call:
2565
2566 myhist->Draw("surf1 [cutg]");
2567
2568To invert the cut, it is enough to put a `-` in front of its name:
2569
2570 myhist->Draw("surf1 [-cutg]");
2571
2572It is possible to apply several cuts (`,` means logical AND):
2573
2574 myhist->Draw("surf1 [cutg1,cutg2]");
2575
2576Begin_Macro(source)
2577../../../tutorials/fit/fit2a.C
2578End_Macro
2579
2580\anchor HP25
2581### Drawing options for 3D histograms
2582
2583
2584| Option | Description |
2585|----------|-------------------------------------------------------------------|
2586| "SCAT" | Draw a scatter plot (legacy draw option).|
2587| "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)`|
2588| "BOX" | Draw a for each cell with volume proportional to the content's absolute value. An hidden line removal algorithm is used|
2589| "BOX1" | Same as BOX but an hidden surface removal algorithm is used|
2590| "BOX2" | Same as "COL". The boxes' colors are picked in the current palette according to the bins' contents (default)|
2591| "BOX2Z" | Same as "BOX2". In addition the color palette is also drawn.|
2592| "BOX3" | Same as BOX1, but the border lines of each lego-bar are not drawn.|
2593
2594Note that instead of `BOX` one can also use `LEGO`.
2595
2596By default, 3D histograms are drawn as a colored box plots.
2597
2598The following example shows a 3D histogram plotted as a scatter plot.
2599
2600Begin_Macro(source)
2601{
2602 auto c06 = new TCanvas("c06","c06",600,400);
2603 gStyle->SetOptStat(kFALSE);
2604 auto h3scat = new TH3F("h3scat","Option SCAT",15,-2,2,15,-2,2,15,0,4);
2605 double x, y, z;
2606 for (Int_t i=0;i<10000;i++) {
2607 gRandom->Rannor(x, y);
2608 z = x*x + y*y;
2609 h3scat->Fill(x,y,z);
2610 }
2611 h3scat->Draw("SCAT"); // This a legacy draw option
2612}
2613End_Macro
2614
2615The following example shows a 3D histogram plotted with the option `BOX`.
2616
2617Begin_Macro(source)
2618{
2619 auto c16 = new TCanvas("c16","c16",600,400);
2620 gStyle->SetOptStat(kFALSE);
2621 auto h3box = new TH3F("h3box","Option BOX",15,-2,2,15,-2,2,15,0,4);
2622 double x, y, z;
2623 for (Int_t i=0;i<10000;i++) {
2624 gRandom->Rannor(x, y);
2625 z = x*x + y*y;
2626 h3box->Fill(x,y,z);
2627 }
2628 h3box->Draw("BOX");
2629}
2630End_Macro
2631
2632The following example shows a 3D histogram plotted with the option `BOX1`.
2633
2634Begin_Macro(source)
2635{
2636 auto c36 = new TCanvas("c36","c36",600,400);
2637 gStyle->SetOptStat(kFALSE);
2638 auto h3box = new TH3F("h3box","Option BOX1",10,-2.,2.,10,-2.,2.,10,-0.5,2.);
2639 double x, y, z;
2640 for (Int_t i=0;i<10000;i++) {
2641 gRandom->Rannor(x, y);
2642 z = abs(sin(x)/x + cos(y)*y);
2643 h3box->Fill(x,y,z);
2644 }
2645 h3box->SetFillColor(9);
2646 h3box->Draw("BOX1");
2647}
2648End_Macro
2649
2650The following example shows a 3D histogram plotted with the option `BOX2`.
2651
2652Begin_Macro(source)
2653{
2654 auto c56 = new TCanvas("c56","c56",600,400);
2655 gStyle->SetOptStat(kFALSE);
2656 auto h3box = new TH3F("h3box","Option BOX2 (default)",10,-2.,2.,10,-2.,2.,10,-0.5,2.);
2657 double x, y, z;
2658 for (Int_t i=0;i<10000;i++) {
2659 gRandom->Rannor(x, y);
2660 z = abs(sin(x)/x + cos(y)*y);
2661 h3box->Fill(x,y,z);
2662 }
2663 h3box->Draw("BOX2 Z");
2664}
2665End_Macro
2666
2667The following example shows a 3D histogram plotted with the option `BOX3`.
2668
2669Begin_Macro(source)
2670{
2671 auto c46 = new TCanvas("c46","c46",600,400);
2672 c46->SetFillColor(38);
2673 gStyle->SetOptStat(kFALSE);
2674 auto h3box = new TH3F("h3box","Option BOX3",15,-2,2,15,-2,2,15,0,4);
2675 double x, y, z;
2676 for (Int_t i=0;i<10000;i++) {
2677 gRandom->Rannor(x, y);
2678 z = x*x + y*y;
2679 h3box->Fill(x,y,z);
2680 }
2681 h3box->Draw("BOX3");
2682}
2683End_Macro
2684
2685For all the `BOX` options each bin is drawn as a 3D box with a volume proportional
2686to the absolute value of the bin content. The bins with a negative content are
2687drawn with a X on each face of the box as shown in the following example:
2688
2689Begin_Macro(source)
2690{
2691 auto c = new TCanvas("c","c",600,400);
2692 gStyle->SetOptStat(kFALSE);
2693 auto h3box = new TH3F("h3box","Option BOX1 with negative bins",3, 0., 4., 3, 0.,4., 3, 0., 4.);
2694 h3box->Fill(0., 2., 2., 10.);
2695 h3box->Fill(2., 2., 2., 5.);
2696 h3box->Fill(2., 2., .5, 2.);
2697 h3box->Fill(2., 2., 3., -1.);
2698 h3box->Fill(3., 2., 2., -10.);
2699 h3box->SetFillColor(8);
2700 h3box->Draw("box1");
2701}
2702End_Macro
2703
2704The following example shows a 3D histogram plotted with the option `ISO`.
2705
2706Begin_Macro(source)
2707{
2708 auto c26 = new TCanvas("c26","c26",600,400);
2709 gStyle->SetOptStat(kFALSE);
2710 auto h3iso = new TH3F("h3iso","Option ISO",15,-2,2,15,-2,2,15,0,4);
2711 double x, y, z;
2712 for (Int_t i=0;i<10000;i++) {
2713 gRandom->Rannor(x, y);
2714 z = x*x + y*y;
2715 h3iso->Fill(x,y,z);
2716 }
2717 h3iso->SetFillColor(kCyan);
2718 h3iso->Draw("ISO");
2719}
2720End_Macro
2721
2722
2723\anchor HP26
2724### Drawing option for histograms' stacks
2725
2726
2727Stacks of histograms are managed with the `THStack`. A `THStack`
2728is a collection of `TH1` (or derived) objects. For painting only the
2729`THStack` containing `TH1` only or
2730`THStack` containing `TH2` only will be considered.
2731
2732By default, histograms are shown stacked:
2733
27341. The first histogram is paint.
27352. The sum of the first and second, etc...
2736
2737If the option `NOSTACK` is specified, the histograms are all paint in
2738the same pad as if the option `SAME` had been specified. This allows to
2739compute X and Y scales common to all the histograms, like
2740`TMultiGraph` does for graphs.
2741
2742If the option `PADS` is specified, the current pad/canvas is
2743subdivided into a number of pads equal to the number of histograms and each
2744histogram is paint into a separate pad.
2745
2746The following example shows various types of stacks (hist023_THStack_simple.C).
2747
2748Begin_Macro(source)
2749../../../tutorials/hist/hist023_THStack_simple.C
2750End_Macro
2751
2752The option `nostackb` allows to draw the histograms next to each
2753other as bar charts:
2754
2755Begin_Macro(source)
2756{
2757 auto cst0 = new TCanvas("cst0","cst0",600,400);
2758 auto hs = new THStack("hs","Stacked 1D histograms: option #font[82]{\"nostackb\"}");
2759
2760 auto h1 = new TH1F("h1","h1",10,-4,4);
2761 h1->FillRandom("gaus",20000);
2762 h1->SetFillColor(kRed);
2763 hs->Add(h1);
2764
2765 auto h2 = new TH1F("h2","h2",10,-4,4);
2766 h2->FillRandom("gaus",15000);
2767 h2->SetFillColor(kBlue);
2768 hs->Add(h2);
2769
2770 auto h3 = new TH1F("h3","h3",10,-4,4);
2771 h3->FillRandom("gaus",10000);
2772 h3->SetFillColor(kGreen);
2773 hs->Add(h3);
2774
2775 hs->Draw("nostackb");
2776 hs->GetXaxis()->SetNdivisions(-10);
2777 cst0->SetGridx();
2778}
2779End_Macro
2780
2781If at least one of the histograms in the stack has errors, the whole stack is
2782visualized by default with error bars. To visualize it without errors the
2783option `HIST` should be used.
2784
2785Begin_Macro(source)
2786{
2787 auto cst1 = new TCanvas("cst1","cst1",700,400);
2788 cst1->Divide(2,1);
2789
2790 auto hst11 = new TH1F("hst11", "", 20, -10, 10);
2791 hst11->Sumw2();
2792 hst11->FillRandom("gaus", 1000);
2793 hst11->SetFillColor(kViolet);
2794 hst11->SetLineColor(kViolet);
2795
2796 auto hst12 = new TH1F("hst12", "", 20, -10, 10);
2797 hst12->FillRandom("gaus", 500);
2798 hst12->SetFillColor(kBlue);
2799 hst12->SetLineColor(kBlue);
2800
2801 THStack st1("st1", "st1");
2802 st1.Add(hst11);
2803 st1.Add(hst12);
2804
2805 cst1->cd(1); st1.Draw();
2806 cst1->cd(2); st1.Draw("hist");
2807}
2808End_Macro
2809
2810\anchor HP27
2811### Drawing of 3D implicit functions
2812
2813
28143D implicit functions (`TF3`) can be drawn as iso-surfaces.
2815The implicit function f(x,y,z) = 0 is drawn in cartesian coordinates.
2816In the following example the options "FB" and "BB" suppress the
2817"Front Box" and "Back Box" around the plot.
2818
2819Begin_Macro(source)
2820{
2821 auto c2 = new TCanvas("c2","c2",600,400);
2822 auto f3 = new TF3("f3","sin(x*x+y*y+z*z-36)",-2,2,-2,2,-2,2);
2823 f3->SetClippingBoxOn(0,0,0);
2824 f3->SetFillColor(30);
2825 f3->SetLineColor(15);
2826 f3->Draw("FBBB");
2827}
2828End_Macro
2829
2830
2831\anchor HP28
2832### Associated functions drawing
2833
2834
2835An associated function is created by `TH1::Fit`. More than on fitted
2836function can be associated with one histogram (see `TH1::Fit`).
2837
2838A `TF1` object `f1` can be added to the list of associated
2839functions of an histogram `h` without calling `TH1::Fit`
2840simply doing:
2841
2842 h->GetListOfFunctions()->Add(f1);
2843
2844or
2845
2846 h->GetListOfFunctions()->Add(f1,someoption);
2847
2848To retrieve a function by name from this list, do:
2849
2850 TF1 *f1 = (TF1*)h->GetListOfFunctions()->FindObject(name);
2851
2852or
2853
2854 TF1 *f1 = h->GetFunction(name);
2855
2856Associated functions are automatically painted when an histogram is drawn.
2857To avoid the painting of the associated functions the option `HIST`
2858should be added to the list of the options used to paint the histogram.
2859
2860
2861\anchor HP29
2862### Drawing using OpenGL
2863
2864
2865The class `TGLHistPainter` allows to paint data set using the OpenGL 3D
2866graphics library. The plotting options start with `GL` keyword.
2867In addition, in order to inform canvases that OpenGL should be used to render
28683D representations, the following option should be set:
2869
2870 gStyle->SetCanvasPreferGL(true);
2871
2872
2873\anchor HP29a
2874#### General information: plot types and supported options
2875
2876The following types of plots are provided:
2877
2878For lego plots the supported options are:
2879
2880| Option | Description |
2881|----------|-------------------------------------------------------------------|
2882| "GLLEGO" | Draw a lego plot. It works also for `TH2Poly`.|
2883| "GLLEGO2"| Bins with color levels.|
2884| "GLLEGO3"| Cylindrical bars.|
2885
2886
2887
2888Lego painter in cartesian supports logarithmic scales for X, Y, Z.
2889In polar only Z axis can be logarithmic, in cylindrical only Y.
2890
2891For surface plots (`TF2` and `TH2`) the supported options are:
2892
2893| Option | Description |
2894|-----------|------------------------------------------------------------------|
2895| "GLSURF" | Draw a surface.|
2896| "GLSURF1" | Surface with color levels|
2897| "GLSURF2" | The same as "GLSURF1" but without polygon outlines.|
2898| "GLSURF3" | Color level projection on top of plot (works only in cartesian coordinate system).|
2899| "GLSURF4" | Same as "GLSURF" but without polygon outlines.|
2900
2901
2902
2903The surface painting in cartesian coordinates supports logarithmic scales along
2904X, Y, Z axis. In polar coordinates only the Z axis can be logarithmic,
2905in cylindrical coordinates only the Y axis.
2906
2907Additional options to SURF and LEGO - Coordinate systems:
2908
2909| Option | Description |
2910|----------|-------------------------------------------------------------------|
2911| " " | Default, cartesian coordinates system.|
2912| "POL" | Polar coordinates system.|
2913| "CYL" | Cylindrical coordinates system.|
2914| "SPH" | Spherical coordinates system.|
2915
2916
2917
2918\anchor HP290
2919#### TH3 as color boxes
2920
2921The supported option is:
2922
2923| Option | Description |
2924|----------|-------------------------------------------------------------------|
2925| "GLCOL" | H3 is drawn using semi-transparent colored boxes. See glvox1.C .|
2926
2927
2928
2929\anchor HP29b
2930#### TH3 as boxes (spheres)
2931
2932The supported options are:
2933
2934| Option | Description |
2935|----------|-------------------------------------------------------------------|
2936| "GLBOX" | TH3 as a set of boxes, size of box is proportional to bin content.|
2937| "GLBOX1" | The same as "glbox", but spheres are drawn instead of boxes.|
2938
2939
2940
2941\anchor HP29c
2942#### TH3 as iso-surface(s)
2943
2944The supported option is:
2945
2946| Option | Description |
2947|----------|-------------------------------------------------------------------|
2948| "GLISO" | TH3 is drawn using iso-surfaces.|
2949
2950
2951
2952\anchor HP29d
2953#### TF3 (implicit function)
2954
2955The supported option is:
2956
2957| Option | Description |
2958|----------|-------------------------------------------------------------------|
2959| "GL" | Draw a TF3.|
2960
2961
2962
2963\anchor HP29e
2964#### Parametric surfaces
2965
2966glparametric.C shows how to create parametric equations and visualize the surface.
2967
2968\anchor HP29f
2969#### Interaction with the plots
2970
2971All the interactions are implemented via standard methods
2972`DistancetoPrimitive()` and `ExecuteEvent()`. That's why all the
2973interactions with the OpenGL plots are possible only when the mouse cursor is
2974in the plot's area (the plot's area is the part of a the pad occupied by
2975gl-produced picture). If the mouse cursor is not above gl-picture, the standard
2976pad interaction is performed.
2977
2978\anchor HP29g
2979#### Selectable parts
2980
2981Different parts of the plot can be selected:
2982
2983- xoz, yoz, xoy back planes: When such a plane selected, it's highlighted in green
2984 if the dynamic slicing by this plane is supported, and it's highlighted in red,
2985 if the dynamic slicing is not supported.
2986- The plot itself:
2987 On surfaces, the selected surface is outlined in red. (TF3 and
2988 ISO are not outlined). On lego plots, the selected bin is
2989 highlighted. The bin number and content are displayed in pad's
2990 status bar. In box plots, the box or sphere is highlighted and
2991 the bin info is displayed in pad's status bar.
2992
2993
2994\anchor HP29h
2995#### Rotation and zooming
2996
2997
2998- Rotation:
2999 When the plot is selected, it can be rotated by pressing and
3000 holding the left mouse button and move the cursor.
3001- Zoom/Unzoom:
3002 Mouse wheel or 'j', 'J', 'k', 'K' keys.
3003
3004
3005\anchor HP29i
3006#### Panning
3007
3008The selected plot can be moved in a pad's area by pressing and
3009holding the left mouse button and the shift key.
3010
3011\anchor HP29j
3012#### Box cut
3013
3014Surface, iso, box, TF3 and parametric painters support box cut by
3015pressing the 'c' or 'C' key when the mouse cursor is in a plot's
3016area. That will display a transparent box, cutting away part of the
3017surface (or boxes) in order to show internal part of plot. This box
3018can be moved inside the plot's area (the full size of the box is
3019equal to the plot's surrounding box) by selecting one of the box
3020cut axes and pressing the left mouse button to move it.
3021
3022\anchor HP29k
3023#### Plot specific interactions (dynamic slicing etc.)
3024
3025Currently, all gl-plots support some form of slicing. When back plane
3026is selected (and if it's highlighted in green) you can press and hold
3027left mouse button and shift key and move this back plane inside
3028plot's area, creating the slice. During this "slicing" plot becomes
3029semi-transparent. To remove all slices (and projected curves for
3030surfaces) double click with left mouse button in a plot's area.
3031
3032\anchor HP29l
3033#### Surface with option "GLSURF"
3034
3035The surface profile is displayed on the slicing plane.
3036The profile projection is drawn on the back plane
3037by pressing `'p'` or `'P'` key.
3038
3039\anchor HP29m
3040#### TF3
3041
3042The contour plot is drawn on the slicing plane. For TF3 the color
3043scheme can be changed by pressing 's' or 'S'.
3044
3045\anchor HP29n
3046#### Box
3047
3048The contour plot corresponding to slice plane position is drawn in real time.
3049
3050\anchor HP29o
3051#### Iso
3052
3053Slicing is similar to "GLBOX" option.
3054
3055\anchor HP29p
3056#### Parametric plot
3057
3058No slicing. Additional keys: 's' or 'S' to change color scheme -
3059about 20 color schemes supported ('s' for "scheme"); 'l' or 'L' to
3060increase number of polygons ('l' for "level" of details), 'w' or 'W'
3061to show outlines ('w' for "wireframe").
3062
3063\anchor HP30
3064#### Highlight mode for histogram
3065
3066\since **ROOT version 6.15/01**
3067
3068\image html hlHisto3_top.gif "Highlight mode"
3069
3070Highlight mode is implemented for `TH1` (and for `TGraph`) class. When
3071highlight mode is on, mouse movement over the bin will be represented
3072graphically. Bin will be highlighted as "bin box" (presented by box
3073object). Moreover, any highlight (change of bin) emits signal
3074`TCanvas::Highlighted()` which allows the user to react and call their own
3075function. For a better understanding see also the tutorial `hist043` to `hist046`
3076located in `$ROOTSYS/tutorials/hist/`.
3077
3078Highlight mode is switched on/off by `TH1::SetHighlight()` function
3079or interactively from `TH1` context menu. `TH1::IsHighlight()` to verify
3080whether the highlight mode enabled or disabled, default it is disabled.
3081
3082~~~ {.cpp}
3083 root [0] .x $ROOTSYS/tutorials/hsimple.C
3084 root [1] hpx->SetHighlight(kTRUE) // or interactively from TH1 context menu
3085 root [2] hpx->IsHighlight()
3086 (bool) true
3087~~~
3088
3089\image html hlsimple_nofun.gif "Highlight mode for histogram"
3090
3091\anchor HP30a
3092#### Highlight mode and user function
3093
3094The user can use (connect) `TCanvas::Highlighted()` signal, which is always
3095emitted if there is a highlight bin and call user function via signal
3096and slot communication mechanism. `TCanvas::Highlighted()` is similar
3097`TCanvas::Picked()`
3098
3099- when selected object (histogram as a whole) is different from previous
3100then emit `Picked()` signal
3101- when selected (highlighted) bin from histogram is different from previous
3102then emit `Highlighted()` signal
3103
3104Any user function (or functions) has to be defined
3105`UserFunction(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)`.
3106In example (see below) has name `PrintInfo()`. All parameters of user
3107function are taken from
3108
3109 void TCanvas::Highlighted(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)
3110
3111- `pad` is pointer to pad with highlighted histogram
3112- `obj` is pointer to highlighted histogram
3113- `x` is highlighted x bin for 1D histogram
3114- `y` is highlighted y bin for 2D histogram (for 1D histogram not in use)
3115
3116Example how to create a connection from any `TCanvas` object to a user
3117`UserFunction()` slot (see also `TQObject::Connect()` for additional info)
3118
3119 TQObject::Connect("TCanvas", "Highlighted(TVirtualPad*,TObject*,Int_t,Int_t)",
3120 0, 0, "UserFunction(TVirtualPad*,TObject*,Int_t,Int_t)");
3121
3122or use non-static "simplified" function
3123`TCanvas::HighlightConnect(const char *slot)`
3124
3125 c1->HighlightConnect("UserFunction(TVirtualPad*,TObject*,Int_t,Int_t)");
3126
3127NOTE the signal and slot string must have a form
3128"(TVirtualPad*,TObject*,Int_t,Int_t)"
3129
3130 root [0] .x $ROOTSYS/tutorials/hsimple.C
3131 root [1] hpx->SetHighlight(kTRUE)
3132 root [2] .x hlprint.C
3133
3134file `hlprint.C`
3135~~~ {.cpp}
3136void PrintInfo(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)
3137{
3138 auto h = (TH1F *)obj;
3139 if (!h->IsHighlight()) // after highlight disabled
3140 h->SetTitle("highlight disable");
3141 else
3142 h->SetTitle(TString::Format("bin[%03d] (%5.2f) content %g", x,
3143 h->GetBinCenter(x), h->GetBinContent(x)));
3144 pad->Update();
3145}
3146
3147void hlprint()
3148{
3149 if (!gPad) return;
3150 gPad->GetCanvas()->HighlightConnect("PrintInfo(TVirtualPad*,TObject*,Int_t,Int_t)");
3151}
3152~~~
3153
3154\image html hlsimple.gif "Highlight mode and simple user function"
3155
3156For more complex demo please see for example tree200_temperature.C file.
3157
3158*/
3159
3161
3164
3165const Int_t kNMAX = 2000;
3166
3167const Int_t kMAXCONTOUR = 104;
3169
3170static std::unique_ptr<TBox> gXHighlightBox, gYHighlightBox; // highlight X and Y box
3171
3193
3195
3196////////////////////////////////////////////////////////////////////////////////
3197/// Default constructor.
3198
3200{
3201 fH = nullptr;
3202 fXaxis = nullptr;
3203 fYaxis = nullptr;
3204 fZaxis = nullptr;
3205 fFunctions = nullptr;
3206 fNcuts = 0;
3207 fStack = nullptr;
3208 fShowProjection = 0;
3209 fShowProjection2 = 0;
3210 fShowOption = "";
3211 for (int i=0; i<kMaxCuts; i++) {
3212 fCuts[i] = nullptr;
3213 fCutsOpt[i] = 0;
3214 }
3215 fXHighlightBin = -1;
3216 fYHighlightBin = -1;
3217 fCurrentF3 = nullptr;
3218
3219 gStringEntries = gEnv->GetValue("Hist.Stats.Entries", "Entries");
3220 gStringMean = gEnv->GetValue("Hist.Stats.Mean", "Mean");
3221 gStringMeanX = gEnv->GetValue("Hist.Stats.MeanX", "Mean x");
3222 gStringMeanY = gEnv->GetValue("Hist.Stats.MeanY", "Mean y");
3223 gStringMeanZ = gEnv->GetValue("Hist.Stats.MeanZ", "Mean z");
3224 gStringStdDev = gEnv->GetValue("Hist.Stats.StdDev", "Std Dev");
3225 gStringStdDevX = gEnv->GetValue("Hist.Stats.StdDevX", "Std Dev x");
3226 gStringStdDevY = gEnv->GetValue("Hist.Stats.StdDevY", "Std Dev y");
3227 gStringStdDevZ = gEnv->GetValue("Hist.Stats.StdDevZ", "Std Dev z");
3228 gStringUnderflow = gEnv->GetValue("Hist.Stats.Underflow", "Underflow");
3229 gStringOverflow = gEnv->GetValue("Hist.Stats.Overflow", "Overflow");
3230 gStringIntegral = gEnv->GetValue("Hist.Stats.Integral", "Integral");
3231 gStringIntegralBinWidth = gEnv->GetValue("Hist.Stats.IntegralBinWidth", "Integral(w)");
3232 gStringSkewness = gEnv->GetValue("Hist.Stats.Skewness", "Skewness");
3233 gStringSkewnessX = gEnv->GetValue("Hist.Stats.SkewnessX", "Skewness x");
3234 gStringSkewnessY = gEnv->GetValue("Hist.Stats.SkewnessY", "Skewness y");
3235 gStringSkewnessZ = gEnv->GetValue("Hist.Stats.SkewnessZ", "Skewness z");
3236 gStringKurtosis = gEnv->GetValue("Hist.Stats.Kurtosis", "Kurtosis");
3237 gStringKurtosisX = gEnv->GetValue("Hist.Stats.KurtosisX", "Kurtosis x");
3238 gStringKurtosisY = gEnv->GetValue("Hist.Stats.KurtosisY", "Kurtosis y");
3239 gStringKurtosisZ = gEnv->GetValue("Hist.Stats.KurtosisZ", "Kurtosis z");
3240}
3241
3242////////////////////////////////////////////////////////////////////////////////
3243/// destructor.
3244
3248
3249////////////////////////////////////////////////////////////////////////////////
3250/// Compute the distance from the point px,py to a line.
3251///
3252/// Compute the closest distance of approach from point px,py to elements of
3253/// an histogram. The distance is computed in pixels units.
3254///
3255/// Algorithm: Currently, this simple model computes the distance from the mouse
3256/// to the histogram contour only.
3257
3259{
3260
3261 Double_t defaultLabelSize = 0.04; // See TAttAxis.h for source of this value
3262
3263 const Int_t big = 9999;
3264 const Int_t kMaxDiff = 7;
3265
3266 if (fPie)
3267 return fPie->DistancetoPrimitive(px, py);
3268
3269 Double_t x = gPad->AbsPixeltoX(px);
3270 Double_t x1 = gPad->AbsPixeltoX(px+1);
3271
3272 Int_t puxmin = gPad->XtoAbsPixel(gPad->GetUxmin());
3273 Int_t puymin = gPad->YtoAbsPixel(gPad->GetUymin());
3274 Int_t puxmax = gPad->XtoAbsPixel(gPad->GetUxmax());
3275 Int_t puymax = gPad->YtoAbsPixel(gPad->GetUymax());
3276 Int_t curdist = big;
3278 Bool_t dsame;
3279 TObject *PadPointer = gPad->GetPadPointer();
3280 if (!PadPointer) return 0;
3281 TString doption = PadPointer->GetDrawOption();
3282 Double_t factor = 1;
3283 if (fH->GetNormFactor() != 0) {
3284 factor = fH->GetNormFactor()/fH->GetSumOfWeights();
3285 }
3286 // return if point is not in the histogram area
3287
3288 // If a 3D view exists, check distance to axis
3289 TView *view = gPad->GetView();
3290 Int_t d1,d2,d3;
3291 if (view && Hoption.Contour != 14) {
3292 Double_t ratio;
3293 d3 = view->GetDistancetoAxis(3, px, py, ratio);
3294 if (d3 <= kMaxDiff) {gPad->SetSelected(fZaxis); return 0;}
3295 d1 = view->GetDistancetoAxis(1, px, py, ratio);
3296 if (d1 <= kMaxDiff) {gPad->SetSelected(fXaxis); return 0;}
3297 d2 = view->GetDistancetoAxis(2, px, py, ratio);
3298 if (d2 <= kMaxDiff) {gPad->SetSelected(fYaxis); return 0;}
3299 if ( px > puxmin && px < puxmax && py > puymax && py < puymin) curdist = 1;
3300 goto FUNCTIONS;
3301 }
3302 // check if point is close to an axis
3303 doption.ToLower();
3304 dsame = kFALSE;
3305 if (doption.Contains("same")) dsame = kTRUE;
3306
3308 if (doption.Contains("y+")) {
3310 if (px <= xyaxis+dyaxis && px >= xyaxis && py >puymax && py < puymin) {
3311 if (!dsame) {
3312 if (gPad->IsVertical()) gPad->SetSelected(fYaxis);
3313 else gPad->SetSelected(fXaxis);
3314 return 0;
3315 }
3316 }
3317 } else {
3319 if (px >= xyaxis-dyaxis && px <= xyaxis && py >puymax && py < puymin) {
3320 if (!dsame) {
3321 if (gPad->IsVertical()) gPad->SetSelected(fYaxis);
3322 else gPad->SetSelected(fXaxis);
3323 return 0;
3324 }
3325 }
3326 }
3327
3329 if (doption.Contains("x+")) {
3331 if (py >= yxaxis-dxaxis && py <= yxaxis && px <puxmax && px > puxmin) {
3332 if (!dsame) {
3333 if (gPad->IsVertical()) gPad->SetSelected(fXaxis);
3334 else gPad->SetSelected(fYaxis);
3335 return 0;
3336 }
3337 }
3338 } else {
3340 if (yxaxis < puymin) yxaxis = puymin;
3342 if (!dsame) {
3343 if (gPad->IsVertical()) gPad->SetSelected(fXaxis);
3344 else gPad->SetSelected(fYaxis);
3345 return 0;
3346 }
3347 }
3348 }
3349
3350 if (fH->IsHighlight()) { // only if highlight is enable
3351 if ((px > puxmin) && (py < puymin) && (px < puxmax) && (py > puymax))
3352 HighlightBin(px, py);
3353 }
3354
3355 // if object is 2D or 3D return this object
3356 if (fH->GetDimension() == 2) {
3357 if (fH->InheritsFrom(TH2Poly::Class())) {
3358 TH2Poly *th2 = (TH2Poly*)fH;
3360 gPad->GetRangeAxis(xmin, ymin, xmax, ymax);
3361 Double_t pxu = gPad->AbsPixeltoX(px);
3362 Double_t pyu = gPad->AbsPixeltoY(py);
3363 if ((pxu>xmax) || (pxu < xmin) || (pyu>ymax) || (pyu < ymin)) {
3364 curdist = big;
3365 goto FUNCTIONS;
3366 } else {
3367 Int_t bin = th2->FindBin(pxu, pyu);
3368 if (bin>0) curdist = 1;
3369 else curdist = big;
3370 goto FUNCTIONS;
3371 }
3372 }
3373 Int_t delta2 = 5; //Give a margin of delta2 pixels to be in the 2-d area
3374 if ( px > puxmin + delta2
3375 && px < puxmax - delta2
3376 && py > puymax + delta2
3377 && py < puymin - delta2) {curdist =1; goto FUNCTIONS;}
3378 }
3379
3380 // point is inside histogram area. Find channel number
3381 if (gPad->IsVertical()) {
3382 Int_t bin = fXaxis->FindFixBin(gPad->PadtoX(x));
3383 Int_t binsup = fXaxis->FindFixBin(gPad->PadtoX(x1));
3384 Double_t binval = factor*fH->GetBinContent(bin);
3385 Int_t pybin = gPad->YtoAbsPixel(gPad->YtoPad(binval));
3386 if (binval == 0 && pybin < puymin) pybin = 10000;
3387 // special case if more than one bin for the pixel
3388 if (binsup-bin>1) {
3392 for (Int_t ibin=bin+1; ibin<binsup; ibin++) {
3396 }
3397 Int_t pybinmin = gPad->YtoAbsPixel(gPad->YtoPad(binvalmax));
3398 Int_t pybinmax = gPad->YtoAbsPixel(gPad->YtoPad(binvalmin));
3400 }
3401 if (bin != binsup) { // Mouse on bin border
3403 Int_t pybinsub = gPad->YtoAbsPixel(gPad->YtoPad(binsupval));
3404 if (py <= TMath::Max(pybinsub,pybin) && py >= TMath::Min(pybinsub,pybin) && pybin != 10000) return 0;
3405 }
3406 if (TMath::Abs(py - pybin) <= kMaxDiff) return TMath::Abs(py - pybin);
3407 } else {
3408 Double_t y = gPad->AbsPixeltoY(py);
3409 Double_t y1 = gPad->AbsPixeltoY(py+1);
3410 Int_t bin = fXaxis->FindFixBin(gPad->PadtoY(y));
3411 Int_t binsup = fXaxis->FindFixBin(gPad->PadtoY(y1));
3412 Double_t binval = factor*fH->GetBinContent(bin);
3413 Int_t pxbin = gPad->XtoAbsPixel(gPad->XtoPad(binval));
3414 if (binval == 0 && pxbin > puxmin) pxbin = 10000;
3415 // special case if more than one bin for the pixel
3416 if (binsup-bin>1) {
3420 for (Int_t ibin=bin+1; ibin<binsup; ibin++) {
3424 }
3425 Int_t pxbinmin = gPad->XtoAbsPixel(gPad->XtoPad(binvalmax));
3426 Int_t pxbinmax = gPad->XtoAbsPixel(gPad->XtoPad(binvalmin));
3428 }
3429 if (TMath::Abs(px - pxbin) <= kMaxDiff) return TMath::Abs(px - pxbin);
3430 }
3431 // Loop on the list of associated functions and user objects
3432FUNCTIONS:
3433 TObject *f;
3434 TIter next(fFunctions);
3435 while ((f = (TObject*) next())) {
3436 Int_t dist;
3437 if (f->InheritsFrom(TF1::Class())) dist = f->DistancetoPrimitive(-px,py);
3438 else dist = f->DistancetoPrimitive(px,py);
3439 if (dist < kMaxDiff) {gPad->SetSelected(f); return dist;}
3440 }
3441 return curdist;
3442}
3443
3444////////////////////////////////////////////////////////////////////////////////
3445/// Display a panel with all histogram drawing options.
3446
3448{
3449
3450 gCurrentHist = fH;
3451 if (!gPad) {
3452 Error("DrawPanel", "need to draw histogram first");
3453 return;
3454 }
3456 editor->Show();
3457 gROOT->ProcessLine(TString::Format("((TCanvas*)0x%zx)->Selected((TVirtualPad*)0x%zx,(TObject*)0x%zx,1)",
3458 (size_t)gPad->GetCanvas(), (size_t)gPad, (size_t)fH).Data());
3459}
3460
3461////////////////////////////////////////////////////////////////////////////////
3462/// Execute the actions corresponding to `event`.
3463///
3464/// This function is called when a histogram is clicked with the locator at
3465/// the pixel position px,py.
3466
3468{
3469
3470 if (!gPad) return;
3471
3472 static Int_t bin, px1, py1, px2, py2, pyold;
3473 static std::unique_ptr<TBox> zoombox;
3475
3476 Int_t bin1, bin2;
3477 Double_t xlow, xup, ylow, binval, x, baroffset, barwidth, binwidth;
3478 Bool_t opaque = gPad->OpaqueMoving();
3479
3480 if (!gPad->IsEditable()) return;
3481
3482 if (fPie) {
3483 fPie->ExecuteEvent(event, px, py);
3484 return;
3485 }
3486 // come here if we have a lego/surface in the pad
3487 TView *view = gPad->GetView();
3488
3489 if (!fShowProjection && view && !view->TestBit(kCannotRotate)) {
3490 view->ExecuteRotateView(event, px, py);
3491 return;
3492 }
3493
3494 TAxis *xaxis = fH->GetXaxis();
3495 TAxis *yaxis = fH->GetYaxis();
3496 Int_t dimension = fH->GetDimension();
3497
3498 // In case of option SAME the axis must be the ones of the first drawn histogram
3499 TString IsSame = fH->GetDrawOption();
3500 IsSame.ToLower();
3501 if (IsSame.Index("same")>=0) {
3502 TH1 *h1;
3503 TIter next(gPad->GetListOfPrimitives());
3504 while ((h1 = (TH1 *)next())) {
3505 if (!h1->InheritsFrom(TH1::Class())) continue;
3506 xaxis = h1->GetXaxis();
3507 yaxis = h1->GetYaxis();
3508 break;
3509 }
3510 }
3511
3512 Double_t factor = 1;
3513 if (fH->GetNormFactor() != 0) {
3514 factor = fH->GetNormFactor()/fH->GetSumOfWeights();
3515 }
3516
3517 switch (event) {
3518
3519 case kButton1Down:
3520
3521 if (!opaque) gVirtualX->SetLineColor(-1);
3522 fH->TAttLine::Modify();
3523
3524 if (opaque && dimension ==2) {
3525 zbx1 = gPad->AbsPixeltoX(px);
3526 zbx2 = gPad->AbsPixeltoX(px);
3527 zby1 = gPad->AbsPixeltoY(py);
3528 zby2 = gPad->AbsPixeltoY(py);
3529 px1 = px;
3530 py1 = py;
3531 if (gPad->GetLogx()) {
3532 zbx1 = TMath::Power(10,zbx1);
3533 zbx2 = TMath::Power(10,zbx2);
3534 }
3535 if (gPad->GetLogy()) {
3536 zby1 = TMath::Power(10,zby1);
3537 zby2 = TMath::Power(10,zby2);
3538 }
3539 if (zoombox) Error("ExecuteEvent", "Last zoom box was not deleted");
3540 zoombox = std::make_unique<TBox>(zbx1, zby1, zbx2, zby2);
3541 Int_t ci = TColor::GetColor("#7d7dff");
3542 TColor *zoomcolor = gROOT->GetColor(ci);
3543 if (!TCanvas::SupportAlpha() || !zoomcolor) zoombox->SetFillStyle(3002);
3544 else zoomcolor->SetAlpha(0.5);
3545 zoombox->SetFillColor(ci);
3546 zoombox->Draw();
3547 gPad->Modified();
3548 gPad->Update();
3549 }
3550 // No break !!!
3551
3552 case kMouseMotion:
3553
3554 if (fShowProjection) {ShowProjection3(px,py); break;}
3555
3556 gPad->SetCursor(kPointer);
3557 if (dimension ==1) {
3558 if (Hoption.Bar) {
3559 baroffset = fH->GetBarOffset();
3560 barwidth = fH->GetBarWidth();
3561 } else {
3562 baroffset = 0;
3563 barwidth = 1;
3564 }
3565 x = gPad->AbsPixeltoX(px);
3566 bin = fXaxis->FindFixBin(gPad->PadtoX(x));
3567 binwidth = fXaxis->GetBinWidth(bin);
3568 xlow = gPad->XtoPad(fXaxis->GetBinLowEdge(bin) + baroffset*binwidth);
3569 xup = gPad->XtoPad(xlow + barwidth*binwidth);
3570 ylow = gPad->GetUymin();
3571 px1 = gPad->XtoAbsPixel(xlow);
3572 px2 = gPad->XtoAbsPixel(xup);
3573 py1 = gPad->YtoAbsPixel(ylow);
3574 py2 = py;
3575 pyold = py;
3576 if (gROOT->GetEditHistograms()) gPad->SetCursor(kArrowVer);
3577 }
3578
3579 break;
3580
3581 case kButton1Motion:
3582
3583 if (dimension ==1) {
3584 if (gROOT->GetEditHistograms()) {
3585 if (!opaque) {
3586 gVirtualX->DrawBox(px1, py1, px2, py2,TVirtualX::kHollow); // Draw the old box
3587 py2 += py - pyold;
3588 gVirtualX->DrawBox(px1, py1, px2, py2,TVirtualX::kHollow); // Draw the new box
3589 pyold = py;
3590 } else {
3591 py2 += py - pyold;
3592 pyold = py;
3593 binval = gPad->PadtoY(gPad->AbsPixeltoY(py2))/factor;
3594 fH->SetBinContent(bin,binval);
3595 gPad->Modified(kTRUE);
3596 }
3597 }
3598 }
3599
3600 if (opaque && dimension ==2) {
3601 if (TMath::Abs(px1-px)>5 && TMath::Abs(py1-py)>5) {
3602 zbx2 = gPad->AbsPixeltoX(px);
3603 zby2 = gPad->AbsPixeltoY(py);
3604 if (gPad->GetLogx()) zbx2 = TMath::Power(10,zbx2);
3605 if (gPad->GetLogy()) zby2 = TMath::Power(10,zby2);
3606 if (zoombox) {
3607 zoombox->SetX2(zbx2);
3608 zoombox->SetY2(zby2);
3609 }
3610 gPad->Modified();
3611 gPad->Update();
3612 }
3613 }
3614
3615 break;
3616
3617 case kWheelUp:
3618
3619 if (dimension ==2) {
3620 bin1 = xaxis->GetFirst()+1;
3621 bin2 = xaxis->GetLast()-1;
3622 bin1 = TMath::Max(bin1, 1);
3623 bin2 = TMath::Min(bin2, xaxis->GetNbins());
3624 if (bin2>bin1) xaxis->SetRange(bin1,bin2);
3625 bin1 = yaxis->GetFirst()+1;
3626 bin2 = yaxis->GetLast()-1;
3627 bin1 = TMath::Max(bin1, 1);
3628 bin2 = TMath::Min(bin2, yaxis->GetNbins());
3629 if (bin2>bin1) yaxis->SetRange(bin1,bin2);
3630 }
3631 gPad->Modified();
3632 gPad->Update();
3633
3634 break;
3635
3636 case kWheelDown:
3637
3638 if (dimension == 2) {
3639 bin1 = xaxis->GetFirst()-1;
3640 bin2 = xaxis->GetLast()+1;
3641 bin1 = TMath::Max(bin1, 1);
3642 bin2 = TMath::Min(bin2, xaxis->GetNbins());
3643 const bool resetXaxisRange = bin1 == 1 && xaxis->GetFirst() == 1 && bin2 == xaxis->GetNbins() && xaxis->GetLast() == xaxis->GetNbins();
3644 if (bin2>bin1) xaxis->SetRange(bin1,bin2);
3645 if (resetXaxisRange) xaxis->ResetBit(TAxis::kAxisRange);
3646 bin1 = yaxis->GetFirst()-1;
3647 bin2 = yaxis->GetLast()+1;
3648 bin1 = TMath::Max(bin1, 1);
3649 bin2 = TMath::Min(bin2, yaxis->GetNbins());
3650 const bool resetYaxisRange = bin1 == 1 && yaxis->GetFirst() == 1 && bin2 == yaxis->GetNbins() && yaxis->GetLast() == yaxis->GetNbins();
3651 if (bin2>bin1) yaxis->SetRange(bin1,bin2);
3652 if (resetYaxisRange) yaxis->ResetBit(TAxis::kAxisRange);
3653 }
3654 gPad->Modified();
3655 gPad->Update();
3656
3657 break;
3658
3659 case kButton1Up:
3660 if (dimension ==1) {
3661 if (gROOT->GetEditHistograms()) {
3662 binval = gPad->PadtoY(gPad->AbsPixeltoY(py2))/factor;
3663 fH->SetBinContent(bin,binval);
3664 PaintInit(); // recalculate Hparam structure and recalculate range
3665 }
3666
3667 // might resize pad pixmap so should be called before any paint routine
3669 }
3670 if (opaque && dimension ==2) {
3671 if (zoombox) {
3672 Double_t x1 = TMath::Min(zoombox->GetX1(), zoombox->GetX2());
3673 Double_t x2 = TMath::Max(zoombox->GetX1(), zoombox->GetX2());
3674 Double_t y1 = TMath::Min(zoombox->GetY1(), zoombox->GetY2());
3675 Double_t y2 = TMath::Max(zoombox->GetY1(), zoombox->GetY2());
3676 x1 = TMath::Max(x1,xaxis->GetXmin());
3677 x2 = TMath::Min(x2,xaxis->GetXmax());
3678 y1 = TMath::Max(y1,yaxis->GetXmin());
3679 y2 = TMath::Min(y2,yaxis->GetXmax());
3680 if (x1<x2 && y1<y2) {
3681 xaxis->SetRangeUser(x1, x2);
3682 yaxis->SetRangeUser(y1, y2);
3683 }
3684 zoombox.reset();
3685 }
3686 }
3687 gPad->Modified(kTRUE);
3688 if (opaque) gVirtualX->SetLineColor(-1);
3689
3690 break;
3691
3692 case kButton1Locate:
3693
3694 ExecuteEvent(kButton1Down, px, py);
3695
3696 while (true) {
3697 px = py = 0;
3698 event = gVirtualX->RequestLocator(1, 1, px, py);
3699
3701
3702 if (event != -1) { // button is released
3703 ExecuteEvent(kButton1Up, px, py);
3704 return;
3705 }
3706 }
3707 }
3708}
3709
3710////////////////////////////////////////////////////////////////////////////////
3711/// Get a contour (as a list of TGraphs) using the Delaunay triangulation.
3712
3714{
3715 // Check if fH contains a TGraphDelaunay2D
3717 TGraphDelaunay2D *dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
3718 // try with the old painter
3719 TGraphDelaunay *dtOld = nullptr;
3720 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
3721
3722 if (!dt && !dtOld) return nullptr;
3723
3724 gCurrentHist = fH;
3725
3726 if (!fGraph2DPainter)
3727 ((THistPainter*)this)->fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
3728
3729 return fGraph2DPainter->GetContourList(contour);
3730}
3731
3732////////////////////////////////////////////////////////////////////////////////
3733/// Display the histogram info (bin number, contents, integral up to bin
3734/// corresponding to cursor position px,py.
3735
3737{
3738
3739 if (!gPad) return (char*)"";
3740
3741 Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
3742 Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
3743 Double_t x1 = gPad->PadtoX(gPad->AbsPixeltoX(px+1));
3745 drawOption.ToLower();
3748 if (fH->GetDimension() == 2) {
3749 if (gPad->GetView() || drawOption.Index("cont") >= 0) {
3750 uxmin=gPad->GetUxmin();
3751 uxmax=gPad->GetUxmax();
3754 x = xmin +(xmax-xmin)*(x-uxmin)/(uxmax-uxmin);
3755 uymin=gPad->GetUymin();
3756 uymax=gPad->GetUymax();
3759 y = ymin +(ymax-ymin)*(y-uymin)/(uymax-uymin);
3760 }
3761 }
3763 if (gPad->IsVertical()) {
3764 binx = fXaxis->FindFixBin(x);
3765 if (drawOption.Index("same") >= 0) {
3766 TH1 *h1;
3767 TIter next(gPad->GetListOfPrimitives());
3768 while ((h1 = (TH1 *)next())) {
3769 if (!h1->InheritsFrom(TH1::Class())) continue;
3770 binmin = h1->GetXaxis()->GetFirst();
3771 break;
3772 }
3773 } else {
3774 binmin = fXaxis->GetFirst();
3775 }
3777 // special case if more than 1 bin in x per pixel
3778 if (binx1-binx>1 && fH->GetDimension() == 1) {
3781 for (Int_t ibin=binx+1; ibin<binx1; ibin++) {
3785 binnear=ibin;
3786 }
3787 }
3788 binx = binnear;
3789 }
3790 } else {
3791 x1 = gPad->PadtoY(gPad->AbsPixeltoY(py+1));
3792 binx = fXaxis->FindFixBin(y);
3793 if (drawOption.Index("same") >= 0) {
3794 TH1 *h1;
3795 TIter next(gPad->GetListOfPrimitives());
3796 while ((h1 = (TH1 *)next())) {
3797 if (!h1->InheritsFrom(TH1::Class())) continue;
3798 binmin = h1->GetXaxis()->GetFirst();
3799 break;
3800 }
3801 } else {
3802 binmin = fXaxis->GetFirst();
3803 }
3805 // special case if more than 1 bin in x per pixel
3806 if (binx1-binx>1 && fH->GetDimension() == 1) {
3809 for (Int_t ibin=binx+1; ibin<binx1; ibin++) {
3813 binnear=ibin;
3814 }
3815 }
3816 binx = binnear;
3817 }
3818 }
3819 if (fH->GetDimension() == 1) {
3821 TProfile *tp = (TProfile*)fH;
3822 fObjectInfo.Form("(x=%g, y=%g, binx=%d, binc=%g, bine=%g, binn=%d)",
3824 (Int_t) tp->GetBinEntries(binx));
3825 }
3826 else {
3827 Double_t integ = 0;
3828 for (Int_t bin=binmin;bin<=binx;bin++) {integ += fH->GetBinContent(bin);}
3829 fObjectInfo.Form("(x=%g, y=%g, binx=%d, binc=%g, Sum=%g)",
3831 }
3832 } else if (fH->GetDimension() == 2) {
3833 if (fH->InheritsFrom(TH2Poly::Class())) {
3834 TH2Poly *th2 = (TH2Poly*)fH;
3835 biny = th2->FindBin(x,y);
3836 fObjectInfo.Form("%s (x=%g, y=%g, bin=%d, binc=%g)",
3837 th2->GetBinTitle(biny),x,y,biny,th2->GetBinContent(biny));
3838 }
3839 else if (fH->InheritsFrom(TProfile2D::Class())) {
3841 biny = fYaxis->FindFixBin(y);
3842 Int_t bin = fH->GetBin(binx,biny);
3843 fObjectInfo.Form("(x=%g, y=%g, binx=%d, biny=%d, binc=%g, bine=%g, binn=%d)",
3844 x, y, binx, biny, fH->GetBinContent(bin),
3845 fH->GetBinError(bin), (Int_t) tp->GetBinEntries(bin));
3846 } else {
3847 biny = fYaxis->FindFixBin(y);
3848 fObjectInfo.Form("(x=%g, y=%g, binx=%d, biny=%d, binc=%g bine=%g)",
3851 }
3852 } else {
3853 // 3d case: retrieving the x,y,z bin is not yet implemented
3854 // print just the x,y info
3855 fObjectInfo.Form("(x=%g, y=%g)",x,y);
3856 }
3857
3858 return (char *)fObjectInfo.Data();
3859}
3860
3861////////////////////////////////////////////////////////////////////////////////
3862/// Set highlight (enable/disable) mode for fH
3863
3865{
3866 if (fH->IsHighlight()) return;
3867
3868 fXHighlightBin = -1;
3869 fYHighlightBin = -1;
3870 // delete previous highlight box
3871 if (gXHighlightBox) gXHighlightBox.reset();
3872 if (gYHighlightBox) gYHighlightBox.reset();
3873 // emit Highlighted() signal (user can check on disabled)
3874 if (gPad->GetCanvas()) gPad->GetCanvas()->Highlighted(gPad, fH, fXHighlightBin, fYHighlightBin);
3875}
3876
3877////////////////////////////////////////////////////////////////////////////////
3878/// Check on highlight bin
3879
3881{
3882 // call from DistancetoPrimitive (only if highlight is enable)
3883
3884 Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
3885 Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
3888 if (!gPad->IsVertical()) binx = fXaxis->FindFixBin(y);
3889
3891 if (binx != fXHighlightBin) {
3893 changedBin = kTRUE;
3894 } else if (fH->GetDimension() == 1) return;
3895 if (biny != fYHighlightBin) {
3897 changedBin = kTRUE;
3898 }
3899 if (!changedBin) return;
3900
3901 // Info("HighlightBin", "histo: %p '%s'\txbin: %d, ybin: %d",
3902 // (void *)fH, fH->GetName(), fXHighlightBin, fYHighlightBin);
3903
3904 // paint highlight bin as box (recursive calls PaintHighlightBin)
3905 gPad->Modified(kTRUE);
3906 gPad->Update();
3907
3908 // emit Highlighted() signal
3909 if (gPad->GetCanvas()) gPad->GetCanvas()->Highlighted(gPad, fH, fXHighlightBin, fYHighlightBin);
3910}
3911
3912////////////////////////////////////////////////////////////////////////////////
3913/// Paint highlight bin as TBox object
3914
3916{
3917 // call from PaintTitle
3918
3919 if (!fH->IsHighlight()) return;
3920
3921 Double_t uxmin = gPad->GetUxmin();
3922 Double_t uxmax = gPad->GetUxmax();
3923 Double_t uymin = gPad->GetUymin();
3924 Double_t uymax = gPad->GetUymax();
3925 if (gPad->GetLogx()) {
3926 uxmin = TMath::Power(10.0, uxmin);
3927 uxmax = TMath::Power(10.0, uxmax);
3928 }
3929 if (gPad->GetLogy()) {
3930 uymin = TMath::Power(10.0, uymin);
3931 uymax = TMath::Power(10.0, uymax);
3932 }
3933
3934 // testing specific possibility (after zoom, draw with "same", log, etc.)
3936 if (gPad->IsVertical()) {
3938 if ((hcenter < uxmin) || (hcenter > uxmax)) return;
3939 } else {
3941 if ((hcenter < uymin) || (hcenter > uymax)) return;
3942 }
3943 if (fH->GetDimension() == 2) {
3945 if ((hcenter < uymin) || (hcenter > uymax)) return;
3946 }
3947
3948 // paint X highlight bin (for 1D or 2D)
3950 if (gPad->IsVertical()) {
3953 hby1 = uymin;
3954 hby2 = uymax;
3955 } else {
3956 hbx1 = uxmin;
3957 hbx2 = uxmax;
3960 }
3961
3962 if (!gXHighlightBox) {
3963 gXHighlightBox = std::make_unique<TBox>(hbx1, hby1, hbx2, hby2);
3964 gXHighlightBox->SetBit(kCannotPick);
3965 gXHighlightBox->SetFillColor(TColor::GetColor("#9797ff"));
3966 if (!TCanvas::SupportAlpha()) gXHighlightBox->SetFillStyle(3001);
3967 else gROOT->GetColor(gXHighlightBox->GetFillColor())->SetAlpha(0.5);
3968 }
3969 gXHighlightBox->SetX1(hbx1);
3970 gXHighlightBox->SetX2(hbx2);
3971 gXHighlightBox->SetY1(hby1);
3972 gXHighlightBox->SetY2(hby2);
3973 gXHighlightBox->Paint();
3974
3975 // Info("PaintHighlightBin", "histo: %p '%s'\txbin: %d, ybin: %d",
3976 // (void *)fH, fH->GetName(), fXHighlightBin, fYHighlightBin);
3977
3978 // paint Y highlight bin (only for 2D)
3979 if (fH->GetDimension() != 2) return;
3980 hbx1 = uxmin;
3981 hbx2 = uxmax;
3984
3985 if (!gYHighlightBox) {
3986 gYHighlightBox = std::make_unique<TBox>(hbx1, hby1, hbx2, hby2);
3987 gYHighlightBox->SetBit(kCannotPick);
3988 gYHighlightBox->SetFillColor(gXHighlightBox->GetFillColor());
3989 gYHighlightBox->SetFillStyle(gXHighlightBox->GetFillStyle());
3990 }
3991 gYHighlightBox->SetX1(hbx1);
3992 gYHighlightBox->SetX2(hbx2);
3993 gYHighlightBox->SetY1(hby1);
3994 gYHighlightBox->SetY2(hby2);
3995 gYHighlightBox->Paint();
3996}
3997
3998////////////////////////////////////////////////////////////////////////////////
3999/// Return `kTRUE` if the cell `ix`, `iy` is inside one of the graphical cuts.
4000
4002{
4003
4004 for (Int_t i=0;i<fNcuts;i++) {
4007 if (fCutsOpt[i] > 0) {
4008 if (!fCuts[i]->IsInside(x,y)) return kFALSE;
4009 } else {
4010 if (fCuts[i]->IsInside(x,y)) return kFALSE;
4011 }
4012 }
4013 return kTRUE;
4014}
4015
4016////////////////////////////////////////////////////////////////////////////////
4017/// Return `kTRUE` if the point `x`, `y` is inside one of the graphical cuts.
4018
4020{
4021
4022 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/// Decode string `choptin` and fill Hoption structure.
4034
4036{
4037
4038 char *l;
4039 char chopt[128];
4041 strlcpy(chopt,choptin,128);
4044
4052 Hoption.Candle = 0;
4053
4054 // special 2D options
4055 Hoption.List = 0;
4056 Hoption.Zscale = 0;
4057 Hoption.FrontBox = 1;
4058 Hoption.BackBox = 1;
4060
4061 Hoption.Zero = 0;
4062
4064
4065 //check for graphical cuts
4066 MakeCuts(chopt);
4067
4068 for (Int_t i=0;i<nch;i++) chopt[i] = toupper(chopt[i]);
4069 if (hdim > 1) Hoption.Color = 1; // Default drawing option for 2D and 3D histograms
4070 if (!nch) Hoption.Hist = 1;
4071 if (fFunctions->First()) Hoption.Func = 1;
4072 if (fH->GetSumw2N() && hdim == 1) Hoption.Error = 2;
4073
4074 char *l1 = strstr(chopt,"PFC"); // Automatic Fill Color
4075 char *l2 = strstr(chopt,"PLC"); // Automatic Line Color
4076 char *l3 = strstr(chopt,"PMC"); // Automatic Marker Color
4077 if (l1 || l2 || l3) {
4078 Int_t i = gPad->NextPaletteColor();
4079 if (l1) {memcpy(l1," ",3); fH->SetFillColor(i);}
4080 if (l2) {memcpy(l2," ",3); fH->SetLineColor(i);}
4081 if (l3) {memcpy(l3," ",3); fH->SetMarkerColor(i);}
4082 Hoption.Hist = 1; // Make sure something is drawn in case there is no drawing option specified.
4083 }
4084
4085 l = strstr(chopt,"MIN0");
4086 if (l) {
4087 Hoption.MinimumZero = 1;
4088 memcpy(l," ",4);
4089 }
4090
4091 l = strstr(chopt,"SPEC");
4092 if (l) {
4093 Hoption.Color = 0;
4094 memcpy(l," ",4);
4095 Int_t bs=0;
4096 l = strstr(chopt,"BF(");
4097 if (l) {
4098 if (sscanf(&l[3],"%d",&bs) > 0) {
4099 Int_t i=0;
4100 while (l[i]!=')') {
4101 l[i] = ' ';
4102 i++;
4103 }
4104 l[i] = ' ';
4105 }
4106 }
4107 Hoption.Spec = TMath::Max(1600,bs);
4108 return 1;
4109 }
4110
4111 l = strstr(chopt,"GL");
4112 if (l) {
4113 memcpy(l," ",2);
4114 }
4115 l = strstr(chopt,"X+");
4116 if (l) {
4117 Hoption.AxisPos = 10;
4118 memcpy(l," ",2);
4119 }
4120 l = strstr(chopt,"Y+");
4121 if (l) {
4122 Hoption.AxisPos += 1;
4123 memcpy(l," ",2);
4124 }
4125 if ((Hoption.AxisPos == 10 || Hoption.AxisPos == 1) && (nch == 2)) Hoption.Hist = 1;
4126 if (Hoption.AxisPos == 11 && nch == 4) Hoption.Hist = 1;
4127
4128 l = strstr(chopt,"SAMES");
4129 if (l) {
4130 if (nch == 5) Hoption.Hist = 1;
4131 Hoption.Same = 2;
4132 memcpy(l," ",5);
4133 if (l[5] == '0') { Hoption.Same += 10; l[5] = ' '; }
4134 }
4135 l = strstr(chopt,"SAME");
4136 if (l) {
4137 if (nch == 4) Hoption.Hist = 1;
4138 Hoption.Same = 1;
4139 memcpy(l," ",4);
4140 if (l[4] == '0') { Hoption.Same += 10; l[4] = ' '; }
4141 }
4142
4143 l = strstr(chopt,"SCAT");
4144 if (l) {
4145 Warning("MakeChopt","option SCAT is deprecated.");
4146 Hoption.Scat = 1;
4147 memcpy(l," ",4);
4148 Hoption.Color = 0;
4149 }
4150
4151 l = strstr(chopt,"PIE");
4152 if (l) {
4153 Hoption.Pie = 1;
4154 memcpy(l," ",3);
4155 }
4156
4157
4158 l = strstr(chopt,"CANDLE");
4159 if (l) {
4161 Hoption.Candle = candle.ParseOption(l);
4162 Hoption.Color = 0;
4163 }
4164
4165 l = strstr(chopt,"VIOLIN");
4166 if (l) {
4168 Hoption.Candle = candle.ParseOption(l);
4169 Hoption.Color = 0;
4170 }
4171
4172 l = strstr(chopt,"LEGO");
4173 if (l) {
4174 Hoption.Color = 0;
4175 Hoption.Lego = 1; memcpy(l," ",4);
4176 if (l[4] == '1') { Hoption.Lego = 11; l[4] = ' '; }
4177 if (l[4] == '2') { Hoption.Lego = 12; l[4] = ' '; }
4178 if (l[4] == '3') { Hoption.Lego = 13; l[4] = ' '; }
4179 if (l[4] == '4') { Hoption.Lego = 14; l[4] = ' '; }
4180 if (l[4] == '9') { Hoption.Lego = 19; l[4] = ' '; }
4181 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4182 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4183 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4184 }
4185
4186 l = strstr(chopt,"SURF");
4187 if (l) {
4188 Hoption.Color = 0;
4189 Hoption.Surf = 1; memcpy(l," ",4);
4190 if (l[4] == '1') { Hoption.Surf = 11; l[4] = ' '; }
4191 if (l[4] == '2') { Hoption.Surf = 12; l[4] = ' '; }
4192 if (l[4] == '3') { Hoption.Surf = 13; l[4] = ' '; }
4193 if (l[4] == '4') { Hoption.Surf = 14; l[4] = ' '; }
4194 if (l[4] == '5') { Hoption.Surf = 15; l[4] = ' '; }
4195 if (l[4] == '6') { Hoption.Surf = 16; l[4] = ' '; }
4196 if (l[4] == '7') { Hoption.Surf = 17; l[4] = ' '; }
4197 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4198 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4199 }
4200
4201 l = strstr(chopt,"TF3");
4202 if (l) {
4203 memcpy(l," ",3);
4204 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4205 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4206 }
4207
4208 l = strstr(chopt,"ISO");
4209 if (l) {
4210 memcpy(l," ",3);
4211 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4212 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4213 Hoption.Color = 0;
4214 }
4215
4216 l = strstr(chopt,"LIST"); if (l) { Hoption.List = 1; memcpy(l," ",4);}
4217
4218 l = strstr(chopt,"CONT");
4219 if (l) {
4220 memcpy(l," ",4);
4221 if (hdim>1) {
4222 Hoption.Color = 0;
4223 Hoption.Contour = 1;
4224 if (l[4] == '1') { Hoption.Contour = 11; l[4] = ' '; }
4225 if (l[4] == '2') { Hoption.Contour = 12; l[4] = ' '; }
4226 if (l[4] == '3') { Hoption.Contour = 13; l[4] = ' '; }
4227 if (l[4] == '4') { Hoption.Contour = 14; l[4] = ' '; }
4228 if (l[4] == '5') { Hoption.Contour = 15; l[4] = ' '; }
4229 } else {
4230 Hoption.Hist = 1;
4231 }
4232 }
4233 l = strstr(chopt,"HBAR");
4234 if (l) {
4235 Hoption.Hist = 0;
4236 Hoption.Bar = 20; memcpy(l," ",4);
4237 if (l[4] == '1') { Hoption.Bar = 21; l[4] = ' '; }
4238 if (l[4] == '2') { Hoption.Bar = 22; l[4] = ' '; }
4239 if (l[4] == '3') { Hoption.Bar = 23; l[4] = ' '; }
4240 if (l[4] == '4') { Hoption.Bar = 24; l[4] = ' '; }
4241 }
4242 l = strstr(chopt,"BAR");
4243 if (l) {
4244 Hoption.Hist = 0;
4245 Hoption.Bar = 10; memcpy(l," ",3);
4246 if (l[3] == '1') { Hoption.Bar = 11; l[3] = ' '; }
4247 if (l[3] == '2') { Hoption.Bar = 12; l[3] = ' '; }
4248 if (l[3] == '3') { Hoption.Bar = 13; l[3] = ' '; }
4249 if (l[3] == '4') { Hoption.Bar = 14; l[3] = ' '; }
4250 }
4251
4252 l = strstr(chopt,"ARR" );
4253 if (l) {
4254 memcpy(l," ", 3);
4255 if (hdim>1) {
4256 Hoption.Arrow = 1;
4257 Hoption.Color = 0;
4258 l = strstr(chopt,"COL"); if (l) { Hoption.Arrow = 2; memcpy(l," ",3); }
4259 l = strstr(chopt,"Z"); if (l) { Hoption.Zscale = 1; memcpy(l," ",1); }
4260 } else {
4261 Hoption.Hist = 1;
4262 }
4263 }
4264 l = strstr(chopt,"BOX" );
4265 if (l) {
4266 memcpy(l," ", 3);
4267 if (hdim>1) {
4268 Hoption.Color = 0;
4269 Hoption.Box = 1;
4270 if (l[3] == '1') { Hoption.Box = 11; l[3] = ' '; }
4271 if (l[3] == '2') { Hoption.Box = 12; l[3] = ' '; }
4272 if (l[3] == '3') { Hoption.Box = 13; l[3] = ' '; }
4273 } else {
4274 Hoption.Hist = 1;
4275 }
4276 }
4277 l = strstr(chopt,"TEXT");
4278 if (l) {
4279 Int_t angle;
4280 if (sscanf(&l[4],"%d",&angle) > 0) {
4281 if (angle < 0) angle=0;
4282 if (angle > 90) angle=90;
4283 Hoption.Text = 1000+angle;
4284 } else {
4285 Hoption.Text = 1;
4286 }
4287 memcpy(l," ", 4);
4288 l = strstr(chopt,"N");
4289 if (l && fH->InheritsFrom(TH2Poly::Class())) Hoption.Text = 3000 + (Hoption.Text != 1 ? Hoption.Text : 0);
4290 Hoption.Color = 0;
4291 }
4292 l = strstr(chopt,"COLZ");
4293 if (l) {
4294 memcpy(l," ",4);
4295 if (hdim > 1) {
4297 Hoption.Color = 1;
4298 Hoption.Zscale = 1;
4299 if (l[4] == '2') { Hoption.Color = 3; l[4] = ' '; }
4300 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4301 l = strstr(chopt,"1"); if (l) { Hoption.Color = 2; memcpy(l," ",1); }
4302 } else {
4303 Hoption.Hist = 1;
4304 }
4305 }
4306 l = strstr(chopt,"COL" );
4307 if (l) {
4308 memcpy(l," ", 3);
4309 if (hdim > 1) {
4311 Hoption.Color = 1;
4312 if (l[3] == '2') { Hoption.Color = 3; l[3] = ' '; }
4313 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4314 l = strstr(chopt,"1"); if (l) { Hoption.Color = 2; memcpy(l," ",1); }
4315 } else {
4316 Hoption.Hist = 1;
4317 }
4318 }
4319 l = strstr(chopt,"FUNC"); if (l) { Hoption.Func = 2; memcpy(l," ",4); Hoption.Hist = 0; }
4320 l = strstr(chopt,"HIST"); if (l) { Hoption.Hist = 2; memcpy(l," ",4); Hoption.Func = 0; Hoption.Error = 0;}
4321 l = strstr(chopt,"AXIS"); if (l) { Hoption.Axis = 1; memcpy(l," ",4); }
4322 l = strstr(chopt,"AXIG"); if (l) { Hoption.Axis = 2; memcpy(l," ",4); }
4323 l = strstr(chopt,"SCAT"); if (l) { Hoption.Scat = 1; memcpy(l," ",4); }
4324 l = strstr(chopt,"POL"); if (l) { Hoption.System = kPOLAR; memcpy(l," ",3); }
4325 l = strstr(chopt,"CYL"); if (l) { Hoption.System = kCYLINDRICAL; memcpy(l," ",3); }
4326 l = strstr(chopt,"SPH"); if (l) { Hoption.System = kSPHERICAL; memcpy(l," ",3); }
4327 l = strstr(chopt,"PSR"); if (l) { Hoption.System = kRAPIDITY; memcpy(l," ",3); }
4328
4329 l = strstr(chopt,"TRI");
4330 if (l) {
4331 if (!explicitColor) Hoption.Color = 0;
4332 Hoption.Tri = 1; memcpy(l," ",3);
4333 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4334 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4335 l = strstr(chopt,"ERR"); if (l) memcpy(l," ",3);
4336 }
4337
4338 l = strstr(chopt,"AITOFF");
4339 if (l) {
4340 Hoption.Proj = 1; memcpy(l," ",6); //Aitoff projection
4341 }
4342 l = strstr(chopt,"MERCATOR");
4343 if (l) {
4344 Hoption.Proj = 2; memcpy(l," ",8); //Mercator projection
4345 }
4346 l = strstr(chopt,"SINUSOIDAL");
4347 if (l) {
4348 Hoption.Proj = 3; memcpy(l," ",10); //Sinusoidal projection
4349 }
4350 l = strstr(chopt,"PARABOLIC");
4351 if (l) {
4352 Hoption.Proj = 4; memcpy(l," ",9); //Parabolic projection
4353 }
4354 l = strstr(chopt,"MOLLWEIDE");
4355 if (l) {
4356 Hoption.Proj = 5; memcpy(l," ",9); //Mollweide projection
4357 }
4358 if (Hoption.Proj > 0) {
4359 if (!explicitColor) Hoption.Color = 0;
4360 Hoption.Contour = 14;
4361 }
4362
4363 if (strstr(chopt,"A")) Hoption.Axis = -1;
4364 if (strstr(chopt,"B")) Hoption.Bar = 1;
4365 if (strstr(chopt,"C") && !strstr(chopt,"CJUST")) { Hoption.Curve =1; Hoption.Hist = -1;}
4366 if (strstr(chopt,"F")) Hoption.Fill =1;
4367 if (strstr(chopt,"][")) {Hoption.Off =1; Hoption.Hist =1;}
4368 if (strstr(chopt,"F2")) Hoption.Fill =2;
4369 if (strstr(chopt,"L")) { Hoption.Line =1; Hoption.Hist = -1;}
4370 if (strstr(chopt,"P")) { Hoption.Mark =1; Hoption.Hist = -1;}
4371 if (strstr(chopt,"Z")) Hoption.Zscale =1;
4372 if (strstr(chopt,"*")) Hoption.Star =1;
4373 if (strstr(chopt,"H")) Hoption.Hist =2;
4374 if (strstr(chopt,"P0")) Hoption.Mark =10;
4375
4376 if (fH->InheritsFrom(TH2Poly::Class())) {
4378 }
4379
4380 if (strstr(chopt,"E")) {
4381 if (hdim == 1) {
4382 Hoption.Error = 1;
4383 if (strstr(chopt,"E1")) Hoption.Error = 11;
4384 if (strstr(chopt,"E2")) Hoption.Error = 12;
4385 if (strstr(chopt,"E3")) Hoption.Error = 13;
4386 if (strstr(chopt,"E4")) Hoption.Error = 14;
4387 if (strstr(chopt,"E5")) Hoption.Error = 15;
4388 if (strstr(chopt,"E6")) Hoption.Error = 16;
4389 if (strstr(chopt,"E0")) Hoption.Error += 40;
4390 if (strstr(chopt,"X0")) {
4391 if (Hoption.Error == 1) Hoption.Error += 20;
4392 Hoption.Error += 10;
4393 }
4395 Hoption.Text += 2000;
4396 Hoption.Error = 0;
4397 }
4398 } else {
4399 if (Hoption.Error == 0) {
4400 Hoption.Error = 100;
4401 if (!explicitColor) Hoption.Color = 0;
4402 }
4403 if (Hoption.Text) {
4404 Hoption.Text += 2000;
4405 Hoption.Error = 0;
4406 }
4407 }
4408 }
4409
4410 if (Hoption.Surf == 15) {
4412 Hoption.Surf = 13;
4413 Warning("MakeChopt","option SURF5 is not supported in Cartesian and Polar modes");
4414 }
4415 }
4416
4417 // Copy options from current style
4418 Hoption.Logx = gPad->GetLogx();
4419 Hoption.Logy = gPad->GetLogy();
4420 Hoption.Logz = gPad->GetLogz();
4421
4422 // Check options incompatibilities
4423 if (Hoption.Bar == 1) Hoption.Hist = -1;
4424 return 1;
4425}
4426
4427////////////////////////////////////////////////////////////////////////////////
4428/// Decode string `choptin` and fill Graphical cuts structure.
4429
4431{
4432
4433 fNcuts = 0;
4434 char *left = (char*)strchr(choptin,'[');
4435 if (!left) return 0;
4436 char *right = (char*)strchr(choptin,']');
4437 if (!right) return 0;
4438 Int_t nch = right-left;
4439 if (nch < 2) return 0;
4440 char *cuts = left+1;
4441 *right = 0;
4442 char *comma, *minus;
4443 Int_t i;
4444 while (true) {
4445 comma = strchr(cuts,',');
4446 if (comma) *comma = 0;
4447 minus = strchr(cuts,'-');
4448 if (minus) cuts = minus+1;
4449 while (*cuts == ' ') cuts++;
4450 Int_t nc = strlen(cuts);
4451 while (cuts[nc-1] == ' ') {cuts[nc-1] = 0; nc--;}
4452 TIter next(gROOT->GetListOfSpecials());
4453 TCutG *cut=nullptr;
4454 TObject *obj;
4455 while ((obj = next())) {
4456 if (!obj->InheritsFrom(TCutG::Class())) continue;
4457 if (strcmp(obj->GetName(),cuts)) continue;
4458 cut = (TCutG*)obj;
4459 break;
4460 }
4461 if (cut) {
4462 fCuts[fNcuts] = cut;
4463 fCutsOpt[fNcuts] = 1;
4464 if (minus) fCutsOpt[fNcuts] = -1;
4465 fNcuts++;
4466 }
4467 if (!comma) break;
4468 cuts = comma+1;
4469 }
4470 for (i=0;i<=nch;i++) left[i] = ' ';
4471 return fNcuts;
4472}
4473
4474////////////////////////////////////////////////////////////////////////////////
4475/// [Control routine to paint any kind of histograms](\ref HP00)
4476
4478{
4479
4480 if (fH->GetBuffer()) fH->BufferEmpty(-1);
4481
4482 //For iOS: put the histogram on the top of stack of pickable objects.
4484
4485 gPad->SetVertical(kTRUE);
4486
4488 gCurrentHist = fH;
4489 TH1 *hsave = fH;
4491
4492 if (!MakeChopt(option)) return; //check options and fill Hoption structure
4493
4494 // Paint using TSpectrum2Painter
4495 if (Hoption.Spec) {
4496 if (!TableInit()) return;
4497 if (!TClass::GetClass("TSpectrum2Painter")) gSystem->Load("libSpectrumPainter");
4498 gROOT->ProcessLineFast(TString::Format("TSpectrum2Painter::PaintSpectrum((TH2F*)0x%zx,\"%s\",%d)",
4499 (size_t)fH, option, Hoption.Spec).Data());
4500 return;
4501 }
4502
4503 // Deflate the labels in case of alphanumeric labels
4507
4508 if (Hoption.Pie) {
4509 if (fH->GetDimension() == 1) {
4510 if (!fPie)
4511 fPie = std::make_unique<TPie>(fH);
4512 fPie->Paint(option);
4513 } else {
4514 Error("Paint", "Option PIE is for 1D histograms only");
4515 }
4516 return;
4517 } else {
4518 fPie.reset();
4519 }
4520
4521 fXbuf.resize(kNMAX);
4522 fYbuf.resize(kNMAX);
4523 if (fH->GetDimension() > 2) {
4524 PaintH3(option);
4526 if (Hoption.Func) {
4531 Hoption = hoptsave;
4532 Hparam = hparsave;
4533 }
4535 fXbuf.clear();
4536 fYbuf.clear();
4537 return;
4538 }
4539 TView *view = gPad->GetView();
4540 if (view) {
4541 if (!Hoption.Lego && !Hoption.Surf && !Hoption.Tri) {
4542 delete view;
4543 gPad->SetView(nullptr);
4544 }
4545 }
4546 if (fH->GetDimension() > 1 || Hoption.Lego || Hoption.Surf) {
4547 // In case of 1D histogram, Z axis becomes Y axis.
4548 Int_t logysav=0, logzsav=0;
4549 if (fH->GetDimension() == 1) {
4552 Hoption.Logz = 0;
4553 if (Hoption.Logy) {
4554 Hoption.Logz = 1;
4555 Hoption.Logy = 0;
4556 }
4557 }
4559 if (Hoption.Func) {
4564 Hoption = hoptsave;
4565 Hparam = hparsave;
4566 }
4569 fXbuf.clear();
4570 fYbuf.clear();
4571 if (fH->GetDimension() == 1) {
4574 }
4575 return;
4576 }
4577
4578 if (Hoption.Bar >= 20) {
4580 fXbuf.clear();
4581 fYbuf.clear();
4582 return;
4583 }
4584
4585 gPad->RangeAxisChanged(); //emit RangeAxisChanged() signal to sync axes
4586 // fill Hparam structure with histo parameters
4587 if (!PaintInit()) {
4588 fXbuf.clear();
4589 fYbuf.clear();
4590 return;
4591 }
4592
4593 // Picture surround (if new page) and page number (if requested).
4594 // Histogram surround (if not option "Same").
4595 PaintFrame();
4596
4597 // Paint histogram axis only
4598 Bool_t gridx = gPad->GetGridx();
4599 Bool_t gridy = gPad->GetGridy();
4600 if (Hoption.Axis > 0) {
4601 if (Hoption.Axis > 1) PaintAxis(kTRUE); //axis with grid
4602 else {
4603 if (gridx) gPad->SetGridx(0);
4604 if (gridy) gPad->SetGridy(0);
4606 if (gridx) gPad->SetGridx(1);
4607 if (gridy) gPad->SetGridy(1);
4608 }
4609 if ((Hoption.Same%10) ==1) Hoption.Same += 1;
4610 goto paintstat;
4611 }
4612 if (gridx || gridy) PaintAxis(kTRUE); // Draw the grid only
4613
4614 // test for options BAR or HBAR
4615 if (Hoption.Bar >= 10) {
4617 }
4618
4619 // do not draw histogram if error bars required
4620 if (!Hoption.Error) {
4621 if (Hoption.Hist && Hoption.Bar<10) PaintHist(option);
4622 }
4623
4624 // test for error bars or option E
4625 if (Hoption.Error) {
4627 if (Hoption.Hist == 2) PaintHist(option);
4628 }
4629
4631
4632 // test for associated function
4633 if (Hoption.Func) {
4638 Hoption = hoptsave;
4639 Hparam = hparsave;
4640 }
4641
4642 if (gridx) gPad->SetGridx(0);
4643 if (gridy) gPad->SetGridy(0);
4645 if (gridx) gPad->SetGridx(1);
4646 if (gridy) gPad->SetGridy(1);
4647
4648 PaintTitle(); // Draw histogram title
4649
4650 // Draw box with histogram statistics and/or fit parameters
4651paintstat:
4652 if ((Hoption.Same%10) != 1 && !fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
4653 TIter next(fFunctions);
4654 TObject *obj = nullptr;
4655 while ((obj = next())) {
4656 if (obj->InheritsFrom(TF1::Class())) break;
4657 obj = nullptr;
4658 }
4659
4660 //Stat is painted twice (first, it will be in canvas' list of primitives),
4661 //second, it will be here, this is not required on iOS.
4662 //Condition is ALWAYS true on a platform different from iOS.
4663 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode())
4664 PaintStat(gStyle->GetOptStat(),(TF1*)obj);
4665 }
4668 fXbuf.clear();
4669 fYbuf.clear();
4670}
4671
4672////////////////////////////////////////////////////////////////////////////////
4673/// [Control function to draw a table as an arrow plot](\ref HP12)
4674
4676{
4678 Double_t dx, dy, x1, x2, y1, y2, xc, yc, dxn, dyn;
4681 Double_t xrg = gPad->GetUxmin();
4682 Double_t yrg = gPad->GetUymin();
4683 Double_t xln = gPad->GetUxmax() - xrg;
4684 Double_t yln = gPad->GetUymax() - yrg;
4685 Double_t cx = (xln/Double_t(ncx))/2.;
4686 Double_t cy = (yln/Double_t(ncy))/2.;
4687 Double_t dn = 1.E-30;
4688
4689 auto arrow = new TArrow();
4690 arrow->SetAngle(30);
4691 arrow->SetFillStyle(1001);
4692 arrow->SetFillColor(fH->GetLineColor());
4693 arrow->SetLineColor(fH->GetLineColor());
4694 arrow->SetLineWidth(fH->GetLineWidth());
4695
4696 // Initialize the levels on the Z axis
4697 Int_t ncolors=0, ndivz=0;
4698 Double_t scale=0.;
4699 if (Hoption.Arrow>1) {
4700 ncolors = gStyle->GetNumberOfColors();
4701 Int_t ndiv = fH->GetContour();
4702 if (ndiv == 0 ) {
4703 ndiv = gStyle->GetNumberContours();
4704 fH->SetContour(ndiv);
4705 }
4706 ndivz = TMath::Abs(ndiv);
4707 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
4709 }
4710
4711 for (Int_t id=1;id<=2;id++) {
4712 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
4715 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
4716 xk = fXaxis->GetBinLowEdge(i);
4717 xstep = fXaxis->GetBinWidth(i);
4718 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
4719 if (i == Hparam.xfirst) {
4720 dx = fH->GetBinContent(i+1, j) - fH->GetBinContent(i, j);
4721 } else if (i == Hparam.xlast) {
4722 dx = fH->GetBinContent(i, j) - fH->GetBinContent(i-1, j);
4723 } else {
4724 dx = 0.5*(fH->GetBinContent(i+1, j) - fH->GetBinContent(i-1, j));
4725 }
4726 if (j == Hparam.yfirst) {
4727 dy = fH->GetBinContent(i, j+1) - fH->GetBinContent(i, j);
4728 } else if (j == Hparam.ylast) {
4729 dy = fH->GetBinContent(i, j) - fH->GetBinContent(i, j-1);
4730 } else {
4731 dy = 0.5*(fH->GetBinContent(i, j+1) - fH->GetBinContent(i, j-1));
4732 }
4733 if (id == 1) {
4736 } else if (id == 2) {
4737 xc = xrg + xln*(Double_t(i - Hparam.xfirst+1)-0.5)/Double_t(ncx);
4738 dxn = cx*dx/dn;
4739 x1 = xc - dxn;
4740 x2 = xc + dxn;
4741 yc = yrg + yln*(Double_t(j - Hparam.yfirst+1)-0.5)/Double_t(ncy);
4742 dyn = cy*dy/dn;
4743 y1 = yc - dyn;
4744 y2 = yc + dyn;
4745 if (Hoption.Arrow>1) {
4746 int color = Int_t(0.01+(fH->GetBinContent(i, j)-fH->GetMinimum())*scale);
4747 Int_t theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
4748 if (theColor > ncolors-1) theColor = ncolors-1;
4749 arrow->SetFillColor(gStyle->GetColorPalette(theColor));
4750 arrow->SetLineColor(gStyle->GetColorPalette(theColor));
4751 }
4752 if (TMath::Abs(x2-x1) > 0. || TMath::Abs(y2-y1) > 0.) {
4753 arrow->PaintArrow(x1, y1, x2, y2, 0.015, "|>");
4754 } else {
4755 arrow->PaintArrow(x1, y1, x2, y2, 0.005, "|>");
4756 }
4757 }
4758 }
4759 }
4760 }
4761
4763}
4764
4765////////////////////////////////////////////////////////////////////////////////
4766/// Draw axis (2D case) of an histogram.
4767///
4768/// If `drawGridOnly` is `TRUE`, only the grid is painted (if needed). This allows
4769/// to draw the grid and the axis separately. In `THistPainter::Paint` this
4770/// feature is used to make sure that the grid is drawn in the background and
4771/// the axis tick marks in the foreground of the pad.
4772
4774{
4775
4776 //On iOS, grid should not be pickable and can not be highlighted.
4777 //Condition is never true on a platform different from iOS.
4778 if (drawGridOnly && (gPad->PadInHighlightMode() || gPad->PadInSelectionMode()))
4779 return;
4780
4781 if (Hoption.Axis == -1) return;
4782 if (Hoption.Same && Hoption.Axis <= 0) return;
4783
4784 // Repainting alphanumeric labels axis on a plot done with
4785 // the option HBAR (horizontal) needs some adjustments.
4786 TAxis *xaxis = nullptr;
4787 TAxis *yaxis = nullptr;
4788 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4789 if (fXaxis->GetLabels() || fYaxis->GetLabels()) { // One axis has alphanumeric labels
4790 TIter next(gPad->GetListOfPrimitives());
4791 TObject *obj;
4792 // Check if the first TH1 of THStack in the pad is drawn with the option HBAR
4793 while ((obj = next())) {
4794 if (!obj->InheritsFrom(TH1::Class()) &&
4795 !obj->InheritsFrom(THStack::Class())) continue;
4796 TString opt = obj->GetDrawOption();
4797 opt.ToLower();
4798 // if drawn with HBAR, the axis should be inverted and the pad set to horizontal
4799 if (strstr(opt,"hbar")) {
4800 gPad->SetVertical(kFALSE);
4801 xaxis = fXaxis;
4802 yaxis = fYaxis;
4803 if (!strcmp(xaxis->GetName(),"xaxis")) {
4804 fXaxis = yaxis;
4805 fYaxis = xaxis;
4806 }
4807 }
4808 break;
4809 }
4810 }
4811 }
4812
4813 static char chopt[10] = "";
4814 Double_t gridl = 0;
4815 Int_t ndiv, ndivx, ndivy, nx1, nx2, ndivsave;
4816 Int_t useHparam = 0;
4820
4821 Double_t axmin = gPad->GetUxmin();
4822 Double_t axmax = gPad->GetUxmax();
4823 Double_t aymin = gPad->GetUymin();
4824 Double_t aymax = gPad->GetUymax();
4825 char *cw = nullptr;
4826 TGaxis axis;
4827
4828 // In case of option 'cont4' or in case of option 'same' over a 'cont4 plot'
4829 // Hparam must be use for the axis limits.
4830 if (Hoption.Contour == 14) useHparam = 1;
4831 if (Hoption.Same) {
4832 TObject *obj;
4833 TIter next(gPad->GetListOfPrimitives());
4834 while ((obj=next())) {
4835 if (strstr(obj->GetDrawOption(),"cont4")) {
4836 useHparam = 1;
4837 break;
4838 }
4839 }
4840 }
4841
4842 // Paint X axis
4843
4844 //To make X-axis selectable on iOS device.
4845 if (gPad->PadInSelectionMode())
4846 gPad->PushSelectableObject(fXaxis);
4847
4848 //This condition is ALWAYS true, unless it works on iOS (can be false on iOS).
4849 if (gPad->PadInSelectionMode() || !gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && gPad->GetSelected() == fXaxis)) {
4851 if (ndivx > 1000) {
4852 nx2 = ndivx/100;
4853 nx1 = TMath::Max(1, ndivx%100);
4854 ndivx = 100*nx2 + Int_t(Float_t(nx1)*gPad->GetAbsWNDC());
4855 }
4856 axis.SetTextAngle(0);
4858
4859 chopt[0] = 0;
4860 strlcat(chopt, "SDH",10);
4861 if (ndivx < 0) strlcat(chopt, "N",10);
4862 if (gPad->GetGridx()) {
4863 gridl = (aymax-aymin)/(gPad->GetY2() - gPad->GetY1());
4864 strlcat(chopt, "W",10);
4865 }
4866
4867 // Define X-Axis limits
4868 if (Hoption.Logx) {
4869 strlcat(chopt, "G",10);
4870 ndiv = TMath::Abs(ndivx);
4871 if (useHparam) {
4874 } else {
4875 umin = TMath::Power(10,axmin);
4876 umax = TMath::Power(10,axmax);
4877 }
4878 } else {
4879 ndiv = TMath::Abs(ndivx);
4880 if (useHparam) {
4881 umin = Hparam.xmin;
4882 umax = Hparam.xmax;
4883 } else {
4884 umin = axmin;
4885 umax = axmax;
4886 }
4887 }
4888
4889 // Display axis as time
4890 if (fXaxis->GetTimeDisplay()) {
4891 strlcat(chopt,"t",10);
4892 if (strlen(fXaxis->GetTimeFormatOnly()) == 0) {
4894 }
4895 }
4896
4897 // The main X axis can be on the bottom or on the top of the pad
4899 if (xAxisPos == 1) {
4900 // Main X axis top
4901 xAxisYPos1 = aymax;
4902 xAxisYPos2 = aymin;
4903 } else {
4904 // Main X axis bottom
4905 xAxisYPos1 = aymin;
4906 xAxisYPos2 = aymax;
4907 }
4908
4909 // Paint the main X axis (always)
4910 uminsave = umin;
4911 umaxsave = umax;
4912 ndivsave = ndiv;
4913 axis.SetOption(chopt);
4914 if (xAxisPos) {
4915 strlcat(chopt, "-",10);
4916 gridl = -gridl;
4917 }
4918 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4919 axis.SetLabelSize(0.);
4920 axis.SetTitle("");
4921 }
4924 umin, umax, ndiv, chopt, gridl, drawGridOnly);
4925
4926 // Paint additional X axis (if needed)
4927 // On iOS, this additional X axis is neither pickable, nor highlighted.
4928 // Additional checks PadInSelectionMode etc. does not effect non-iOS platform.
4929 if (gPad->GetTickx() && !gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
4930 if (xAxisPos) {
4931 cw=strstr(chopt,"-");
4932 *cw='z';
4933 } else {
4934 strlcat(chopt, "-",10);
4935 }
4936 if (gPad->GetTickx() < 2) strlcat(chopt, "U",10);
4937 if ((cw=strstr(chopt,"W"))) *cw='z';
4938 axis.SetTitle("");
4942 }
4943 }//End of "if pad in selection mode etc".
4944
4945 // Paint Y axis
4946 //On iOS, Y axis must pushed into the stack of selectable objects.
4947 if (gPad->PadInSelectionMode())
4948 gPad->PushSelectableObject(fYaxis);
4949
4950 //This conditions is ALWAYS true on a platform, different from iOS (on iOS can be true, can be false).
4951 if (gPad->PadInSelectionMode() || !gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && gPad->GetSelected() == fYaxis)) {
4954
4955 chopt[0] = 0;
4956 strlcat(chopt, "SDH",10);
4957 if (ndivy < 0) strlcat(chopt, "N",10);
4958 if (gPad->GetGridy()) {
4959 gridl = (axmax-axmin)/(gPad->GetX2() - gPad->GetX1());
4960 strlcat(chopt, "W",10);
4961 }
4962
4963 // Define Y-Axis limits
4964 if (Hoption.Logy) {
4965 strlcat(chopt, "G",10);
4966 ndiv = TMath::Abs(ndivy);
4967 if (useHparam) {
4970 } else {
4971 umin = TMath::Power(10,aymin);
4972 umax = TMath::Power(10,aymax);
4973 }
4974 } else {
4975 ndiv = TMath::Abs(ndivy);
4976 if (useHparam) {
4977 umin = Hparam.ymin;
4978 umax = Hparam.ymax;
4979 } else {
4980 umin = aymin;
4981 umax = aymax;
4982 }
4983 }
4984
4985 // Display axis as time
4986 if (fYaxis->GetTimeDisplay()) {
4987 strlcat(chopt,"t",10);
4988 if (strlen(fYaxis->GetTimeFormatOnly()) == 0) {
4990 }
4991 }
4992
4993 // The main Y axis can be on the left or on the right of the pad
4995 if (yAxisPos == 1) {
4996 // Main Y axis left
4997 yAxisXPos1 = axmax;
4998 yAxisXPos2 = axmin;
4999 } else {
5000 // Main Y axis right
5001 yAxisXPos1 = axmin;
5002 yAxisXPos2 = axmax;
5003 }
5004
5005 // Paint the main Y axis (always)
5006 uminsave = umin;
5007 umaxsave = umax;
5008 ndivsave = ndiv;
5009 axis.SetOption(chopt);
5010 if (yAxisPos) {
5011 strlcat(chopt, "+L",10);
5012 gridl = -gridl;
5013 }
5014 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
5015 axis.SetLabelSize(0.);
5016 axis.SetTitle("");
5017 }
5020 umin, umax, ndiv, chopt, gridl, drawGridOnly);
5021
5022 // Paint the additional Y axis (if needed)
5023 // Additional checks for pad mode are required on iOS: this "second" axis is
5024 // neither pickable, nor highlighted. Additional checks have no effect on non-iOS platform.
5025 if (gPad->GetTicky() && !gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
5026 if (gPad->GetTicky() < 2) {
5027 strlcat(chopt, "U",10);
5029 } else {
5030 strlcat(chopt, "+L",10);
5031 }
5032 if ((cw=strstr(chopt,"W"))) *cw='z';
5033 axis.SetTitle("");
5037 }
5038 }//End of "if pad is in selection mode etc."
5039
5040 // Reset the axis if they have been inverted in case of option HBAR
5041 if (xaxis) {
5042 fXaxis = xaxis;
5043 fYaxis = yaxis;
5044 }
5045}
5046
5047////////////////////////////////////////////////////////////////////////////////
5048/// [Draw a bar-chart in a normal pad.](\ref HP10)
5049
5051{
5052
5053 Int_t bar = Hoption.Bar - 10;
5057 TBox box;
5059 if (hcolor == gPad->GetFrameFillColor()) ++hcolor;
5061 box.SetFillColor(hcolor);
5062 box.SetFillStyle(hstyle);
5063 box.SetLineStyle(fH->GetLineStyle());
5064 box.SetLineColor(fH->GetLineColor());
5065 box.SetLineWidth(fH->GetLineWidth());
5066 for (Int_t bin=fXaxis->GetFirst();bin<=fXaxis->GetLast();bin++) {
5067 y = fH->GetBinContent(bin);
5068 xmin = gPad->XtoPad(fXaxis->GetBinLowEdge(bin));
5069 xmax = gPad->XtoPad(fXaxis->GetBinUpEdge(bin));
5070 ymin = gPad->GetUymin();
5071 ymax = gPad->YtoPad(y);
5072 if (ymax < gPad->GetUymin()) continue;
5073 if (ymax > gPad->GetUymax()) ymax = gPad->GetUymax();
5074 if (ymin < gPad->GetUymin()) ymin = gPad->GetUymin();
5075 if (Hoption.MinimumZero && ymin < 0)
5076 ymin=TMath::Min(0.,gPad->GetUymax());
5077 w = (xmax-xmin)*width;
5078 xmin += offset*(xmax-xmin);
5079 xmax = xmin + w;
5080 if (bar < 1) {
5081 box.PaintBox(xmin,ymin,xmax,ymax);
5082 } else {
5083 umin = xmin + bar*(xmax-xmin)/10.;
5084 umax = xmax - bar*(xmax-xmin)/10.;
5085 box.SetFillColor(TColor::GetColorBright(hcolor)); //bright
5086 box.PaintBox(xmin,ymin,umin,ymax);
5087 box.SetFillColor(hcolor);
5088 box.PaintBox(umin,ymin,umax,ymax);
5089 box.SetFillColor(TColor::GetColorDark(hcolor)); //dark
5090 box.PaintBox(umax,ymin,xmax,ymax);
5091 }
5092 }
5093}
5094
5095////////////////////////////////////////////////////////////////////////////////
5096/// [Draw a bar char in a rotated pad (X vertical, Y horizontal)](\ref HP10)
5097
5099{
5100
5101 gPad->SetVertical(kFALSE);
5102
5103 PaintInitH();
5104
5105 TAxis *xaxis = fXaxis;
5106 TAxis *yaxis = fYaxis;
5107 if (!strcmp(xaxis->GetName(),"xaxis")) {
5108 fXaxis = yaxis;
5109 fYaxis = xaxis;
5110 }
5111
5112 PaintFrame();
5114
5115 Int_t bar = Hoption.Bar - 20;
5119 TBox box;
5121 if (hcolor == gPad->GetFrameFillColor()) ++hcolor;
5123 box.SetFillColor(hcolor);
5124 box.SetFillStyle(hstyle);
5125 box.SetLineStyle(fH->GetLineStyle());
5126 box.SetLineColor(fH->GetLineColor());
5127 box.SetLineWidth(fH->GetLineWidth());
5128 for (Int_t bin=fYaxis->GetFirst();bin<=fYaxis->GetLast();bin++) {
5129 ymin = gPad->YtoPad(fYaxis->GetBinLowEdge(bin));
5130 ymax = gPad->YtoPad(fYaxis->GetBinUpEdge(bin));
5131 xmin = gPad->GetUxmin();
5132 xmax = gPad->XtoPad(fH->GetBinContent(bin));
5133 if (xmax < gPad->GetUxmin()) continue;
5134 if (xmax > gPad->GetUxmax()) xmax = gPad->GetUxmax();
5135 if (xmin < gPad->GetUxmin()) xmin = gPad->GetUxmin();
5136 if (Hoption.MinimumZero && xmin < 0)
5137 xmin=TMath::Min(0.,gPad->GetUxmax());
5138 w = (ymax-ymin)*width;
5139 ymin += offset*(ymax-ymin);
5140 ymax = ymin + w;
5141 if (bar < 1) {
5142 box.PaintBox(xmin,ymin,xmax,ymax);
5143 } else {
5144 umin = ymin + bar*(ymax-ymin)/10.;
5145 umax = ymax - bar*(ymax-ymin)/10.;
5146 box.SetFillColor(TColor::GetColorDark(hcolor)); //dark
5147 box.PaintBox(xmin,ymin,xmax,umin);
5148 box.SetFillColor(hcolor);
5149 box.PaintBox(xmin,umin,xmax,umax);
5150 box.SetFillColor(TColor::GetColorBright(hcolor)); //bright
5151 box.PaintBox(xmin,umax,xmax,ymax);
5152 }
5153 }
5154
5155 PaintTitle();
5156
5157 // Draw box with histogram statistics and/or fit parameters
5158 if ((Hoption.Same%10) != 1 && !fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
5159 TIter next(fFunctions);
5160 TObject *obj = nullptr;
5161 while ((obj = next())) {
5162 if (obj->InheritsFrom(TF1::Class())) break;
5163 obj = nullptr;
5164 }
5165 PaintStat(gStyle->GetOptStat(),(TF1*)obj);
5166 }
5167
5168 fXaxis = xaxis;
5169 fYaxis = yaxis;
5170}
5171
5172////////////////////////////////////////////////////////////////////////////////
5173/// [Control function to draw a 2D histogram as a box plot](\ref HP13)
5174
5176{
5177
5180 if (fH->GetFillColor() == 0) fH->SetFillStyle(0);
5181 if (Hoption.Box == 11) fH->SetFillStyle(1001);
5182 fH->TAttLine::Modify();
5183 fH->TAttFill::Modify();
5184
5185 Double_t z, xk,xstep, yk, ystep, xcent, ycent, xlow, xup, ylow, yup;
5186 Double_t ux1 = gPad->PixeltoX(1);
5187 Double_t ux0 = gPad->PixeltoX(0);
5188 Double_t uy1 = gPad->PixeltoY(1);
5189 Double_t uy0 = gPad->PixeltoY(0);
5190 Double_t dxmin = 0.51*(gPad->PadtoX(ux1)-gPad->PadtoX(ux0));
5191 Double_t dymin = 0.51*(gPad->PadtoY(uy0)-gPad->PadtoY(uy1));
5192
5193 Double_t zmin = TMath::Max(fH->GetMinimum(),0.);
5196 Double_t zminlin = zmin, zmaxlin = zmax;
5197
5198 // In case of option SAME, zmin and zmax values are taken from the
5199 // first plotted 2D histogram.
5200 if (Hoption.Same > 0 && Hoption.Same < 10) {
5201 TH2 *h2;
5202 TIter next(gPad->GetListOfPrimitives());
5203 while ((h2 = (TH2 *)next())) {
5204 if (!h2->InheritsFrom(TH2::Class())) continue;
5205 zmin = TMath::Max(h2->GetMinimum(), 0.);
5206 zmax = TMath::Max(TMath::Abs(h2->GetMaximum()),
5207 TMath::Abs(h2->GetMinimum()));
5208 zminlin = zmin;
5209 zmaxlin = zmax;
5210 if (Hoption.Logz) {
5211 if (zmin <= 0) {
5212 zmin = TMath::Log10(zmax*0.001);
5213 } else {
5214 zmin = TMath::Log10(zmin);
5215 }
5216 zmax = TMath::Log10(zmax);
5217 }
5218 break;
5219 }
5220 } else {
5221 if (Hoption.Logz) {
5222 if (zmin > 0) {
5223 zmin = TMath::Log10(zmin);
5224 zmax = TMath::Log10(zmax);
5225 } else {
5226 return;
5227 }
5228 }
5229 }
5230
5231 Double_t zratio, dz = zmax - zmin;
5233 if (fH->GetMinimum()<0) kZminNeg = kTRUE;
5235
5236 // Define the dark and light colors the "button style" boxes.
5237 Color_t color = fH->GetFillColor();
5238 Color_t light=0, dark=0;
5239 if (Hoption.Box == 11) {
5241 dark = TColor::GetColorDark(color);
5242 }
5243
5244 // Loop over all the bins and draw the boxes
5245 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
5248 ycent = 0.5*ystep;
5249 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
5250 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
5251 xk = fXaxis->GetBinLowEdge(i);
5252 xstep = fXaxis->GetBinWidth(i);
5253 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
5254 xcent = 0.5*xstep;
5255 z = Hparam.factor*fH->GetBinContent(bin);
5256 kZNeg = kFALSE;
5257
5258 if (TMath::Abs(z) < zminlin) continue; // Can be the case with ...
5259 if (TMath::Abs(z) > zmaxlin) z = zmaxlin; // ... option Same
5260 if (kZminNeg && z==0) continue; // Do not draw empty bins if case of histo with negative bins.
5261
5262 if (z < 0) {
5263 if (Hoption.Logz) continue;
5264 z = -z;
5265 kZNeg = kTRUE;
5266 }
5267 if (Hoption.Logz) {
5268 if (z != 0) z = TMath::Log10(z);
5269 else z = zmin;
5270 }
5271
5272 if (dz == 0) continue;
5273 zratio = TMath::Sqrt((z-zmin)/dz);
5274 if (zratio == 0) continue;
5275
5276 xup = xcent*zratio + xk + xcent;
5277 xlow = 2*(xk + xcent) - xup;
5278 if (xup-xlow < dxmin) xup = xlow+dxmin;
5279 if (Hoption.Logx) {
5280 if (xup > 0) xup = TMath::Log10(xup);
5281 else continue;
5282 if (xlow > 0) xlow = TMath::Log10(xlow);
5283 else continue;
5284 }
5285
5286 yup = ycent*zratio + yk + ycent;
5287 ylow = 2*(yk + ycent) - yup;
5288 if (yup-ylow < dymin) yup = ylow+dymin;
5289 if (Hoption.Logy) {
5290 if (yup > 0) yup = TMath::Log10(yup);
5291 else continue;
5292 if (ylow > 0) ylow = TMath::Log10(ylow);
5293 else continue;
5294 }
5295
5296 xlow = TMath::Max(xlow, gPad->GetUxmin());
5297 ylow = TMath::Max(ylow, gPad->GetUymin());
5298 xup = TMath::Min(xup , gPad->GetUxmax());
5299 yup = TMath::Min(yup , gPad->GetUymax());
5300
5301 if (xlow >= xup) continue;
5302 if (ylow >= yup) continue;
5303
5304 if (Hoption.Box == 1) {
5305 fH->SetFillColor(color);
5306 fH->TAttFill::Modify();
5307 gPad->PaintBox(xlow, ylow, xup, yup);
5308 if (kZNeg) {
5309 gPad->PaintLine(xlow, ylow, xup, yup);
5310 gPad->PaintLine(xlow, yup, xup, ylow);
5311 }
5312 } else if (Hoption.Box == 11) {
5313 // Draw the center of the box
5314 fH->SetFillColor(color);
5315 fH->TAttFill::Modify();
5316 gPad->PaintBox(xlow, ylow, xup, yup);
5317
5318 // Draw top&left part of the box
5319 Double_t x[7], y[7];
5320 Double_t bwidth = 0.1;
5321 x[0] = xlow; y[0] = ylow;
5322 x[1] = xlow + bwidth*(xup-xlow); y[1] = ylow + bwidth*(yup-ylow);
5323 x[2] = x[1]; y[2] = yup - bwidth*(yup-ylow);
5324 x[3] = xup - bwidth*(xup-xlow); y[3] = y[2];
5325 x[4] = xup; y[4] = yup;
5326 x[5] = xlow; y[5] = yup;
5327 x[6] = xlow; y[6] = ylow;
5328 if (kZNeg) fH->SetFillColor(dark);
5329 else fH->SetFillColor(light);
5330 fH->TAttFill::Modify();
5331 gPad->PaintFillArea(7, x, y);
5332
5333 // Draw bottom&right part of the box
5334 x[0] = xlow; y[0] = ylow;
5335 x[1] = xlow + bwidth*(xup-xlow); y[1] = ylow + bwidth*(yup-ylow);
5336 x[2] = xup - bwidth*(xup-xlow); y[2] = y[1];
5337 x[3] = x[2]; y[3] = yup - bwidth*(yup-ylow);
5338 x[4] = xup; y[4] = yup;
5339 x[5] = xup; y[5] = ylow;
5340 x[6] = xlow; y[6] = ylow;
5341 if (kZNeg) fH->SetFillColor(light);
5342 else fH->SetFillColor(dark);
5343 fH->TAttFill::Modify();
5344 gPad->PaintFillArea(7, x, y);
5345 }
5346 }
5347 }
5348
5352 fH->TAttFill::Modify();
5353}
5354
5355
5356
5357////////////////////////////////////////////////////////////////////////////////
5358/// [Control function to draw a 2D histogram as a candle (box) plot or violin plot](\ref HP14)
5359
5361{
5362 TH1D *hproj = nullptr;
5363 TH2D *h2 = (TH2D*)fH;
5364
5367 myCandle.SetMarkerColor(fH->GetLineColor());
5368 myCandle.SetLineColor(fH->GetLineColor());
5369 myCandle.SetLineWidth(fH->GetLineWidth());
5370 myCandle.SetFillColor(fH->GetFillColor());
5371 myCandle.SetFillStyle(fH->GetFillStyle());
5372 myCandle.SetMarkerSize(fH->GetMarkerSize());
5373 myCandle.SetMarkerStyle(fH->GetMarkerStyle());
5375
5376 Bool_t swapXY = myCandle.IsHorizontal();
5377 const Double_t standardCandleWidth = 0.66;
5378 const Double_t standardHistoWidth = 0.8;
5379
5380 double allMaxContent = 0, allMaxIntegral = 0;
5381 if (myCandle.IsViolinScaled())
5382 allMaxContent = h2->GetBinContent(h2->GetMaximumBin());
5383
5384 if (!swapXY) { // Vertical candle
5385 //Determining the slice with the maximum integral - if necessary
5386 if (myCandle.IsCandleScaled())
5387 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast; i++) {
5388 hproj = h2->ProjectionY("_px", i, i);
5389 if (hproj->Integral() > allMaxIntegral) allMaxIntegral = hproj->Integral();
5390 }
5391 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast; i++) {
5393 Double_t binWidth = fXaxis->GetBinWidth(i);
5394 hproj = h2->ProjectionY("_px", i, i);
5395 if (hproj->GetEntries() != 0) {
5397 Double_t offset = fH->GetBarOffset()*binWidth;
5398 double myMaxContent = hproj->GetBinContent(hproj->GetMaximumBin());
5399 double myIntegral = hproj->Integral();
5401 if (candleWidth > 0.999 && candleWidth < 1.001) {
5404 }
5405 if (Hoption.Logz && myMaxContent > 0) {
5407 if (myCandle.IsViolinScaled() && myMaxContent > 0 && allMaxContent > 0)
5409 } else if (myCandle.IsViolinScaled() && (allMaxContent > 0))
5411 if (myCandle.IsCandleScaled() && (allMaxIntegral > 0))
5413
5414 myCandle.SetAxisPosition(binPosX+binWidth/2. + offset);
5415 myCandle.SetCandleWidth(candleWidth*binWidth);
5416 myCandle.SetHistoWidth(histoWidth*binWidth);
5417 myCandle.SetHistogram(hproj);
5418 myCandle.Paint();
5419 }
5420 }
5421 } else { // Horizontal candle
5422 //Determining the slice with the maximum integral - if necessary
5423 if (myCandle.IsCandleScaled())
5424 for (Int_t i=Hparam.yfirst; i<=Hparam.ylast; i++) {
5425 hproj = h2->ProjectionX("_py", i, i);
5426 if (hproj->Integral() > allMaxIntegral) allMaxIntegral = hproj->Integral();
5427 }
5428 for (Int_t i=Hparam.yfirst; i<=Hparam.ylast; i++) {
5430 Double_t binWidth = fYaxis->GetBinWidth(i);
5431 hproj = h2->ProjectionX("_py", i, i);
5432 if (hproj->GetEntries() != 0) {
5434 Double_t offset = fH->GetBarOffset()*binWidth;
5435 double myMaxContent = hproj->GetBinContent(hproj->GetMaximumBin());
5436 double myIntegral = hproj->Integral();
5438 if (candleWidth > 0.999 && candleWidth < 1.001) {
5441 }
5442 if (Hoption.Logz && myMaxContent > 0) {
5444 if (myCandle.IsViolinScaled() && myMaxContent > 0 && allMaxContent > 0)
5446 } else if (myCandle.IsViolinScaled() && (allMaxContent > 0))
5448 if (myCandle.IsCandleScaled() && (allMaxIntegral > 0))
5450
5451 myCandle.SetAxisPosition(binPosY+binWidth/2. + offset);
5452 myCandle.SetCandleWidth(candleWidth*binWidth);
5453 myCandle.SetHistoWidth(histoWidth*binWidth);
5454 myCandle.SetHistogram(hproj);
5455 myCandle.Paint();
5456 }
5457 }
5458 }
5459 delete hproj;
5460}
5461
5462
5463
5464////////////////////////////////////////////////////////////////////////////////
5465/// Returns the rendering regions for an axis to use in the COL2 option
5466///
5467/// The algorithm analyses the size of the axis compared to the size of
5468/// the rendering region. It figures out the boundaries to use for each color
5469/// of the rendering region. Only one axis is computed here.
5470///
5471/// This allows for a single computation of the boundaries before iterating
5472/// through all of the bins.
5473///
5474/// \param pAxis the axis to consider
5475/// \param nPixels the number of pixels to render axis into
5476/// \param isLog whether the axis is log scale
5477
5478std::vector<THistRenderingRegion>
5480{
5481 std::vector<THistRenderingRegion> regions;
5482
5483 enum STRATEGY { Bins, Pixels } strategy;
5484
5485 Int_t nBins = (pAxis->GetLast() - pAxis->GetFirst() + 1);
5486
5487 if (nBins >= nPixels) {
5488 // more bins than pixels... we should loop over pixels and sample
5489 strategy = Pixels;
5490 } else {
5491 // fewer bins than pixels... we should loop over bins
5492 strategy = Bins;
5493 }
5494
5495 if (isLog) {
5496
5497 Double_t xMin = pAxis->GetBinLowEdge(pAxis->GetFirst());
5498 Int_t binOffset=0;
5499 while (xMin <= 0 && ((pAxis->GetFirst()+binOffset) != pAxis->GetLast()) ) {
5500 binOffset++;
5501 xMin = pAxis->GetBinLowEdge(pAxis->GetFirst()+binOffset);
5502 }
5503 if (xMin <= 0) {
5504 // this should cause an error if we have
5505 return regions;
5506 }
5507 Double_t xMax = pAxis->GetBinUpEdge(pAxis->GetLast());
5508
5509 if (strategy == Bins) {
5510 // logarithmic plot. we find the pixel for the bin
5511 // pixel = eta * log10(V) - alpha
5512 // where eta = nPixels/(log10(Vmax)-log10(Vmin))
5513 // and alpha = nPixels*log10(Vmin)/(log10(Vmax)-log10(Vmin))
5514 // and V is axis value
5516 Double_t offset = -1.0 * eta * TMath::Log10(xMin);
5517
5518 for (Int_t bin=pAxis->GetFirst()+binOffset; bin<=pAxis->GetLast(); bin++) {
5519
5520 // linear plot. we simply need to find the appropriate bin
5521 // for the
5522 Double_t xLowValue = pAxis->GetBinLowEdge(bin);
5523 Double_t xUpValue = pAxis->GetBinUpEdge(bin);
5526 THistRenderingRegion region = {std::make_pair(xPx0, xPx1),
5527 std::make_pair(bin, bin+1)};
5528 regions.push_back(region);
5529 }
5530
5531 } else {
5532
5533 // loop over pixels
5534
5536
5537 for (Int_t pixelIndex=0; pixelIndex<(nPixels-1); pixelIndex++) {
5538 // linear plot
5539 Int_t binLow = pAxis->FindBin(xMin*TMath::Power(10.0, beta*pixelIndex));
5540 Int_t binHigh = pAxis->FindBin(xMin*TMath::Power(10.0, beta*(pixelIndex+1)));
5541 THistRenderingRegion region = { std::make_pair(pixelIndex, pixelIndex+1),
5542 std::make_pair(binLow, binHigh)};
5543 regions.push_back(region);
5544 }
5545 }
5546 } else {
5547 // standard linear plot
5548
5549 if (strategy == Bins) {
5550 // loop over bins
5551 for (Int_t bin=pAxis->GetFirst(); bin<=pAxis->GetLast(); bin++) {
5552
5553 // linear plot. we simply need to find the appropriate bin
5554 // for the
5555 Int_t xPx0 = ((bin - pAxis->GetFirst()) * nPixels)/nBins;
5556 Int_t xPx1 = xPx0 + nPixels/nBins;
5557
5558 // make sure we don't compute beyond our bounds
5559 if (xPx1>= nPixels) xPx1 = nPixels-1;
5560
5561 THistRenderingRegion region = {std::make_pair(xPx0, xPx1),
5562 std::make_pair(bin, bin+1)};
5563 regions.push_back(region);
5564 }
5565 } else {
5566 // loop over pixels
5568 // linear plot
5569 Int_t binLow = (nBins*pixelIndex)/nPixels + pAxis->GetFirst();
5570 Int_t binHigh = binLow + nBins/nPixels;
5571 THistRenderingRegion region = { std::make_pair(pixelIndex, pixelIndex+1),
5572 std::make_pair(binLow, binHigh)};
5573 regions.push_back(region);
5574 }
5575 }
5576 }
5577
5578 return regions;
5579}
5580
5581////////////////////////////////////////////////////////////////////////////////
5582/// [Rendering scheme for the COL2 and COLZ2 options] (\ref HP14)
5583
5585{
5586
5587 if (Hoption.System != kCARTESIAN) {
5588 Error("THistPainter::PaintColorLevelsFast(Option_t*)",
5589 "Only cartesian coordinates supported by 'COL2' option. Using 'COL' option instead.");
5590 PaintColorLevels(nullptr);
5591 return;
5592 }
5593
5594 Double_t z;
5595
5596 // Use existing max or min values. If either is already set
5597 // the appropriate value to use.
5598 Double_t zmin = fH->GetMinimumStored();
5599 Double_t zmax = fH->GetMaximumStored();
5600 Double_t originalZMin = zmin;
5601 Double_t originalZMax = zmax;
5602 if ((zmin == -1111) && (zmax == -1111)) {
5603 fH->GetMinimumAndMaximum(zmin, zmax);
5604 fH->SetMinimum(zmin);
5605 fH->SetMaximum(zmax);
5606 } else if (zmin == -1111) {
5607 zmin = fH->GetMinimum();
5608 fH->SetMinimum(zmin);
5609 } else if (zmax == -1111) {
5610 zmax = fH->GetMaximum();
5611 fH->SetMaximum(zmax);
5612 }
5613
5614 Double_t dz = zmax - zmin;
5615 if (dz <= 0) { // Histogram filled with a constant value
5616 zmax += 0.1*TMath::Abs(zmax);
5617 zmin -= 0.1*TMath::Abs(zmin);
5618 dz = zmax - zmin;
5619 }
5620
5621 if (Hoption.Logz) {
5622 if (zmin > 0) {
5623 zmin = TMath::Log10(zmin);
5624 zmax = TMath::Log10(zmax);
5625 dz = zmax - zmin;
5626 } else {
5627 Error("THistPainter::PaintColorLevelsFast(Option_t*)",
5628 "Cannot plot logz because bin content is less than 0.");
5629 return;
5630 }
5631 }
5632
5633 // Initialize the levels on the Z axis
5634 Int_t ndiv = fH->GetContour();
5635 if (ndiv == 0 ) {
5636 ndiv = gStyle->GetNumberContours();
5637 fH->SetContour(ndiv);
5638 }
5639 std::vector<Double_t> colorBounds(ndiv);
5640 std::vector<Double_t> contours(ndiv, 0);
5641 if (!fH->TestBit(TH1::kUserContour)) {
5642 fH->SetContour(ndiv);
5643 } else {
5644 fH->GetContour(contours.data());
5645 }
5646
5647 Double_t step = 1.0/ndiv;
5648 for (Int_t i=0; i<ndiv; ++i) {
5649 colorBounds[i] = step*i;
5650 }
5651
5652 auto pFrame = gPad->GetFrame();
5653 Int_t px0 = gPad->XtoPixel(pFrame->GetX1());
5654 Int_t px1 = gPad->XtoPixel(pFrame->GetX2());
5655 Int_t py0 = gPad->YtoPixel(pFrame->GetY1());
5656 Int_t py1 = gPad->YtoPixel(pFrame->GetY2());
5657 Int_t nXPixels = px1-px0;
5658 Int_t nYPixels = py0-py1; // y=0 is at the top of the screen
5659
5660 std::vector<Double_t> buffer(nXPixels*nYPixels, 0);
5661
5664 if (xRegions.empty() || yRegions.empty()) {
5665 Error("THistPainter::PaintColorLevelFast(Option_t*)",
5666 "Encountered error while computing rendering regions.");
5667 return;
5668 }
5669
5672 Double_t minValue = 1.;
5673 Double_t maxValue = 0.;
5674 for (auto& yRegion : yRegions) {
5675 for (auto& xRegion : xRegions ) {
5676
5677 const auto& xBinRange = xRegion.fBinRange;
5678 const auto& yBinRange = yRegion.fBinRange;
5679
5680 // sample the range
5681 z = fH->GetBinContent(xBinRange.second-1, yBinRange.second-1);
5682
5683 if (Hoption.Logz) {
5684 if (z > 0) z = TMath::Log10(z);
5685 else z = zmin;
5686 }
5687
5688 // obey the user's max and min values if they were set
5689 if (z > zmax) z = zmax;
5690 if (z < zmin) z = zmin;
5691
5693 // contours are absolute values
5694 auto index = TMath::BinarySearch(contours.size(), contours.data(), z);
5695 z = colorBounds[index];
5696 } else {
5697 Int_t index = 0;
5698 if (dz != 0) {
5699 index = 0.001 + ((z - zmin)/dz)*ndiv;
5700 }
5701
5702 if (index == static_cast<Int_t>(colorBounds.size())) {
5703 index--;
5704 }
5705
5706 // Do a little bookkeeping to use later for getting libAfterImage to produce
5707 // the correct colors
5708 if (index == 0) {
5709 minExists = kTRUE;
5710 } else if (index == static_cast<Int_t>(colorBounds.size()-1)) {
5711 maxExists = kTRUE;
5712 }
5713
5714 z = colorBounds[index];
5715
5716 if (z < minValue) {
5717 minValue = z;
5718 }
5719 if (z > maxValue) {
5720 maxValue = z;
5721 }
5722 }
5723
5724 // fill in the actual pixels
5725 const auto& xPixelRange = xRegion.fPixelRange;
5726 const auto& yPixelRange = yRegion.fPixelRange;
5727 for (Int_t xPx = xPixelRange.first; xPx <= xPixelRange.second; ++xPx) {
5728 for (Int_t yPx = yPixelRange.first; yPx <= yPixelRange.second; ++yPx) {
5730 buffer[pixel] = z;
5731 }
5732 }
5733 } // end px loop
5734 } // end py loop
5735
5736 // This is a bit of a hack to ensure that we span the entire color range and
5737 // don't screw up the colors for a sparse histogram. No one will notice that I set a
5738 // single pixel on the edge of the image to a different color. This is even more
5739 // true because the chosen pixels will be covered by the axis.
5740 if (minValue != maxValue) {
5741 if ( !minExists) {
5742 buffer.front() = 0;
5743 }
5744
5745 if ( !maxExists) {
5746 buffer[buffer.size()-nXPixels] = 0.95;
5747 }
5748 }
5749
5750 // Generate the TImage
5753 pImage->SetImageQuality(TAttImage::kImgBest);
5754 pImage->SetImage(buffer.data(), nXPixels, nYPixels, pPalette);
5755 delete pPalette;
5756
5757 Window_t wid = static_cast<Window_t>(gVirtualX->GetWindowID(gPad->GetPixmapID()));
5758 pImage->PaintImage(wid, px0, py1, 0, 0, nXPixels, nYPixels);
5759 delete pImage;
5760
5762
5763 // Reset the maximum and minimum values to their original values
5764 // when this function was called. If we don't do this, an initial
5765 // value of -1111 will be replaced with the true max or min values.
5768}
5769
5770////////////////////////////////////////////////////////////////////////////////
5771/// [Control function to draw a 2D histogram as a color plot.](\ref HP14)
5772
5774{
5775 Double_t z, e, zc, xk, xstep, yk, ystep, xlow, xup, ylow, yup;
5776
5777 Double_t zmin = fH->GetMinimum();
5778 Double_t zmax = fH->GetMaximum();
5779
5780 Double_t dz = zmax - zmin;
5781 if (dz <= 0) { // Histogram filled with a constant value
5782 zmax += 0.1*TMath::Abs(zmax);
5783 zmin -= 0.1*TMath::Abs(zmin);
5784 dz = zmax - zmin;
5785 }
5786
5787 // In case of option SAME, zmin and zmax values are taken from the
5788 // first plotted 2D histogram.
5789 if (Hoption.Same > 0 && Hoption.Same < 10) {
5790 TH2 *h2;
5791 TIter next(gPad->GetListOfPrimitives());
5792 while ((h2 = (TH2 *)next())) {
5793 if (!h2->InheritsFrom(TH2::Class())) continue;
5794 zmin = h2->GetMinimum();
5795 zmax = h2->GetMaximum();
5796 fH->SetMinimum(zmin);
5797 fH->SetMaximum(zmax);
5798 if (Hoption.Logz) {
5799 if (zmin <= 0) {
5800 zmin = TMath::Log10(zmax*0.001);
5801 } else {
5802 zmin = TMath::Log10(zmin);
5803 }
5804 zmax = TMath::Log10(zmax);
5805 }
5806 dz = zmax - zmin;
5807 break;
5808 }
5809 } else {
5810 if (Hoption.Logz) {
5811 if (zmin > 0) {
5812 zmin = TMath::Log10(zmin);
5813 zmax = TMath::Log10(zmax);
5814 dz = zmax - zmin;
5815 } else {
5816 return;
5817 }
5818 }
5819 }
5820
5823 fH->SetFillStyle(1001);
5824 fH->TAttFill::Modify();
5825
5826 // Initialize the levels on the Z axis
5827 Int_t ncolors = gStyle->GetNumberOfColors();
5828 Int_t ndiv = fH->GetContour();
5829 if (ndiv == 0 ) {
5830 ndiv = gStyle->GetNumberContours();
5831 fH->SetContour(ndiv);
5832 }
5833 Int_t ndivz = TMath::Abs(ndiv);
5834 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
5835 Double_t scale = (dz ? ndivz / dz : 1.0);
5836
5837 Int_t color;
5838 TProfile2D* prof2d = dynamic_cast<TProfile2D*>(fH);
5839 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
5842 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
5843 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
5844 xk = fXaxis->GetBinLowEdge(i);
5845 xstep = fXaxis->GetBinWidth(i);
5846 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
5847 z = fH->GetBinContent(bin);
5848 e = fH->GetBinError(bin);
5849 // if fH is a profile histogram do not draw empty bins
5850 if (prof2d) {
5851 const Double_t binEntries = prof2d->GetBinEntries(bin);
5852 if (binEntries == 0)
5853 continue;
5854 } else {
5855 // don't draw the empty bins for non-profile histograms
5856 // with positive content
5857 if (z == 0 && e == 0) {
5858 if (zmin >= 0 || Hoption.Logz) continue;
5859 if (Hoption.Color == 2) continue;
5860 }
5861 }
5862
5863 if (Hoption.Logz) {
5864 if (z > 0) z = TMath::Log10(z);
5865 else z = zmin;
5866 }
5867 if (z < zmin && !Hoption.Zero) continue;
5868 xup = xk + xstep;
5869 xlow = xk;
5870 if (Hoption.Logx) {
5871 if (xup > 0) xup = TMath::Log10(xup);
5872 else continue;
5873 if (xlow > 0) xlow = TMath::Log10(xlow);
5874 else continue;
5875 }
5876 yup = yk + ystep;
5877 ylow = yk;
5878 if (Hoption.Logy) {
5879 if (yup > 0) yup = TMath::Log10(yup);
5880 else continue;
5881 if (ylow > 0) ylow = TMath::Log10(ylow);
5882 else continue;
5883 }
5884 if (xup < gPad->GetUxmin()) continue;
5885 if (yup < gPad->GetUymin()) continue;
5886 if (xlow > gPad->GetUxmax()) continue;
5887 if (ylow > gPad->GetUymax()) continue;
5888 if (xlow < gPad->GetUxmin()) xlow = gPad->GetUxmin();
5889 if (ylow < gPad->GetUymin()) ylow = gPad->GetUymin();
5890 if (xup > gPad->GetUxmax()) xup = gPad->GetUxmax();
5891 if (yup > gPad->GetUymax()) yup = gPad->GetUymax();
5892
5894 zc = fH->GetContourLevelPad(0);
5895 if (z < zc) continue;
5896 color = -1;
5897 for (Int_t k=0; k<ndiv; k++) {
5898 zc = fH->GetContourLevelPad(k);
5899 if (z < zc) {
5900 continue;
5901 } else {
5902 color++;
5903 }
5904 }
5905 } else {
5906 color = Int_t(0.01+(z-zmin)*scale);
5907 }
5908
5909 Int_t theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
5910 if (theColor > ncolors-1) theColor = ncolors-1;
5912 if (Hoption.System != kPOLAR) {
5914 fH->TAttFill::Modify();
5915 gPad->PaintBox(xlow, ylow, xup, yup);
5916 } else {
5917 Double_t midx = (gPad->GetUxmin() + gPad->GetUxmax()) / 2,
5918 midy = (gPad->GetUymin() + gPad->GetUymax()) / 2,
5919 a1 = (xlow - gPad->GetUxmin()) / (gPad->GetUxmax() - gPad->GetUxmin()) * 360,
5920 a2 = (xup - gPad->GetUxmin()) / (gPad->GetUxmax() - gPad->GetUxmin()) * 360,
5921 rx = gPad->GetUxmax() - gPad->GetUxmin(),
5922 ry = gPad->GetUymax() - gPad->GetUymin(),
5923 r1 = (ylow - gPad->GetUymin()) / (gPad->GetUymax() - gPad->GetUymin()) * rx / 2,
5924 r2 = (yup - gPad->GetUymin()) / (gPad->GetUymax() - gPad->GetUymin()) * rx / 2;
5925
5926 TCrown crown(midx, midy, r1, r2, a1, a2);
5927 crown.SetYXRatio(rx > 0 ? ry / rx : 1);
5928 crown.SetFillColor(fillColor);
5929 crown.SetLineColor(fH->GetLineColor());
5930 crown.SetLineWidth(fH->GetLineWidth());
5931 crown.SetLineStyle(fH->GetLineStyle());
5932 crown.Paint();
5933 }
5934 }
5935 }
5936
5938
5941 fH->TAttFill::Modify();
5942
5943}
5944
5945////////////////////////////////////////////////////////////////////////////////
5946/// [Control function to draw a 2D histogram as a contour plot.](\ref HP16)
5947
5949{
5950
5951 Int_t i, j, count, ncontour, icol, n, lj, m, ix, jx, ljfill;
5952 Int_t itars, mode, ir[4];
5953 Double_t xsave, ysave, thesave,phisave,x[4], y[4], zc[4];
5954
5955 if (Hoption.Contour == 14) {
5956 Hoption.Surf = 12;
5957 Hoption.Axis = 1;
5958 thesave = gPad->GetTheta();
5959 phisave = gPad->GetPhi();
5960 gPad->SetPhi(0.);
5961 gPad->SetTheta(90.);
5963 gPad->SetPhi(phisave);
5964 gPad->SetTheta(thesave);
5965 TView *view = gPad->GetView();
5966 if (view) view->SetBit(kCannotRotate); //tested in ExecuteEvent
5967 PaintAxis();
5968 return;
5969 }
5970
5971 if (Hoption.Same) {
5972 // If the contour is painted on a 3d plot, the contour lines are
5973 // paint in 3d too.
5974 TObject *obj;
5975 TIter next(gPad->GetListOfPrimitives());
5976 while ((obj=next())) {
5977 if (strstr(obj->GetDrawOption(),"surf") ||
5978 strstr(obj->GetDrawOption(),"lego") ||
5979 strstr(obj->GetDrawOption(),"tri")) {
5980 Hoption.Surf = 16;
5982 return;
5983 }
5984 }
5985 }
5986
5987 if (Hoption.Contour == 15) {
5988 TGraphDelaunay2D *dt = nullptr;
5989 TGraphDelaunay *dtOld = nullptr;
5991 dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
5992 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
5993 if (!dt && !dtOld) return;
5994 if (!fGraph2DPainter)
5995 fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
5996 fGraph2DPainter->Paint(option);
5997 return;
5998 }
5999
6000 gPad->SetBit(TGraph::kClipFrame);
6001
6002 std::vector<Double_t> levels(2*kMAXCONTOUR);
6003 std::vector<Double_t> xarr(2*kMAXCONTOUR);
6004 std::vector<Double_t> yarr(2*kMAXCONTOUR);
6005 std::vector<Int_t> itarr(2*kMAXCONTOUR);
6006
6007 Int_t npmax = 0;
6008 for (i=0;i<2*kMAXCONTOUR;i++) itarr[i] = 0;
6009
6010 ncontour = fH->GetContour();
6011 if (ncontour == 0) {
6014 }
6015 if (ncontour > kMAXCONTOUR) {
6016 Warning("PaintContour", "maximum number of contours is %d, asked for %d",
6019 }
6021
6022 for (i=0;i<ncontour;i++) levels[i] = fH->GetContourLevelPad(i);
6026 if (Hoption.Contour == 13) {
6027 fH->TAttLine::Modify();
6028 }
6029
6030 std::vector<std::unique_ptr<TPolyLine>> polys;
6031 TObjArray *contours = nullptr;
6032 TList *list = nullptr;
6033 TGraph *graph = nullptr;
6034 std::vector<Int_t> np;
6035 if (Hoption.Contour == 1) {
6036 np.resize(ncontour);
6037 for (i=0;i<ncontour;i++)
6038 np[i] = 0;
6039 for (i=0;i<ncontour;i++)
6040 polys.emplace_back(std::make_unique<TPolyLine>(100));
6041 if (Hoption.List == 1) {
6042 contours = (TObjArray*)gROOT->GetListOfSpecials()->FindObject("contours");
6043 if (contours) {
6044 gROOT->GetListOfSpecials()->Remove(contours);
6045 count = contours->GetSize();
6046 for (i=0;i<count;i++) {
6047 list = (TList*)contours->At(i);
6048 if (list) list->Delete();
6049 }
6050 contours->Delete();
6051 delete contours;
6052 }
6054 contours->SetName("contours");
6055 gROOT->GetListOfSpecials()->Add(contours);
6056 for (i=0;i<ncontour;i++) {
6057 list = new TList();
6058 contours->Add(list);
6059 }
6060 }
6061 }
6063 Int_t ncolors = gStyle->GetNumberOfColors();
6065
6066 Int_t k,ipoly;
6067 for (j=Hparam.yfirst; j<Hparam.ylast; j++) {
6068 y[0] = fYaxis->GetBinCenter(j);
6069 y[1] = y[0];
6070 y[2] = fYaxis->GetBinCenter(j+1);
6071 y[3] = y[2];
6072 for (i=Hparam.xfirst; i<Hparam.xlast; i++) {
6073 zc[0] = fH->GetBinContent(i, j);
6074 zc[1] = fH->GetBinContent(i+1, j);
6075 zc[2] = fH->GetBinContent(i+1, j+1);
6076 zc[3] = fH->GetBinContent(i, j+1);
6077 if (!IsInside(fXaxis->GetBinCenter(i),fYaxis->GetBinCenter(j))) continue;
6078 if (Hoption.Logz) {
6079 if (zc[0] > 0) zc[0] = TMath::Log10(zc[0]);
6080 else zc[0] = Hparam.zmin;
6081 if (zc[1] > 0) zc[1] = TMath::Log10(zc[1]);
6082 else zc[1] = Hparam.zmin;
6083 if (zc[2] > 0) zc[2] = TMath::Log10(zc[2]);
6084 else zc[2] = Hparam.zmin;
6085 if (zc[3] > 0) zc[3] = TMath::Log10(zc[3]);
6086 else zc[3] = Hparam.zmin;
6087 }
6088 for (k=0;k<4;k++) {
6089 ir[k] = TMath::BinarySearch(ncontour, levels.data(), zc[k]);
6090 }
6091 if (ir[0] != ir[1] || ir[1] != ir[2] || ir[2] != ir[3] || ir[3] != ir[0]) {
6092 x[0] = fXaxis->GetBinCenter(i);
6093 x[3] = x[0];
6094 x[1] = fXaxis->GetBinCenter(i+1);
6095 x[2] = x[1];
6096 if (zc[0] <= zc[1]) n = 0; else n = 1;
6097 if (zc[2] <= zc[3]) m = 2; else m = 3;
6098 if (zc[n] > zc[m]) n = m;
6099 n++;
6100 lj=1;
6101 for (ix=1;ix<=4;ix++) {
6102 m = n%4 + 1;
6103 ljfill = PaintContourLine(zc[n-1],ir[n-1],x[n-1],y[n-1],zc[m-1],
6104 ir[m-1],x[m-1],y[m-1], xarr.data()+lj-1,yarr.data()+lj-1,itarr.data()+lj-1, levels.data());
6105 lj += 2*ljfill;
6106 n = m;
6107 }
6108
6109 if (zc[0] <= zc[1]) n = 0; else n = 1;
6110 if (zc[2] <= zc[3]) m = 2; else m = 3;
6111 if (zc[n] > zc[m]) n = m;
6112 n++;
6113 lj=2;
6114 for (ix=1;ix<=4;ix++) {
6115 if (n == 1) m = 4;
6116 else m = n-1;
6117 ljfill = PaintContourLine(zc[n-1],ir[n-1],x[n-1],y[n-1],zc[m-1],
6118 ir[m-1],x[m-1],y[m-1],xarr.data()+lj-1,yarr.data()+lj-1,itarr.data()+lj-1, levels.data());
6119 lj += 2*ljfill;
6120 n = m;
6121 }
6122
6123 // Re-order endpoints
6124
6125 count = 0;
6126 for (ix=1; ix<=lj-5; ix +=2) {
6127 //count = 0;
6128 while (itarr[ix-1] != itarr[ix]) {
6129 xsave = xarr[ix];
6130 ysave = yarr[ix];
6131 itars = itarr[ix];
6132 for (jx=ix; jx<=lj-5; jx +=2) {
6133 xarr[jx] = xarr[jx+2];
6134 yarr[jx] = yarr[jx+2];
6135 itarr[jx] = itarr[jx+2];
6136 }
6137 xarr[lj-3] = xsave;
6138 yarr[lj-3] = ysave;
6139 itarr[lj-3] = itars;
6140 if (count > 100) break;
6141 count++;
6142 }
6143 }
6144
6145 if (count > 100) continue;
6146 for (ix=1; ix<=lj-2; ix +=2) {
6147 theColor = Int_t((itarr[ix-1]+0.99)*Float_t(ncolors)/Float_t(ndivz));
6149 if (Hoption.Contour == 11) {
6151 }
6152 if (Hoption.Contour == 12) {
6153 mode = icol%5;
6154 if (mode == 0) mode = 5;
6156 }
6157 if (Hoption.Contour != 1) {
6158 fH->TAttLine::Modify();
6159 gPad->PaintPolyLine(2,xarr.data()+ix-1,yarr.data()+ix-1);
6160 continue;
6161 }
6162
6163 ipoly = itarr[ix-1];
6164 if (ipoly >=0 && ipoly <ncontour) {
6165 polys[ipoly]->SetPoint(np[ipoly] ,xarr[ix-1],yarr[ix-1]);
6166 polys[ipoly]->SetPoint(np[ipoly]+1,xarr[ix], yarr[ix]);
6167 np[ipoly] += 2;
6168 if (npmax < np[ipoly]) npmax = np[ipoly];
6169 }
6170 }
6171 } // end of if (ir[0]
6172 } //end of for (i
6173 } //end of for (j
6174
6176 std::vector<Double_t> xp, yp;
6178 Int_t istart;
6179 Int_t first = ncontour;
6180 std::vector<Int_t> polysort;
6182 if (Hoption.Contour != 1) goto theEND;
6183
6184 //The 2 points line generated above are now sorted/merged to generate
6185 //a list of consecutive points.
6186 // If the option "List" has been specified, the list of points is saved
6187 // in the form of TGraph objects in the ROOT list of special objects.
6188 xmin = gPad->GetUxmin();
6189 ymin = gPad->GetUymin();
6190 xp.resize(2*npmax);
6191 yp.resize(2*npmax);
6192 polysort.resize(ncontour);
6193 //find first positive contour
6194 for (ipoly=0;ipoly<ncontour;ipoly++) {
6195 if (levels[ipoly] >= 0) {first = ipoly; break;}
6196 }
6197 //store negative contours from 0 to minimum, then all positive contours
6198 k = 0;
6199 for (ipoly=first-1;ipoly>=0;ipoly--) {polysort[k] = ipoly; k++;}
6200 for (ipoly=first;ipoly<ncontour;ipoly++) {polysort[k] = ipoly; k++;}
6201 // we can now draw sorted contours
6202 contListNb = 0;
6203 fH->SetFillStyle(1001);
6204 for (k=0;k<ncontour;k++) {
6205 ipoly = polysort[k];
6206 if (np[ipoly] == 0) continue;
6207 if (Hoption.List) list = (TList*)contours->At(contListNb);
6208 contListNb++;
6209 Double_t *xx = polys[ipoly]->GetX();
6210 Double_t *yy = polys[ipoly]->GetY();
6211 istart = 0;
6212 while (true) {
6213 iminus = npmax;
6214 iplus = iminus+1;
6215 xp[iminus]= xx[istart]; yp[iminus] = yy[istart];
6216 xp[iplus] = xx[istart+1]; yp[iplus] = yy[istart+1];
6217 xx[istart] = xmin; yy[istart] = ymin;
6218 xx[istart+1] = xmin; yy[istart+1] = ymin;
6219 while (true) {
6220 nadd = 0;
6221 for (i=2;i<np[ipoly];i+=2) {
6222 if ((iplus < 2*npmax-1) && (xx[i] == xp[iplus]) && (yy[i] == yp[iplus])) {
6223 iplus++;
6224 xp[iplus] = xx[i+1]; yp[iplus] = yy[i+1];
6225 xx[i] = xmin; yy[i] = ymin;
6226 xx[i+1] = xmin; yy[i+1] = ymin;
6227 nadd++;
6228 }
6229 if ((iminus > 0) && (xx[i+1] == xp[iminus]) && (yy[i+1] == yp[iminus])) {
6230 iminus--;
6231 xp[iminus] = xx[i]; yp[iminus] = yy[i];
6232 xx[i] = xmin; yy[i] = ymin;
6233 xx[i+1] = xmin; yy[i+1] = ymin;
6234 nadd++;
6235 }
6236 }
6237 if (nadd == 0) break;
6238 }
6239 theColor = Int_t((ipoly+0.99)*Float_t(ncolors)/Float_t(ndivz));
6241 if (ndivz > 1) fH->SetFillColor(icol);
6242 fH->TAttFill::Modify();
6243 gPad->PaintFillArea(iplus-iminus+1,xp.data()+iminus,yp.data()+iminus);
6244 if (Hoption.List) {
6245 graph = new TGraph(iplus-iminus+1,xp.data()+iminus,yp.data()+iminus);
6246 graph->SetFillColor(icol);
6247 graph->SetLineWidth(fH->GetLineWidth());
6248 list->Add(graph);
6249 }
6250 //check if more points are left
6251 istart = 0;
6252 for (i=2;i<np[ipoly];i+=2) {
6253 if (xx[i] != xmin && yy[i] != ymin) {
6254 istart = i;
6255 break;
6256 }
6257 }
6258 if (istart == 0) break;
6259 }
6260 }
6261
6262theEND:
6263 gPad->ResetBit(TGraph::kClipFrame);
6268}
6269
6270////////////////////////////////////////////////////////////////////////////////
6271/// Fill the matrix `xarr` and `yarr` for Contour Plot.
6272
6276{
6277
6278 Bool_t vert;
6280 Int_t n, i, icount;
6281
6282 if (x1 == x2) {
6283 vert = kTRUE;
6284 tlen = y2 - y1;
6285 } else {
6286 vert = kFALSE;
6287 tlen = x2 - x1;
6288 }
6289
6290 n = icont1 +1;
6291 tdif = elev2 - elev1;
6292 i = 0;
6293 icount = 0;
6294 while (n <= icont2 && i <= kMAXCONTOUR/2 -3) {
6295 //elev = fH->GetContourLevel(n);
6296 elev = levels[n];
6297 diff = elev - elev1;
6298 pdif = diff/tdif;
6299 xlen = tlen*pdif;
6300 if (vert) {
6301 if (Hoption.Logx)
6302 xarr[i] = TMath::Log10(x1);
6303 else
6304 xarr[i] = x1;
6305 if (Hoption.Logy)
6306 yarr[i] = TMath::Log10(y1 + xlen);
6307 else
6308 yarr[i] = y1 + xlen;
6309 } else {
6310 if (Hoption.Logx)
6311 xarr[i] = TMath::Log10(x1 + xlen);
6312 else
6313 xarr[i] = x1 + xlen;
6314 if (Hoption.Logy)
6315 yarr[i] = TMath::Log10(y1);
6316 else
6317 yarr[i] = y1;
6318 }
6319 itarr[i] = n;
6320 icount++;
6321 i +=2;
6322 n++;
6323 }
6324 return icount;
6325}
6326
6327////////////////////////////////////////////////////////////////////////////////
6328/// [Draw 1D histograms error bars.](\ref HP09)
6329
6331{
6332
6333 // On iOS, we do not highlight histogram, if it's not picked at the moment
6334 // (but part of histogram (axis or pavestat) was picked, that's why this code
6335 // is called at all. This conditional statement never executes on non-iOS platform.
6336 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH) return;
6337
6338 const Int_t kBASEMARKER=8;
6339 Double_t xp, yp, ex1, ex2, ey1, ey2;
6340 Double_t delta;
6342 Double_t xi1, xi2, xi3, xi4, yi1, yi2, yi3, yi4;
6344 Double_t logxmin = 0;
6345 Double_t logymin = 0;
6346 Double_t offset = 0.;
6347 Double_t width = 0.;
6348 Int_t i, k, npoints, first, last, fixbin;
6349 Int_t if1 = 0;
6350 Int_t if2 = 0;
6353 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};
6354 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};
6355
6356 std::vector<Double_t> xline, yline;
6358 if (Hoption.Error >= 40) {Hoption.Error -=40; option0 = 1;}
6359 if (Int_t(Hoption.Error/10) == 2) {optionEX0 = 1; Hoption.Error -= 10;}
6360 if (Hoption.Error == 31) {optionEX0 = 1; Hoption.Error = 1;}
6361 if (Hoption.Error == 11) option1 = 1;
6362 if (Hoption.Error == 12) option2 = 1;
6363 if (Hoption.Error == 13) option3 = 1;
6364 if (Hoption.Error == 14) {option4 = 1; option3 = 1;}
6365 if (Hoption.Error == 15) {optionI0 = 1; option3 = 1;}
6366 if (Hoption.Error == 16) {optionI0 = 1; option4 = 1; option3 = 1;}
6367 if (option2+option3 == 0) optionE = 1;
6368 if (Hoption.Error == 0) optionE = 0;
6369 if (fXaxis->GetXbins()->fN) fixbin = 0;
6370 else fixbin = 1;
6371
6372 offset = fH->GetBarOffset();
6373 width = fH->GetBarWidth();
6374
6376 if (optionEX0) {
6377 xerror = 0;
6378 } else {
6379 xerror = gStyle->GetErrorX();
6380 }
6382 if (errormarker == 1) symbolsize = 0.01;
6384 if (errormarker >= 20 && errormarker <= 49) {
6385 sbasex *= cxx[errormarker-20];
6386 sbasey *= cyy[errormarker-20];
6387 }
6388 // set the graphics attributes
6389
6390 fH->TAttLine::Modify();
6391 fH->TAttFill::Modify();
6392 fH->TAttMarker::Modify();
6393
6394 // set the first and last bin
6395
6396 Double_t factor = Hparam.factor;
6397 first = Hparam.xfirst;
6398 last = Hparam.xlast;
6399 npoints = last - first +1;
6400 xmin = gPad->GetUxmin();
6401 xmax = gPad->GetUxmax();
6402 ymin = gPad->GetUymin();
6403 ymax = gPad->GetUymax();
6404
6405
6406 if (option3) {
6407 xline.resize(2*npoints);
6408 yline.resize(2*npoints);
6409 if ((npoints > 0) && (xline.empty() || yline.empty())) {
6410 Error("PaintErrors", "too many points, out of memory");
6411 return;
6412 }
6413 if1 = 1;
6414 if2 = 2*npoints;
6415 }
6416
6417 // compute the offset of the error bars due to the symbol size
6418 s2x = gPad->PixeltoX(Int_t(0.5*sbasex)) - gPad->PixeltoX(0);
6419 s2y =-gPad->PixeltoY(Int_t(0.5*sbasey)) + gPad->PixeltoY(0);
6420
6421 // compute size of the lines at the end of the error bars
6423 bxsize = gPad->PixeltoX(dxend) - gPad->PixeltoX(0);
6424 bysize =-gPad->PixeltoY(dxend) + gPad->PixeltoY(0);
6425
6426
6427 if (fixbin) {
6429 else xp = Hparam.xmin + 0.5*Hparam.xbinsize;
6430 } else {
6431 delta = fH->GetBinWidth(first);
6432 xp = fH->GetBinLowEdge(first) + 0.5*delta;
6433 }
6434
6435 // if errormarker = 0 or symbolsize = 0. no symbol is drawn
6438
6439 // ---------------------- Loop over the points---------------------
6440 for (k=first; k<=last; k++) {
6441
6442 // get the data
6443 // xp = X position of the current point
6444 // yp = Y position of the current point
6445 // ex1 = Low X error
6446 // ex2 = Up X error
6447 // ey1 = Low Y error
6448 // ey2 = Up Y error
6449 // (xi,yi) = Error bars coordinates
6450
6451 // apply offset on errors for bar histograms
6452 Double_t xminTmp = gPad->XtoPad(fXaxis->GetBinLowEdge(k));
6453 Double_t xmaxTmp = gPad->XtoPad(fXaxis->GetBinUpEdge(k));
6454 if (Hoption.Logx) {
6457 }
6460 xmaxTmp = xminTmp + w;
6461 xp = (xminTmp+xmaxTmp)/2.;
6462
6463 if (Hoption.Logx) {
6464 if (xp <= 0) goto L30;
6465 if (xp < logxmin) goto L30;
6466 if (xp > TMath::Power(10,xmax)) break;
6467 } else {
6468 if (xp < xmin) goto L30;
6469 if (xp > xmax) break;
6470 }
6471 yp = factor*fH->GetBinContent(k);
6472 if (optionI0 && yp==0) goto L30;
6473 if (fixbin) {
6475 } else {
6476 delta = fH->GetBinWidth(k);
6477 ex1 = xerror*delta;
6478 }
6479 if (fH->GetBinErrorOption() == TH1::kNormal) {
6480 ey1 = factor*fH->GetBinError(k);
6481 ey2 = ey1;
6482 } else {
6483 ey1 = factor*fH->GetBinErrorLow(k);
6484 ey2 = factor*fH->GetBinErrorUp(k);
6485 }
6486 ex2 = ex1;
6487
6488 xi4 = xp;
6489 xi3 = xp;
6490 xi2 = xp + ex2;
6491 xi1 = xp - ex1;
6492
6493 yi1 = yp;
6494 yi2 = yp;
6495 yi3 = yp - ey1;
6496 yi4 = yp + ey2;
6497
6498 // take the LOG if necessary
6499 if (Hoption.Logx) {
6504 }
6505 if (Hoption.Logy) {
6510 }
6511
6512 // test if error bars are not outside the limits
6513 // otherwise they are truncated
6514
6519
6520 // test if the marker is on the frame limits. If "Yes", the
6521 // marker will not be drawn and the error bars will be readjusted.
6522
6523 drawmarker = kTRUE;
6524 if (!option0 && !option3) {
6525 if (Hoption.Logy && yp < logymin) goto L30;
6526 if (yi1 < ymin || yi1 > ymax) goto L30;
6527 if (Hoption.Error != 0 && yp == 0 && ey1 <= 0) drawmarker = kFALSE;
6528 }
6530
6531 // draw the error rectangles
6532 if (option2) {
6533 if (yi3 >= ymax) goto L30;
6534 if (yi4 <= ymin) goto L30;
6535 gPad->PaintBox(xi1,yi3,xi2,yi4);
6536 }
6537
6538 // keep points for fill area drawing
6539 if (option3) {
6540 xline[if1-1] = xi3;
6541 xline[if2-1] = xi3;
6542 yline[if1-1] = yi4;
6543 yline[if2-1] = yi3;
6544 if1++;
6545 if2--;
6546 }
6547
6548 // draw the error bars
6549 if (Hoption.Logy && yp < logymin) drawmarker = kFALSE;
6550 if (optionE && drawmarker) {
6551 if ((yi3 < yi1 - s2y) && (yi3 < ymax)) gPad->PaintLine(xi3,yi3,xi4,TMath::Min(yi1 - s2y,ymax));
6552 if ((yi1 + s2y < yi4) && (yi4 > ymin)) gPad->PaintLine(xi3,TMath::Max(yi1 + s2y, ymin),xi4,yi4);
6553 // don't duplicate the horizontal line
6554 if (Hoption.Hist != 2) {
6556 if (xi1 < xi3 - s2x) gPad->PaintLine(xi1,yi1,xi3 - s2x,yi2);
6557 if (xi3 + s2x < xi2) gPad->PaintLine(xi3 + s2x,yi1,xi2,yi2);
6558 }
6559 }
6560 }
6561 if (optionE && !drawmarker && (ey1 != 0 || ey2 !=0)) {
6562 if ((yi3 < yi1) && (yi3 < ymax)) gPad->PaintLine(xi3,yi3,xi4,TMath::Min(yi1,ymax));
6563 if ((yi1 < yi4) && (yi4 > ymin)) gPad->PaintLine(xi3,TMath::Max(yi1,ymin),xi4,yi4);
6564 // don't duplicate the horizontal line
6565 if (Hoption.Hist != 2) {
6567 if (xi1 < xi3) gPad->PaintLine(xi1,yi1,xi3,yi2);
6568 if (xi3 < xi2) gPad->PaintLine(xi3,yi1,xi2,yi2);
6569 }
6570 }
6571 }
6572
6573 // draw line at the end of the error bars
6574
6575 if (option1 && drawmarker) {
6576
6577 if (yi3 < yi1-s2y && yi3 < ymax && yi3 > ymin) gPad->PaintLine(xi3 - bxsize, yi3 , xi3 + bxsize, yi3);
6578 if (yi4 > yi1+s2y && yi4 < ymax && yi4 > ymin) gPad->PaintLine(xi3 - bxsize, yi4 , xi3 + bxsize, yi4);
6580 if (xi1 < xi3-s2x) gPad->PaintLine(xi1 , yi1 - bysize, xi1 , yi1 + bysize);
6581 if (xi2 > xi3+s2x) gPad->PaintLine(xi2 , yi1 - bysize, xi2 , yi1 + bysize);
6582 }
6583 }
6584
6585 // draw the marker
6586
6587 if (drawmarker) gPad->PaintPolyMarker(1, &xi3, &yi1);
6588
6589L30:
6590 if (fixbin) xp += Hparam.xbinsize;
6591 else {
6592 if (k < last) {
6593 delta = fH->GetBinWidth(k+1);
6594 xp = fH->GetBinLowEdge(k+1) + 0.5*delta;
6595 }
6596 }
6597 } //end of for loop
6598
6599 // draw the filled area
6600
6601 if (option3) {
6602 TGraph graph;
6603 graph.SetLineStyle(fH->GetLineStyle());
6604 graph.SetLineColor(fH->GetLineColor());
6605 graph.SetLineWidth(fH->GetLineWidth());
6606 graph.SetFillStyle(fH->GetFillStyle());
6607 graph.SetFillColor(fH->GetFillColor());
6608 Int_t logx = gPad->GetLogx();
6609 Int_t logy = gPad->GetLogy();
6610 gPad->SetLogx(0);
6611 gPad->SetLogy(0);
6612
6613 // In some cases the number of points in the fill area is smaller than
6614 // 2*npoints. In such cases the array xline and yline must be arranged
6615 // before being plotted. The next loop does that.
6616 if (if2 > npoints) {
6617 for (i=1; i<if1; i++) {
6618 xline[if1-2+i] = xline[if2-1+i];
6619 yline[if1-2+i] = yline[if2-1+i];
6620 }
6621 npoints = if1-1;
6622 }
6623 if (option4) graph.PaintGraph(2*npoints,xline.data(),yline.data(),"FC");
6624 else graph.PaintGraph(2*npoints,xline.data(),yline.data(),"F");
6625 gPad->SetLogx(logx);
6626 gPad->SetLogy(logy);
6627 }
6628}
6629
6630////////////////////////////////////////////////////////////////////////////////
6631/// Draw 2D histograms errors.
6632
6634{
6635
6636 fH->TAttMarker::Modify();
6637 fH->TAttLine::Modify();
6638
6639 // Define the 3D view
6640 fXbuf[0] = Hparam.xmin;
6641 fYbuf[0] = Hparam.xmax;
6642 fXbuf[1] = Hparam.ymin;
6643 fYbuf[1] = Hparam.ymax;
6644 fXbuf[2] = Hparam.zmin;
6645 fYbuf[2] = Hparam.zmax*(1. + gStyle->GetHistTopMargin());
6646 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
6647 TView *view = gPad ? gPad->GetView() : nullptr;
6648 if (!view) {
6649 Error("Paint2DErrors", "no TView in current pad");
6650 return;
6651 }
6652 Double_t thedeg = 90 - gPad->GetTheta();
6653 Double_t phideg = -90 - gPad->GetPhi();
6654 Double_t psideg = view->GetPsi();
6655 Int_t irep;
6656 view->SetView(phideg, thedeg, psideg, irep);
6657
6658 // Set color/style for back box
6659 fLego->SetFillStyle(gPad->GetFrameFillStyle());
6660 fLego->SetFillColor(gPad->GetFrameFillColor());
6661 fLego->TAttFill::Modify();
6662 Int_t backcolor = gPad->GetFrameFillColor();
6663 if (Hoption.System != kCARTESIAN) backcolor = 0;
6664 view->PadRange(backcolor);
6665 fLego->SetFillStyle(fH->GetFillStyle());
6666 fLego->SetFillColor(fH->GetFillColor());
6667 fLego->TAttFill::Modify();
6668
6669 // Paint the Back Box if needed
6670 if (Hoption.BackBox && !Hoption.Same && !Hoption.Lego && !Hoption.Surf) {
6671 fLego->InitMoveScreen(-1.1,1.1);
6672 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
6674 fLego->BackBox(90);
6675 }
6676
6677 // Paint the Errors
6678 Double_t x, ex, x1, x2;
6679 Double_t y, ey, y1, y2;
6680 Double_t z, ez1, ez2, z1, z2;
6681 Double_t temp1[3],temp2[3];
6683 if (Hoption.Error == 110) {
6684 xyerror = 0;
6685 } else {
6687 }
6688
6690 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
6691 y = fYaxis->GetBinCenter(j);
6693 y1 = y-ey;
6694 y2 = y+ey;
6695 if (Hoption.Logy) {
6696 if (y > 0) y = TMath::Log10(y);
6697 else continue;
6698 if (y1 > 0) y1 = TMath::Log10(y1);
6699 else y1 = Hparam.ymin;
6700 if (y2 > 0) y2 = TMath::Log10(y2);
6701 else y2 = Hparam.ymin;
6702 }
6705 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
6706 xk = fXaxis->GetBinLowEdge(i);
6707 xstep = fXaxis->GetBinWidth(i);
6708 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
6709 Int_t bin = fH->GetBin(i,j);
6710 x = fXaxis->GetBinCenter(i);
6712 x1 = x-ex;
6713 x2 = x+ex;
6714 if (Hoption.Logx) {
6715 if (x > 0) x = TMath::Log10(x);
6716 else continue;
6717 if (x1 > 0) x1 = TMath::Log10(x1);
6718 else x1 = Hparam.xmin;
6719 if (x2 > 0) x2 = TMath::Log10(x2);
6720 else x2 = Hparam.xmin;
6721 }
6722 z = fH->GetBinContent(bin);
6723 if (fH->GetBinErrorOption() == TH1::kNormal) {
6724 ez1 = fH->GetBinError(bin);
6725 ez2 = ez1;
6726 }
6727 else {
6728 ez1 = fH->GetBinErrorLow(bin);
6729 ez2 = fH->GetBinErrorUp(bin);
6730 }
6731 z1 = z - ez1;
6732 z2 = z + ez2;
6733 if (Hoption.Logz) {
6734 if (z > 0) z = TMath::Log10(z);
6735 else z = Hparam.zmin;
6736 if (z1 > 0) z1 = TMath::Log10(z1);
6737 else z1 = Hparam.zmin;
6738 if (z2 > 0) z2 = TMath::Log10(z2);
6739 else z2 = Hparam.zmin;
6740
6741 }
6742 if (z <= Hparam.zmin) continue;
6743 if (z > Hparam.zmax) z = Hparam.zmax;
6744
6745 temp1[0] = x1;
6746 temp1[1] = y;
6747 temp1[2] = z;
6748 temp2[0] = x2;
6749 temp2[1] = y;
6750 temp2[2] = z;
6751 gPad->PaintLine3D(temp1, temp2);
6752 temp1[0] = x;
6753 temp1[1] = y1;
6754 temp1[2] = z;
6755 temp2[0] = x;
6756 temp2[1] = y2;
6757 temp2[2] = z;
6758 gPad->PaintLine3D(temp1, temp2);
6759 temp1[0] = x;
6760 temp1[1] = y;
6761 temp1[2] = z1;
6762 temp2[0] = x;
6763 temp2[1] = y;
6764 temp2[2] = z2;
6765 gPad->PaintLine3D(temp1, temp2);
6766 temp1[0] = x;
6767 temp1[1] = y;
6768 temp1[2] = z;
6769 view->WCtoNDC(temp1, &temp2[0]);
6770 gPad->PaintPolyMarker(1, &temp2[0], &temp2[1]);
6771 }
6772 }
6773
6774 // Paint the Front Box if needed
6775 if (Hoption.FrontBox) {
6776 fLego->InitMoveScreen(-1.1,1.1);
6778 fLego->FrontBox(90);
6779 }
6780
6781 // Paint the Axis if needed
6782 if (!Hoption.Axis && !Hoption.Same && !Hoption.Lego && !Hoption.Surf) {
6783 TGaxis axis;
6784 PaintLegoAxis(&axis, 90);
6785 }
6786
6787 fLego.reset();
6788}
6789
6790////////////////////////////////////////////////////////////////////////////////
6791/// Calculate range and clear pad (canvas).
6792
6794{
6795
6796 if (Hoption.Same) return;
6797
6799
6800 if (Hoption.Lego || Hoption.Surf || Hoption.Tri ||
6801 Hoption.Contour == 14 || Hoption.Error >= 100) {
6802 TObject *frame = gPad->FindObject("TFrame");
6803 if (frame) gPad->Remove(frame);
6804 return;
6805 }
6806
6807 //The next statement is always executed on non-iOS platform,
6808 //on iOS depends on pad mode.
6809 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode())
6810 gPad->PaintPadFrame(Hparam.xmin,Hparam.ymin,Hparam.xmax,Hparam.ymax);
6811}
6812
6813////////////////////////////////////////////////////////////////////////////////
6814/// [Paint functions associated to an histogram.](\ref HP28")
6815
6817{
6818 auto lnk = fFunctions->FirstLink();
6819
6820 while (lnk) {
6821 auto obj = lnk->GetObject();
6823 if (obj->InheritsFrom(TF2::Class())) {
6824 if (!obj->TestBit(TF2::kNotDraw)) {
6825 if (Hoption.Lego || Hoption.Surf || Hoption.Error >= 100) {
6826 TF2 *f2 = (TF2*)obj;
6827 f2->SetMinimum(fH->GetMinimum());
6828 f2->SetMaximum(fH->GetMaximum());
6829 f2->SetRange(fH->GetXaxis()->GetXmin(), fH->GetYaxis()->GetXmin(), fH->GetXaxis()->GetXmax(), fH->GetYaxis()->GetXmax() );
6830 f2->Paint("surf same");
6831 } else {
6832 obj->Paint("cont3 same");
6833 }
6834 }
6835 } else if (obj->InheritsFrom(TF1::Class())) {
6836 if (!obj->TestBit(TF1::kNotDraw)) obj->Paint("lsame");
6837 } else {
6838 //Let's make this 'function' selectable on iOS device (for example, it can be TPaveStat).
6839 gPad->PushSelectableObject(obj);
6840
6841 //The next statement is ALWAYS executed on non-iOS platform, on iOS it depends on pad's mode
6842 //and picked object.
6843 if (!gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && obj == gPad->GetSelected()))
6844 obj->Paint(lnk->GetOption());
6845 }
6846 lnk = lnk->Next();
6847 }
6848}
6849
6850////////////////////////////////////////////////////////////////////////////////
6851/// [Control routine to draw 1D histograms](\ref HP01b)
6852
6854{
6855
6856 //On iOS: do not highlight hist, if part of it was selected.
6857 //Never executes on non-iOS platform.
6858 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
6859 return;
6860
6861 static char chopth[17];
6862
6864 Int_t i, j, first, last, nbins, fixbin;
6865 Double_t c1, yb;
6866 yb = 0;
6867
6868 strlcpy(chopth, " ",17);
6869
6872 Double_t baroffset = fH->GetBarOffset();
6873 Double_t barwidth = fH->GetBarWidth();
6876 gStyle->SetBarOffset(baroffset);
6877 gStyle->SetBarWidth(barwidth);
6878
6879 // Create "LIFE" structure to keep current histogram status
6880
6881 first = Hparam.xfirst;
6882 last = Hparam.xlast;
6883 nbins = last - first + 1;
6884
6885 std::vector<Double_t> keepx, keepy;
6886 if (fXaxis->GetXbins()->fN) fixbin = 0;
6887 else fixbin = 1;
6888 if (fixbin) keepx.resize(2);
6889 else keepx.resize(nbins+1);
6890 keepy.resize(nbins);
6891 Double_t logymin = 0;
6893
6894 // Loop on histogram bins
6895
6896 for (j=first; j<=last;j++) {
6898 if (TMath::Abs(ymax-ymin) > 0) {
6900 else yb = c1;
6901 }
6902 if (!Hoption.Line) {
6903 yb = TMath::Max(yb, ymin);
6904 yb = TMath::Min(yb, ymax);
6905 }
6906 keepy[j-first] = yb;
6907 }
6908
6909 // Draw histogram according to value of FillStyle and FillColor
6910
6911 if (fixbin) { keepx[0] = Hparam.xmin; keepx[1] = Hparam.xmax; }
6912 else {
6913 for (i=0; i<nbins; i++) keepx[i] = fXaxis->GetBinLowEdge(i+first);
6914 keepx[nbins] = fXaxis->GetBinUpEdge(nbins-1+first);
6915 }
6916
6917 // Prepare Fill area (systematic with option "Bar").
6918
6920 htype = oldhtype;
6921 if (Hoption.Bar) {
6922 if (htype == 0 || htype == 1000) htype = 1001;
6923 }
6924
6926
6927 // Code option for GrapHist
6928
6929 if (Hoption.Line) chopth[0] = 'L';
6930 if (Hoption.Star) chopth[1] = '*';
6931 if (Hoption.Mark) chopth[2] = 'P';
6932 if (Hoption.Mark == 10) chopth[3] = '0';
6934 if (Hoption.Curve) chopth[3] = 'C';
6935 if (Hoption.Hist > 0) chopth[4] = 'H';
6936 else if (Hoption.Bar) chopth[5] = 'B';
6937 if (Hoption.Logy) chopth[6] = '1';
6938 if (fH->GetFillColor() && htype) {
6939 if (Hoption.Hist > 0 || Hoption.Curve || Hoption.Line) {
6940 chopth[7] = 'F';
6941 }
6942 }
6943 }
6944 if (!fixbin && strlen(chopth)) {
6945 chopth[8] = 'N';
6946 }
6947
6948 if (Hoption.Fill == 2) chopth[13] = '2';
6949
6950 // Option LOGX
6951
6952 if (Hoption.Logx) {
6953 chopth[9] = 'G';
6954 chopth[10] = 'X';
6955 if (fixbin) {
6956 keepx[0] = TMath::Power(10,keepx[0]);
6957 keepx[1] = TMath::Power(10,keepx[1]);
6958 }
6959 }
6960
6961 if (Hoption.Off) {
6962 chopth[11] = ']';
6963 chopth[12] = '[';
6964 }
6965
6966 // Draw the histogram
6967
6968 TGraph graph;
6969 graph.SetLineWidth(lw);
6970 graph.SetLineStyle(fH->GetLineStyle());
6971 graph.SetLineColor(fH->GetLineColor());
6972 graph.SetFillStyle(htype);
6973 graph.SetFillColor(fH->GetFillColor());
6975 graph.SetMarkerSize(fH->GetMarkerSize());
6978
6979 graph.PaintGrapHist(nbins, keepx.data(), keepy.data() ,chopth);
6980
6983
6985}
6986
6987////////////////////////////////////////////////////////////////////////////////
6988/// [Control function to draw a 3D histograms.](\ref HP01d)
6989
6991{
6992
6993 TString cmd;
6994 TString opt = option;
6995 opt.ToLower();
6996 Int_t irep;
6997 Float_t NEntries = fH->GetEntries();
6998
6999 if (fCurrentF3 || strstr(opt,"tf3")) {
7000 PaintTF3();
7001 return;
7002 }
7003
7004 if (NEntries > 0) {
7005 if (Hoption.Box || Hoption.Lego || Hoption.Color) {
7006 if (Hoption.Box == 11 || Hoption.Lego == 11) {
7007 PaintH3Box(1);
7008 } else if (Hoption.Box == 12 || Hoption.Lego == 12 || Hoption.Color == 1) {
7009 PaintH3Box(2);
7010 } else if (Hoption.Box == 13 || Hoption.Lego == 13) {
7011 PaintH3Box(3);
7012 } else {
7014 }
7015 return;
7016 }
7017
7018 if (strstr(opt,"iso")) {
7019 PaintH3Iso();
7020 return;
7021 }
7022 }
7023
7024 TView *view = gPad ? gPad->GetView() : nullptr;
7025 if (!view) return;
7026
7027 if (strstr(opt,"fb")) Hoption.FrontBox = 0;
7028 if (strstr(opt,"bb")) Hoption.BackBox = 0;
7029
7030 Double_t thedeg = 90 - gPad->GetTheta();
7031 Double_t phideg = -90 - gPad->GetPhi();
7032 Double_t psideg = view->GetPsi();
7033 view->SetView(phideg, thedeg, psideg, irep);
7034
7035 if(NEntries > 0) { // Paint as 3D scatter plot
7036 cmd.Form("TPolyMarker3D::PaintH3((TH1 *)0x%zx,\"%s\");",(size_t)fH,option);
7037 gROOT->ProcessLine(cmd.Data());
7038 } else {
7039 TAxis* xAxis = fH->GetXaxis();
7040 TAxis* yAxis = fH->GetYaxis();
7041 TAxis* zAxis = fH->GetZaxis();
7042 Double_t xmin = xAxis->GetXmin();
7043 Double_t xmax = xAxis->GetXmax();
7044 Double_t ymin = yAxis->GetXmin();
7045 Double_t ymax = yAxis->GetXmax();
7046 Double_t zmin = zAxis->GetXmin();
7047 Double_t zmax = zAxis->GetXmax();
7048 view->SetRange(xmin, ymin, zmin, xmax, ymax, zmax); // Set the axis limits (Xmin, Ymin, Zmin, Xmax, Ymax, Zmax)
7049 }
7050
7051 if (Hoption.Same) return;
7052
7053 // Draw axis
7054 view->SetOutlineToCube();
7055 TSeqCollection *ol = view->GetOutline();
7056 if (ol && Hoption.BackBox && Hoption.FrontBox) ol->Paint(option);
7058
7059 if (!Hoption.Axis && !Hoption.Same) {
7060 TGaxis axis;
7061 PaintLegoAxis(&axis, 90);
7062 }
7063
7064 // Draw palette. In case of 4D plot with TTree::Draw() the palette should
7065 // be painted with the option colz.
7066 if (fH->GetDrawOption() && strstr(opt,"colz")) {
7067 Int_t ndiv = fH->GetContour();
7068 if (ndiv == 0 ) {
7069 ndiv = gStyle->GetNumberContours();
7070 fH->SetContour(ndiv);
7071 }
7072 PaintPalette();
7073 }
7074
7075 // Draw title
7076 PaintTitle();
7077
7078 //Draw stats and fit results
7079 TF1 *fit = nullptr;
7080 TIter next(fFunctions);
7081 while (auto obj = next()) {
7082 if (obj->InheritsFrom(TF1::Class())) {
7083 fit = (TF1*)obj;
7084 break;
7085 }
7086 }
7087 if ((Hoption.Same%10) != 1) {
7088 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7090 }
7091 }
7092
7093}
7094
7095////////////////////////////////////////////////////////////////////////////////
7096/// Compute histogram parameters used by the drawing routines.
7097
7099{
7100
7101 if (fH->GetDimension() > 1 || Hoption.Lego || Hoption.Surf) return 1;
7102
7103 Int_t i;
7104 static const char *where = "PaintInit";
7106 Int_t maximum = 0;
7107 Int_t minimum = 0;
7108 if (fH->GetMaximumStored() != -1111) maximum = 1;
7109 if (fH->GetMinimumStored() != -1111) minimum = 1;
7110
7111 // Compute X axis parameters
7112
7113 Int_t last = fXaxis->GetLast();
7114 Int_t first = fXaxis->GetFirst();
7117 Hparam.xlast = last;
7118 Hparam.xfirst = first;
7121
7122 // if log scale in X, replace xmin,max by the log
7123 if (Hoption.Logx) {
7124 if (Hparam.xmax<=0) {
7125 Error(where, "cannot set X axis to log scale");
7126 return 0;
7127 }
7128 if (Hparam.xlowedge <=0 ) {
7129 if (Hoption.Same) {
7130 TH1* h1 = nullptr;
7131 TObject *obj;
7132 TIter next(gPad->GetListOfPrimitives());
7133 while ((obj = (TObject *)next())) {
7134 if (obj->InheritsFrom(TH1::Class())) { h1 = (TH1*)(obj) ; break; }
7135 if (obj->InheritsFrom(THStack::Class())) { h1 = ((THStack*)(obj))->GetHistogram() ; break; }
7136 if (obj->InheritsFrom(TGraph::Class())) { h1 = ((TGraph*)(obj))->GetHistogram() ; break; }
7137 if (obj->InheritsFrom(TMultiGraph::Class())) { h1 = ((TMultiGraph*)(obj))->GetHistogram(); break; }
7138 if (obj->InheritsFrom(TGraph2D::Class())) { h1 = ((TGraph2D*)(obj))->GetHistogram(); break; }
7139 if (obj->InheritsFrom(TF1::Class())) { h1 = ((TF1*)(obj))->GetHistogram(); break; }
7140 }
7141 if (h1) {
7143 } else {
7144 Error(where, "undefined user's coordinates. Cannot use option SAME");
7145 return 0;
7146 }
7147 } else {
7148 for (i=first; i<=last; i++) {
7149 Double_t binLow = fXaxis->GetBinLowEdge(i);
7150 if (binLow>0) {
7151 Hparam.xlowedge = binLow;
7152 break;
7153 }
7154 if (binLow == 0 && fH->GetBinContent(i) !=0) {
7155 Hparam.xlowedge = fXaxis->GetBinUpEdge(i)*0.001;
7156 break;
7157 }
7158 }
7159 if (Hparam.xlowedge<=0) {
7160 Error(where, "cannot set X axis to log scale");
7161 return 0;
7162 }
7163 }
7165 }
7170 if (Hparam.xlast > last) Hparam.xlast = last;
7171 if (Hparam.xfirst < first) Hparam.xfirst = first;
7172 }
7173
7174 // Compute Y axis parameters
7175 Double_t bigp = TMath::Power(10,32);
7176 Double_t ymax = -bigp;
7177 Double_t ymin = bigp;
7178 Double_t c1, e1;
7179 Double_t xv[1];
7180 Double_t fval;
7181 TObject *f;
7182 TF1 *f1;
7183 Double_t allchan = 0;
7184 Int_t nonNullErrors = 0;
7185 TIter next(fFunctions);
7186 for (i=first; i<=last;i++) {
7187 c1 = fH->GetBinContent(i);
7189 if (Hoption.Logy) {
7190 if (c1 > 0) ymin = TMath::Min(ymin,c1);
7191 } else {
7193 }
7194 if (Hoption.Error) {
7196 e1 = fH->GetBinError(i);
7197 else
7198 e1 = fH->GetBinErrorUp(i);
7199 if (e1 > 0) nonNullErrors++;
7202 e1 = fH->GetBinErrorLow(i);
7203
7204 if (Hoption.Logy) {
7205 if (c1-e1>0.01*TMath::Abs(c1)) ymin = TMath::Min(ymin,c1-e1);
7206 } else {
7208 }
7209 }
7210 if (Hoption.Func) {
7211 xv[0] = fXaxis->GetBinCenter(i);
7212 while ((f = (TObject*) next())) {
7213 if (f->IsA() == TF1::Class()) {
7214 f1 = (TF1*)f;
7215 if (xv[0] < f1->GetXmin() || xv[0] > f1->GetXmax()) continue;
7216 fval = f1->Eval(xv[0],0,0);
7217 if (f1->GetMaximumStored() != -1111) fval = TMath::Min(f1->GetMaximumStored(), fval);
7219 if (Hoption.Logy) {
7220 if (c1 > 0 && fval > 0.3*c1) ymin = TMath::Min(ymin,fval);
7221 }
7222 }
7223 }
7224 next.Reset();
7225 }
7226 allchan += c1;
7227 }
7228 if (!nonNullErrors) {
7229 if (Hoption.Error) {
7230 if (!Hoption.Mark && !Hoption.Line && !Hoption.Star && !Hoption.Curve) Hoption.Hist = 2;
7231 Hoption.Error=0;
7232 }
7233 }
7234
7235
7236 // Take into account maximum , minimum
7237
7238 if (Hoption.Logy && ymin <= 0) {
7239 if (ymax >= 1) ymin = TMath::Max(.005,ymax*1e-10);
7240 else ymin = 0.001*ymax;
7241 }
7242
7243 Double_t xm = ymin;
7244 if (maximum) ymax = fH->GetMaximumStored();
7245 if (minimum) xm = fH->GetMinimumStored();
7246 if (Hoption.Logy && xm < 0) {
7247 Error(where, "log scale requested with a negative argument (%f)", xm);
7248 return 0;
7249 } else if (Hoption.Logy && xm>=0 && ymax==0) { // empty histogram in log scale
7250 ymin = 0.01;
7251 ymax = 10.;
7252 } else {
7253 ymin = xm;
7254 }
7255
7256 if (ymin >= ymax) {
7257 if (Hoption.Logy) {
7258 if (ymax > 0) ymin = 0.001*ymax;
7259 else {
7260 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", ymax);
7261 return 0;
7262 }
7263 }
7264 else {
7265 if (ymin > 0) {
7266 ymin = 0;
7267 ymax *= 2;
7268 } else if (ymin < 0) {
7269 ymax = 0;
7270 ymin *= 2;
7271 } else {
7272 ymin = 0;
7273 ymax = 1;
7274 }
7275 }
7276 }
7277
7278 // In some cases, mainly because of precision issues, ymin and ymax could almost equal.
7279 if (TMath::AreEqualRel(ymin,ymax,1E-15)) {
7280 ymin = ymin*(1-1E-14);
7281 ymax = ymax*(1+1E-14);
7282 }
7283
7284 // take into account normalization factor
7285 Hparam.allchan = allchan;
7286 Double_t factor = allchan;
7287 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
7288 if (allchan) factor /= allchan;
7289 if (factor == 0) factor = 1;
7290 Hparam.factor = factor;
7291 ymax = factor*ymax;
7292 ymin = factor*ymin;
7293 //just in case the norm factor is negative
7294 // this may happen with a positive norm factor and a negative integral !
7295 if (ymax < ymin) {
7296 Double_t temp = ymax;
7297 ymax = ymin;
7298 ymin = temp;
7299 }
7300
7301 // For log scales, histogram coordinates are LOG10(ymin) and
7302 // LOG10(ymax). Final adjustment (if not option "Same"
7303 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
7304 // Maximum and Minimum are not defined.
7305 if (Hoption.Logy) {
7306 if (ymin <=0 || ymax <=0) {
7307 Error(where, "Cannot set Y axis to log scale");
7308 return 0;
7309 }
7311 if (!minimum) ymin += TMath::Log10(0.5);
7313 if (!maximum) ymax += TMath::Log10(2*(0.9/0.95));
7314 if (!Hoption.Same) {
7315 Hparam.ymin = ymin;
7316 Hparam.ymax = ymax;
7317 }
7318 return 1;
7319 }
7320
7321 // final adjustment of ymin for linear scale.
7322 // if minimum is not set , then ymin is set to zero if >0
7323 // or to ymin - margin if <0.
7324 if (!minimum) {
7325 if (Hoption.MinimumZero) {
7326 if (ymin >= 0) ymin = 0;
7327 else ymin -= yMARGIN*(ymax-ymin);
7328 } else {
7330 if (ymin >= 0 && (ymin-dymin <= 0)) ymin = 0;
7331 else ymin -= dymin;
7332 }
7333 }
7334
7335 // final adjustment of YMAXI for linear scale (if not option "Same"):
7336 // decrease histogram height to MAX% of allowed height if HMAXIM
7337 // has not been called.
7338 if (!maximum) {
7339 ymax += yMARGIN*(ymax-ymin);
7340 }
7341
7342 Hparam.ymin = ymin;
7343 Hparam.ymax = ymax;
7344 return 1;
7345}
7346
7347////////////////////////////////////////////////////////////////////////////////
7348/// Compute histogram parameters used by the drawing routines for a rotated pad.
7349
7351{
7352
7353 static const char *where = "PaintInitH";
7355 Int_t maximum = 0;
7356 Int_t minimum = 0;
7357 if (fH->GetMaximumStored() != -1111) maximum = 1;
7358 if (fH->GetMinimumStored() != -1111) minimum = 1;
7359
7360 // Compute X axis parameters
7361
7362 Int_t last = fXaxis->GetLast();
7363 Int_t first = fXaxis->GetFirst();
7366 Hparam.xlast = last;
7367 Hparam.xfirst = first;
7370
7371 // if log scale in Y, replace ymin,max by the log
7372 if (Hoption.Logy) {
7373 if (Hparam.xlowedge <=0 ) {
7376 }
7377 if (Hparam.ymin <=0 || Hparam.ymax <=0) {
7378 Error(where, "cannot set Y axis to log scale");
7379 return 0;
7380 }
7385 if (Hparam.xlast > last) Hparam.xlast = last;
7386 }
7387
7388 // Compute Y axis parameters
7389 Double_t bigp = TMath::Power(10,32);
7390 Double_t xmax = -bigp;
7391 Double_t xmin = bigp;
7392 Double_t c1, e1;
7393 Double_t xv[1];
7394 Double_t fval;
7395 Int_t i;
7396 TObject *f;
7397 TF1 *f1;
7398 Double_t allchan = 0;
7399 TIter next(fFunctions);
7400 for (i=first; i<=last;i++) {
7401 c1 = fH->GetBinContent(i);
7404 if (Hoption.Error) {
7405 e1 = fH->GetBinError(i);
7408 }
7409 if (Hoption.Func) {
7410 xv[0] = fXaxis->GetBinCenter(i);
7411 while ((f = (TObject*) next())) {
7412 if (f->IsA() == TF1::Class()) {
7413 f1 = (TF1*)f;
7414 if (xv[0] < f1->GetXmin() || xv[0] > f1->GetXmax()) continue;
7415 fval = f1->Eval(xv[0],0,0);
7417 if (Hoption.Logy) {
7418 if (fval > 0.3*c1) xmin = TMath::Min(xmin,fval);
7419 }
7420 }
7421 }
7422 next.Reset();
7423 }
7424 allchan += c1;
7425 }
7426
7427 // Take into account maximum , minimum
7428
7429 if (Hoption.Logx && xmin <= 0) {
7430 if (xmax >= 1) xmin = TMath::Max(.5,xmax*1e-10);
7431 else xmin = 0.001*xmax;
7432 }
7433 Double_t xm = xmin;
7434 if (maximum) xmax = fH->GetMaximumStored();
7435 if (minimum) xm = fH->GetMinimumStored();
7436 if (Hoption.Logx && xm <= 0) {
7437 Error(where, "log scale requested with zero or negative argument (%f)", xm);
7438 return 0;
7439 }
7440 else xmin = xm;
7441 if (xmin >= xmax) {
7442 if (Hoption.Logx) {
7443 if (xmax > 0) xmin = 0.001*xmax;
7444 else {
7445 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", xmax);
7446 return 0;
7447 }
7448 }
7449 else {
7450 if (xmin > 0) {
7451 xmin = 0;
7452 xmax *= 2;
7453 } else if (xmin < 0) {
7454 xmax = 0;
7455 xmin *= 2;
7456 } else {
7457 xmin = 0;
7458 xmax = 1;
7459 }
7460 }
7461 }
7462
7463 // take into account normalization factor
7464 Hparam.allchan = allchan;
7465 Double_t factor = allchan;
7466 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
7467 if (allchan) factor /= allchan;
7468 if (factor == 0) factor = 1;
7469 Hparam.factor = factor;
7470 xmax = factor*xmax;
7471 xmin = factor*xmin;
7472
7473 // For log scales, histogram coordinates are LOG10(ymin) and
7474 // LOG10(ymax). Final adjustment (if not option "Same"
7475 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
7476 // Maximum and Minimum are not defined.
7477 if (Hoption.Logx) {
7478 if (xmin <=0 || xmax <=0) {
7479 Error(where, "Cannot set Y axis to log scale");
7480 return 0;
7481 }
7483 if (!minimum) xmin += TMath::Log10(0.5);
7485 if (!maximum) xmax += TMath::Log10(2*(0.9/0.95));
7486 if (!Hoption.Same) {
7487 Hparam.xmin = xmin;
7488 Hparam.xmax = xmax;
7489 }
7490 return 1;
7491 }
7492
7493 // final adjustment of ymin for linear scale.
7494 // if minimum is not set , then ymin is set to zero if >0
7495 // or to ymin - margin if <0.
7496 if (!minimum) {
7497 if (xmin >= 0) xmin = 0;
7498 else xmin -= yMARGIN*(xmax-xmin);
7499 }
7500
7501 // final adjustment of YMAXI for linear scale (if not option "Same"):
7502 // decrease histogram height to MAX% of allowed height if HMAXIM
7503 // has not been called.
7504 if (!maximum) {
7505 xmax += yMARGIN*(xmax-xmin);
7506 }
7507 Hparam.xmin = xmin;
7508 Hparam.xmax = xmax;
7509 return 1;
7510}
7511
7512////////////////////////////////////////////////////////////////////////////////
7513/// [Control function to draw a 3D histogram with boxes.](\ref HP25)
7514
7516{
7517 // Predefined box structure
7518 Double_t wxyz[8][3] = { {-1,-1,-1}, {1,-1,-1}, {1,1,-1}, {-1,1,-1},
7519 {-1,-1, 1}, {1,-1, 1}, {1,1, 1}, {-1,1, 1} };
7520 Int_t iface[6][4] = { {0,3,2,1}, {4,5,6,7},
7521 {0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7} };
7522
7523 // Define dimensions of world space
7524 TAxis *xaxis = fH->GetXaxis();
7525 TAxis *yaxis = fH->GetYaxis();
7526 TAxis *zaxis = fH->GetZaxis();
7527
7528 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7529 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7530 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7531 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7532 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7533 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7534
7535 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7536
7537 // Set view
7538 TView *view = gPad ? gPad->GetView() : nullptr;
7539 if (!view) {
7540 Error("PaintH3", "no TView in current pad");
7541 return;
7542 }
7543 Double_t thedeg = 90 - gPad->GetTheta();
7544 Double_t phideg = -90 - gPad->GetPhi();
7545 Double_t psideg = view->GetPsi();
7546 Int_t irep;
7547 view->SetView(phideg, thedeg, psideg, irep);
7548
7549 Int_t backcolor = gPad->GetFrameFillColor();
7550 view->PadRange(backcolor);
7551
7552 // Draw back surfaces of frame box
7553 fLego->InitMoveScreen(-1.1,1.1);
7554 if (Hoption.BackBox) {
7555 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
7557 fLego->BackBox(90);
7558 }
7559
7561
7562 // Define order of drawing
7563 Double_t *tnorm = view->GetTnorm();
7564 if (!tnorm) return;
7565 Int_t incrx = (tnorm[ 8] < 0.) ? -1 : +1;
7566 Int_t incry = (tnorm[ 9] < 0.) ? -1 : +1;
7567 Int_t incrz = (tnorm[10] < 0.) ? -1 : +1;
7568 Int_t ix1 = (incrx == +1) ? xaxis->GetFirst() : xaxis->GetLast();
7569 Int_t iy1 = (incry == +1) ? yaxis->GetFirst() : yaxis->GetLast();
7570 Int_t iz1 = (incrz == +1) ? zaxis->GetFirst() : zaxis->GetLast();
7571 Int_t ix2 = (incrx == +1) ? xaxis->GetLast() : xaxis->GetFirst();
7572 Int_t iy2 = (incry == +1) ? yaxis->GetLast() : yaxis->GetFirst();
7573 Int_t iz2 = (incrz == +1) ? zaxis->GetLast() : zaxis->GetFirst();
7574
7575 // Set graphic attributes (colour, style, etc.)
7580
7581 fH->SetFillStyle(1001);
7582 fH->TAttFill::Modify();
7583 fH->TAttLine::Modify();
7584 Int_t ncolors = gStyle->GetNumberOfColors();
7586
7587 // Create bin boxes and draw
7591
7592 Double_t pmin[3], pmax[3], sxyz[8][3];
7593 for (Int_t ix = ix1; ix !=ix2+incrx; ix += incrx) {
7594 pmin[0] = xaxis->GetBinLowEdge(ix);
7595 pmax[0] = xaxis->GetBinUpEdge(ix);
7596 for (Int_t iy = iy1; iy != iy2+incry; iy += incry) {
7597 pmin[1] = yaxis->GetBinLowEdge(iy);
7598 pmax[1] = yaxis->GetBinUpEdge(iy);
7599 for (Int_t iz = iz1; iz != iz2+incrz; iz += incrz) {
7600 pmin[2] = zaxis->GetBinLowEdge(iz);
7601 pmax[2] = zaxis->GetBinUpEdge(iz);
7602 Double_t w = fH->GetBinContent(fH->GetBin(ix,iy,iz));
7603 Bool_t neg = kFALSE;
7604 Int_t n = 5;
7605 if (w<0) {
7606 w = -w;
7607 neg = kTRUE;
7608 }
7609 if (w < wmin) continue;
7610 if (w > wmax) w = wmax;
7611 Double_t scale = (TMath::Power((w-wmin)/(wmax-wmin),1./3.))/2.;
7612 if (scale == 0) continue;
7613 for (Int_t i=0; i<3; ++i) {
7614 Double_t c = (pmax[i] + pmin[i])*0.5;
7615 Double_t d = (pmax[i] - pmin[i])*scale;
7616 for (Int_t k=0; k<8; ++k) { // set bin box vertices
7617 sxyz[k][i] = wxyz[k][i]*d + c;
7618 }
7619 }
7620 for (Int_t k=0; k<8; ++k) { // transform to normalized space
7621 view->WCtoNDC(&sxyz[k][0],&sxyz[k][0]);
7622 }
7623 Double_t x[8], y[8]; // draw bin box faces
7624 for (Int_t k=0; k<6; ++k) {
7625 for (Int_t i=0; i<4; ++i) {
7626 Int_t iv = iface[k][i];
7627 x[i] = sxyz[iv][0];
7628 y[i] = sxyz[iv][1];
7629 }
7630 x[4] = x[0] ; y[4] = y[0];
7631 if (neg) {
7632 x[5] = x[2] ; y[5] = y[2];
7633 x[6] = x[3] ; y[6] = y[3];
7634 x[7] = x[1] ; y[7] = y[1];
7635 n = 8;
7636 } else {
7637 n = 5;
7638 }
7639 Double_t z = (x[2]-x[0])*(y[3]-y[1]) - (y[2]-y[0])*(x[3]-x[1]);
7640 if (z <= 0.) continue;
7641 if (iopt == 2) {
7642 theColor = ncolors*((w-wmin)/(wmax-wmin)) -1;
7644 } else {
7645 if (k == 3 || k == 5) {
7647 } else if (k == 0 || k == 1) {
7649 } else {
7651 }
7652 }
7653 fH->TAttFill::Modify();
7654 gPad->PaintFillArea(4, x, y);
7655 if (iopt != 3)gPad->PaintPolyLine(n, x, y);
7656 }
7657 }
7658 }
7659 }
7660
7661 // Draw front surfaces of frame box
7662 if (Hoption.FrontBox) fLego->FrontBox(90);
7663
7664 // Draw axis and title
7665 if (!Hoption.Axis && !Hoption.Same) {
7666 TGaxis axis;
7667 PaintLegoAxis(&axis, 90);
7668 }
7669 PaintTitle();
7670
7671 // Draw palette. if needed.
7672 if (Hoption.Zscale) {
7673 Int_t ndiv = fH->GetContour();
7674 if (ndiv == 0 ) {
7675 ndiv = gStyle->GetNumberContours();
7676 fH->SetContour(ndiv);
7677 }
7678 PaintPalette();
7679 }
7680
7681 //Draw stats and fit results
7682 TF1 *fit = nullptr;
7683 TIter next(fFunctions);
7684 while (auto obj = next()) {
7685 if (obj->InheritsFrom(TF1::Class())) {
7686 fit = (TF1*)obj;
7687 break;
7688 }
7689 }
7690 if ((Hoption.Same%10) != 1) {
7691 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7693 }
7694 }
7695
7696 fLego.reset();
7697
7700 fH->TAttFill::Modify();
7701}
7702
7703////////////////////////////////////////////////////////////////////////////////
7704/// [Control function to draw a 3D histogram with boxes.](\ref HP25)
7705
7707{
7708 // Predefined box structure
7709 Double_t wxyz[8][3] = {
7710 {-1,-1,-1}, {1,-1,-1}, {1,1,-1}, {-1,1,-1}, // bottom vertices
7711 {-1,-1, 1}, {1,-1, 1}, {1,1, 1}, {-1,1, 1} // top vertices
7712 };
7713 Int_t iface[6][4] = {
7714 {0,3,2,1}, {4,5,6,7}, // bottom and top faces
7715 {0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7} // side faces
7716 };
7717 Double_t normal[6][3] = {
7718 {0,0,-1}, {0,0,1}, // Z-, Z+
7719 {0,-1,0}, {1,0,0}, {0,1,0}, {-1,0,0} // Y-, X+, Y+, X-
7720 };
7721
7722 // Define dimensions of world space
7723 TAxis *xaxis = fH->GetXaxis();
7724 TAxis *yaxis = fH->GetYaxis();
7725 TAxis *zaxis = fH->GetZaxis();
7726
7727 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7728 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7729 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7730 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7731 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7732 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7733
7734 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7735
7736 // Set view
7737 TView *view = gPad ? gPad->GetView() : nullptr;
7738 if (!view) {
7739 Error("PaintH3", "no TView in current pad");
7740 return;
7741 }
7742 Double_t thedeg = 90 - gPad->GetTheta();
7743 Double_t phideg = -90 - gPad->GetPhi();
7744 Double_t psideg = view->GetPsi();
7745 Int_t irep;
7746 view->SetView(phideg, thedeg, psideg, irep);
7747
7748 Int_t backcolor = gPad->GetFrameFillColor();
7749 view->PadRange(backcolor);
7750
7751 // Draw front surfaces of frame box
7752 if (Hoption.FrontBox) {
7753 fLego->InitMoveScreen(-1.1,1.1);
7755 }
7756
7757 // Initialize hidden line removal algorithm "raster screen"
7758 fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
7759
7760 // Define order of drawing
7761 Double_t *tnorm = view->GetTnorm();
7762 if (!tnorm) return;
7763 Int_t incrx = (tnorm[ 8] < 0.) ? +1 : -1;
7764 Int_t incry = (tnorm[ 9] < 0.) ? +1 : -1;
7765 Int_t incrz = (tnorm[10] < 0.) ? +1 : -1;
7766 Int_t ix1 = (incrx == +1) ? xaxis->GetFirst() : xaxis->GetLast();
7767 Int_t iy1 = (incry == +1) ? yaxis->GetFirst() : yaxis->GetLast();
7768 Int_t iz1 = (incrz == +1) ? zaxis->GetFirst() : zaxis->GetLast();
7769 Int_t ix2 = (incrx == +1) ? xaxis->GetLast() : xaxis->GetFirst();
7770 Int_t iy2 = (incry == +1) ? yaxis->GetLast() : yaxis->GetFirst();
7771 Int_t iz2 = (incrz == +1) ? zaxis->GetLast() : zaxis->GetFirst();
7772
7773 // Set line attributes (colour, style, etc.)
7774 fH->TAttLine::Modify();
7775
7776 // Create bin boxes and draw
7777 const Int_t NTMAX = 100;
7778 Double_t tt[NTMAX][2];
7782 Double_t pmin[3], pmax[3], sxyz[8][3], pp[4][2];
7783 for (Int_t ix = ix1; ix !=ix2+incrx; ix += incrx) {
7784 pmin[0] = xaxis->GetBinLowEdge(ix);
7785 pmax[0] = xaxis->GetBinUpEdge(ix);
7786 for (Int_t iy = iy1; iy != iy2+incry; iy += incry) {
7787 pmin[1] = yaxis->GetBinLowEdge(iy);
7788 pmax[1] = yaxis->GetBinUpEdge(iy);
7789 for (Int_t iz = iz1; iz != iz2+incrz; iz += incrz) {
7790 pmin[2] = zaxis->GetBinLowEdge(iz);
7791 pmax[2] = zaxis->GetBinUpEdge(iz);
7792 Double_t w = fH->GetBinContent(fH->GetBin(ix,iy,iz));
7793 Bool_t neg = kFALSE;
7794 if (w<0) {
7795 w = -w;
7796 neg = kTRUE;
7797 }
7798 if (w < wmin) continue;
7799 if (w > wmax) w = wmax;
7800 Double_t scale = (TMath::Power((w-wmin)/(wmax-wmin),1./3.))/2.;
7801 if (scale == 0) continue;
7802 for (Int_t i=0; i<3; ++i) {
7803 Double_t c = (pmax[i] + pmin[i])*0.5;
7804 Double_t d = (pmax[i] - pmin[i])*scale;
7805 for (Int_t k=0; k<8; ++k) { // set bin box vertices
7806 sxyz[k][i] = wxyz[k][i]*d + c;
7807 }
7808 }
7809 for (Int_t k=0; k<8; ++k) { // transform to normalized space
7810 view->WCtoNDC(&sxyz[k][0],&sxyz[k][0]);
7811 }
7812 for (Int_t k=0; k<6; ++k) { // draw box faces
7813 Double_t zn;
7814 view->FindNormal(normal[k][0], normal[k][1], normal[k][2], zn);
7815 if (zn <= 0) continue;
7816 for (Int_t i=0; i<4; ++i) {
7817 Int_t ip = iface[k][i];
7818 pp[i][0] = sxyz[ip][0];
7819 pp[i][1] = sxyz[ip][1];
7820 }
7821 for (Int_t i=0; i<4; ++i) {
7822 Int_t i1 = i;
7823 Int_t i2 = (i == 3) ? 0 : i + 1;
7824 Int_t nt;
7825 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7826 Double_t xdel = pp[i2][0] - pp[i1][0];
7827 Double_t ydel = pp[i2][1] - pp[i1][1];
7828 Double_t x[2], y[2];
7829 for (Int_t it = 0; it < nt; ++it) {
7830 x[0] = pp[i1][0] + xdel*tt[it][0];
7831 y[0] = pp[i1][1] + ydel*tt[it][0];
7832 x[1] = pp[i1][0] + xdel*tt[it][1];
7833 y[1] = pp[i1][1] + ydel*tt[it][1];
7834 gPad->PaintPolyLine(2, x, y);
7835 }
7836 }
7837 if (neg) {
7838 Int_t i1 = 0;
7839 Int_t i2 = 2;
7840 Int_t nt;
7841 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7842 Double_t xdel = pp[i2][0] - pp[i1][0];
7843 Double_t ydel = pp[i2][1] - pp[i1][1];
7844 Double_t x[2], y[2];
7845 for (Int_t it = 0; it < nt; ++it) {
7846 x[0] = pp[i1][0] + xdel*tt[it][0];
7847 y[0] = pp[i1][1] + ydel*tt[it][0];
7848 x[1] = pp[i1][0] + xdel*tt[it][1];
7849 y[1] = pp[i1][1] + ydel*tt[it][1];
7850 gPad->PaintPolyLine(2, x, y);
7851 }
7852 i1 = 1;
7853 i2 = 3;
7854 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7855 xdel = pp[i2][0] - pp[i1][0];
7856 ydel = pp[i2][1] - pp[i1][1];
7857 for (Int_t it = 0; it < nt; ++it) {
7858 x[0] = pp[i1][0] + xdel*tt[it][0];
7859 y[0] = pp[i1][1] + ydel*tt[it][0];
7860 x[1] = pp[i1][0] + xdel*tt[it][1];
7861 y[1] = pp[i1][1] + ydel*tt[it][1];
7862 gPad->PaintPolyLine(2, x, y);
7863 }
7864 }
7865 fLego->FillPolygonBorder(4, &pp[0][0]); // update raster screen
7866 }
7867 }
7868 }
7869 }
7870
7871 // Draw frame box
7872 if (Hoption.BackBox) {
7873 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
7875 fLego->BackBox(90);
7876 }
7877
7878 if (Hoption.FrontBox) fLego->FrontBox(90);
7879
7880 // Draw axis and title
7881 if (!Hoption.Axis && !Hoption.Same) {
7882 TGaxis axis;
7883 PaintLegoAxis(&axis, 90);
7884 }
7885 PaintTitle();
7886
7887 //Draw stats and fit results
7888 TF1 *fit = nullptr;
7889 TIter next(fFunctions);
7890 while (auto obj = next()) {
7891 if (obj->InheritsFrom(TF1::Class())) {
7892 fit = (TF1*)obj;
7893 break;
7894 }
7895 }
7896 if ((Hoption.Same%10) != 1) {
7897 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7899 }
7900 }
7901
7902 fLego.reset();
7903}
7904
7905////////////////////////////////////////////////////////////////////////////////
7906/// [Control function to draw a 3D histogram with Iso Surfaces.](\ref HP25)
7907
7909{
7910
7911 const Double_t ydiff = 1;
7912 const Double_t yligh1 = 10;
7913 const Double_t qa = 0.15;
7914 const Double_t qd = 0.15;
7915 const Double_t qs = 0.8;
7917 Int_t i, irep;
7918 Int_t nbcol = 28;
7919 Int_t icol1 = 201;
7920 Int_t ic1 = icol1;
7921 Int_t ic2 = ic1+nbcol;
7922 Int_t ic3 = ic2+nbcol;
7923
7924 TAxis *xaxis = fH->GetXaxis();
7925 TAxis *yaxis = fH->GetYaxis();
7926 TAxis *zaxis = fH->GetZaxis();
7927
7928 Int_t nx = fH->GetNbinsX();
7929 Int_t ny = fH->GetNbinsY();
7930 Int_t nz = fH->GetNbinsZ();
7931
7932 std::vector<Double_t> x(nx);
7933 std::vector<Double_t> y(ny);
7934 std::vector<Double_t> z(nz);
7935
7936 for (i=0; i<nx; i++) x[i] = xaxis->GetBinCenter(i+1);
7937 for (i=0; i<ny; i++) y[i] = yaxis->GetBinCenter(i+1);
7938 for (i=0; i<nz; i++) z[i] = zaxis->GetBinCenter(i+1);
7939
7940 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7941 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7942 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7943 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7944 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7945 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7946
7947 Double_t s[3];
7948 s[0] = fH->GetSumOfWeights()/(fH->GetNbinsX()*fH->GetNbinsY()*fH->GetNbinsZ());
7949 s[1] = 0.5*s[0];
7950 s[2] = 1.5*s[0];
7951
7952 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7953
7954 TView *view = gPad ? gPad->GetView() : nullptr;
7955 if (!view) {
7956 Error("PaintH3Iso", "no TView in current pad");
7957 return;
7958 }
7959 Double_t thedeg = 90 - gPad->GetTheta();
7960 Double_t phideg = -90 - gPad->GetPhi();
7961 Double_t psideg = view->GetPsi();
7962 view->SetView(phideg, thedeg, psideg, irep);
7963
7964 Int_t backcolor = gPad->GetFrameFillColor();
7965 if (Hoption.System != kCARTESIAN) backcolor = 0;
7966 view->PadRange(backcolor);
7967
7968 Double_t dcol = 0.5/Double_t(nbcol);
7969 TColor *colref = gROOT->GetColor(fH->GetFillColor());
7970 if (!colref) {
7971 return;
7972 }
7973 Float_t r, g, b, hue, light, satur;
7974 colref->GetRGB(r,g,b);
7976 TColor *acol;
7977 for (Int_t col=0;col<nbcol;col++) {
7978 acol = gROOT->GetColor(col+icol1);
7979 TColor::HLStoRGB(hue, .4+col*dcol, satur, r, g, b);
7980 if (acol) acol->SetRGB(r, g, b);
7981 }
7982
7983 fLego->InitMoveScreen(-1.1,1.1);
7984
7985 if (Hoption.BackBox) {
7986 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
7988 fLego->BackBox(90);
7989 }
7990
7991 fLego->LightSource(0, ydiff, 0, 0, 0, irep);
7992 fLego->LightSource(1, yligh1, 1, 1, 1, irep);
7993 fLego->SurfaceProperty(qa, qd, qs, 1, irep);
7994 fmin = ydiff*qa;
7995 fmax = ydiff*qa + (yligh1+0.1)*(qd+qs);
7996 fLego->SetIsoSurfaceParameters(fmin, fmax, nbcol, ic1, ic2, ic3);
7997
7998 fLego->IsoSurface(1, s, nx, ny, nz, x.data(), y.data(), z.data(), "BF");
7999
8000 if (Hoption.FrontBox) {
8001 fLego->InitMoveScreen(-1.1,1.1);
8003 fLego->FrontBox(90);
8004 }
8005 if (!Hoption.Axis && !Hoption.Same) {
8006 TGaxis axis;
8007 PaintLegoAxis(&axis, 90);
8008 }
8009
8010 PaintTitle();
8011
8012 //Draw stats and fit results
8013 TF1 *fit = nullptr;
8014 TIter next(fFunctions);
8015 while (auto obj = next()) {
8016 if (obj->InheritsFrom(TF1::Class())) {
8017 fit = (TF1*)obj;
8018 break;
8019 }
8020 }
8021 if ((Hoption.Same%10) != 1) {
8022 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
8024 }
8025 }
8026
8027 fLego.reset();
8028}
8029
8030////////////////////////////////////////////////////////////////////////////////
8031/// [Control function to draw a 2D histogram as a lego plot.](\ref HP17)
8032
8034{
8035
8036 Int_t raster = 1;
8037 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
8038 Int_t nx = Hparam.xlast - Hparam.xfirst + 1;
8039 Int_t ny = Hparam.ylast - Hparam.yfirst + 1;
8040 Double_t zmin = Hparam.zmin;
8041 Double_t zmax = Hparam.zmax;
8046 Double_t dangle = 10*3.141592/180; //Delta angle for Rapidity option
8047 Double_t deltaz = TMath::Abs(zmin);
8048 if (deltaz == 0) deltaz = 1;
8049 if (zmin >= zmax) {
8050 zmin -= 0.5*deltaz;
8051 zmax += 0.5*deltaz;
8052 }
8053 Double_t z1c = zmin;
8054 Double_t z2c = zmin + (zmax-zmin)*(1+gStyle->GetHistTopMargin());
8055
8056 // Compute the lego limits and instantiate a lego object
8057 fXbuf[0] = -1;
8058 fYbuf[0] = 1;
8059 fXbuf[1] = -1;
8060 fYbuf[1] = 1;
8061 if (Hoption.System == kPOLAR) {
8062 fXbuf[2] = z1c;
8063 fYbuf[2] = z2c;
8064 } else if (Hoption.System == kCYLINDRICAL) {
8065 if (Hoption.Logy) {
8066 if (ylab1 > 0) fXbuf[2] = TMath::Log10(ylab1);
8067 else fXbuf[2] = 0;
8068 if (ylab2 > 0) fYbuf[2] = TMath::Log10(ylab2);
8069 else fYbuf[2] = 0;
8070 } else {
8071 fXbuf[2] = ylab1;
8072 fYbuf[2] = ylab2;
8073 }
8074 z1c = 0; z2c = 1;
8075 } else if (Hoption.System == kSPHERICAL) {
8076 fXbuf[2] = -1;
8077 fYbuf[2] = 1;
8078 z1c = 0; z2c = 1;
8079 } else if (Hoption.System == kRAPIDITY) {
8080 fXbuf[2] = -1/TMath::Tan(dangle);
8081 fYbuf[2] = 1/TMath::Tan(dangle);
8082 } else {
8083 fXbuf[0] = xlab1;
8084 fYbuf[0] = xlab2;
8085 fXbuf[1] = ylab1;
8086 fYbuf[1] = ylab2;
8087 fXbuf[2] = z1c;
8088 fYbuf[2] = z2c;
8089 raster = 0;
8090 }
8091
8092 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data(), Hoption.System);
8093
8094 Int_t nids = -1;
8095 TH1 * hid = nullptr;
8096 Color_t colormain = -1, colordark = -1;
8098
8099 // LEGO3 is like LEGO1 except that the black lines around each lego are not drawn.
8100 if (Hoption.Lego == 13) {
8101 Hoption.Lego = 11;
8102 fLego->SetMesh(0);
8103 }
8104 // LEGO4 is like LEGO1 except no shadows are drawn.
8105 if (Hoption.Lego == 14) {
8106 Hoption.Lego = 11;
8108 }
8109
8110 // Initialize the levels on the Z axis
8111 Int_t ndiv = fH->GetContour();
8112 if (ndiv == 0 ) {
8113 ndiv = gStyle->GetNumberContours();
8114 fH->SetContour(ndiv);
8115 }
8116 Int_t ndivz = TMath::Abs(ndiv);
8117 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
8118
8119 // Initialize colors
8120 if (!fStack) {
8121 fLego->SetEdgeAtt(fH->GetLineColor(),fH->GetLineStyle(),fH->GetLineWidth(),0);
8122 } else {
8123 for (Int_t id=0;id<=fStack->GetSize();id++) {
8124 hid = (TH1*)fStack->At((id==0)?id:id-1);
8125 fLego->SetEdgeAtt(hid->GetLineColor(),hid->GetLineStyle(),hid->GetLineWidth(),id);
8126 }
8127 }
8128
8129 if (Hoption.Lego == 11) {
8130 nids = 1;
8131 if (fStack) nids = fStack->GetSize();
8132 hid = fH;
8133 for (Int_t id=0;id<=nids;id++) {
8134 if (id > 0 && fStack) hid = (TH1*)fStack->At(id-1);
8135 colormain = hid->GetFillColor();
8136 if (colormain == 1) colormain = 17; //avoid drawing with black
8138 else colordark = colormain;
8139 fLego->SetColorMain(colormain,id);
8140 fLego->SetColorDark(colordark,id);
8141 if (id <= 1) fLego->SetColorMain(colormain,-1); // Set Bottom color
8142 if (id == nids) fLego->SetColorMain(colormain,99); // Set Top color
8143 }
8144 }
8145
8146 // Now ready to draw the lego plot
8147 Int_t irep = 0;
8148
8149 TView *view = gPad ? gPad->GetView() : nullptr;
8150 if (!view) {
8151 Error("PaintLego", "no TView in current pad");
8152 return;
8153 }
8154
8155 Double_t thedeg = 90 - gPad->GetTheta();
8156 Double_t phideg = -90 - gPad->GetPhi();
8157 Double_t psideg = view->GetPsi();
8158 view->SetView(phideg, thedeg, psideg, irep);
8159
8160 fLego->SetLineColor(kBlack); // zgrid color for lego1 & lego2
8161 fLego->SetFillStyle(fH->GetFillStyle());
8162
8163 // Set color/style for back box
8164 fLego->SetFillStyle(gPad->GetFrameFillStyle());
8165 fLego->SetFillColor(gPad->GetFrameFillColor());
8166 fLego->TAttFill::Modify();
8167
8168 Int_t backcolor = gPad->GetFrameFillColor();
8169 if (Hoption.System != kCARTESIAN) backcolor = 0;
8170 view->PadRange(backcolor);
8171
8172 fLego->SetFillStyle(fH->GetFillStyle());
8173 fLego->SetFillColor(fH->GetFillColor());
8174 fLego->TAttFill::Modify();
8175
8176 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
8177
8178 if (raster) fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
8179 else fLego->InitMoveScreen(-1.1,1.1);
8180
8181 if (Hoption.Lego == 19) {
8183 if (Hoption.BackBox) fLego->BackBox(90);
8184 if (Hoption.FrontBox) fLego->FrontBox(90);
8185 if (!Hoption.Axis) { TGaxis axis; PaintLegoAxis(&axis, 90); }
8186 return;
8187 }
8188
8189 if (Hoption.Lego == 11 || Hoption.Lego == 12) {
8192 fLego->BackBox(90);
8193 }
8194 }
8195
8196 if (Hoption.Lego == 12) DefineColorLevels(ndivz);
8197
8198 fLego->SetLegoFunction(&TPainter3dAlgorithms::LegoFunction);
8200 if (Hoption.Lego == 11) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode3);
8201 if (Hoption.Lego == 12) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode2);
8202 if (Hoption.System == kPOLAR) {
8203 if (Hoption.Lego == 1) fLego->LegoPolar(1,nx,ny,"FB");
8204 if (Hoption.Lego == 11) fLego->LegoPolar(1,nx,ny,"BF");
8205 if (Hoption.Lego == 12) fLego->LegoPolar(1,nx,ny,"BF");
8206 } else if (Hoption.System == kCYLINDRICAL) {
8207 if (Hoption.Lego == 1) fLego->LegoCylindrical(1,nx,ny,"FB");
8208 if (Hoption.Lego == 11) fLego->LegoCylindrical(1,nx,ny,"BF");
8209 if (Hoption.Lego == 12) fLego->LegoCylindrical(1,nx,ny,"BF");
8210 } else if (Hoption.System == kSPHERICAL) {
8211 if (Hoption.Lego == 1) fLego->LegoSpherical(0,1,nx,ny,"FB");
8212 if (Hoption.Lego == 11) fLego->LegoSpherical(0,1,nx,ny,"BF");
8213 if (Hoption.Lego == 12) fLego->LegoSpherical(0,1,nx,ny,"BF");
8214 } else if (Hoption.System == kRAPIDITY) {
8215 if (Hoption.Lego == 1) fLego->LegoSpherical(1,1,nx,ny,"FB");
8216 if (Hoption.Lego == 11) fLego->LegoSpherical(1,1,nx,ny,"BF");
8217 if (Hoption.Lego == 12) fLego->LegoSpherical(1,1,nx,ny,"BF");
8218 } else {
8219 if (Hoption.Lego == 1) {
8221 fLego->LegoCartesian(90,nx,ny,"FB");}
8222 if (Hoption.Lego == 11) fLego->LegoCartesian(90,nx,ny,"BF");
8223 if (Hoption.Lego == 12) fLego->LegoCartesian(90,nx,ny,"BF");
8224 }
8225
8226 if (Hoption.Lego == 1 || Hoption.Lego == 11) {
8229 fLego->BackBox(90);
8230 }
8231 }
8232 if (Hoption.System == kCARTESIAN) {
8233 fLego->InitMoveScreen(-1.1,1.1);
8235 if (Hoption.FrontBox) fLego->FrontBox(90);
8236 }
8237 if (!Hoption.Axis && !Hoption.Same) {
8238 TGaxis axis;
8239 PaintLegoAxis(&axis, 90);
8240 }
8242 fLego.reset();
8243}
8244
8245////////////////////////////////////////////////////////////////////////////////
8246/// Draw the axis for legos and surface plots.
8247
8249{
8250
8251 static Double_t epsil = 0.001;
8252
8255 Double_t r[24] /* was [3][8] */;
8256 Int_t ndivx, ndivy, ndivz, i;
8257 Double_t x1[3], x2[3], y1[3], y2[3], z1[3], z2[3], av[24] /* was [3][8] */;
8258 static char chopax[8], chopay[8], chopaz[8];
8259 Int_t ix1, ix2, iy1, iy2, iz1, iz2;
8260 Double_t rad;
8261
8262 TView *view = gPad ? gPad->GetView() : nullptr;
8263 if (!view) {
8264 Error("PaintLegoAxis", "no TView in current pad");
8265 return;
8266 }
8267
8268 // In polar coordinates, draw a short line going from the external circle
8269 // corresponding to r = 1 up to r = 1.1
8270 if (Hoption.System == kPOLAR) {
8271 r[0] = 1;
8272 r[1] = 0;
8273 r[2] = 0;
8274 view->WCtoNDC(r, x1);
8275 r[0] = 1.1;
8276 r[1] = 0;
8277 r[2] = 0;
8278 view->WCtoNDC(r, x2);
8279 gPad->PaintLine(x1[0],x1[1],x2[0],x2[1]);
8280 return;
8281 }
8282
8283 if (Hoption.System != kCARTESIAN) return;
8284
8285 rad = TMath::ATan(1.) * 4. /180.;
8286 cosa = TMath::Cos(ang*rad);
8287 sina = TMath::Sin(ang*rad);
8288
8289 view->AxisVertex(ang, av, ix1, ix2, iy1, iy2, iz1, iz2);
8290 for (i = 1; i <= 8; ++i) {
8291 r[i*3 - 3] = av[i*3 - 3] + av[i*3 - 2]*cosa;
8292 r[i*3 - 2] = av[i*3 - 2]*sina;
8293 r[i*3 - 1] = av[i*3 - 1];
8294 }
8295
8296 view->WCtoNDC(&r[ix1*3 - 3], x1);
8297 view->WCtoNDC(&r[ix2*3 - 3], x2);
8298 view->WCtoNDC(&r[iy1*3 - 3], y1);
8299 view->WCtoNDC(&r[iy2*3 - 3], y2);
8300 view->WCtoNDC(&r[iz1*3 - 3], z1);
8301 view->WCtoNDC(&r[iz2*3 - 3], z2);
8302
8303 view->SetAxisNDC(x1, x2, y1, y2, z1, z2);
8304
8305 Double_t *rmin = view->GetRmin();
8306 Double_t *rmax = view->GetRmax();
8307 if (!rmin || !rmax) return;
8308
8309 // Initialize the axis options
8310 if (x1[0] > x2[0]) strlcpy(chopax, "SDH=+",8);
8311 else strlcpy(chopax, "SDH=-",8);
8312 if (y1[0] > y2[0]) strlcpy(chopay, "SDH=+",8);
8313 else strlcpy(chopay, "SDH=-",8);
8314 if (z2[1] > z1[1]) strlcpy(chopaz, "SDH=+",8);
8315 else strlcpy(chopaz, "SDH=-",8);
8316
8317 // Option LOG is required ?
8318 if (Hoption.Logx) strlcat(chopax,"G",8);
8319 if (Hoption.Logy) strlcat(chopay,"G",8);
8320 if (Hoption.Logz) strlcat(chopaz,"G",8);
8321
8322 // Initialize the number of divisions. If the
8323 // number of divisions is negative, option 'N' is required.
8327 if (ndivx < 0) {
8329 strlcat(chopax, "N",8);
8330 }
8331 if (ndivy < 0) {
8333 strlcat(chopay, "N",8);
8334 }
8335 if (ndivz < 0) {
8337 strlcat(chopaz, "N",8);
8338 }
8339
8340 // Set Axis attributes.
8341 // The variable SCALE rescales the VSIZ
8342 // in order to have the same label size for all angles.
8343
8344 axis->SetLineWidth(1);
8345
8346 // X axis drawing
8347 if (TMath::Abs(x1[0] - x2[0]) >= epsil || TMath::Abs(x1[1] - x2[1]) > epsil) {
8350 if (Hoption.Logx && !fH->InheritsFrom(TH3::Class())) {
8351 bmin = TMath::Power(10, rmin[0]);
8352 bmax = TMath::Power(10, rmax[0]);
8353 } else {
8354 bmin = rmin[0];
8355 bmax = rmax[0];
8356 }
8357 // Option time display is required ?
8358 if (fXaxis->GetTimeDisplay()) {
8359 strlcat(chopax,"t",8);
8360 if (strlen(fXaxis->GetTimeFormatOnly()) == 0) {
8362 } else {
8364 }
8365 }
8366 axis->SetOption(chopax);
8367 axis->PaintAxis(x1[0], x1[1], x2[0], x2[1], bmin, bmax, ndivx, chopax);
8368 }
8369
8370 // Y axis drawing
8371 if (TMath::Abs(y1[0] - y2[0]) >= epsil || TMath::Abs(y1[1] - y2[1]) > epsil) {
8374 if (fYaxis->GetTitleOffset() == 0) axis->SetTitleOffset(1.5);
8375
8376 if (fH->GetDimension() < 2) {
8377 strlcpy(chopay, "V=+UN",8);
8378 ndivy = 0;
8379 }
8380 if (TMath::Abs(y1[0] - y2[0]) < epsil) {
8381 y2[0] = y1[0];
8382 }
8383 if (Hoption.Logy && !fH->InheritsFrom(TH3::Class())) {
8384 bmin = TMath::Power(10, rmin[1]);
8385 bmax = TMath::Power(10, rmax[1]);
8386 } else {
8387 bmin = rmin[1];
8388 bmax = rmax[1];
8389 }
8390 // Option time display is required ?
8391 if (fYaxis->GetTimeDisplay()) {
8392 strlcat(chopay,"t",8);
8393 if (strlen(fYaxis->GetTimeFormatOnly()) == 0) {
8395 } else {
8397 }
8398 }
8399 axis->SetOption(chopay);
8400 axis->PaintAxis(y1[0], y1[1], y2[0], y2[1], bmin, bmax, ndivy, chopay);
8401 }
8402
8403 // Z axis drawing
8404 if (TMath::Abs(z1[0] - z2[0]) >= 100*epsil || TMath::Abs(z1[1] - z2[1]) > 100*epsil) {
8406 if (Hoption.Logz && !fH->InheritsFrom(TH3::Class())) {
8407 bmin = TMath::Power(10, rmin[2]);
8408 bmax = TMath::Power(10, rmax[2]);
8409 } else {
8410 bmin = rmin[2];
8411 bmax = rmax[2];
8412 }
8413 // Option time display is required ?
8414 if (fZaxis->GetTimeDisplay()) {
8415 strlcat(chopaz,"t",8);
8416 if (strlen(fZaxis->GetTimeFormatOnly()) == 0) {
8418 } else {
8420 }
8421 }
8422 axis->SetOption(chopaz);
8424 if (ztit.Index(";")>0) {
8425 ztit.Remove(ztit.Index(";"),ztit.Length());
8426 axis->SetTitle(ztit.Data());
8427 }
8428 axis->PaintAxis(z1[0], z1[1], z2[0], z2[1], bmin, bmax, ndivz, chopaz);
8429 }
8430
8431 //fH->SetLineStyle(1); /// otherwise fEdgeStyle[i] gets overwritten!
8432}
8433
8434////////////////////////////////////////////////////////////////////////////////
8435/// [Paint the color palette on the right side of the pad.](\ref HP22)
8436
8438{
8440 TView *view = gPad ? gPad->GetView() : nullptr;
8441 if (palette) {
8442 if (view) {
8443 if (!palette->TestBit(TPaletteAxis::kHasView)) {
8445 delete palette; palette = nullptr;
8446 }
8447 } else {
8448 if (palette->TestBit(TPaletteAxis::kHasView)) {
8450 delete palette; palette = nullptr;
8451 }
8452 }
8453 // make sure the histogram member of the palette is setup correctly. It may not be after a Clone()
8454 if (palette && !palette->GetHistogram()) palette->SetHistogram(fH);
8455 }
8456
8457 if (!palette) {
8458 Double_t xup = gPad->GetUxmax();
8459 Double_t x2 = gPad->PadtoX(gPad->GetX2());
8460 Double_t ymin = gPad->PadtoY(gPad->GetUymin());
8461 Double_t ymax = gPad->PadtoY(gPad->GetUymax());
8462 Double_t xr = 0.05*(gPad->GetX2() - gPad->GetX1());
8463 Double_t xmin = gPad->PadtoX(xup +0.1*xr);
8464 Double_t xmax = gPad->PadtoX(xup + xr);
8465 if (xmax > x2) xmax = gPad->PadtoX(gPad->GetX2()-0.01*xr);
8468 palette->Paint();
8469 }
8470}
8471
8472////////////////////////////////////////////////////////////////////////////////
8473/// [Control function to draw a 2D histogram as a scatter plot.](\ref HP11)
8474
8476{
8477
8478 fH->TAttMarker::Modify();
8479
8480 Int_t k, marker;
8481 Double_t dz, z, xk,xstep, yk, ystep;
8482 Double_t scale = 1;
8484 Double_t zmax = fH->GetMaximum();
8485 Double_t zmin = fH->GetMinimum();
8486 if (zmin == 0 && zmax == 0) return;
8487 if (zmin == zmax) {
8488 zmax += 0.1*TMath::Abs(zmax);
8489 zmin -= 0.1*TMath::Abs(zmin);
8490 }
8492 if (Hoption.Logz) {
8493 if (zmin > 0) zmin = TMath::Log10(zmin);
8494 else zmin = 0;
8495 if (zmax > 0) zmax = TMath::Log10(zmax);
8496 else zmax = 0;
8497 if (zmin == 0 && zmax == 0) return;
8498 dz = zmax - zmin;
8499 scale = 100/dz;
8500 if (ncells > 10000) scale /= 5;
8501 ltest = kTRUE;
8502 } else {
8503 dz = zmax - zmin;
8504 if (dz >= kNMAX || zmax < 1) {
8505 scale = (kNMAX-1)/dz;
8506 if (ncells > 10000) scale /= 5;
8507 ltest = kTRUE;
8508 }
8509 }
8510 if (fH->GetMinimumStored() == -1111) {
8512 if (Hoption.MinimumZero) {
8513 if (zmin >= 0) zmin = 0;
8514 else zmin -= yMARGIN*(zmax-zmin);
8515 } else {
8516 Double_t dzmin = yMARGIN*(zmax-zmin);
8517 if (zmin >= 0 && (zmin-dzmin <= 0)) zmin = 0;
8518 else zmin -= dzmin;
8519 }
8520 }
8521
8522 TString opt = option;
8523 opt.ToLower();
8524 if (opt.Contains("scat=")) {
8525 char optscat[100];
8526 strlcpy(optscat,opt.Data(),100);
8527 char *oscat = strstr(optscat,"scat=");
8528 char *blank = strstr(oscat," "); if (blank) *blank = 0;
8529 sscanf(oscat+5,"%lg",&scale);
8530 }
8531 // use an independent instance of a random generator
8532 // instead of gRandom to avoid conflicts and
8533 // to get same random numbers when drawing the same histogram
8535 marker=0;
8536 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
8539 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
8540 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
8541 xk = fXaxis->GetBinLowEdge(i);
8542 xstep = fXaxis->GetBinWidth(i);
8543 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
8544 z = fH->GetBinContent(bin);
8545 if (z < zmin) z = zmin;
8546 if (z > zmax) z = zmax;
8547 if (Hoption.Logz) {
8548 if (z > 0) z = TMath::Log10(z) - zmin;
8549 } else {
8550 z -= zmin;
8551 }
8552 if (z <= 0) continue;
8553 k = Int_t(z*scale);
8554 if (ltest) k++;
8555 if (k > 0) {
8556 for (Int_t loop=0; loop<k; loop++) {
8557 if (k+marker >= kNMAX) {
8558 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
8559 marker=0;
8560 }
8561 fXbuf[marker] = (random.Rndm()*xstep) + xk;
8562 fYbuf[marker] = (random.Rndm()*ystep) + yk;
8563 if (Hoption.Logx) {
8564 if (fXbuf[marker] > 0) fXbuf[marker] = TMath::Log10(fXbuf[marker]);
8565 else break;
8566 }
8567 if (Hoption.Logy) {
8568 if (fYbuf[marker] > 0) fYbuf[marker] = TMath::Log10(fYbuf[marker]);
8569 else break;
8570 }
8571 if (fXbuf[marker] < gPad->GetUxmin()) break;
8572 if (fYbuf[marker] < gPad->GetUymin()) break;
8573 if (fXbuf[marker] > gPad->GetUxmax()) break;
8574 if (fYbuf[marker] > gPad->GetUymax()) break;
8575 marker++;
8576 }
8577 }
8578 }
8579 }
8580 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
8581
8583}
8584
8585////////////////////////////////////////////////////////////////////////////////
8586/// Static function to paint special objects like vectors and matrices.
8587/// This function is called via `gROOT->ProcessLine` to paint these objects
8588/// without having a direct dependency of the graphics or histogramming
8589/// system.
8590
8592{
8593
8594 if (!obj) return;
8597
8598 if (obj->InheritsFrom(TMatrixFBase::Class())) {
8599 // case TMatrixF
8600 TH2F *R__TMatrixFBase = new TH2F((TMatrixFBase &)*obj);
8601 R__TMatrixFBase->SetBit(kCanDelete);
8602 R__TMatrixFBase->Draw(option);
8603
8604 } else if (obj->InheritsFrom(TMatrixDBase::Class())) {
8605 // case TMatrixD
8606 TH2D *R__TMatrixDBase = new TH2D((TMatrixDBase &)*obj);
8607 R__TMatrixDBase->SetBit(kCanDelete);
8608 R__TMatrixDBase->Draw(option);
8609
8610 } else if (obj->InheritsFrom(TVectorF::Class())) {
8611 //case TVectorF
8612 TH1F *R__TVectorF = new TH1F((TVectorF &)*obj);
8613 R__TVectorF->SetBit(kCanDelete);
8614 R__TVectorF->Draw(option);
8615
8616 } else if (obj->InheritsFrom(TVectorD::Class())) {
8617 //case TVectorD
8618 TH1D *R__TVectorD = new TH1D((TVectorD &)*obj);
8619 R__TVectorD->SetBit(kCanDelete);
8620 R__TVectorD->Draw(option);
8621 }
8622
8623 TH1::AddDirectory(status);
8624}
8625
8626////////////////////////////////////////////////////////////////////////////////
8627/// [Draw the statistics box for 1D and profile histograms.](\ref HP07)
8628
8630{
8631 TString tt, tf;
8632 Int_t dofit;
8633 TPaveStats *stats = nullptr;
8634 TIter next(fFunctions);
8635 while (auto obj = next()) {
8636 if (obj->InheritsFrom(TPaveStats::Class())) {
8637 stats = (TPaveStats*)obj;
8638 break;
8639 }
8640 }
8641
8642 if (stats && dostat) {
8643 dofit = stats->GetOptFit();
8644 dostat = stats->GetOptStat();
8645 } else {
8646 dofit = gStyle->GetOptFit();
8647 }
8648 if (!dofit) fit = nullptr;
8649 if (dofit == 1) dofit = 111;
8650 if (dostat == 1) dostat = 1111;
8651 Int_t print_name = dostat%10;
8652 Int_t print_entries = (dostat/10)%10;
8653 Int_t print_mean = (dostat/100)%10;
8654 Int_t print_stddev = (dostat/1000)%10;
8655 Int_t print_under = (dostat/10000)%10;
8656 Int_t print_over = (dostat/100000)%10;
8657 Int_t print_integral= (dostat/1000000)%10;
8658 Int_t print_skew = (dostat/10000000)%10;
8659 Int_t print_kurt = (dostat/100000000)%10;
8663 Int_t print_fval = dofit%10;
8664 Int_t print_ferrors = (dofit/10)%10;
8665 Int_t print_fchi2 = (dofit/100)%10;
8666 Int_t print_fprob = (dofit/1000)%10;
8668 if (fit) {
8669 if (print_fval < 2) nlinesf += fit->GetNumberFreeParameters();
8670 else nlinesf += fit->GetNpar();
8671 }
8673
8674 // Pavetext with statistics
8675 Bool_t done = kFALSE;
8676 if (!dostat && !fit) {
8677 if (stats) { fFunctions->Remove(stats); delete stats;}
8678 return;
8679 }
8681 if (fit) statw = 1.8*gStyle->GetStatW();
8683 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
8684 stath = 0.25*(nlines+nlinesf)*gStyle->GetStatH();
8685 }
8686 if (stats) {
8687 stats->Clear();
8688 done = kTRUE;
8689 } else {
8690 stats = new TPaveStats(
8693 gStyle->GetStatX(),
8694 gStyle->GetStatY(),"brNDC");
8695
8696 stats->SetParent(fH);
8697 stats->SetOptFit(dofit);
8698 stats->SetOptStat(dostat);
8699 stats->SetFillColor(gStyle->GetStatColor());
8700 stats->SetFillStyle(gStyle->GetStatStyle());
8701 stats->SetBorderSize(gStyle->GetStatBorderSize());
8702 stats->SetTextFont(gStyle->GetStatFont());
8703 if (gStyle->GetStatFont()%10 > 2)
8704 stats->SetTextSize(gStyle->GetStatFontSize());
8705 stats->SetFitFormat(gStyle->GetFitFormat());
8706 stats->SetStatFormat(gStyle->GetStatFormat());
8707 stats->SetName("stats");
8708
8709 stats->SetTextColor(gStyle->GetStatTextColor());
8710 stats->SetTextAlign(12);
8711 stats->SetBit(kCanDelete);
8712 stats->SetBit(kMustCleanup);
8713 }
8714 if (print_name) stats->AddText(fH->GetName());
8715 if (print_entries) {
8716 if (fH->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(fH->GetEntries()+0.5));
8717 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(fH->GetEntries()));
8718 stats->AddText(tt.Data());
8719 }
8720 if (print_mean) {
8721 if (print_mean == 1) {
8722 tf.Form("%s = %s%s",gStringMean.Data(),"%",stats->GetStatFormat());
8723 tt.Form(tf.Data(),fH->GetMean(1));
8724 } else {
8725 tf.Form("%s = %s%s #pm %s%s",gStringMean.Data(),"%",stats->GetStatFormat()
8726 ,"%",stats->GetStatFormat());
8727 tt.Form(tf.Data(),fH->GetMean(1),fH->GetMeanError(1));
8728 }
8729 stats->AddText(tt.Data());
8731 if (print_mean == 1) {
8732 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
8733 tt.Form(tf.Data(),fH->GetMean(2));
8734 } else {
8735 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
8736 ,"%",stats->GetStatFormat());
8737 tt.Form(tf.Data(),fH->GetMean(2),fH->GetMeanError(2));
8738 }
8739 stats->AddText(tt.Data());
8740 }
8741 }
8742 if (print_stddev) {
8743 if (print_stddev == 1) {
8744 tf.Form("%s = %s%s",gStringStdDev.Data(),"%",stats->GetStatFormat());
8745 tt.Form(tf.Data(),fH->GetStdDev(1));
8746 } else {
8747 tf.Form("%s = %s%s #pm %s%s",gStringStdDev.Data(),"%",stats->GetStatFormat()
8748 ,"%",stats->GetStatFormat());
8749 tt.Form(tf.Data(),fH->GetStdDev(1),fH->GetStdDevError(1));
8750 }
8751 stats->AddText(tt.Data());
8753 if (print_stddev == 1) {
8754 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
8755 tt.Form(tf.Data(),fH->GetStdDev(2));
8756 } else {
8757 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
8758 ,"%",stats->GetStatFormat());
8759 tt.Form(tf.Data(),fH->GetStdDev(2),fH->GetStdDevError(2));
8760 }
8761 stats->AddText(tt.Data());
8762 }
8763 }
8764 if (print_under) {
8765 tf.Form("%s = %s%s",gStringUnderflow.Data(),"%",stats->GetStatFormat());
8766 tt.Form(tf.Data(),fH->GetBinContent(0));
8767 stats->AddText(tt.Data());
8768 }
8769 if (print_over) {
8770 tf.Form("%s = %s%s",gStringOverflow.Data(),"%",stats->GetStatFormat());
8771 tt.Form(tf.Data(),fH->GetBinContent(fXaxis->GetNbins()+1));
8772 stats->AddText(tt.Data());
8773 }
8774 if (print_integral) {
8775 if (print_integral == 1) {
8776 tf.Form("%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
8777 tt.Form(tf.Data(),fH->Integral());
8778 } else {
8779 tf.Form("%s = %s%s",gStringIntegralBinWidth.Data(),"%",stats->GetStatFormat());
8780 tt.Form(tf.Data(),fH->Integral("width"));
8781 }
8782 stats->AddText(tt.Data());
8783 }
8784 if (print_skew) {
8785 if (print_skew == 1) {
8786 tf.Form("%s = %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat());
8787 tt.Form(tf.Data(),fH->GetSkewness(1));
8788 } else {
8789 tf.Form("%s = %s%s #pm %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat()
8790 ,"%",stats->GetStatFormat());
8791 tt.Form(tf.Data(),fH->GetSkewness(1),fH->GetSkewness(11));
8792 }
8793 stats->AddText(tt.Data());
8794 }
8795 if (print_kurt) {
8796 if (print_kurt == 1) {
8797 tf.Form("%s = %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat());
8798 tt.Form(tf.Data(),fH->GetKurtosis(1));
8799 } else {
8800 tf.Form("%s = %s%s #pm %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat()
8801 ,"%",stats->GetStatFormat());
8802 tt.Form(tf.Data(),fH->GetKurtosis(1),fH->GetKurtosis(11));
8803 }
8804 stats->AddText(tt.Data());
8805 }
8806
8807 // Draw Fit parameters
8808 if (fit) {
8809 Int_t ndf = fit->GetNDF();
8810 tf.Form("#chi^{2} / ndf = %s%s / %d","%",stats->GetFitFormat(),ndf);
8811 tt.Form(tf.Data(),fit->GetChisquare());
8812 if (print_fchi2) stats->AddText(tt.Data());
8813 if (print_fprob) {
8814 tf.Form("Prob = %s%s","%",stats->GetFitFormat());
8815 tt.Form(tf.Data(),TMath::Prob(fit->GetChisquare(),ndf));
8816 stats->AddText(tt.Data());
8817 }
8818 if (print_fval || print_ferrors) {
8820 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
8821 fit->GetParLimits(ipar,parmin,parmax);
8823 if (print_ferrors) {
8824 tf.Form("%-8s = %s%s #pm %s ", fit->GetParName(ipar), "%",stats->GetFitFormat(),
8825 GetBestFormat(fit->GetParameter(ipar), fit->GetParError(ipar), stats->GetFitFormat()));
8826 tt.Form(tf.Data(),fit->GetParameter(ipar)
8827 ,fit->GetParError(ipar));
8828 } else {
8829 tf.Form("%-8s = %s%s ",fit->GetParName(ipar), "%",stats->GetFitFormat());
8830 tt.Form(tf.Data(),fit->GetParameter(ipar));
8831 }
8832 stats->AddText(tt.Data());
8833 }
8834 }
8835 }
8836
8837 if (!done) fFunctions->Add(stats);
8838 stats->Paint(stats->GetOption());
8839}
8840
8841////////////////////////////////////////////////////////////////////////////////
8842/// [Draw the statistics box for 2D histograms.](\ref HP07)
8843
8845{
8846
8847 if (fH->GetDimension() != 2) return;
8848 TH2 *h2 = (TH2*)fH;
8849
8850 TString tt, tf;
8851 Int_t dofit;
8852 TPaveStats *stats = nullptr;
8853 TIter next(fFunctions);
8854 while (auto obj = next()) {
8855 if (obj->InheritsFrom(TPaveStats::Class())) {
8856 stats = (TPaveStats*)obj;
8857 break;
8858 }
8859 }
8860 if (stats && dostat) {
8861 dofit = stats->GetOptFit();
8862 dostat = stats->GetOptStat();
8863 } else {
8864 dofit = gStyle->GetOptFit();
8865 }
8866 if (dostat == 1) dostat = 1111;
8867 Int_t print_name = dostat%10;
8868 Int_t print_entries = (dostat/10)%10;
8869 Int_t print_mean = (dostat/100)%10;
8870 Int_t print_stddev = (dostat/1000)%10;
8871 Int_t print_under = (dostat/10000)%10;
8872 Int_t print_over = (dostat/100000)%10;
8873 Int_t print_integral= (dostat/1000000)%10;
8874 Int_t print_skew = (dostat/10000000)%10;
8875 Int_t print_kurt = (dostat/100000000)%10;
8877 if (print_under || print_over) nlines += 3;
8878
8879 // Pavetext with statistics
8880 if (!gStyle->GetOptFit()) fit = nullptr;
8881 Bool_t done = kFALSE;
8882 if (!dostat && !fit) {
8883 if (stats) { fFunctions->Remove(stats); delete stats;}
8884 return;
8885 }
8887 if (fit) statw = 1.8*gStyle->GetStatW();
8889 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
8890 stath = 0.25*nlines*gStyle->GetStatH();
8891 }
8892 if (fit) stath += gStyle->GetStatH();
8893 if (stats) {
8894 stats->Clear();
8895 done = kTRUE;
8896 } else {
8897 stats = new TPaveStats(
8900 gStyle->GetStatX(),
8901 gStyle->GetStatY(),"brNDC");
8902
8903 stats->SetParent(fH);
8904 stats->SetOptFit(dofit);
8905 stats->SetOptStat(dostat);
8906 stats->SetFillColor(gStyle->GetStatColor());
8907 stats->SetFillStyle(gStyle->GetStatStyle());
8908 stats->SetBorderSize(gStyle->GetStatBorderSize());
8909 stats->SetName("stats");
8910
8911 stats->SetTextColor(gStyle->GetStatTextColor());
8912 stats->SetTextAlign(12);
8913 stats->SetTextFont(gStyle->GetStatFont());
8914 if (gStyle->GetStatFont()%10 > 2)
8915 stats->SetTextSize(gStyle->GetStatFontSize());
8916 stats->SetFitFormat(gStyle->GetFitFormat());
8917 stats->SetStatFormat(gStyle->GetStatFormat());
8918 stats->SetBit(kCanDelete);
8919 stats->SetBit(kMustCleanup);
8920 }
8921 if (print_name) stats->AddText(h2->GetName());
8922 if (print_entries) {
8923 if (h2->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(h2->GetEntries()+0.5));
8924 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(h2->GetEntries()));
8925 stats->AddText(tt.Data());
8926 }
8927 if (print_mean) {
8928 if (print_mean == 1) {
8929 tf.Form("%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
8930 tt.Form(tf.Data(),h2->GetMean(1));
8931 stats->AddText(tt.Data());
8932 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
8933 tt.Form(tf.Data(),h2->GetMean(2));
8934 stats->AddText(tt.Data());
8935 } else {
8936 tf.Form("%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
8937 ,"%",stats->GetStatFormat());
8938 tt.Form(tf.Data(),h2->GetMean(1),h2->GetMeanError(1));
8939 stats->AddText(tt.Data());
8940 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
8941 ,"%",stats->GetStatFormat());
8942 tt.Form(tf.Data(),h2->GetMean(2),h2->GetMeanError(2));
8943 stats->AddText(tt.Data());
8944 }
8945 }
8946 if (print_stddev) {
8947 if (print_stddev == 1) {
8948 tf.Form("%s = %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat());
8949 tt.Form(tf.Data(),h2->GetStdDev(1));
8950 stats->AddText(tt.Data());
8951 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
8952 tt.Form(tf.Data(),h2->GetStdDev(2));
8953 stats->AddText(tt.Data());
8954 } else {
8955 tf.Form("%s = %s%s #pm %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat()
8956 ,"%",stats->GetStatFormat());
8957 tt.Form(tf.Data(),h2->GetStdDev(1),h2->GetStdDevError(1));
8958 stats->AddText(tt.Data());
8959 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
8960 ,"%",stats->GetStatFormat());
8961 tt.Form(tf.Data(),h2->GetStdDev(2),h2->GetStdDevError(2));
8962 stats->AddText(tt.Data());
8963 }
8964 }
8965 if (print_integral) {
8966 tf.Form("%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
8967 tt.Form(tf.Data(),fH->Integral());
8968 stats->AddText(tt.Data());
8969 }
8970 if (print_skew) {
8971 if (print_skew == 1) {
8972 tf.Form("%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
8973 tt.Form(tf.Data(),h2->GetSkewness(1));
8974 stats->AddText(tt.Data());
8975 tf.Form("%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
8976 tt.Form(tf.Data(),h2->GetSkewness(2));
8977 stats->AddText(tt.Data());
8978 } else {
8979 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
8980 ,"%",stats->GetStatFormat());
8981 tt.Form(tf.Data(),h2->GetSkewness(1),h2->GetSkewness(11));
8982 stats->AddText(tt.Data());
8983 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
8984 ,"%",stats->GetStatFormat());
8985 tt.Form(tf.Data(),h2->GetSkewness(2),h2->GetSkewness(12));
8986 stats->AddText(tt.Data());
8987 }
8988 }
8989 if (print_kurt) {
8990 if (print_kurt == 1) {
8991 tf.Form("%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
8992 tt.Form(tf.Data(),h2->GetKurtosis(1));
8993 stats->AddText(tt.Data());
8994 tf.Form("%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
8995 tt.Form(tf.Data(),h2->GetKurtosis(2));
8996 stats->AddText(tt.Data());
8997 } else {
8998 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
8999 ,"%",stats->GetStatFormat());
9000 tt.Form(tf.Data(),h2->GetKurtosis(1),h2->GetKurtosis(11));
9001 stats->AddText(tt.Data());
9002 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
9003 ,"%",stats->GetStatFormat());
9004 tt.Form(tf.Data(),h2->GetKurtosis(2),h2->GetKurtosis(12));
9005 stats->AddText(tt.Data());
9006 }
9007 }
9008 if (print_under || print_over) {
9009 //get 3*3 under/overflows for 2d hist
9010 Double_t unov[9];
9011
9012 Int_t cellsX = h2->GetXaxis()->GetNbins() + 1;
9013 Int_t cellsY = h2->GetYaxis()->GetNbins() + 1;
9014 Int_t firstX = std::max(1, h2->GetXaxis()->GetFirst());
9015 Int_t firstY = std::max(1, h2->GetYaxis()->GetFirst());
9016 Int_t lastX = std::min(h2->GetXaxis()->GetLast(), h2->GetXaxis()->GetNbins());
9017 Int_t lastY = std::min(h2->GetYaxis()->GetLast(), h2->GetYaxis()->GetNbins());
9018
9019 unov[0] = h2->Integral( 0, firstX-1, lastY+1, cellsY );
9020 unov[1] = h2->Integral(firstX , lastX , lastY+1, cellsY );
9021 unov[2] = h2->Integral(lastX+1, cellsX , lastY+1, cellsY );
9022 unov[3] = h2->Integral( 0, firstX-1, firstY , lastY );
9023 unov[4] = h2->Integral(firstX , lastX , firstY , lastY );
9024 unov[5] = h2->Integral(lastX+1, cellsX , firstY , lastY );
9025 unov[6] = h2->Integral( 0, firstX-1, 0, firstY-1);
9026 unov[7] = h2->Integral(firstX, lastX, 0, firstY-1);
9027 unov[8] = h2->Integral(lastX+1, cellsX , 0, firstY-1);
9028
9029 tt.Form("%g|%g|%g\n", unov[0], unov[1], unov[2]);
9030 stats->AddText(tt.Data());
9031 tt.Form("%g|%g|%g\n", unov[3], unov[4], unov[5]);
9032 stats->AddText(tt.Data());
9033 tt.Form("%g|%g|%g\n", unov[6], unov[7], unov[8]);
9034 stats->AddText(tt.Data());
9035 }
9036
9037 // Draw Fit parameters
9038 if (fit) {
9039 Int_t ndf = fit->GetNDF();
9040 tt.Form("#chi^{2} / ndf = %6.4g / %d",fit->GetChisquare(),ndf);
9041 stats->AddText(tt.Data());
9042 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
9043 tt.Form("%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
9044 ,fit->GetParameter(ipar)
9045 ,fit->GetParError(ipar));
9046 stats->AddText(tt.Data());
9047 }
9048 }
9049
9050 if (!done) fFunctions->Add(stats);
9051 stats->Paint(stats->GetOption());
9052}
9053
9054////////////////////////////////////////////////////////////////////////////////
9055/// [Draw the statistics box for 3D histograms.](\ref HP07)
9056
9058{
9059
9060 if (fH->GetDimension() != 3) return;
9061 TH3 *h3 = (TH3*)fH;
9062
9063 TString tt, tf;
9064 Int_t dofit;
9065 TPaveStats *stats = nullptr;
9066 TIter next(fFunctions);
9067 while (auto obj = next()) {
9068 if (obj->InheritsFrom(TPaveStats::Class())) {
9069 stats = (TPaveStats*)obj;
9070 break;
9071 }
9072 }
9073 if (stats && dostat) {
9074 dofit = stats->GetOptFit();
9075 dostat = stats->GetOptStat();
9076 } else {
9077 dofit = gStyle->GetOptFit();
9078 }
9079 if (dostat == 1) dostat = 1111;
9080 Int_t print_name = dostat%10;
9081 Int_t print_entries = (dostat/10)%10;
9082 Int_t print_mean = (dostat/100)%10;
9083 Int_t print_stddev = (dostat/1000)%10;
9084 Int_t print_under = (dostat/10000)%10;
9085 Int_t print_over = (dostat/100000)%10;
9086 Int_t print_integral= (dostat/1000000)%10;
9087 Int_t print_skew = (dostat/10000000)%10;
9088 Int_t print_kurt = (dostat/100000000)%10;
9090 if (print_under || print_over) nlines += 3;
9091
9092 // Pavetext with statistics
9093 if (!gStyle->GetOptFit()) fit = nullptr;
9094 Bool_t done = kFALSE;
9095 if (!dostat && !fit) {
9096 if (stats) { fFunctions->Remove(stats); delete stats;}
9097 return;
9098 }
9100 if (fit) statw = 1.8*gStyle->GetStatW();
9102 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
9103 stath = 0.25*nlines*gStyle->GetStatH();
9104 }
9105 if (fit) stath += gStyle->GetStatH();
9106 if (stats) {
9107 stats->Clear();
9108 done = kTRUE;
9109 } else {
9110 stats = new TPaveStats(
9113 gStyle->GetStatX(),
9114 gStyle->GetStatY(),"brNDC");
9115
9116 stats->SetParent(fH);
9117 stats->SetOptFit(dofit);
9118 stats->SetOptStat(dostat);
9119 stats->SetFillColor(gStyle->GetStatColor());
9120 stats->SetFillStyle(gStyle->GetStatStyle());
9121 stats->SetBorderSize(gStyle->GetStatBorderSize());
9122 stats->SetName("stats");
9123
9124 stats->SetTextColor(gStyle->GetStatTextColor());
9125 stats->SetTextAlign(12);
9126 stats->SetTextFont(gStyle->GetStatFont());
9127 stats->SetFitFormat(gStyle->GetFitFormat());
9128 stats->SetStatFormat(gStyle->GetStatFormat());
9129 stats->SetBit(kCanDelete);
9130 stats->SetBit(kMustCleanup);
9131 }
9132 if (print_name) stats->AddText(h3->GetName());
9133 if (print_entries) {
9134 if (h3->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(h3->GetEntries()+0.5));
9135 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(h3->GetEntries()+0.5));
9136 stats->AddText(tt.Data());
9137 }
9138 if (print_mean) {
9139 if (print_mean == 1) {
9140 tf.Form("%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
9141 tt.Form(tf.Data(),h3->GetMean(1));
9142 stats->AddText(tt.Data());
9143 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
9144 tt.Form(tf.Data(),h3->GetMean(2));
9145 stats->AddText(tt.Data());
9146 tf.Form("%s = %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat());
9147 tt.Form(tf.Data(),h3->GetMean(3));
9148 stats->AddText(tt.Data());
9149 } else {
9150 tf.Form("%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
9151 ,"%",stats->GetStatFormat());
9152 tt.Form(tf.Data(),h3->GetMean(1),h3->GetMeanError(1));
9153 stats->AddText(tt.Data());
9154 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
9155 ,"%",stats->GetStatFormat());
9156 tt.Form(tf.Data(),h3->GetMean(2),h3->GetMeanError(2));
9157 stats->AddText(tt.Data());
9158 tf.Form("%s = %s%s #pm %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat()
9159 ,"%",stats->GetStatFormat());
9160 tt.Form(tf.Data(),h3->GetMean(3),h3->GetMeanError(3));
9161 stats->AddText(tt.Data());
9162 }
9163 }
9164 if (print_stddev) {
9165 if (print_stddev == 1) {
9166 tf.Form("%s = %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat());
9167 tt.Form(tf.Data(),h3->GetStdDev(1));
9168 stats->AddText(tt.Data());
9169 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
9170 tt.Form(tf.Data(),h3->GetStdDev(2));
9171 stats->AddText(tt.Data());
9172 tf.Form("%s = %s%s",gStringStdDevZ.Data(),"%",stats->GetStatFormat());
9173 tt.Form(tf.Data(),h3->GetStdDev(3));
9174 stats->AddText(tt.Data());
9175 } else {
9176 tf.Form("%s = %s%s #pm %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat()
9177 ,"%",stats->GetStatFormat());
9178 tt.Form(tf.Data(),h3->GetStdDev(1),h3->GetStdDevError(1));
9179 stats->AddText(tt.Data());
9180 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
9181 ,"%",stats->GetStatFormat());
9182 tt.Form(tf.Data(),h3->GetStdDev(2),h3->GetStdDevError(2));
9183 stats->AddText(tt.Data());
9184 tf.Form("%s = %s%s #pm %s%s",gStringStdDevZ.Data(),"%",stats->GetStatFormat()
9185 ,"%",stats->GetStatFormat());
9186 tt.Form(tf.Data(),h3->GetStdDev(3),h3->GetStdDevError(3));
9187 stats->AddText(tt.Data());
9188 }
9189 }
9190 if (print_integral) {
9191 tt.Form("%s = %6.4g",gStringIntegral.Data(),h3->Integral());
9192 stats->AddText(tt.Data());
9193 }
9194 if (print_skew) {
9195 if (print_skew == 1) {
9196 tf.Form("%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
9197 tt.Form(tf.Data(),h3->GetSkewness(1));
9198 stats->AddText(tt.Data());
9199 tf.Form("%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
9200 tt.Form(tf.Data(),h3->GetSkewness(2));
9201 stats->AddText(tt.Data());
9202 tf.Form("%s = %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat());
9203 tt.Form(tf.Data(),h3->GetSkewness(3));
9204 stats->AddText(tt.Data());
9205 } else {
9206 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
9207 ,"%",stats->GetStatFormat());
9208 tt.Form(tf.Data(),h3->GetSkewness(1),h3->GetSkewness(11));
9209 stats->AddText(tt.Data());
9210 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
9211 ,"%",stats->GetStatFormat());
9212 tt.Form(tf.Data(),h3->GetSkewness(2),h3->GetSkewness(12));
9213 stats->AddText(tt.Data());
9214 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat()
9215 ,"%",stats->GetStatFormat());
9216 tt.Form(tf.Data(),h3->GetSkewness(3),h3->GetSkewness(13));
9217 stats->AddText(tt.Data());
9218 }
9219 }
9220 if (print_kurt) {
9221 if (print_kurt == 1) {
9222 tf.Form("%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
9223 tt.Form(tf.Data(),h3->GetKurtosis(1));
9224 stats->AddText(tt.Data());
9225 tf.Form("%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
9226 tt.Form(tf.Data(),h3->GetKurtosis(2));
9227 stats->AddText(tt.Data());
9228 tf.Form("%s = %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat());
9229 tt.Form(tf.Data(),h3->GetKurtosis(3));
9230 stats->AddText(tt.Data());
9231 } else {
9232 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
9233 ,"%",stats->GetStatFormat());
9234 tt.Form(tf.Data(),h3->GetKurtosis(1),h3->GetKurtosis(11));
9235 stats->AddText(tt.Data());
9236 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
9237 ,"%",stats->GetStatFormat());
9238 tt.Form(tf.Data(),h3->GetKurtosis(2),h3->GetKurtosis(12));
9239 stats->AddText(tt.Data());
9240 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat()
9241 ,"%",stats->GetStatFormat());
9242 tt.Form(tf.Data(),h3->GetKurtosis(3),h3->GetKurtosis(13));
9243 stats->AddText(tt.Data());
9244 }
9245 }
9246 if (print_under || print_over) {
9247 // no underflow - overflow printing for a 3D histogram
9248 // one would need a 3D table
9249 }
9250
9251 // Draw Fit parameters
9252 if (fit) {
9253 Int_t ndf = fit->GetNDF();
9254 tt.Form("#chi^{2} / ndf = %6.4g / %d",fit->GetChisquare(),ndf);
9255 stats->AddText(tt.Data());
9256 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
9257 tt.Form("%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
9258 ,fit->GetParameter(ipar)
9259 ,fit->GetParError(ipar));
9260 stats->AddText(tt.Data());
9261 }
9262 }
9263
9264 if (!done) fFunctions->Add(stats);
9265 stats->Paint(stats->GetOption());
9266}
9267
9268////////////////////////////////////////////////////////////////////////////////
9269/// [Control function to draw a 2D histogram as a surface plot.](\ref HP18)
9270
9272{
9273
9274 const Double_t ydiff = 1;
9275 const Double_t yligh1 = 10;
9276 const Double_t qa = 0.15;
9277 const Double_t qd = 0.15;
9278 const Double_t qs = 0.8;
9280 Int_t raster = 0;
9281 Int_t irep = 0;
9282
9283 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
9286 Double_t zmin = Hparam.zmin;
9287 Double_t zmax = Hparam.zmax;
9292 Double_t dangle = 10*3.141592/180; //Delta angle for Rapidity option
9293 Double_t deltaz = TMath::Abs(zmin);
9294 if (deltaz == 0) deltaz = 1;
9295 if (zmin >= zmax) {
9296 zmin -= 0.5*deltaz;
9297 zmax += 0.5*deltaz;
9298 }
9299 Double_t z1c = zmin;
9300 Double_t z2c = zmin + (zmax-zmin)*(1+gStyle->GetHistTopMargin());
9301 // Compute the lego limits and instantiate a lego object
9302 fXbuf[0] = -1;
9303 fYbuf[0] = 1;
9304 fXbuf[1] = -1;
9305 fYbuf[1] = 1;
9306 if (Hoption.System >= kPOLAR && (Hoption.Surf == 1 || Hoption.Surf == 13)) raster = 1;
9307 if (Hoption.System == kPOLAR) {
9308 fXbuf[2] = z1c;
9309 fYbuf[2] = z2c;
9310 } else if (Hoption.System == kCYLINDRICAL) {
9311 if (Hoption.Logy) {
9312 if (ylab1 > 0) fXbuf[2] = TMath::Log10(ylab1);
9313 else fXbuf[2] = 0;
9314 if (ylab2 > 0) fYbuf[2] = TMath::Log10(ylab2);
9315 else fYbuf[2] = 0;
9316 } else {
9317 fXbuf[2] = ylab1;
9318 fYbuf[2] = ylab2;
9319 }
9320 z1c = 0; z2c = 1;
9321 } else if (Hoption.System == kSPHERICAL) {
9322 fXbuf[2] = -1;
9323 fYbuf[2] = 1;
9324 z1c = 0; z2c = 1;
9325 } else if (Hoption.System == kRAPIDITY) {
9326 fXbuf[2] = -1/TMath::Tan(dangle);
9327 fYbuf[2] = 1/TMath::Tan(dangle);
9328 } else {
9329 fXbuf[0] = xlab1;
9330 fYbuf[0] = xlab2;
9331 fXbuf[1] = ylab1;
9332 fYbuf[1] = ylab2;
9333 fXbuf[2] = z1c;
9334 fYbuf[2] = z2c;
9335 }
9336
9337 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data(), Hoption.System);
9338 fLego->SetEdgeAtt(fH->GetLineColor(),fH->GetLineStyle(),fH->GetLineWidth(),0);
9339 fLego->SetFillColor(fH->GetFillColor());
9340
9341 // Initialize the levels on the Z axis
9342 Int_t ndiv = fH->GetContour();
9343 if (ndiv == 0 ) {
9344 ndiv = gStyle->GetNumberContours();
9345 fH->SetContour(ndiv);
9346 }
9347 Int_t ndivz = TMath::Abs(ndiv);
9348 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
9349
9350 if (Hoption.Surf == 13 || Hoption.Surf == 15) fLego->SetMesh(3);
9351 if (Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) fLego->SetMesh(0);
9352
9353 // Close the surface in case of non cartesian coordinates.
9354
9355 if (Hoption.System != kCARTESIAN) {nx++; ny++;}
9356
9357 // Now ready to draw the surface plot
9358
9359 TView *view = gPad ? gPad->GetView() : nullptr;
9360 if (!view) {
9361 Error("PaintSurface", "no TView in current pad");
9362 return;
9363 }
9364
9365 Double_t thedeg = 90 - gPad->GetTheta();
9366 Double_t phideg = -90 - gPad->GetPhi();
9367 Double_t psideg = view->GetPsi();
9368 view->SetView(phideg, thedeg, psideg, irep);
9369
9370 // Set color/style for back box
9371 if (Hoption.Same) {
9372 fLego->SetFillStyle(0);
9373 fLego->SetFillColor(1);
9374 } else {
9375 fLego->SetFillStyle(gPad->GetFrameFillStyle());
9376 fLego->SetFillColor(gPad->GetFrameFillColor());
9377 }
9378 fLego->TAttFill::Modify();
9379
9380 Int_t backcolor = gPad->GetFrameFillColor();
9381 if (Hoption.System != kCARTESIAN) backcolor = 0;
9382 view->PadRange(backcolor);
9383
9384 fLego->SetFillStyle(fH->GetFillStyle());
9385 fLego->SetFillColor(fH->GetFillColor());
9386 fLego->TAttFill::Modify();
9387
9388 // Draw the filled contour on top
9390
9392 if (Hoption.Surf == 13 || Hoption.Surf == 15) {
9394 Hoption.Surf = 23;
9395 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9397 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"BF");
9398 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9399 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9400 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9401 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"BF");
9403 fLego->SetMesh(1);
9404 }
9405
9406 if (raster) fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
9407 else fLego->InitMoveScreen(-1.1,1.1);
9408
9409 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) {
9410 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9413 fLego->BackBox(90);
9414 }
9415 }
9416
9417 // Gouraud Shading surface
9418 if (Hoption.Surf == 14) {
9419 // Set light sources
9420 fLego->LightSource(0, ydiff, 0,0,0,irep);
9421 fLego->LightSource(1, yligh1 ,1,1,1,irep);
9422 fLego->SurfaceProperty(qa, qd, qs, 1, irep);
9423 fmin = ydiff*qa;
9424 fmax = fmin + (yligh1+0.1)*(qd+qs);
9425 Int_t nbcol = 28;
9426 icol1 = 201;
9427 Double_t dcol = 0.5/Double_t(nbcol);
9428 TColor *colref = gROOT->GetColor(fH->GetFillColor());
9429 if (!colref) return;
9431 colref->GetRGB(r,g,b);
9433 TColor *acol;
9434 for (Int_t col=0;col<nbcol;col++) {
9435 acol = gROOT->GetColor(col+icol1);
9436 TColor::HLStoRGB(hue,.4+col*dcol,satur,r,g,b);
9437 if (acol) acol->SetRGB(r,g,b);
9438 }
9439 fLego->Spectrum(nbcol, fmin, fmax, icol1, 1, irep);
9440 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::GouraudFunction);
9442 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"BF");
9443 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9444 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9445 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9446 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"BF");
9447 } else if (Hoption.Surf == 15) {
9448 // The surface is not drawn in this case.
9449 } else {
9450 // Draw the surface
9451 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 16 || Hoption.Surf == 17) {
9453 } else {
9454 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9455 }
9456 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9457 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceRaster1);
9458 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode2);
9459 if (Hoption.System == kPOLAR) {
9460 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfacePolar(1,nx,ny,"FB");
9461 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfacePolar(1,nx,ny,"BF");
9462 } else if (Hoption.System == kCYLINDRICAL) {
9463 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceCylindrical(1,nx,ny,"FB");
9464 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9465 } else if (Hoption.System == kSPHERICAL) {
9466 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceSpherical(0,1,nx,ny,"FB");
9467 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9468 } else if (Hoption.System == kRAPIDITY) {
9469 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceSpherical(1,1,nx,ny,"FB");
9470 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9471 } else {
9472 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove1);
9473 if (Hoption.Surf == 16) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove3);
9474 if (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16) fLego->SurfaceCartesian(90,nx,ny,"FB");
9475 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCartesian(90,nx,ny,"BF");
9476 }
9477 }
9478
9479 // Paint the line contour on top for option SURF7
9480 if (Hoption.Surf == 17) {
9481 fLego->InitMoveScreen(-1.1,1.1);
9482 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9483 Hoption.Surf = 23;
9484 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9486 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"FB");
9487 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"FB");
9488 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"FB");
9489 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"FB");
9490 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"FB");
9491 }
9492
9493 if ((!Hoption.Same) &&
9494 (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16)) {
9497 fLego->BackBox(90);
9498 }
9499 }
9500 if (Hoption.System == kCARTESIAN) {
9501 fLego->InitMoveScreen(-1.1,1.1);
9503 if (Hoption.FrontBox) fLego->FrontBox(90);
9504 }
9505 if (!Hoption.Axis && !Hoption.Same) {
9506 TGaxis axis;
9507 PaintLegoAxis(&axis, 90);
9508 }
9509
9511
9512 fLego.reset();
9513}
9514
9515////////////////////////////////////////////////////////////////////////////////
9516/// Control function to draw a table using Delaunay triangles.
9517
9519{
9520
9521 TGraphDelaunay2D *dt = nullptr;
9522 TGraphDelaunay *dtOld = nullptr;
9523
9524 // Check if fH contains a TGraphDelaunay2D
9526 dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
9527 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
9528 if (!dt && !dtOld) return;
9529
9530 // If needed, create a TGraph2DPainter
9531 if (!fGraph2DPainter)
9532 fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
9533
9534 // Define the 3D view
9535 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
9536 if (Hoption.Same) {
9537 TView *viewsame = gPad ? gPad->GetView() : nullptr;
9538 if (!viewsame) {
9539 Error("PaintTriangles", "no TView in current pad, do not use option SAME");
9540 return;
9541 }
9542 Double_t *rmin = viewsame->GetRmin();
9543 Double_t *rmax = viewsame->GetRmax();
9544 if (!rmin || !rmax) return;
9545 fXbuf[0] = rmin[0];
9546 fYbuf[0] = rmax[0];
9547 fXbuf[1] = rmin[1];
9548 fYbuf[1] = rmax[1];
9549 fXbuf[2] = rmin[2];
9550 fYbuf[2] = rmax[2];
9551 fH->SetMaximum(rmax[2]);
9552 fH->SetMinimum(rmin[2]);
9553 fH->GetXaxis()->SetRangeUser(rmin[0],rmax[0]);
9554 fH->GetYaxis()->SetRangeUser(rmin[1],rmax[1]);
9555 } else {
9556 fXbuf[0] = Hparam.xmin;
9557 fYbuf[0] = Hparam.xmax;
9558 fXbuf[1] = Hparam.ymin;
9559 fYbuf[1] = Hparam.ymax;
9560 fXbuf[2] = Hparam.zmin;
9561 fYbuf[2] = Hparam.zmax;
9562 }
9563
9564 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
9565 TView *view = gPad ? gPad->GetView() : nullptr;
9566 if (!view) {
9567 Error("PaintTriangles", "no TView in current pad");
9568 return;
9569 }
9570 Double_t thedeg = 90 - gPad->GetTheta();
9571 Double_t phideg = -90 - gPad->GetPhi();
9572 Double_t psideg = view->GetPsi();
9573 Int_t irep;
9574 view->SetView(phideg, thedeg, psideg, irep);
9575
9576 // Set color/style for back box
9577 fLego->SetFillStyle(gPad->GetFrameFillStyle());
9578 fLego->SetFillColor(gPad->GetFrameFillColor());
9579 fLego->TAttFill::Modify();
9580 Int_t backcolor = gPad->GetFrameFillColor();
9581 if (Hoption.System != kCARTESIAN) backcolor = 0;
9582 view->PadRange(backcolor);
9583 fLego->SetFillStyle(fH->GetFillStyle());
9584 fLego->SetFillColor(fH->GetFillColor());
9585 fLego->TAttFill::Modify();
9586
9587 // Paint the Back Box if needed
9588 if (Hoption.BackBox && !Hoption.Same) {
9589 fLego->InitMoveScreen(-1.1,1.1);
9590 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9592 fLego->BackBox(90);
9593 }
9594
9595 // Paint the triangles
9596 fGraph2DPainter->Paint(option);
9597
9598 // Paint the Front Box if needed
9599 if (Hoption.FrontBox) {
9600 fLego->InitMoveScreen(-1.1,1.1);
9602 fLego->FrontBox(90);
9603 }
9604
9605 // Paint the Axis if needed
9606 if (!Hoption.Axis && !Hoption.Same) {
9607 TGaxis axis;
9608 PaintLegoAxis(&axis, 90);
9609 }
9610
9612
9613 fLego.reset();
9614}
9615
9616////////////////////////////////////////////////////////////////////////////////
9617/// Define the color levels used to paint legos, surfaces etc..
9618
9620{
9621
9622 Int_t i, irep;
9623
9624 // Initialize the color levels
9625 if (ndivz >= 100) {
9626 Warning("PaintSurface", "too many color levels, %d >= 100, reset to 99", ndivz);
9627 ndivz = 99;
9628 }
9629 std::vector<Double_t> funlevel(ndivz+1);
9630 std::vector<Int_t> colorlevel(ndivz+1);
9632 Int_t ncolors = gStyle->GetNumberOfColors();
9633 for (i = 0; i < ndivz; ++i) {
9635 theColor = Int_t((i+0.99)*Float_t(ncolors)/Float_t(ndivz));
9637 }
9638 colorlevel[ndivz] = gStyle->GetColorPalette(ncolors-1);
9639 fLego->ColorFunction(ndivz, funlevel.data(), colorlevel.data(), irep);
9640}
9641
9642////////////////////////////////////////////////////////////////////////////////
9643/// [Control function to draw 2D/3D histograms (tables).](\ref HP01c)
9644
9646{
9647
9648 // Fill Hparam structure with histo parameters
9649 if (!TableInit()) return;
9650
9651 // Draw histogram frame
9652 PaintFrame();
9653
9654 // If palette option not specified, delete a possible existing palette
9655 if (!Hoption.Zscale) {
9656 TObject *palette = fFunctions->FindObject("palette");
9657 if (palette) { fFunctions->Remove(palette); delete palette;}
9658 }
9659
9660 // Do not draw the histogram. Only the attached functions will be drawn.
9661 if (Hoption.Func == 2) {
9662 if (Hoption.Zscale) {
9663 Int_t ndiv = fH->GetContour();
9664 if (ndiv == 0 ) {
9665 ndiv = gStyle->GetNumberContours();
9666 fH->SetContour(ndiv);
9667 }
9668 PaintPalette();
9669 }
9670
9671 // Draw the histogram according to the option
9672 } else {
9673 if (fH->InheritsFrom(TH2Poly::Class()) && Hoption.Axis<=0) {
9674 if (Hoption.Fill) PaintTH2PolyBins("f");
9678 if (Hoption.Line) PaintTH2PolyBins("l");
9679 if (Hoption.Mark) PaintTH2PolyBins("P");
9680 } else if (Hoption.Axis<=0) {
9684 if (Hoption.Color) {
9687 }
9690 if (Hoption.Error >= 100) Paint2DErrors(option);
9692 }
9696 }
9697
9698 // Draw histogram title
9699 PaintTitle();
9700
9701 // Draw the axes
9702 if (!Hoption.Lego && !Hoption.Surf &&
9703 !Hoption.Tri && !(Hoption.Error >= 100)) PaintAxis(kFALSE);
9704
9705 TF1 *fit = nullptr;
9706 TIter next(fFunctions);
9707 while (auto obj = next()) {
9708 if (obj->InheritsFrom(TF1::Class())) {
9709 fit = (TF1*)obj;
9710 break;
9711 }
9712 }
9713 if ((Hoption.Same%10) != 1) {
9714 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
9715 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
9716 //ALWAYS executed on non-iOS platform.
9717 //On iOS, depends on mode.
9719 }
9720 }
9721 }
9722}
9723
9724////////////////////////////////////////////////////////////////////////////////
9725/// Control function to draw a TH2Poly bins' contours.
9726///
9727/// - option = "F" draw the bins as filled areas.
9728/// - option = "L" draw the bins as line.
9729/// - option = "P" draw the bins as markers.
9730
9732{
9733
9734 //Do not highlight the histogram, if its part was picked.
9735 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH) return;
9736
9737 TString opt = option;
9738 opt.ToLower();
9739 Bool_t line = kFALSE;
9740 Bool_t fill = kFALSE;
9741 Bool_t mark = kFALSE;
9742 if (opt.Contains("l")) line = kTRUE;
9743 if (opt.Contains("f")) fill = kTRUE;
9744 if (opt.Contains("p")) mark = kTRUE;
9745
9746 TH2PolyBin *b;
9747 Double_t z;
9748
9749 TIter next(((TH2Poly*)fH)->GetBins());
9750 TObject *obj, *poly;
9751
9752 while ((obj=next())) {
9753 b = (TH2PolyBin*)obj;
9754 z = b->GetContent();
9755 if (z==0 && Hoption.Zero) continue; // Do not draw empty bins in case of option "COL0 L"
9756 poly = b->GetPolygon();
9757
9758 // Paint the TGraph bins.
9759 if (poly->IsA() == TGraph::Class()) {
9760 TGraph *g = (TGraph*)poly;
9761 g->TAttLine::Modify();
9762 g->TAttMarker::Modify();
9763 g->TAttFill::Modify();
9764 if (line) {
9765 Int_t fs = g->GetFillStyle();
9767 g->SetFillStyle(0);
9769 g->Paint("F");
9771 g->SetFillStyle(fs);
9772 }
9773 if (fill) g->Paint("F");
9774 if (mark) g->Paint("P");
9775 }
9776
9777 // Paint the TMultiGraph bins.
9778 if (poly->IsA() == TMultiGraph::Class()) {
9780 TList *gl = mg->GetListOfGraphs();
9781 if (!gl) return;
9782 TGraph *g;
9783 TIter nextg(gl);
9784 while ((g = (TGraph*) nextg())) {
9785 g->TAttLine::Modify();
9786 g->TAttMarker::Modify();
9787 g->TAttFill::Modify();
9788 if (line) {
9789 Int_t fs = g->GetFillStyle();
9791 g->SetFillStyle(0);
9793 g->Paint("F");
9795 g->SetFillStyle(fs);
9796 }
9797 if (fill) g->Paint("F");
9798 if (mark) g->Paint("P");
9799 }
9800 }
9801 }
9802}
9803
9804////////////////////////////////////////////////////////////////////////////////
9805/// [Control function to draw a TH2Poly as a color plot.](\ref HP20a)
9806
9808{
9809
9810 //Do not highlight the histogram, if its part was picked.
9811 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
9812 return;
9813
9814 Int_t ncolors, color, theColor;
9815 Double_t z, zc;
9816 Double_t zmin = fH->GetMinimum();
9817 Double_t zmax = fH->GetMaximum();
9818 if (Hoption.Logz) {
9819 if (zmax > 0) {
9820 if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
9821 zmin = TMath::Log10(zmin);
9822 zmax = TMath::Log10(zmax);
9823 } else {
9824 return;
9825 }
9826 }
9827 Double_t dz = zmax - zmin;
9828
9829 // Initialize the levels on the Z axis
9830 ncolors = gStyle->GetNumberOfColors();
9831 Int_t ndiv = fH->GetContour();
9832 if (ndiv == 0 ) {
9833 ndiv = gStyle->GetNumberContours();
9834 fH->SetContour(ndiv);
9835 }
9836 Int_t ndivz = TMath::Abs(ndiv);
9837 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
9839
9840 TIter next(((TH2Poly*)fH)->GetBins());
9841
9842 while (auto obj = next()) {
9843 TH2PolyBin *b = (TH2PolyBin*)obj;
9844 TObject *poly = b->GetPolygon();
9845
9846 z = b->GetContent();
9847 if (z==0 && Hoption.Zero) continue;
9848 if (Hoption.Logz) {
9849 if (z > 0) z = TMath::Log10(z);
9850 else z = zmin;
9851 }
9852 if (z < zmin) continue;
9853
9854 // Define the bin color.
9856 zc = fH->GetContourLevelPad(0);
9857 if (z < zc) continue;
9858 color = -1;
9859 for (Int_t k=0; k<ndiv; k++) {
9860 zc = fH->GetContourLevelPad(k);
9861 if (z < zc) {
9862 continue;
9863 } else {
9864 color++;
9865 }
9866 }
9867 } else {
9868 color = Int_t(0.01+(z-zmin)*scale);
9869 }
9870 theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
9871 if (theColor > ncolors-1) theColor = ncolors-1;
9872
9873 // Paint the TGraph bins.
9874 if (poly->IsA() == TGraph::Class()) {
9875 TGraph *g = (TGraph*)poly;
9876 g->SetFillColor(gStyle->GetColorPalette(theColor));
9877 g->TAttFill::Modify();
9878 g->Paint("F");
9879 }
9880
9881 // Paint the TMultiGraph bins.
9882 if (poly->IsA() == TMultiGraph::Class()) {
9884 TList *gl = mg->GetListOfGraphs();
9885 if (!gl) return;
9886 TGraph *g;
9887 TIter nextg(gl);
9888 while ((g = (TGraph*) nextg())) {
9889 g->SetFillColor(gStyle->GetColorPalette(theColor));
9890 g->TAttFill::Modify();
9891 g->Paint("F");
9892 }
9893 }
9894 }
9896}
9897
9898////////////////////////////////////////////////////////////////////////////////
9899/// [Control function to draw a TH2Poly as a scatter plot.](\ref HP20a)
9900
9902{
9903
9904 //Do not highlight the histogram, if its part was selected.
9905 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
9906 return;
9907
9908 Int_t k, loop, marker=0;
9909 Double_t z, xk,xstep, yk, ystep, xp, yp;
9910 Double_t scale = 1;
9911 Double_t zmin = fH->GetMinimum();
9912 Double_t zmax = fH->GetMaximum();
9913 if (Hoption.Logz) {
9914 if (zmax > 0) {
9915 if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
9916 zmin = TMath::Log10(zmin);
9917 zmax = TMath::Log10(zmax);
9918 } else {
9919 return;
9920 }
9921 }
9922 Double_t dz = zmax - zmin;
9923 scale = (kNMAX-1)/dz;
9924
9925
9926 // use an independent instance of a random generator
9927 // instead of gRandom to avoid conflicts and
9928 // to get same random numbers when drawing the same histogram
9930
9931 TH2PolyBin *b;
9932
9933 TIter next(((TH2Poly*)fH)->GetBins());
9934 TObject *obj, *poly;
9935
9936 Double_t maxarea = 0, a;
9937 while ((obj=next())) {
9938 b = (TH2PolyBin*)obj;
9939 a = b->GetArea();
9940 if (a>maxarea) maxarea = a;
9941 }
9942
9943 next.Reset();
9944
9945 while ((obj=next())) {
9946 b = (TH2PolyBin*)obj;
9947 poly = b->GetPolygon();
9948 z = b->GetContent();
9949 if (z < zmin) z = zmin;
9950 if (z > zmax) z = zmax;
9951 if (Hoption.Logz) {
9952 if (z > 0) z = TMath::Log10(z) - zmin;
9953 } else {
9954 z -= zmin;
9955 }
9956 k = Int_t((z*scale)*(b->GetArea()/maxarea));
9957 xk = b->GetXMin();
9958 yk = b->GetYMin();
9959 xstep = b->GetXMax()-xk;
9960 ystep = b->GetYMax()-yk;
9961
9962 // Paint the TGraph bins.
9963 if (poly->IsA() == TGraph::Class()) {
9964 TGraph *g = (TGraph*)poly;
9965 if (k <= 0 || z <= 0) continue;
9966 loop = 0;
9967 while (loop<k) {
9968 if (k+marker >= kNMAX) {
9969 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
9970 marker=0;
9971 }
9972 xp = (random.Rndm()*xstep) + xk;
9973 yp = (random.Rndm()*ystep) + yk;
9974 if (g->IsInside(xp,yp)) {
9975 fXbuf[marker] = xp;
9976 fYbuf[marker] = yp;
9977 marker++;
9978 loop++;
9979 }
9980 }
9981 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
9982 }
9983
9984 // Paint the TMultiGraph bins.
9985 if (poly->IsA() == TMultiGraph::Class()) {
9987 TList *gl = mg->GetListOfGraphs();
9988 if (!gl) return;
9989 if (k <= 0 || z <= 0) continue;
9990 loop = 0;
9991 while (loop<k) {
9992 if (k+marker >= kNMAX) {
9993 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
9994 marker=0;
9995 }
9996 xp = (random.Rndm()*xstep) + xk;
9997 yp = (random.Rndm()*ystep) + yk;
9998 if (mg->IsInside(xp,yp)) {
9999 fXbuf[marker] = xp;
10000 fYbuf[marker] = yp;
10001 marker++;
10002 loop++;
10003 }
10004 }
10005 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10006 }
10007 }
10008 PaintTH2PolyBins("l");
10009}
10010
10011////////////////////////////////////////////////////////////////////////////////
10012/// [Control function to draw a TH2Poly as a text plot.](\ref HP20a)
10013
10015{
10016
10017 TLatex text;
10018 text.SetTextFont(gStyle->GetTextFont());
10019 text.SetTextColor(fH->GetMarkerColor());
10020 text.SetTextSize(0.02*fH->GetMarkerSize());
10021
10022 Double_t x, y, z, e, angle = 0;
10023 TString tt, tf;
10024 tf.Form("%s%s","%",gStyle->GetPaintTextFormat());
10025 if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
10026 Int_t opt = (Int_t)Hoption.Text/1000;
10027
10028 text.SetTextAlign(22);
10029 if (Hoption.Text == 1) angle = 0;
10030 text.SetTextAngle(angle);
10031 text.TAttText::Modify();
10032
10033 TH2PolyBin *b;
10034
10035 TIter next(((TH2Poly*)fH)->GetBins());
10036 TObject *obj, *p;
10037
10038 while ((obj=next())) {
10039 b = (TH2PolyBin*)obj;
10040 p = b->GetPolygon();
10041 x = (b->GetXMin()+b->GetXMax())/2;
10042 if (Hoption.Logx) {
10043 if (x > 0) x = TMath::Log10(x);
10044 else continue;
10045 }
10046 y = (b->GetYMin()+b->GetYMax())/2;
10047 if (Hoption.Logy) {
10048 if (y > 0) y = TMath::Log10(y);
10049 else continue;
10050 }
10051 z = b->GetContent();
10052 if (z < fH->GetMinimum() || (z == 0 && !Hoption.MinimumZero)) continue;
10053 if (opt==2) {
10054 e = fH->GetBinError(b->GetBinNumber());
10055 tf.Form("#splitline{%s%s}{#pm %s%s}",
10057 "%",gStyle->GetPaintTextFormat());
10058 tt.Form(tf.Data(),z,e);
10059 } else {
10060 tt.Form(tf.Data(),z);
10061 }
10062 if (opt==3) text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),p->GetName());
10063 else text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),tt.Data());
10064 }
10065
10066 PaintTH2PolyBins("l");
10067}
10068
10069////////////////////////////////////////////////////////////////////////////////
10070/// [Control function to draw a 1D/2D histograms with the bin values.](\ref HP15)
10071
10073{
10074
10075 TLatex text;
10076 text.SetTextFont(((int)gStyle->GetTextFont()/10)*10+2); // font precision must be 2
10077 text.SetTextColor(fH->GetMarkerColor());
10078 text.SetTextSize(0.02*fH->GetMarkerSize());
10079
10080 Double_t x, y, z, e, angle = 0;
10081 TString tt, tf;
10082 tf.Form("%s%s","%",gStyle->GetPaintTextFormat());
10083 if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
10084
10085 // 1D histograms
10086 if (fH->GetDimension() == 1) {
10088 Double_t yt;
10089 TProfile *hp = (TProfile*)fH;
10090 if (Hoption.Text>2000 && fH->InheritsFrom(TProfile::Class())) {
10091 Hoption.Text = Hoption.Text-2000;
10092 getentries = kTRUE;
10093 }
10094 if (Hoption.Text == 1) angle = 90;
10095 text.SetTextAlign(11);
10096 if (angle == 90) text.SetTextAlign(12);
10097 if (angle == 0) text.SetTextAlign(21);
10098 text.TAttText::Modify();
10099 Double_t dt = 0.02*(gPad->GetY2()-gPad->GetY1());
10100 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10101 if (Hoption.Bar) {
10102 x = fH->GetXaxis()->GetBinLowEdge(i)+
10103 fH->GetXaxis()->GetBinWidth(i)*
10104 (fH->GetBarOffset()+0.5*fH->GetBarWidth());
10105 } else {
10106 x = fH->GetXaxis()->GetBinCenter(i);
10107 }
10108 y = fH->GetBinContent(i);
10109 yt = y;
10110 if (Hoption.MinimumZero && y<0) y = 0;
10111 if (getentries) yt = hp->GetBinEntries(i);
10112 if (yt == 0.) continue;
10113 tt.Form(tf.Data(),yt);
10114 if (Hoption.Logx) {
10115 if (x > 0) x = TMath::Log10(x);
10116 else continue;
10117 }
10118 if (Hoption.Logy) {
10119 if (y > 0) y = TMath::Log10(y);
10120 else continue;
10121 }
10122 if (y >= gPad->GetY2()) continue;
10123 if (y <= gPad->GetY1()) continue;
10124 text.PaintLatex(x,y+0.2*dt,angle,0.02*fH->GetMarkerSize(),tt.Data());
10125 }
10126
10127 // 2D histograms
10128 } else {
10129 text.SetTextAlign(22);
10130 if (Hoption.Text == 1) angle = 0;
10131 text.SetTextAngle(angle);
10132 text.TAttText::Modify();
10133 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
10134 y = fYaxis->GetBinCenter(j);
10135 if (Hoption.Logy) {
10136 if (y > 0) y = TMath::Log10(y);
10137 else continue;
10138 }
10139 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10140 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
10141 x = fXaxis->GetBinCenter(i);
10142 if (Hoption.Logx) {
10143 if (x > 0) x = TMath::Log10(x);
10144 else continue;
10145 }
10146 if (!IsInside(x,y)) continue;
10147 z = fH->GetBinContent(bin);
10148 if (z < Hparam.zmin || (z == 0 && !Hoption.MinimumZero)) continue;
10149 if (Hoption.Text>2000) {
10150 e = fH->GetBinError(bin);
10151 tf.Form("#splitline{%s%s}{#pm %s%s}",
10153 "%",gStyle->GetPaintTextFormat());
10154 tt.Form(tf.Data(),z,e);
10155 } else {
10156 tt.Form(tf.Data(),z);
10157 }
10158 text.PaintLatex(x,y+fH->GetBarOffset()*fYaxis->GetBinWidth(j),
10159 angle,0.02*fH->GetMarkerSize(),tt.Data());
10160 }
10161 }
10162 }
10163}
10164
10165////////////////////////////////////////////////////////////////////////////////
10166/// [Control function to draw a 3D implicit functions.](\ref HP27)
10167
10169{
10170
10171 Int_t irep;
10172
10173 TAxis *xaxis = fH->GetXaxis();
10174 TAxis *yaxis = fH->GetYaxis();
10175 TAxis *zaxis = fH->GetZaxis();
10176
10177 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
10178 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
10179 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
10180 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
10181 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
10182 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
10183
10184 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
10185
10186 TView *view = gPad ? gPad->GetView() : nullptr;
10187 if (!view) {
10188 Error("PaintTF3", "no TView in current pad");
10189 return;
10190 }
10191 Double_t thedeg = 90 - gPad->GetTheta();
10192 Double_t phideg = -90 - gPad->GetPhi();
10193 Double_t psideg = view->GetPsi();
10194 view->SetView(phideg, thedeg, psideg, irep);
10195
10196 fLego->InitMoveScreen(-1.1,1.1);
10197
10198 if (Hoption.BackBox) {
10199 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
10201 fLego->BackBox(90);
10202 }
10203
10205
10206 fLego->ImplicitFunction(fCurrentF3, fXbuf.data(), fYbuf.data(), fH->GetNbinsX(),
10207 fH->GetNbinsY(),
10208 fH->GetNbinsZ(), "BF");
10209
10210 if (Hoption.FrontBox) {
10211 fLego->InitMoveScreen(-1.1,1.1);
10213 fLego->FrontBox(90);
10214 }
10215 if (!Hoption.Axis && !Hoption.Same) {
10216 TGaxis axis;
10217 PaintLegoAxis(&axis, 90);
10218 }
10219
10220 PaintTitle();
10221
10222 fLego.reset();
10223}
10224
10225/////////////////////////////////////////////////////////////new TGaxis///////////////////
10226/// Draw the histogram title
10227///
10228/// The title is drawn according to the title alignment returned by
10229/// `GetTitleAlign()`. It is a 2 digits integer): hv
10230///
10231/// where `h` is the horizontal alignment and `v` is the
10232/// vertical alignment.
10233///
10234/// - `h` can get the values 1 2 3 for left, center, and right
10235/// - `v` can get the values 1 2 3 for bottom, middle and top
10236///
10237/// for instance the default alignment is: 13 (left top)
10238
10240{
10241 // probably best place for calls PaintHighlightBin
10242 // calls after paint histo (1D or 2D) and before paint title and stats
10243 if (!gPad->GetView()) PaintHighlightBin();
10244
10245 if (Hoption.Same) return;
10246 if (fH->TestBit(TH1::kNoTitle)) return;
10247 Int_t nt = strlen(fH->GetTitle());
10248 TPaveText *title = nullptr;
10249 TObject *obj;
10250 TIter next(gPad->GetListOfPrimitives());
10251 while ((obj = next())) {
10252 if (!obj->InheritsFrom(TPaveText::Class())) continue;
10253 title = (TPaveText*)obj;
10254 if (strcmp(title->GetName(),"title")) {title = nullptr; continue;}
10255 break;
10256 }
10257 if (nt == 0 || gStyle->GetOptTitle() <= 0) {
10258 if (title) delete title;
10259 return;
10260 }
10263
10264 if (ht <= 0) {
10265 if (gStyle->GetTitleFont("")%10 == 3) {
10266 Double_t hw = TMath::Max((Double_t)gPad->XtoPixel(gPad->GetX2()),
10267 (Double_t)gPad->YtoPixel(gPad->GetY1()));
10268 ht = 1.1*(gStyle->GetTitleSize("")/hw);
10269 } else {
10270 ht = 1.1*gStyle->GetTitleFontSize();
10271 }
10272 }
10273 if (ht <= 0) ht = 0.05;
10274 if (wt <= 0) {
10275 TLatex l;
10276 l.SetTextSize(ht);
10277 l.SetTitle(fH->GetTitle());
10278 // adjustment in case the title has several lines (#splitline)
10279 ht = TMath::Max(ht, 1.2*l.GetYsize()/(gPad->GetY2() - gPad->GetY1()));
10280 Double_t wndc = l.GetXsize()/(gPad->GetX2() - gPad->GetX1());
10281 wt = TMath::Min(0.7, 0.02+wndc);
10282 }
10283 if (title) {
10284 TText *t0 = (TText*)title->GetLine(0);
10285 if (t0) {
10286 if (!strcmp(t0->GetTitle(),fH->GetTitle())) return;
10287 t0->SetTitle(fH->GetTitle());
10288 if (wt > 0) title->SetX2NDC(title->GetX1NDC()+wt);
10289 }
10290 return;
10291 }
10292
10294 if (talh < 1) talh = 1; else if (talh > 3) talh = 3;
10296 if (talv < 1) talv = 1; else if (talv > 3) talv = 3;
10298 xpos = gStyle->GetTitleX();
10299 ypos = gStyle->GetTitleY();
10300 if (talh == 2) xpos = xpos-wt/2.;
10301 if (talh == 3) xpos = xpos-wt;
10302 if (talv == 2) ypos = ypos+ht/2.;
10303 if (talv == 1) ypos = ypos+ht;
10304
10305 TPaveText *ptitle = new TPaveText(xpos, ypos-ht, xpos+wt, ypos,"blNDC");
10306
10307 // box with the histogram title
10308 ptitle->SetFillColor(gStyle->GetTitleFillColor());
10309 ptitle->SetFillStyle(gStyle->GetTitleStyle());
10310 ptitle->SetName("title");
10311 ptitle->SetBorderSize(gStyle->GetTitleBorderSize());
10312 ptitle->SetTextColor(gStyle->GetTitleTextColor());
10313 ptitle->SetTextFont(gStyle->GetTitleFont(""));
10314 if (gStyle->GetTitleFont("")%10 > 2)
10315 ptitle->SetTextSize(gStyle->GetTitleFontSize());
10316 ptitle->AddText(fH->GetTitle());
10317 ptitle->SetBit(kCanDelete);
10318 ptitle->Draw();
10319 ptitle->Paint("blNDC");
10320
10321 if(!gPad->IsEditable()) delete ptitle;
10322}
10323
10324////////////////////////////////////////////////////////////////////////////////
10325/// Process message `mess`.
10326
10327void THistPainter::ProcessMessage(const char *mess, const TObject *obj)
10328{
10329 if (!strcmp(mess,"SetF3")) {
10330 fCurrentF3 = (TF3 *)obj;
10331 }
10332}
10333
10334////////////////////////////////////////////////////////////////////////////////
10335/// Static function.
10336///
10337/// Convert Right Ascension, Declination to X,Y using an AITOFF projection.
10338/// This procedure can be used to create an all-sky map in Galactic
10339/// coordinates with an equal-area Aitoff projection. Output map
10340/// coordinates are zero longitude centered.
10341/// Also called Hammer-Aitoff projection (first presented by Ernst von Hammer in 1892)
10342///
10343/// source: GMT
10344///
10345/// code from Ernst-Jan Buis
10346
10348{
10349
10350 Double_t x, y;
10351
10353 Double_t delta = b*TMath::DegToRad();
10354 Double_t r2 = TMath::Sqrt(2.);
10355 Double_t f = 2*r2/TMath::Pi();
10356 Double_t cdec = TMath::Cos(delta);
10359 y = TMath::Sin(delta)*r2/denom;
10360 x *= TMath::RadToDeg()/f;
10361 y *= TMath::RadToDeg()/f;
10362 // x *= -1.; // for a skymap swap left<->right
10363 Al = x;
10364 Ab = y;
10365
10366 return 0;
10367}
10368
10369////////////////////////////////////////////////////////////////////////////////
10370/// Static function
10371///
10372/// Probably the most famous of the various map projections, the Mercator projection
10373/// takes its name from Mercator who presented it in 1569. It is a cylindrical, conformal projection
10374/// with no distortion along the equator.
10375/// The Mercator projection has been used extensively for world maps in which the distortion towards
10376/// the polar regions grows rather large, thus incorrectly giving the impression that, for example,
10377/// Greenland is larger than South America. In reality, the latter is about eight times the size of
10378/// Greenland. Also, the Former Soviet Union looks much bigger than Africa or South America. One may wonder
10379/// whether this illusion has had any influence on U.S. foreign policy.' (Source: GMT)
10380/// code from Ernst-Jan Buis
10381
10383{
10384
10385 Al = l;
10387 Ab = TMath::Log(aid);
10388 return 0;
10389}
10390
10391////////////////////////////////////////////////////////////////////////////////
10392/// Static function code for sinusoidal projection
10393/// from Ernst-Jan Buis
10394/// Source https://en.wikipedia.org/wiki/Sinusoidal_projection
10395
10397{
10398
10399 Al = l*cos(b*TMath::DegToRad());
10400 Ab = b;
10401 return 0;
10402}
10403
10404////////////////////////////////////////////////////////////////////////////////
10405/// Static function code for parabolic projection
10406/// from Ernst-Jan Buis
10407
10409{
10410
10411 Al = l*(2.*TMath::Cos(2*b*TMath::DegToRad()/3) - 1);
10412 Ab = 180*TMath::Sin(b*TMath::DegToRad()/3);
10413 return 0;
10414}
10415
10416////////////////////////////////////////////////////////////////////////////////
10417/// Static function.
10418///
10419/// Convert Right Ascension, Declination to X,Y using an MOLLWEIDE projection.
10420/// This procedure can be used to create an all-sky map in Galactic
10421/// coordinates with an equal-area Mollweide projection. Output map
10422/// coordinates are zero longitude centered.
10423/// It is also known as the Babinet projection, homalographic projection, homolographic projection, and elliptical projection.
10424/// Source: https://en.wikipedia.org/wiki/Mollweide_projection
10425///
10426/// code from Marco Meyer-Conde
10427
10429{
10430
10431 Double_t theta0 = b * TMath::DegToRad(), theta = theta0;
10432
10433 for (int i = 0; i < 100; i++) {
10434 Double_t num = 2 * theta + TMath::Sin(2 * theta) - TMath::Pi() * TMath::Sin(theta0);
10435 Double_t den = 4 * TMath::Power(TMath::Cos(theta), 2);
10436
10437 if (den < 1e-20) {
10438 theta = theta0;
10439 break;
10440 }
10441
10442 theta -= num / den;
10443
10444 if (TMath::Abs(num / den) < 1e-4) break;
10445 }
10446
10447 Al = l * TMath::Cos(theta);
10448 Ab = 90 * TMath::Sin(theta);
10449
10450 return 0;
10451}
10452
10453////////////////////////////////////////////////////////////////////////////////
10454/// Recompute the histogram range following graphics operations.
10455
10457{
10458
10459 if (Hoption.Same) return;
10460
10461 // Compute x,y range
10463 xmax = Hparam.xmax,
10464 ymin = Hparam.ymin,
10465 ymax = Hparam.ymax,
10466 xscale = 1;
10467
10468 std::function<Int_t(Double_t,Double_t,Double_t&,Double_t&)> func;
10469
10470 if (Hoption.Proj == 1) {
10471 func = ProjectAitoff2xy;
10472 xscale = 0.9999;
10473 } else if (Hoption.Proj == 2) {
10474 if (Hparam.ymin <= -90 || Hparam.ymax >= 90) {
10475 Warning("Mercator Projection", "Latitude out of range %f or %f", Hparam.ymin, Hparam.ymax);
10476 Hoption.Proj = 0;
10477 } else {
10480 }
10481 } else if (Hoption.Proj == 3) {
10482 func = ProjectSinusoidal2xy;
10483 } else if (Hoption.Proj == 4) {
10484 func = ProjectParabolic2xy;
10485 } else if (Hoption.Proj == 5) {
10486 func = ProjectMollweide2xy;
10487 }
10488
10489 if (func) {
10491
10495 func(Hparam.xmax, Hparam.ymin, xmax, ymin);
10496
10497 if (xmin > xmin_aid) xmin = xmin_aid;
10498 if (ymin > ymin_aid) ymin = ymin_aid;
10499 if (xmax < xmax_aid) xmax = xmax_aid;
10500 if (ymax < ymax_aid) ymax = ymax_aid;
10501 if (Hparam.ymin < 0 && Hparam.ymax > 0) {
10502 // there is an 'equator', check its range in the plot..
10503 func(Hparam.xmin*xscale, 0, xmin_aid, ymin_aid);
10504 func(Hparam.xmax*xscale, 0, xmax_aid, ymin_aid);
10505 if (xmin > xmin_aid) xmin = xmin_aid;
10506 if (xmax < xmax_aid) xmax = xmax_aid;
10507 }
10508 if (Hparam.xmin < 0 && Hparam.xmax > 0) {
10509 func(0, Hparam.ymin, xmin_aid, ymin_aid);
10510 func(0, Hparam.ymax, xmax_aid, ymax_aid);
10511 if (ymin > ymin_aid) ymin = ymin_aid;
10512 if (ymax < ymax_aid) ymax = ymax_aid;
10513 }
10514 }
10515
10516 Hparam.xmin = xmin;
10517 Hparam.xmax = xmax;
10518 Hparam.ymin = ymin;
10519 Hparam.ymax = ymax;
10520
10521 Double_t dx = xmax-xmin;
10522 Double_t dy = ymax-ymin;
10523 Double_t dxr = dx/(1 - gPad->GetLeftMargin() - gPad->GetRightMargin());
10524 Double_t dyr = dy/(1 - gPad->GetBottomMargin() - gPad->GetTopMargin());
10525
10526 // Range() could change the size of the pad pixmap and therefore should
10527 // be called before the other paint routines
10528 gPad->Range(xmin - dxr*gPad->GetLeftMargin(),
10529 ymin - dyr*gPad->GetBottomMargin(),
10530 xmax + dxr*gPad->GetRightMargin(),
10531 ymax + dyr*gPad->GetTopMargin());
10532 gPad->RangeAxis(xmin, ymin, xmax, ymax);
10533}
10534
10535////////////////////////////////////////////////////////////////////////////////
10536/// Set current histogram to `h`
10537
10539{
10540
10541 if (h == nullptr) return;
10542 fH = h;
10543 fXaxis = h->GetXaxis();
10544 fYaxis = h->GetYaxis();
10545 fZaxis = h->GetZaxis();
10547}
10548
10549////////////////////////////////////////////////////////////////////////////////
10550/// Initialize various options to draw 2D histograms.
10551
10553{
10554
10555 static const char *where = "TableInit";
10556
10557 Int_t first, last;
10559 Double_t zmin, zmax;
10560 Int_t maximum = 0;
10561 Int_t minimum = 0;
10562 if (fH->GetMaximumStored() != -1111) maximum = 1;
10563 if (fH->GetMinimumStored() != -1111) minimum = 1;
10564
10565 // ----------------- Compute X axis parameters
10566 first = fXaxis->GetFirst();
10567 last = fXaxis->GetLast();
10568 Hparam.xlast = last;
10569 Hparam.xfirst = first;
10574
10575 // if log scale in X, replace xmin,max by the log
10576 if (Hoption.Logx) {
10577 // find the first edge of a bin that is > 0
10578 if (Hparam.xlowedge <=0 ) {
10581 }
10582 if (Hparam.xmin <=0 || Hparam.xmax <=0) {
10583 Error(where, "cannot set X axis to log scale");
10584 return 0;
10585 }
10587 if (Hparam.xfirst < first) Hparam.xfirst = first;
10589 if (Hparam.xlast > last) Hparam.xlast = last;
10592 }
10593
10594 // ----------------- Compute Y axis parameters
10595 first = fYaxis->GetFirst();
10596 last = fYaxis->GetLast();
10597 Hparam.ylast = last;
10598 Hparam.yfirst = first;
10601 if (!Hparam.ybinsize) Hparam.ybinsize = 1;
10604
10605 // if log scale in Y, replace ymin,max by the log
10606 if (Hoption.Logy) {
10607 if (Hparam.ylowedge <=0 ) {
10610 }
10611 if (Hparam.ymin <=0 || Hparam.ymax <=0) {
10612 Error(where, "cannot set Y axis to log scale");
10613 return 0;
10614 }
10616 if (Hparam.yfirst < first) Hparam.yfirst = first;
10618 if (Hparam.ylast > last) Hparam.ylast = last;
10621 }
10622
10623
10624 // ----------------- Compute Z axis parameters
10625 Double_t bigp = TMath::Power(10,32);
10626 zmax = -bigp;
10627 zmin = bigp;
10628 Double_t c1, e1;
10629 Double_t allchan = 0;
10630 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
10631 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10632 c1 = fH->GetBinContent(i,j);
10633 zmax = TMath::Max(zmax,c1);
10634 if (Hoption.Error) {
10635 e1 = fH->GetBinError(i,j);
10636 zmax = TMath::Max(zmax,c1+e1);
10637 }
10638 zmin = TMath::Min(zmin,c1);
10639 allchan += c1;
10640 }
10641 }
10642
10643 // Take into account maximum , minimum
10644
10645 if (maximum) zmax = fH->GetMaximumStored();
10646 if (minimum) zmin = fH->GetMinimumStored();
10647 if (Hoption.Logz && zmax < 0) {
10648 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10649 return 0;
10650 } else if (Hoption.Logz && zmin>=0 && zmax==0) { // empty histogram in log scale
10651 zmin = 0.01;
10652 zmax = 10.;
10653 }
10654 if (zmin >= zmax) {
10655 if (Hoption.Logz) {
10656 if (zmax > 0) zmin = 0.001*zmax;
10657 else {
10658 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10659 return 0;
10660 }
10661 }
10662 }
10663
10664 // take into account normalization factor
10665 Hparam.allchan = allchan;
10666 Double_t factor = allchan;
10667 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
10668 if (allchan) factor /= allchan;
10669 if (factor == 0) factor = 1;
10670 Hparam.factor = factor;
10671 zmax = factor*zmax;
10672 zmin = factor*zmin;
10673 c1 = zmax;
10674 if (TMath::Abs(zmin) > TMath::Abs(c1)) c1 = zmin;
10675
10676 // For log scales, histogram coordinates are log10(ymin) and
10677 // log10(ymax). Final adjustment (if not option "Same")
10678 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
10679 // Maximum and Minimum are not defined.
10680 if (Hoption.Logz) {
10681 if (zmin <= 0) {
10682 zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
10683 fH->SetMinimum(zmin);
10684 }
10685 zmin = TMath::Log10(zmin);
10686 if (!minimum) zmin += TMath::Log10(0.5);
10687 zmax = TMath::Log10(zmax);
10688 if (!maximum) zmax += TMath::Log10(2*(0.9/0.95));
10689 goto LZMIN;
10690 }
10691
10692 // final adjustment of YMAXI for linear scale (if not option "Same"):
10693 // decrease histogram height to MAX% of allowed height if HMAXIM
10694 // has not been called.
10695 // MAX% is the value in percent which has been set in HPLSET
10696 // (default is 90%).
10697 if (!maximum) {
10698 zmax += yMARGIN*(zmax-zmin);
10699 }
10700
10701 // final adjustment of ymin for linear scale.
10702 // if minimum is not set , then ymin is set to zero if >0
10703 // or to ymin - yMARGIN if <0.
10704 if (!minimum) {
10705 if (Hoption.MinimumZero) {
10706 if (zmin >= 0) zmin = 0;
10707 else zmin -= yMARGIN*(zmax-zmin);
10708 } else {
10709 Double_t dzmin = yMARGIN*(zmax-zmin);
10710 if (zmin >= 0 && (zmin-dzmin <= 0)) zmin = 0;
10711 else zmin -= dzmin;
10712 }
10713 }
10714
10715LZMIN:
10716 Hparam.zmin = zmin;
10717 Hparam.zmax = zmax;
10718
10719 // Set bar offset and width
10722
10723 return 1;
10724}
10725
10726////////////////////////////////////////////////////////////////////////////////
10727/// This function returns the best format to print the error value (e)
10728/// knowing the parameter value (v) and the format (f) used to print it.
10729
10731{
10732
10733 static TString ef;
10734 TString tf, tv;
10735
10736 // print v with the format f in tv.
10737 tf.Form("%s%s","%",f);
10738 tv.Form(tf.Data(),v);
10739
10740 // Analyse tv.
10741 int ie = tv.Index("e");
10742 int iE = tv.Index("E");
10743 int id = tv.Index(".");
10744
10745 // v has been printed with the exponent notation.
10746 // There is 2 cases, the exponent is positive or negative
10747 if (ie >= 0 || iE >= 0) {
10748 if (tv.Index("+") >= 0) {
10749 if (e < 1) {
10750 ef.Form("%s.1f","%");
10751 } else {
10752 if (ie >= 0) {
10753 ef.Form("%s.%de","%",ie-id-1);
10754 } else {
10755 ef.Form("%s.%dE","%",iE-id-1);
10756 }
10757 }
10758 } else {
10759 if (ie >= 0) {
10760 ef.Form("%s.%de","%",ie-id-1);
10761 } else {
10762 ef.Form("%s.%dE","%",iE-id-1);
10763 }
10764 }
10765
10766 // There is not '.' in tv. e will be printed with one decimal digit.
10767 } else if (id < 0) {
10768 ef.Form("%s.1f","%");
10769
10770 // There is a '.' in tv and no exponent notation. e's decimal part will
10771 // have the same number of digits as v's one.
10772 } else {
10773 ef.Form("%s.%df","%",tv.Length()-id-1);
10774 }
10775
10776 return ef.Data();
10777}
10778
10779////////////////////////////////////////////////////////////////////////////////
10780/// Set projection.
10781
10783{
10784 if (fShowProjection2) {
10785 auto name2 = TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2);
10786 auto c2 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name2.Data()));
10787 if (c2) c2->Close();
10788 fShowProjection2 = 0;
10789 }
10790 if (fShowProjection) {
10791 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10792 auto c1 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name1.Data()));
10793 if (c1) c1->Close();
10794 fShowProjection = 0;
10795 }
10796
10797 if (nbins <= 0) return;
10798
10799 TString opt = option;
10800 opt.ToLower();
10801 Int_t projection = 0;
10802 if (opt.Contains("x")) projection = 1;
10803 if (opt.Contains("y")) projection = 2;
10804 if (opt.Contains("z")) projection = 3;
10805 if (opt.Contains("xy")) projection = 4;
10806 if (opt.Contains("yx")) projection = 5;
10807 if (opt.Contains("xz")) projection = 6;
10808 if (opt.Contains("zx")) projection = 7;
10809 if (opt.Contains("yz")) projection = 8;
10810 if (opt.Contains("zy")) projection = 9;
10811 if (projection < 4) fShowOption = option+1;
10812 else fShowOption = option+2;
10813 fShowProjection = projection+100*nbins;
10814 fShowProjection2 = 0;
10815 gROOT->MakeDefCanvas();
10816 gPad->SetName(TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection).Data());
10817 gPad->SetGrid();
10818}
10819
10821{
10822 if (fShowProjection2) {
10823 auto name2 = TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2);
10824 auto c2 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name2.Data()));
10825 if (c2) c2->Close();
10826 fShowProjection2 = 0;
10827 }
10828 if (fShowProjection) {
10829 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10830 auto c1 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name1.Data()));
10831 if (c1) c1->Close();
10832 fShowProjection = 0;
10833 }
10834
10835 if ((nbinsX <= 0) || (nbinsY <= 0)) return;
10836
10837
10838 TString opt = option;
10839 opt.ToLower();
10840 Int_t projection = 0;
10841 if (opt.Contains("x")) projection = 1;
10842 if (opt.Contains("y")) projection = 2;
10843 if (opt.Contains("z")) projection = 3;
10844 if (opt.Contains("xy")) projection = 4;
10845 if (opt.Contains("yx")) projection = 5;
10846 if (opt.Contains("xz")) projection = 6;
10847 if (opt.Contains("zx")) projection = 7;
10848 if (opt.Contains("yz")) projection = 8;
10849 if (opt.Contains("zy")) projection = 9;
10850 if (projection < 4) fShowOption = option+1;
10851 else fShowOption = option+2;
10854 gROOT->MakeDefCanvas();
10855 gPad->SetName(TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection).Data());
10856 gPad->SetGrid();
10857 gROOT->MakeDefCanvas();
10858 gPad->SetName(TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2).Data());
10859 gPad->SetGrid();
10860}
10861
10862
10863////////////////////////////////////////////////////////////////////////////////
10864/// Show projection onto X.
10865
10867{
10868
10869 Int_t nbins = (Int_t)fShowProjection/100;
10870 gPad->SetDoubleBuffer(0); // turn off double buffer mode
10871 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
10872
10873 // Erase old position and draw a line at current position
10874 static int pyold1 = 0;
10875 static int pyold2 = 0;
10876 float uxmin = gPad->GetUxmin();
10877 float uxmax = gPad->GetUxmax();
10878 int pxmin = gPad->XtoAbsPixel(uxmin);
10879 int pxmax = gPad->XtoAbsPixel(uxmax);
10880 Float_t upy = gPad->AbsPixeltoY(py);
10881 Float_t y = gPad->PadtoY(upy);
10882 Int_t biny1 = fH->GetYaxis()->FindBin(y);
10883 Int_t biny2 = TMath::Min(biny1+nbins-1, fH->GetYaxis()->GetNbins());
10884 Int_t py1 = gPad->YtoAbsPixel(gPad->GetLogy() ? TMath::Log10(fH->GetYaxis()->GetBinLowEdge(biny1)) : fH->GetYaxis()->GetBinLowEdge(biny1));
10885 Int_t py2 = gPad->YtoAbsPixel(gPad->GetLogy() ? TMath::Log10(fH->GetYaxis()->GetBinUpEdge(biny2)) : fH->GetYaxis()->GetBinUpEdge(biny2));
10886
10888 gVirtualX->DrawBox(pxmin,py1,pxmax,py2,TVirtualX::kFilled);
10889 pyold1 = py1;
10890 pyold2 = py2;
10891
10892 // Create or set the new canvas proj x
10894 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10895 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(name1.Data());
10896 if (c) {
10897 c->Clear();
10898 } else {
10899 fShowProjection = 0;
10900 fShowProjection2 = 0;
10901 pyold1 = 0;
10902 pyold2 = 0;
10903 return;
10904 }
10905 c->cd();
10906 c->SetLogy(ctxt.GetSaved()->GetLogz());
10907 c->SetLogx(ctxt.GetSaved()->GetLogx());
10908
10909 // Draw slice corresponding to mouse position
10910 TString prjName = TString::Format("slice_px_of_%s",fH->GetName());
10911 TH1D *hp = ((TH2*)fH)->ProjectionX(prjName, biny1, biny2);
10912 if (hp) {
10913 hp->SetFillColor(38);
10914 // apply a patch from Oliver Freyermuth to set the title in the projection
10915 // using the range of the projected Y values
10916 if (biny1 == biny2) {
10919 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
10921 if (fH->GetYaxis()->GetLabels() != nullptr) {
10922 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf] %s", biny1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetYaxis()->GetBinLabel(biny1)));
10923 } else {
10924 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf]", biny1, valuePrecision, valueFrom, valuePrecision, valueTo));
10925 }
10926 } else {
10929 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
10930 // biny1 is used here to get equal precision no matter how large the binrange is,
10931 // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
10933 if (fH->GetYaxis()->GetLabels() != nullptr) {
10934 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)));
10935 } else {
10936 hp->SetTitle(TString::Format("ProjectionX of biny=[%d,%d] [y=%.*lf..%.*lf]", biny1, biny2, valuePrecision, valueFrom, valuePrecision, valueTo));
10937 }
10938 }
10939 hp->SetXTitle(fH->GetXaxis()->GetTitle());
10940 hp->SetYTitle(((TH2*)fH)->GetZaxis()->GetTitle() ? ((TH2*)fH)->GetZaxis()->GetTitle() : "Number of Entries");
10941 hp->Draw();
10942 c->Update();
10943 }
10944}
10945
10946////////////////////////////////////////////////////////////////////////////////
10947/// Show projection onto Y.
10948
10950{
10951
10952 Int_t nbins = (Int_t)fShowProjection/100;
10953 if (fShowProjection2)
10954 nbins = (Int_t)fShowProjection2/100;
10955 gPad->SetDoubleBuffer(0); // turn off double buffer mode
10956 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
10957
10958 // Erase old position and draw a line at current position
10959 static int pxold1 = 0;
10960 static int pxold2 = 0;
10961 float uymin = gPad->GetUymin();
10962 float uymax = gPad->GetUymax();
10963 int pymin = gPad->YtoAbsPixel(uymin);
10964 int pymax = gPad->YtoAbsPixel(uymax);
10965 Float_t upx = gPad->AbsPixeltoX(px);
10966 Float_t x = gPad->PadtoX(upx);
10967 Int_t binx1 = fH->GetXaxis()->FindBin(x);
10968 Int_t binx2 = TMath::Min(binx1+nbins-1, fH->GetXaxis()->GetNbins());
10969 Int_t px1 = gPad->XtoAbsPixel(gPad->GetLogx() ? TMath::Log10(fH->GetXaxis()->GetBinLowEdge(binx1)) : fH->GetXaxis()->GetBinLowEdge(binx1));
10970 Int_t px2 = gPad->XtoAbsPixel(gPad->GetLogx() ? TMath::Log10(fH->GetXaxis()->GetBinUpEdge(binx2)) : fH->GetXaxis()->GetBinUpEdge(binx2));
10971
10973 gVirtualX->DrawBox(px1,pymin,px2,pymax,TVirtualX::kFilled);
10974 pxold1 = px1;
10975 pxold2 = px2;
10976
10977 // Create or set the new canvas proj y
10979
10980 TString name2 = fShowProjection2 ? TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2)
10981 : TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10982
10983 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(name2.Data());
10984 if (c) {
10985 c->Clear();
10986 } else {
10987 fShowProjection = 0;
10988 fShowProjection2 = 0;
10989 pxold1 = 0;
10990 pxold2 = 0;
10991 return;
10992 }
10993 c->cd();
10994 c->SetLogy(ctxt.GetSaved()->GetLogz());
10995 c->SetLogx(ctxt.GetSaved()->GetLogy());
10996
10997 // Draw slice corresponding to mouse position
10998 TString prjName = TString::Format("slice_py_of_%s",fH->GetName());
10999 TH1D *hp = ((TH2*)fH)->ProjectionY(prjName, binx1, binx2);
11000 if (hp) {
11001 hp->SetFillColor(38);
11002 // apply a patch from Oliver Freyermuth to set the title in the projection
11003 // using the range of the projected X values
11004 if (binx1 == binx2) {
11007 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11009 if (fH->GetXaxis()->GetLabels() != nullptr) {
11010 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf] [%s]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetXaxis()->GetBinLabel(binx1)));
11011 } else {
11012 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo));
11013 }
11014 } else {
11017 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11018 // binx1 is used here to get equal precision no matter how large the binrange is,
11019 // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
11021 if (fH->GetXaxis()->GetLabels() != nullptr) {
11022 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)));
11023 } else {
11024 hp->SetTitle(TString::Format("ProjectionY of binx=[%d,%d] [x=%.*lf..%.*lf]", binx1, binx2, valuePrecision, valueFrom, valuePrecision, valueTo));
11025 }
11026 }
11027 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11028 hp->SetYTitle(((TH2*)fH)->GetZaxis()->GetTitle() ? ((TH2*)fH)->GetZaxis()->GetTitle() : "Number of Entries");
11029 hp->Draw(fShowProjection2 ? "hbar" : "");
11030 c->Update();
11031 }
11032}
11033
11034////////////////////////////////////////////////////////////////////////////////
11035/// Show projection (specified by `fShowProjection`) of a `TH3`.
11036/// The drawing option for the projection is in `fShowOption`.
11037///
11038/// First implementation; R.Brun
11039///
11040/// Full implementation: Tim Tran (timtran@jlab.org) April 2006
11041
11043{
11044
11045 Int_t nbins=(Int_t)fShowProjection/100; //decode nbins
11046 if (fH->GetDimension() < 3) {
11047 if (fShowProjection2 % 100 == 1) {
11048 ShowProjectionY(px, py);
11049 }
11050 if (fShowProjection % 100 == 1) {
11051 ShowProjectionX(px, py);
11052 return;
11053 }
11054 if (fShowProjection % 100 == 2) {
11055 ShowProjectionY(px, py);
11056 return;
11057 }
11058 }
11059
11060 gPad->SetDoubleBuffer(0); // turn off double buffer mode
11061 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
11062
11063 // Erase old position and draw a line at current position
11064 TView *view = gPad->GetView();
11065 if (!view) return;
11066 TH3 *h3 = (TH3*)fH;
11067 TAxis *xaxis = h3->GetXaxis();
11068 TAxis *yaxis = h3->GetYaxis();
11069 TAxis *zaxis = h3->GetZaxis();
11070 Double_t u[3],xx[3];
11071
11072 static TPoint line1[2];//store end points of a line, initialised 0 by default
11073 static TPoint line2[2];// second line when slice thickness > 1 bin thickness
11074 static TPoint line3[2];
11075 static TPoint line4[2];
11076 static TPoint endface1[5];
11077 static TPoint endface2[5];
11078 static TPoint rect1[5];//store vertices of the polyline (rectangle), initialsed 0 by default
11079 static TPoint rect2[5];// second rectangle when slice thickness > 1 bin thickness
11080
11081 Double_t uxmin = gPad->GetUxmin();
11082 Double_t uxmax = gPad->GetUxmax();
11083 Double_t uymin = gPad->GetUymin();
11084 Double_t uymax = gPad->GetUymax();
11085
11086 int pxmin = gPad->XtoAbsPixel(uxmin);
11087 int pxmax = gPad->XtoAbsPixel(uxmax);
11088 if (pxmin==pxmax) return;
11089 int pymin = gPad->YtoAbsPixel(uymin);
11090 int pymax = gPad->YtoAbsPixel(uymax);
11091 if (pymin==pymax) return;
11094 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(TString::Format("c_%zx_projection_%d",
11095 (size_t)fH, fShowProjection).Data());
11096 if (!c) {
11097 fShowProjection = 0;
11098 return;
11099 }
11100
11102
11103 switch ((Int_t)fShowProjection%100) {
11104 case 1:
11105 // "x"
11106 {
11107 Int_t firstY = yaxis->GetFirst();
11108 Int_t lastY = yaxis->GetLast();
11110 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11111 yaxis->SetRange(biny,biny2);
11112 Int_t firstZ = zaxis->GetFirst();
11113 Int_t lastZ = zaxis->GetLast();
11115 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11116 zaxis->SetRange(binz,binz2);
11117 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11118 if (nbins>1 && line1[0].GetX()) {
11119 gVirtualX->DrawPolyLine(2,line2);
11120 gVirtualX->DrawPolyLine(2,line3);
11121 gVirtualX->DrawPolyLine(2,line4);
11122 gVirtualX->DrawPolyLine(5,endface1);
11123 gVirtualX->DrawPolyLine(5,endface2);
11124 }
11125 xx[0] = xaxis->GetXmin();
11126 xx[2] = zaxis->GetBinCenter(binz);
11127 xx[1] = yaxis->GetBinCenter(biny);
11128 view->WCtoNDC(xx,u);
11129 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11130 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11131 xx[0] = xaxis->GetXmax();
11132 view->WCtoNDC(xx,u);
11133 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11134 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11135 gVirtualX->DrawPolyLine(2,line1);
11136 if (nbins>1) {
11137 xx[0] = xaxis->GetXmin();
11138 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11139 xx[1] = yaxis->GetBinCenter(biny);
11140 view->WCtoNDC(xx,u);
11141 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11142 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11143 xx[0] = xaxis->GetXmax();
11144 view->WCtoNDC(xx,u);
11145 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11146 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11147
11148 xx[0] = xaxis->GetXmin();
11149 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11150 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11151 view->WCtoNDC(xx,u);
11152 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11153 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11154 xx[0] = xaxis->GetXmax();
11155 view->WCtoNDC(xx,u);
11156 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11157 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11158
11159 xx[0] = xaxis->GetXmin();
11160 xx[2] = zaxis->GetBinCenter(binz);
11161 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11162 view->WCtoNDC(xx,u);
11163 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11164 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11165 xx[0] = xaxis->GetXmax();
11166 view->WCtoNDC(xx,u);
11167 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11168 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11169
11170 endface1[0].SetX(line1[0].GetX());
11171 endface1[0].SetY(line1[0].GetY());
11172 endface1[1].SetX(line2[0].GetX());
11173 endface1[1].SetY(line2[0].GetY());
11174 endface1[2].SetX(line3[0].GetX());
11175 endface1[2].SetY(line3[0].GetY());
11176 endface1[3].SetX(line4[0].GetX());
11177 endface1[3].SetY(line4[0].GetY());
11178 endface1[4].SetX(line1[0].GetX());
11179 endface1[4].SetY(line1[0].GetY());
11180
11181 endface2[0].SetX(line1[1].GetX());
11182 endface2[0].SetY(line1[1].GetY());
11183 endface2[1].SetX(line2[1].GetX());
11184 endface2[1].SetY(line2[1].GetY());
11185 endface2[2].SetX(line3[1].GetX());
11186 endface2[2].SetY(line3[1].GetY());
11187 endface2[3].SetX(line4[1].GetX());
11188 endface2[3].SetY(line4[1].GetY());
11189 endface2[4].SetX(line1[1].GetX());
11190 endface2[4].SetY(line1[1].GetY());
11191
11192 gVirtualX->DrawPolyLine(2,line2);
11193 gVirtualX->DrawPolyLine(2,line3);
11194 gVirtualX->DrawPolyLine(2,line4);
11195 gVirtualX->DrawPolyLine(5,endface1);
11196 gVirtualX->DrawPolyLine(5,endface2);
11197 }
11198 c->Clear();
11199 c->cd();
11200 TH1 *hp = h3->Project3D("x");
11201 yaxis->SetRange(firstY,lastY);
11202 zaxis->SetRange(firstZ,lastZ);
11203 if (hp) {
11204 hp->SetFillColor(38);
11205 if (nbins == 1)
11206 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny),
11207 binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
11208 else {
11209 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),
11210 binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
11211 }
11212 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11213 hp->SetYTitle("Number of Entries");
11214 hp->Draw(fShowOption.Data());
11215 }
11216 }
11217 break;
11218
11219 case 2:
11220 // "y"
11221 {
11222 Int_t firstX = xaxis->GetFirst();
11223 Int_t lastX = xaxis->GetLast();
11225 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11226 xaxis->SetRange(binx,binx2);
11227 Int_t firstZ = zaxis->GetFirst();
11228 Int_t lastZ = zaxis->GetLast();
11230 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11231 zaxis->SetRange(binz,binz2);
11232 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11233 if (nbins>1 && line1[0].GetX()) {
11234 gVirtualX->DrawPolyLine(2,line2);
11235 gVirtualX->DrawPolyLine(2,line3);
11236 gVirtualX->DrawPolyLine(2,line4);
11237 gVirtualX->DrawPolyLine(5,endface1);
11238 gVirtualX->DrawPolyLine(5,endface2);
11239 }
11240 xx[0]=xaxis->GetBinCenter(binx);
11241 xx[2] = zaxis->GetBinCenter(binz);
11242 xx[1] = yaxis->GetXmin();
11243 view->WCtoNDC(xx,u);
11244 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11245 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11246 xx[1] = yaxis->GetXmax();
11247 view->WCtoNDC(xx,u);
11248 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11249 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11250 gVirtualX->DrawPolyLine(2,line1);
11251 if (nbins>1) {
11252 xx[1] = yaxis->GetXmin();
11253 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11254 xx[0] = xaxis->GetBinCenter(binx);
11255 view->WCtoNDC(xx,u);
11256 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11257 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11258 xx[1] = yaxis->GetXmax();
11259 view->WCtoNDC(xx,u);
11260 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11261 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11262
11263 xx[1] = yaxis->GetXmin();
11264 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11265 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11266 view->WCtoNDC(xx,u);
11267 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11268 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11269 xx[1] = yaxis->GetXmax();
11270 view->WCtoNDC(xx,u);
11271 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11272 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11273
11274 xx[1] = yaxis->GetXmin();
11275 xx[2] = zaxis->GetBinCenter(binz);
11276 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11277 view->WCtoNDC(xx,u);
11278 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11279 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11280 xx[1] = yaxis->GetXmax();
11281 view->WCtoNDC(xx,u);
11282 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11283 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11284
11285 endface1[0].SetX(line1[0].GetX());
11286 endface1[0].SetY(line1[0].GetY());
11287 endface1[1].SetX(line2[0].GetX());
11288 endface1[1].SetY(line2[0].GetY());
11289 endface1[2].SetX(line3[0].GetX());
11290 endface1[2].SetY(line3[0].GetY());
11291 endface1[3].SetX(line4[0].GetX());
11292 endface1[3].SetY(line4[0].GetY());
11293 endface1[4].SetX(line1[0].GetX());
11294 endface1[4].SetY(line1[0].GetY());
11295
11296 endface2[0].SetX(line1[1].GetX());
11297 endface2[0].SetY(line1[1].GetY());
11298 endface2[1].SetX(line2[1].GetX());
11299 endface2[1].SetY(line2[1].GetY());
11300 endface2[2].SetX(line3[1].GetX());
11301 endface2[2].SetY(line3[1].GetY());
11302 endface2[3].SetX(line4[1].GetX());
11303 endface2[3].SetY(line4[1].GetY());
11304 endface2[4].SetX(line1[1].GetX());
11305 endface2[4].SetY(line1[1].GetY());
11306
11307 gVirtualX->DrawPolyLine(2,line2);
11308 gVirtualX->DrawPolyLine(2,line3);
11309 gVirtualX->DrawPolyLine(2,line4);
11310 gVirtualX->DrawPolyLine(5,endface1);
11311 gVirtualX->DrawPolyLine(5,endface2);
11312 }
11313 c->Clear();
11314 c->cd();
11315 TH1 *hp = h3->Project3D("y");
11316 xaxis->SetRange(firstX,lastX);
11317 zaxis->SetRange(firstZ,lastZ);
11318 if (hp) {
11319 hp->SetFillColor(38);
11320 if (nbins == 1)
11321 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
11322 binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
11323 else
11324 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),
11325 binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
11326 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11327 hp->SetYTitle("Number of Entries");
11328 hp->Draw(fShowOption.Data());
11329 }
11330 }
11331 break;
11332
11333 case 3:
11334 // "z"
11335 {
11336 Int_t firstX = xaxis->GetFirst();
11337 Int_t lastX = xaxis->GetLast();
11339 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11340 xaxis->SetRange(binx,binx2);
11341 Int_t firstY = yaxis->GetFirst();
11342 Int_t lastY = yaxis->GetLast();
11344 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11345 yaxis->SetRange(biny,biny2);
11346 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11347 if (nbins>1 && line1[0].GetX()) {
11348 gVirtualX->DrawPolyLine(2,line2);
11349 gVirtualX->DrawPolyLine(2,line3);
11350 gVirtualX->DrawPolyLine(2,line4);
11351 gVirtualX->DrawPolyLine(5,endface1);
11352 gVirtualX->DrawPolyLine(5,endface2);
11353 }
11354 xx[0] = xaxis->GetBinCenter(binx);
11355 xx[1] = yaxis->GetBinCenter(biny);
11356 xx[2] = zaxis->GetXmin();
11357 view->WCtoNDC(xx,u);
11358 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11359 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11360 xx[2] = zaxis->GetXmax();
11361 view->WCtoNDC(xx,u);
11362 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11363 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11364 gVirtualX->DrawPolyLine(2,line1);
11365 if (nbins>1) {
11366 xx[2] = zaxis->GetXmin();
11367 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11368 xx[0] = xaxis->GetBinCenter(binx);
11369 view->WCtoNDC(xx,u);
11370 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11371 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11372 xx[2] = zaxis->GetXmax();
11373 view->WCtoNDC(xx,u);
11374 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11375 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11376
11377 xx[2] = zaxis->GetXmin();
11378 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11379 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11380 view->WCtoNDC(xx,u);
11381 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11382 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11383 xx[2] = zaxis->GetXmax();
11384 view->WCtoNDC(xx,u);
11385 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11386 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11387
11388 xx[2] = zaxis->GetXmin();
11389 xx[1] = yaxis->GetBinCenter(biny);
11390 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11391 view->WCtoNDC(xx,u);
11392 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11393 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11394 xx[2] = zaxis->GetXmax();
11395 view->WCtoNDC(xx,u);
11396 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11397 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11398
11399 endface1[0].SetX(line1[0].GetX());
11400 endface1[0].SetY(line1[0].GetY());
11401 endface1[1].SetX(line2[0].GetX());
11402 endface1[1].SetY(line2[0].GetY());
11403 endface1[2].SetX(line3[0].GetX());
11404 endface1[2].SetY(line3[0].GetY());
11405 endface1[3].SetX(line4[0].GetX());
11406 endface1[3].SetY(line4[0].GetY());
11407 endface1[4].SetX(line1[0].GetX());
11408 endface1[4].SetY(line1[0].GetY());
11409
11410 endface2[0].SetX(line1[1].GetX());
11411 endface2[0].SetY(line1[1].GetY());
11412 endface2[1].SetX(line2[1].GetX());
11413 endface2[1].SetY(line2[1].GetY());
11414 endface2[2].SetX(line3[1].GetX());
11415 endface2[2].SetY(line3[1].GetY());
11416 endface2[3].SetX(line4[1].GetX());
11417 endface2[3].SetY(line4[1].GetY());
11418 endface2[4].SetX(line1[1].GetX());
11419 endface2[4].SetY(line1[1].GetY());
11420
11421 gVirtualX->DrawPolyLine(2,line2);
11422 gVirtualX->DrawPolyLine(2,line3);
11423 gVirtualX->DrawPolyLine(2,line4);
11424 gVirtualX->DrawPolyLine(5,endface1);
11425 gVirtualX->DrawPolyLine(5,endface2);
11426 }
11427 c->Clear();
11428 c->cd();
11429 TH1 *hp = h3->Project3D("z");
11430 xaxis->SetRange(firstX,lastX);
11431 yaxis->SetRange(firstY,lastY);
11432 if (hp) {
11433 hp->SetFillColor(38);
11434 if (nbins == 1)
11435 hp->SetTitle(TString::Format("ProjectionZ of binx=%d [x=%.1f..%.1f] biny=%d [y=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
11436 biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny)));
11437 else
11438 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),
11439 biny, biny2, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny2) ) );
11440 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11441 hp->SetYTitle("Number of Entries");
11442 hp->Draw(fShowOption.Data());
11443 }
11444 }
11445 break;
11446
11447 case 4:
11448 // "xy"
11449 {
11450 Int_t first = zaxis->GetFirst();
11451 Int_t last = zaxis->GetLast();
11452 Int_t binz = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11453 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11454 zaxis->SetRange(binz,binz2);
11455 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11456 if (nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11457 xx[0] = xaxis->GetXmin();
11458 xx[1] = yaxis->GetXmax();
11459 xx[2] = zaxis->GetBinCenter(binz);
11460 view->WCtoNDC(xx,u);
11461 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11462 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11463 rect1[4].SetX(rect1[0].GetX());
11464 rect1[4].SetY(rect1[0].GetY());
11465 xx[0] = xaxis->GetXmax();
11466 view->WCtoNDC(xx,u);
11467 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11468 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11469 xx[1] = yaxis->GetXmin();
11470 view->WCtoNDC(xx,u);
11471 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11472 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11473 xx[0] = xaxis->GetXmin();
11474 view->WCtoNDC(xx,u);
11475 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11476 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11477 gVirtualX->DrawPolyLine(5,rect1);
11478 if (nbins>1) {
11479 xx[0] = xaxis->GetXmin();
11480 xx[1] = yaxis->GetXmax();
11481 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11482 view->WCtoNDC(xx,u);
11483 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11484 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11485 rect2[4].SetX(rect2[0].GetX());
11486 rect2[4].SetY(rect2[0].GetY());
11487 xx[0] = xaxis->GetXmax();
11488 view->WCtoNDC(xx,u);
11489 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11490 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11491 xx[1] = yaxis->GetXmin();
11492 view->WCtoNDC(xx,u);
11493 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11494 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11495 xx[0] = xaxis->GetXmin();
11496 view->WCtoNDC(xx,u);
11497 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11498 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11499 gVirtualX->DrawPolyLine(5,rect2);
11500 }
11501
11502 c->Clear();
11503 c->cd();
11504 TH2 *hp = (TH2*)h3->Project3D("xy");
11505 zaxis->SetRange(first,last);
11506 if (hp) {
11507 hp->SetFillColor(38);
11508 if (nbins==1)hp->SetTitle(TString::Format("ProjectionXY of binz=%d [z=%.1f..%.f]", binz,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz)));
11509 else hp->SetTitle(TString::Format("ProjectionXY, binz=[%d,%d] [z=%.1f..%.1f]", binz,binz2,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz2)));
11510 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11511 hp->SetYTitle(fH->GetXaxis()->GetTitle());
11512 hp->SetZTitle("Number of Entries");
11513 hp->Draw(fShowOption.Data());
11514 }
11515 }
11516 break;
11517
11518 case 5:
11519 // "yx"
11520 {
11521 Int_t first = zaxis->GetFirst();
11522 Int_t last = zaxis->GetLast();
11523 Int_t binz = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11524 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11525 zaxis->SetRange(binz,binz2);
11526 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11527 if (nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11528 xx[0] = xaxis->GetXmin();
11529 xx[1] = yaxis->GetXmax();
11530 xx[2] = zaxis->GetBinCenter(binz);
11531 view->WCtoNDC(xx,u);
11532 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11533 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11534 rect1[4].SetX(rect1[0].GetX());
11535 rect1[4].SetY(rect1[0].GetY());
11536 xx[0] = xaxis->GetXmax();
11537 view->WCtoNDC(xx,u);
11538 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11539 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11540 xx[1] = yaxis->GetXmin();
11541 view->WCtoNDC(xx,u);
11542 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11543 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11544 xx[0] = xaxis->GetXmin();
11545 view->WCtoNDC(xx,u);
11546 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11547 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11548 gVirtualX->DrawPolyLine(5,rect1);
11549 if (nbins>1) {
11550 xx[0] = xaxis->GetXmin();
11551 xx[1] = yaxis->GetXmax();
11552 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11553 view->WCtoNDC(xx,u);
11554 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11555 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11556 rect2[4].SetX(rect2[0].GetX());
11557 rect2[4].SetY(rect2[0].GetY());
11558 xx[0] = xaxis->GetXmax();
11559 view->WCtoNDC(xx,u);
11560 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11561 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11562 xx[1] = yaxis->GetXmin();
11563 view->WCtoNDC(xx,u);
11564 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11565 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11566 xx[0] = xaxis->GetXmin();
11567 view->WCtoNDC(xx,u);
11568 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11569 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11570 gVirtualX->DrawPolyLine(5,rect2);
11571 }
11572 c->Clear();
11573 c->cd();
11574 TH2 *hp = (TH2*)h3->Project3D("yx");
11575 zaxis->SetRange(first,last);
11576 if (hp) {
11577 hp->SetFillColor(38);
11578 if (nbins==1)hp->SetTitle(TString::Format("ProjectionYX of binz=%d [z=%.1f..%.f]", binz,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz)));
11579 else hp->SetTitle(TString::Format("ProjectionYX, binz=[%d,%d] [z=%.1f..%.1f]", binz,binz2,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz2)));
11580 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11581 hp->SetYTitle(fH->GetYaxis()->GetTitle());
11582 hp->SetZTitle("Number of Entries");
11583 hp->Draw(fShowOption.Data());
11584 }
11585 }
11586 break;
11587
11588 case 6:
11589 // "xz"
11590 {
11591 Int_t first = yaxis->GetFirst();
11592 Int_t last = yaxis->GetLast();
11593 Int_t biny = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11594 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11595 yaxis->SetRange(biny,biny2);
11596 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11597 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11598 xx[0] = xaxis->GetXmin();
11599 xx[2] = zaxis->GetXmax();
11600 xx[1] = yaxis->GetBinCenter(biny);
11601 view->WCtoNDC(xx,u);
11602 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11603 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11604 rect1[4].SetX(rect1[0].GetX());
11605 rect1[4].SetY(rect1[0].GetY());
11606 xx[0] = xaxis->GetXmax();
11607 view->WCtoNDC(xx,u);
11608 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11609 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11610 xx[2] = zaxis->GetXmin();
11611 view->WCtoNDC(xx,u);
11612 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11613 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11614 xx[0] = xaxis->GetXmin();
11615 view->WCtoNDC(xx,u);
11616 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11617 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11618 gVirtualX->DrawPolyLine(5,rect1);
11619 if (nbins>1) {
11620 xx[0] = xaxis->GetXmin();
11621 xx[2] = zaxis->GetXmax();
11622 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11623 view->WCtoNDC(xx,u);
11624 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11625 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11626 rect2[4].SetX(rect2[0].GetX());
11627 rect2[4].SetY(rect2[0].GetY());
11628 xx[0] = xaxis->GetXmax();
11629 view->WCtoNDC(xx,u);
11630 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11631 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11632 xx[2] = zaxis->GetXmin();
11633 view->WCtoNDC(xx,u);
11634 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11635 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11636 xx[0] = xaxis->GetXmin();
11637 view->WCtoNDC(xx,u);
11638 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11639 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11640 gVirtualX->DrawPolyLine(5,rect2);
11641 }
11642 c->Clear();
11643 c->cd();
11644 TH2 *hp = (TH2*)h3->Project3D("xz");
11645 yaxis->SetRange(first,last);
11646 if (hp) {
11647 hp->SetFillColor(38);
11648 if (nbins==1)hp->SetTitle(TString::Format("ProjectionXZ of biny=%d [y=%.1f..%.f]", biny,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny)));
11649 else hp->SetTitle(TString::Format("ProjectionXZ, biny=[%d,%d] [y=%.1f..%.1f]", biny,biny2,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny2)));
11650 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11651 hp->SetYTitle(fH->GetXaxis()->GetTitle());
11652 hp->SetZTitle("Number of Entries");
11653 hp->Draw(fShowOption.Data());
11654 }
11655 }
11656 break;
11657
11658 case 7:
11659 // "zx"
11660 {
11661 Int_t first = yaxis->GetFirst();
11662 Int_t last = yaxis->GetLast();
11663 Int_t biny = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11664 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11665 yaxis->SetRange(biny,biny2);
11666 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11667 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11668 xx[0] = xaxis->GetXmin();
11669 xx[2] = zaxis->GetXmax();
11670 xx[1] = yaxis->GetBinCenter(biny);
11671 view->WCtoNDC(xx,u);
11672 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11673 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11674 rect1[4].SetX(rect1[0].GetX());
11675 rect1[4].SetY(rect1[0].GetY());
11676 xx[0] = xaxis->GetXmax();
11677 view->WCtoNDC(xx,u);
11678 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11679 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11680 xx[2] = zaxis->GetXmin();
11681 view->WCtoNDC(xx,u);
11682 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11683 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11684 xx[0] = xaxis->GetXmin();
11685 view->WCtoNDC(xx,u);
11686 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11687 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11688 gVirtualX->DrawPolyLine(5,rect1);
11689 if (nbins>1) {
11690 xx[0] = xaxis->GetXmin();
11691 xx[2] = zaxis->GetXmax();
11692 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11693 view->WCtoNDC(xx,u);
11694 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11695 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11696 rect2[4].SetX(rect2[0].GetX());
11697 rect2[4].SetY(rect2[0].GetY());
11698 xx[0] = xaxis->GetXmax();
11699 view->WCtoNDC(xx,u);
11700 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11701 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11702 xx[2] = zaxis->GetXmin();
11703 view->WCtoNDC(xx,u);
11704 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11705 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11706 xx[0] = xaxis->GetXmin();
11707 view->WCtoNDC(xx,u);
11708 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11709 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11710 gVirtualX->DrawPolyLine(5,rect2);
11711 }
11712 c->Clear();
11713 c->cd();
11714 TH2 *hp = (TH2*)h3->Project3D("zx");
11715 yaxis->SetRange(first,last);
11716 if (hp) {
11717 hp->SetFillColor(38);
11718 if (nbins==1)hp->SetTitle(TString::Format("ProjectionZX of biny=%d [y=%.1f..%.f]", biny,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny)));
11719 else hp->SetTitle(TString::Format("ProjectionZX, biny=[%d,%d] [y=%.1f..%.1f]", biny,biny2,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny2)));
11720 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11721 hp->SetYTitle(fH->GetZaxis()->GetTitle());
11722 hp->SetZTitle("Number of Entries");
11723 hp->Draw(fShowOption.Data());
11724 }
11725 }
11726 break;
11727
11728 case 8:
11729 // "yz"
11730 {
11731 Int_t first = xaxis->GetFirst();
11732 Int_t last = xaxis->GetLast();
11733 Int_t binx = first + Int_t((last-first)*(px-pxmin)/(pxmax-pxmin));
11734 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11735 xaxis->SetRange(binx,binx2);
11736 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11737 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11738 xx[2] = zaxis->GetXmin();
11739 xx[1] = yaxis->GetXmax();
11740 xx[0] = xaxis->GetBinCenter(binx);
11741 view->WCtoNDC(xx,u);
11742 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11743 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11744 rect1[4].SetX(rect1[0].GetX());
11745 rect1[4].SetY(rect1[0].GetY());
11746 xx[2] = zaxis->GetXmax();
11747 view->WCtoNDC(xx,u);
11748 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11749 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11750 xx[1] = yaxis->GetXmin();
11751 view->WCtoNDC(xx,u);
11752 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11753 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11754 xx[2] = zaxis->GetXmin();
11755 view->WCtoNDC(xx,u);
11756 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11757 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11758 gVirtualX->DrawPolyLine(5,rect1);
11759 if (nbins>1) {
11760 xx[2] = zaxis->GetXmin();
11761 xx[1] = yaxis->GetXmax();
11762 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11763 view->WCtoNDC(xx,u);
11764 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11765 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11766 rect2[4].SetX(rect2[0].GetX());
11767 rect2[4].SetY(rect2[0].GetY());
11768 xx[2] = zaxis->GetXmax();
11769 view->WCtoNDC(xx,u);
11770 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11771 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11772 xx[1] = yaxis->GetXmin();
11773 view->WCtoNDC(xx,u);
11774 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11775 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11776 xx[2] = zaxis->GetXmin();
11777 view->WCtoNDC(xx,u);
11778 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11779 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11780 gVirtualX->DrawPolyLine(5,rect2);
11781 }
11782 c->Clear();
11783 c->cd();
11784 TH2 *hp = (TH2*)h3->Project3D("yz");
11785 xaxis->SetRange(first,last);
11786 if (hp) {
11787 hp->SetFillColor(38);
11788 if (nbins==1)hp->SetTitle(TString::Format("ProjectionYZ of binx=%d [x=%.1f..%.f]", binx,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx)));
11789 else hp->SetTitle(TString::Format("ProjectionYZ, binx=[%d,%d] [x=%.1f..%.1f]", binx,binx2,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx2)));
11790 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11791 hp->SetYTitle(fH->GetYaxis()->GetTitle());
11792 hp->SetZTitle("Number of Entries");
11793 hp->Draw(fShowOption.Data());
11794 }
11795 }
11796 break;
11797
11798 case 9:
11799 // "zy"
11800 {
11801 Int_t first = xaxis->GetFirst();
11802 Int_t last = xaxis->GetLast();
11803 Int_t binx = first + Int_t((last-first)*(px-pxmin)/(pxmax-pxmin));
11804 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11805 xaxis->SetRange(binx,binx2);
11806 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11807 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11808 xx[2] = zaxis->GetXmin();
11809 xx[1] = yaxis->GetXmax();
11810 xx[0] = xaxis->GetBinCenter(binx);
11811 view->WCtoNDC(xx,u);
11812 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11813 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11814 rect1[4].SetX(rect1[0].GetX());
11815 rect1[4].SetY(rect1[0].GetY());
11816 xx[2] = zaxis->GetXmax();
11817 view->WCtoNDC(xx,u);
11818 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11819 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11820 xx[1] = yaxis->GetXmin();
11821 view->WCtoNDC(xx,u);
11822 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11823 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11824 xx[2] = zaxis->GetXmin();
11825 view->WCtoNDC(xx,u);
11826 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11827 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11828 gVirtualX->DrawPolyLine(5,rect1);
11829 if (nbins>1) {
11830 xx[2] = zaxis->GetXmin();
11831 xx[1] = yaxis->GetXmax();
11832 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11833 view->WCtoNDC(xx,u);
11834 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11835 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11836 rect2[4].SetX(rect2[0].GetX());
11837 rect2[4].SetY(rect2[0].GetY());
11838 xx[2] = zaxis->GetXmax();
11839 view->WCtoNDC(xx,u);
11840 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11841 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11842 xx[1] = yaxis->GetXmin();
11843 view->WCtoNDC(xx,u);
11844 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11845 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11846 xx[2] = zaxis->GetXmin();
11847 view->WCtoNDC(xx,u);
11848 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11849 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11850 gVirtualX->DrawPolyLine(5,rect2);
11851 }
11852 c->Clear();
11853 c->cd();
11854 TH2 *hp = (TH2*)h3->Project3D("zy");
11855 xaxis->SetRange(first,last);
11856 if (hp) {
11857 hp->SetFillColor(38);
11858 if (nbins==1)hp->SetTitle(TString::Format("ProjectionZY of binx=%d [x=%.1f..%.f]", binx,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx)));
11859 else hp->SetTitle(TString::Format("ProjectionZY, binx=[%d,%d] [x=%.1f..%.1f]", binx,binx2,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx2)));
11860 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11861 hp->SetYTitle(fH->GetZaxis()->GetTitle());
11862 hp->SetZTitle("Number of Entries");
11863 hp->Draw(fShowOption.Data());
11864 }
11865 }
11866 break;
11867 }
11868 c->Update();
11869}
@ kMouseMotion
Definition Buttons.h:23
@ kWheelUp
Definition Buttons.h:18
@ kButton1Motion
Definition Buttons.h:20
@ kButton1Up
Definition Buttons.h:19
@ kWheelDown
Definition Buttons.h:18
@ kButton1Down
Definition Buttons.h:17
@ kButton1Locate
Definition Buttons.h:22
@ kArrowVer
Definition GuiTypes.h:374
@ kPointer
Definition GuiTypes.h:375
Handle_t Window_t
Window handle.
Definition GuiTypes.h:29
#define d(i)
Definition RSha256.hxx:102
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
#define c(i)
Definition RSha256.hxx:101
#define g(i)
Definition RSha256.hxx:105
#define a(i)
Definition RSha256.hxx:99
#define h(i)
Definition RSha256.hxx:106
#define e(i)
Definition RSha256.hxx:103
short Style_t
Style number (short)
Definition RtypesCore.h:96
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:59
short Color_t
Color number (short)
Definition RtypesCore.h:99
unsigned int UInt_t
Unsigned integer 4 bytes (unsigned int)
Definition RtypesCore.h:60
short Width_t
Line width (short)
Definition RtypesCore.h:98
float Float_t
Float 4 bytes (float)
Definition RtypesCore.h:71
short Short_t
Signed Short integer 2 bytes (short)
Definition RtypesCore.h:53
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
double Double_t
Double 8 bytes.
Definition RtypesCore.h:73
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
const char Option_t
Option string (const char)
Definition RtypesCore.h:80
#define BIT(n)
Definition Rtypes.h:91
#define ClassImp(name)
Definition Rtypes.h:376
@ kBlack
Definition Rtypes.h:66
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
R__EXTERN TEnv * gEnv
Definition TEnv.h:170
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t option
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void pixel
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t wmin
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize wid
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t np
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize id
Option_t Option_t TPoint TPoint const char x2
Option_t Option_t TPoint TPoint const char x1
Option_t Option_t TPoint TPoint angle
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void xpos
Option_t Option_t TPoint TPoint const char mode
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char backcolor
Option_t Option_t TPoint TPoint const char y2
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void ypos
Option_t Option_t width
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize fs
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t wmax
Option_t Option_t TPoint TPoint const char text
Option_t Option_t TPoint TPoint const char y1
R__EXTERN TH1 * gCurrentHist
R__EXTERN Hoption_t Hoption
float xmin
int ncx
float ymin
int ncy
float xmax
float ymax
static TString gStringStdDevZ
static TString gStringStdDevX
static TString gStringIntegralBinWidth
const UInt_t kCannotRotate
static TString gStringStdDev
const Int_t kNMAX
Hparam_t Hparam
const Int_t kMAXCONTOUR
static TString gStringOverflow
static TString gStringUnderflow
static TString gStringSkewnessY
static TString gStringMean
static TString gStringKurtosis
Hoption_t Hoption
static TString gStringMeanX
static TString gStringEntries
static TString gStringIntegral
static TString gStringKurtosisY
static TString gStringStdDevY
static TString gStringMeanY
static TString gStringSkewnessX
static TString gStringKurtosisX
static std::unique_ptr< TBox > gXHighlightBox
static std::unique_ptr< TBox > gYHighlightBox
static TString gStringSkewnessZ
TH1 * gCurrentHist
static TString gStringMeanZ
static TString gStringSkewness
static TString gStringKurtosisZ
const Int_t kMaxCuts
const Int_t kCYLINDRICAL
const Int_t kSPHERICAL
const Int_t kRAPIDITY
#define gROOT
Definition TROOT.h:411
R__EXTERN TStyle * gStyle
Definition TStyle.h:442
R__EXTERN TSystem * gSystem
Definition TSystem.h:572
const Int_t kCARTESIAN
Definition TView3D.cxx:33
const Int_t kPOLAR
Definition TView3D.cxx:34
#define gPad
#define gVirtualX
Definition TVirtualX.h:337
polygon * polys
Definition X3DBuffer.c:24
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:31
virtual Style_t GetFillStyle() const
Return the fill area style.
Definition TAttFill.h:32
virtual void SetFillColor(Color_t fcolor)
Set the fill area color.
Definition TAttFill.h:38
virtual void SetFillStyle(Style_t fstyle)
Set the fill area style.
Definition TAttFill.h:40
virtual Color_t GetLineColor() const
Return the line color.
Definition TAttLine.h:35
virtual void SetLineStyle(Style_t lstyle)
Set the line style.
Definition TAttLine.h:44
virtual Width_t GetLineWidth() const
Return the line width.
Definition TAttLine.h:37
virtual void SetLineWidth(Width_t lwidth)
Set the line width.
Definition TAttLine.h:45
virtual void SetLineColor(Color_t lcolor)
Set the line color.
Definition TAttLine.h:42
virtual Style_t GetLineStyle() const
Return the line style.
Definition TAttLine.h:36
virtual Style_t GetMarkerStyle() const
Return the marker style.
Definition TAttMarker.h:33
virtual void SetMarkerColor(Color_t mcolor=1)
Set the marker color.
Definition TAttMarker.h:39
virtual Color_t GetMarkerColor() const
Return the marker color.
Definition TAttMarker.h:32
virtual Size_t GetMarkerSize() const
Return the marker size.
Definition TAttMarker.h:34
virtual void SetMarkerStyle(Style_t mstyle=1)
Set the marker style.
Definition TAttMarker.h:41
virtual void SetMarkerSize(Size_t msize=1)
Set the marker size.
Definition TAttMarker.h:46
static Style_t GetMarkerStyleBase(Style_t style)
Internal helper function that returns the corresponding marker style with line width 1 for the given ...
virtual Font_t GetTextFont() const
Return the text font.
Definition TAttText.h:37
virtual void SetTextAngle(Float_t tangle=0)
Set the text angle.
Definition TAttText.h:45
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:1075
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:2475
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:3079
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:1927
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:2096
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:2139
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()
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition TEnv.cxx:491
1-Dim function class
Definition TF1.h:182
virtual Double_t GetXmax() const
Definition TF1.h:540
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:1911
virtual void GetParLimits(Int_t ipar, Double_t &parmin, Double_t &parmax) const
Return limits for parameter ipar.
Definition TF1.cxx:1962
virtual Double_t GetParError(Int_t ipar) const
Return value of parameter number ipar.
Definition TF1.cxx:1952
static TClass * Class()
Double_t GetChisquare() const
Return the Chisquare after fitting. See ROOT::Fit::FitResult::Chi2()
Definition TF1.h:424
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:3420
virtual Double_t GetMaximumStored() const
Definition TF1.h:453
virtual Int_t GetNpar() const
Definition TF1.h:461
virtual Int_t GetNumberFreeParameters() const
Return the number of free parameters.
Definition TF1.cxx:1922
@ 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:3433
virtual const char * GetParName(Int_t ipar) const
Definition TF1.h:509
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:1441
virtual Double_t GetXmin() const
Definition TF1.h:536
virtual Double_t GetParameter(Int_t ipar) const
Definition TF1.h:492
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:752
void SetRange(Double_t xmin, Double_t xmax) override
Initialize the upper and lower bounds to draw the function.
Definition TF2.h:148
static TClass * Class()
A 3-Dim 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:2944
virtual void PaintAxis(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax, Double_t &wmin, Double_t &wmax, Int_t &ndiv, Option_t *chopt="", Double_t gridlength=0, Bool_t drawGridOnly=kFALSE)
Control function to draw an axis.
Definition TGaxis.cxx:1008
void SetTitleOffset(Float_t titleoffset=1)
Definition TGaxis.h:130
virtual void SetTitle(const char *title="")
Change the title of the axis.
Definition TGaxis.cxx:2917
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:955
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:2909
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:1987
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:1996
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:108
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:7631
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:9089
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:7559
virtual Double_t GetSkewness(Int_t axis=1) const
Definition TH1.cxx:7695
virtual Double_t GetContourLevelPad(Int_t level) const
Return the value of contour number "level" in Pad coordinates.
Definition TH1.cxx:8469
virtual Int_t GetDimension() const
Definition TH1.h:527
static void AddDirectory(Bool_t add=kTRUE)
Sets the flag controlling the automatic add of histograms in memory.
Definition TH1.cxx:1264
@ 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:4964
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:8574
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:9105
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:7970
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:9248
virtual Double_t GetBinLowEdge(Int_t bin) const
Return bin lower edge for 1D histogram.
Definition TH1.cxx:9178
virtual Double_t GetEntries() const
Return the current number of entries.
Definition TH1.cxx:4401
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:7599
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:8760
@ kNormal
Errors with Normal (Wald) approximation: errorUp=errorLow= sqrt(N)
Definition TH1.h:114
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition TH1.cxx:5064
virtual Int_t GetContour(Double_t *levels=nullptr)
Return contour values into array levels if pointer levels is non zero.
Definition TH1.cxx:8440
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:9189
virtual void SetContour(Int_t nlevels, const Double_t *levels=nullptr)
Set the number and values of contour levels.
Definition TH1.cxx:8512
virtual Double_t GetBinErrorUp(Int_t bin) const
Return upper error associated to bin number bin.
Definition TH1.cxx:9136
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:7679
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:8664
static Bool_t AddDirectoryStatus()
Static function: cannot be inlined on Windows/NT.
Definition TH1.cxx:742
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:5248
virtual Int_t BufferEmpty(Int_t action=0)
Fill histogram with all entries in the buffer.
Definition TH1.cxx:1384
virtual Double_t GetKurtosis(Int_t axis=1) const
Definition TH1.cxx:7768
2-D histogram with a double per channel (see TH1 documentation)
Definition TH2.h:356
2-D histogram with a float per channel (see TH1 documentation)
Definition TH2.h:307
Helper class to represent a bin in the TH2Poly histogram.
Definition TH2Poly.h:25
2D Histogram with Polygonal Bins
Definition TH2Poly.h:66
static TClass * Class()
Service class for 2-D histogram classes.
Definition TH2.h:30
static TClass * Class()
The 3-D histogram classes derived from the 1-D histogram classes.
Definition TH3.h:40
static TClass * Class()
The Histogram stack class.
Definition THStack.h:40
static TClass * Class()
The histogram painter class.
static Int_t ProjectSinusoidal2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function code for sinusoidal projection from Ernst-Jan Buis Source https://en....
void Paint(Option_t *option="") override
Control routine to paint any kind of histograms
TAxis * fYaxis
Pointer to Y axis.
std::unique_ptr< TPainter3dAlgorithms > fLego
Pointer to a TPainter3dAlgorithms object.
std::vector< Double_t > fXbuf
X buffer coordinates.
Int_t fXHighlightBin
X highlight bin.
TF3 * fCurrentF3
Current TF3 function.
virtual void PaintErrors(Option_t *option)
Draw 1D histograms error bars.
~THistPainter() override
destructor.
Int_t fShowProjection2
True if a second projection must be drawn (when calling SetShowProjectionXY on a TH2)
virtual void PaintTF3()
Control function to draw a 3D implicit functions.
virtual Int_t TableInit()
Initialize various options to draw 2D histograms.
virtual void PaintTH2PolyScatterPlot(Option_t *option)
Control function to draw a TH2Poly as a scatter plot.
static Int_t ProjectMollweide2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
static Int_t ProjectAitoff2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
virtual void PaintText(Option_t *option)
Control function to draw a 1D/2D histograms with the bin values.
Int_t DistancetoPrimitive(Int_t px, Int_t py) override
Compute the distance from the point px,py to a line.
virtual void PaintAxis(Bool_t drawGridOnly=kFALSE)
Draw axis (2D case) of an histogram.
virtual void PaintColorLevelsFast(Option_t *option)
[Rendering scheme for the COL2 and COLZ2 options] (HP14)
virtual Int_t PaintInit()
Compute histogram parameters used by the drawing routines.
virtual void Paint2DErrors(Option_t *option)
Draw 2D histograms errors.
Int_t fYHighlightBin
Y highlight bin.
virtual void PaintCandlePlot(Option_t *option)
Control function to draw a 2D histogram as a candle (box) plot or violin plot
virtual void PaintScatterPlot(Option_t *option)
Control function to draw a 2D histogram as a scatter plot.
void SetShowProjectionXY(const char *option, Int_t nbinsY, Int_t nbinsX) override
virtual void PaintLego(Option_t *option)
Control function to draw a 2D histogram as a lego plot.
virtual void PaintH3(Option_t *option="")
Control function to draw a 3D histograms.
Int_t fNcuts
Number of graphical cuts.
TString fShowOption
Option to draw the projection.
virtual void PaintHighlightBin(Option_t *option="")
Paint highlight bin as TBox object.
virtual void PaintTH2PolyBins(Option_t *option)
Control function to draw a TH2Poly bins' contours.
virtual Int_t PaintContourLine(Double_t elev1, Int_t icont1, Double_t x1, Double_t y1, Double_t elev2, Int_t icont2, Double_t x2, Double_t y2, Double_t *xarr, Double_t *yarr, Int_t *itarr, Double_t *levels)
Fill the matrix xarr and yarr for Contour Plot.
Int_t fShowProjection
True if a projection must be drawn.
virtual void PaintLegoAxis(TGaxis *axis, Double_t ang)
Draw the axis for legos and surface plots.
virtual void PaintTriangles(Option_t *option)
Control function to draw a table using Delaunay triangles.
virtual void HighlightBin(Int_t px, Int_t py)
Check on highlight bin.
virtual void PaintH3Box(Int_t iopt)
Control function to draw a 3D histogram with boxes.
Int_t MakeCuts(char *cutsopt) override
Decode string choptin and fill Graphical cuts structure.
TList * fFunctions
Pointer to histogram list of functions.
void DrawPanel() override
Display a panel with all histogram drawing options.
std::unique_ptr< TPie > fPie
Pointer to a TPie in case of option PIE.
static void PaintSpecialObjects(const TObject *obj, Option_t *option)
Static function to paint special objects like vectors and matrices.
virtual void PaintTitle()
new TGaxis/////////////////// Draw the histogram title
virtual void PaintTH2PolyColorLevels(Option_t *option)
Control function to draw a TH2Poly as a color plot.
virtual std::vector< THistRenderingRegion > ComputeRenderingRegions(TAxis *pAxis, Int_t nPixels, bool isLog)
Returns the rendering regions for an axis to use in the COL2 option.
virtual void ShowProjectionX(Int_t px, Int_t py)
Show projection onto X.
virtual void PaintPalette()
Paint the color palette on the right side of the pad.
TAxis * fXaxis
Pointer to X axis.
virtual void PaintStat2(Int_t dostat, TF1 *fit)
Draw the statistics box for 2D histograms.
virtual void PaintArrows(Option_t *option)
Control function to draw a table as an arrow plot
virtual void RecalculateRange()
Recompute the histogram range following graphics operations.
void PaintStat(Int_t dostat, TF1 *fit) override
Draw the statistics box for 1D and profile histograms.
static Int_t ProjectParabolic2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function code for parabolic projection from Ernst-Jan Buis.
std::unique_ptr< TGraph2DPainter > fGraph2DPainter
Pointer to a TGraph2DPainter object.
virtual void PaintBarH(Option_t *option)
Draw a bar char in a rotated pad (X vertical, Y horizontal)
virtual void PaintStat3(Int_t dostat, TF1 *fit)
Draw the statistics box for 3D histograms.
virtual void PaintSurface(Option_t *option)
Control function to draw a 2D histogram as a surface plot.
TList * fStack
Pointer to stack of histograms (if any)
THistPainter()
Default constructor.
TH1 * fH
Pointer to histogram to paint.
virtual void PaintTH2PolyText(Option_t *option)
Control function to draw a TH2Poly as a text plot.
virtual void ShowProjection3(Int_t px, Int_t py)
Show projection (specified by fShowProjection) of a TH3.
TAxis * fZaxis
Pointer to Z axis.
void SetHistogram(TH1 *h) override
Set current histogram to h
virtual void PaintFunction(Option_t *option)
[Paint functions associated to an histogram.](HP28")
virtual void PaintBar(Option_t *option)
Draw a bar-chart in a normal pad.
static Int_t ProjectMercator2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
virtual void PaintBoxes(Option_t *option)
Control function to draw a 2D histogram as a box plot
virtual Int_t MakeChopt(Option_t *option)
Decode string choptin and fill Hoption structure.
char * GetObjectInfo(Int_t px, Int_t py) const override
Display the histogram info (bin number, contents, integral up to bin corresponding to cursor position...
TList * GetContourList(Double_t contour) const override
Get a contour (as a list of TGraphs) using the Delaunay triangulation.
void ProcessMessage(const char *mess, const TObject *obj) override
Process message mess.
void SetShowProjection(const char *option, Int_t nbins) override
Set projection.
virtual void ShowProjectionY(Int_t px, Int_t py)
Show projection onto Y.
static const char * GetBestFormat(Double_t v, Double_t e, const char *f)
This function returns the best format to print the error value (e) knowing the parameter value (v) an...
virtual void PaintContour(Option_t *option)
Control function to draw a 2D histogram as a contour plot.
TCutG * fCuts[kMaxCuts]
Pointers to graphical cuts.
virtual void PaintTable(Option_t *option)
Control function to draw 2D/3D histograms (tables).
void ExecuteEvent(Int_t event, Int_t px, Int_t py) override
Execute the actions corresponding to event.
virtual Int_t PaintInitH()
Compute histogram parameters used by the drawing routines for a rotated pad.
virtual void PaintFrame()
Calculate range and clear pad (canvas).
Int_t fCutsOpt[kMaxCuts]
Sign of each cut.
virtual void PaintH3Iso()
Control function to draw a 3D histogram with Iso Surfaces.
std::vector< Double_t > fYbuf
Y buffer coordinates.
virtual void PaintH3BoxRaster()
Control function to draw a 3D histogram with boxes.
virtual void PaintHist(Option_t *option)
Control routine to draw 1D histograms
void SetHighlight() override
Set highlight (enable/disable) mode for fH.
virtual void DefineColorLevels(Int_t ndivz)
Define the color levels used to paint legos, surfaces etc..
TString fObjectInfo
virtual void PaintColorLevels(Option_t *option)
Control function to draw a 2D histogram as a color plot.
Bool_t IsInside(Int_t x, Int_t y) override
Return kTRUE if the cell ix, iy is inside one of the graphical cuts.
A class to define a conversion from pixel values to pixel color.
Definition TAttImage.h:33
static TImagePalette * CreateCOLPalette(Int_t nContours)
Factory method to creates an image palette for histogram plotting.
An abstract interface to image processing library.
Definition TImage.h:29
static TImage * Create()
Create an image.
Definition TImage.cxx:35
void Reset()
To draw Mathematical Formula.
Definition TLatex.h:18
A doubly linked list.
Definition TList.h:38
TObject * FindObject(const char *name) const override
Find an object in this list using its name.
Definition TList.cxx:576
void Add(TObject *obj) override
Definition TList.h:81
TObject * Remove(TObject *obj) override
Remove object from the list.
Definition TList.cxx:820
TObject * First() const override
Return the first object in the list. Returns 0 when list is empty.
Definition TList.cxx:657
virtual TObjLink * FirstLink() const
Definition TList.h:102
TObject * At(Int_t idx) const override
Returns the object at position idx. Returns 0 if idx is out of range.
Definition TList.cxx:355
void AddFirst(TObject *obj) override
Add object at the beginning of the list.
Definition TList.cxx:98
TMatrixTBase.
static TClass * Class()
A TMultiGraph is a collection of TGraph (or derived) objects.
Definition TMultiGraph.h:34
TList * GetListOfGraphs() const
Definition TMultiGraph.h:68
static TClass * Class()
virtual Int_t IsInside(Double_t x, Double_t y) const
Return 1 if the point (x,y) is inside one of the graphs 0 otherwise.
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:41
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:457
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:202
virtual Option_t * GetDrawOption() const
Get option used by the graphics system to draw this object.
Definition TObject.cxx:441
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1057
virtual TObject * FindObject(const char *name) const
Must be redefined in derived classes.
Definition TObject.cxx:421
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:864
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:543
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1071
virtual const char * GetTitle() const
Returns title of object.
Definition TObject.cxx:501
void ResetBit(UInt_t f)
Definition TObject.h:201
@ kCannotPick
if object in a pad cannot be picked
Definition TObject.h:73
@ kCanDelete
if object in a list can be deleted
Definition TObject.h:68
@ kMustCleanup
if object destructor must call RecursiveRemove()
Definition TObject.h:70
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
static TClass * Class()
A Pave (see TPave) with text, lines or/and boxes inside.
Definition TPaveText.h:21
static TClass * Class()
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
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 quidistributed combined Tausworthe generator by ...
Definition TRandom2.h:27
Sequenceable collection abstract base class.
Basic string class.
Definition TString.h:139
void ToLower()
Change string to lower-case.
Definition TString.cxx:1182
const char * Data() const
Definition TString.h:376
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2378
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2356
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:632
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:651
Int_t GetOptStat() const
Definition TStyle.h: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:1242
Float_t GetTitleY() const
Definition TStyle.h:283
Style_t GetTitleFont(Option_t *axis="X") const
Return title font.
Definition TStyle.cxx:1218
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:1103
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:1177
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:1870
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:699
Short_t Max(Short_t a, Short_t b)
Returns the largest of a and b.
Definition TMathBase.h:251
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:646
constexpr Double_t PiOver2()
Definition TMath.h:52
Double_t Log(Double_t x)
Returns the natural logarithm of x.
Definition TMath.h:762
constexpr Double_t DegToRad()
Conversion from degree to radian: .
Definition TMath.h:80
Double_t Sqrt(Double_t x)
Returns the square root of x.
Definition TMath.h:668
LongDouble_t Power(LongDouble_t x, LongDouble_t y)
Returns x raised to the power y.
Definition TMath.h:727
Short_t Min(Short_t a, Short_t b)
Returns the smallest of a and b.
Definition TMathBase.h:199
Double_t Cos(Double_t)
Returns the cosine of an angle of x radians.
Definition TMath.h:600
constexpr Double_t Pi()
Definition TMath.h:38
Bool_t AreEqualRel(Double_t af, Double_t bf, Double_t relPrec)
Comparing floating points.
Definition TMath.h:427
Double_t Sin(Double_t)
Returns the sine of an angle of x radians.
Definition TMath.h:594
Double_t Tan(Double_t)
Returns the tangent of an angle of x radians.
Definition TMath.h:606
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:348
constexpr Double_t RadToDeg()
Conversion from radian to degree: .
Definition TMath.h:73
Double_t Log10(Double_t x)
Returns the common (base-10) logarithm of x.
Definition TMath.h:768
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:124
Histograms' drawing options structure.
Definition Hoption.h:24
int Curve
"C" A smooth Curve is drawn.
Definition Hoption.h:32
int Proj
"AITOFF", "MERCATOR", "SINUSOIDAL" and "PARABOLIC" projections for 2d plots.
Definition Hoption.h:59
int Axis
"A" Axis are not drawn around the graph.
Definition Hoption.h:30
int Box
"BOX" Draw 2D plot with proportional Boxes.
Definition Hoption.h:41
int Scat
"SCAT" Draw 2D plot a Scatter plot.
Definition Hoption.h:48
int Text
"TEXT" Draw 2D plot with the content of each cell.
Definition Hoption.h:50
int Color
"COL" Draw 2D plot with Colored boxes.
Definition Hoption.h:43
int AxisPos
"X+" and "Y+" Axis position
Definition Hoption.h:60
int List
"LIST" Generate the TObjArray "contours". To be used with option "CONT"
Definition Hoption.h:58
int Logx
log scale in X. Also set by histogram option
Definition Hoption.h:70
int Zscale
"Z" Display the color palette.
Definition Hoption.h:55
int MinimumZero
"MIN0" or gStyle->GetHistMinimumZero()
Definition Hoption.h:63
int Contour
"CONTn" Draw 2D plot as a Contour plot (0 <= n <= 5).
Definition Hoption.h:44
int Off
"][" The first and last vertical lines are not drawn.
Definition Hoption.h:35
int Func
"FUNC" Draw only the function (for example in case of fit).
Definition Hoption.h:45
long Candle
"CANDLE" and "VIOLIN" Draw a 2D histogram as candle/box plot or violin plot.
Definition Hoption.h:53
int Spec
"SPEC" TSpectrum graphics
Definition Hoption.h:61
int FrontBox
"FB" Suppress the front box for the 3D plots.
Definition Hoption.h:56
int Pie
"PIE" Draw 1D plot as a pie chart.
Definition Hoption.h:52
int Star
"*" With option "P", a * is plotted at each point.
Definition Hoption.h:39
int Zero
"0" if selected with any LEGO option the empty bins are not drawn.
Definition Hoption.h:62
int Logz
log scale in Z. Also set by histogram option
Definition Hoption.h:72
int Tri
"TRI" Draw TGraph2D with Delaunay triangles.
Definition Hoption.h:51
int BackBox
"BB" Suppress the back box for the 3D plots.
Definition Hoption.h:57
int Mark
"P" The current Marker is drawn at each point.
Definition Hoption.h:37
int Arrow
"ARR" Draw 2D plot with Arrows.
Definition Hoption.h:40
int Line
"L" A simple polyline through every point is drawn.
Definition Hoption.h:36
int Same
"SAME" Histogram is plotted in the current pad.
Definition Hoption.h:38
int Lego
"LEGO" and "LEGOn" Draw as a Lego plot(1 <= n <= 4).
Definition Hoption.h:47
int Bar
"B", "BAR" and "HBAR" A Bar chart is drawn at each point.
Definition Hoption.h:31
int Fill
"F" A fill area is drawn ("CF" draw a smooth fill area).
Definition Hoption.h:34
int Hist
"HIST" Draw only the histogram.
Definition Hoption.h:46
int Surf
"SURF" and "SURFn" Draw as a Surface ((1 <= n <= 4).
Definition Hoption.h:49
int Logy
log scale in Y. Also set by histogram option
Definition Hoption.h:71
int System
"POL", "CYL", "SPH" and "PSR" Type of coordinate system for 3D plots.
Definition Hoption.h:54
int Error
"En" Draw Errors with current marker type and size (0 <= n <=6).
Definition Hoption.h:33
Histogram parameters structure.
Definition Hparam.h:27
Double_t baroffset
Offset of bin for bars or legos [0,1].
Definition Hparam.h:42
Double_t ylowedge
Low edge of axis.
Definition Hparam.h:33
Double_t xmin
Minimum value along X.
Definition Hparam.h:30
Int_t ylast
Last bin number along Y.
Definition Hparam.h:47
Int_t xfirst
First bin number along X.
Definition Hparam.h:44
Double_t zmin
Minimum value along Z.
Definition Hparam.h:38
Double_t xbinsize
Bin size in case of equidistant bins.
Definition Hparam.h:28
Double_t ymin
Minimum value along y.
Definition Hparam.h:34
Double_t allchan
Integrated sum of contents.
Definition Hparam.h:41
Double_t xlowedge
Low edge of axis.
Definition Hparam.h:29
Double_t ymax
Maximum value along y.
Definition Hparam.h:35
Double_t factor
Multiplication factor (normalization)
Definition Hparam.h:40
Int_t xlast
Last bin number along X.
Definition Hparam.h:45
Double_t ybinsize
Bin size in case of equidistant bins.
Definition Hparam.h:32
Double_t barwidth
Width of bin for bars and legos [0,1].
Definition Hparam.h:43
Double_t zmax
Maximum value along Z.
Definition Hparam.h:39
Double_t xmax
Maximum value along X.
Definition Hparam.h:31
Int_t yfirst
First bin number along Y.
Definition Hparam.h:46
auto * th2
Definition textalign.C:18
TMarker m
Definition textangle.C:8
TLine l
Definition textangle.C:4
auto * tt
Definition textangle.C:16