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.
1113In other words, option `COLZ0` forces the painting of bins with content < set minimum with
1114 a color corresponding to the set minimum. In contrast, option `COLZ` would not draw values
1115 smaller than the specified minimum. Note that both `COLZ` and `COLZ0` still do not draw
1116 empty bins, ie bins with `content == error == 0`, if the set min is not negative.
1117(Note that option `COLZ0` for TH2Poly has a different behavior than for TH2.)
1118
1119The following example illustrates the option `0` combined with the option `COL`.
1120
1121Begin_Macro(source)
1122{
1123 auto c1 = new TCanvas("c1","c1",600,600);
1124 c1->Divide(1,2);
1125 auto hcol21 = new TH2F("hcol21","Option COLZ",40,-4,4,40,-20,20);
1126 auto hcol22 = new TH2F("hcol22","Option COLZ0",40,-4,4,40,-20,20);
1127 float px, py;
1128 for (Int_t i = 0; i < 25000; i++) {
1129 gRandom->Rannor(px,py);
1130 hcol21->Fill(px,5*py);
1131 hcol22->Fill(px,5*py);
1132 }
1133 hcol21->SetBit(TH1::kNoStats);
1134 hcol22->SetBit(TH1::kNoStats);
1135 c1->cd(1); hcol21->Draw("COLZ");
1136 c1->cd(2); hcol22->Draw("COLZ0");
1137 hcol21->SetMaximum(100);
1138 hcol21->SetMinimum(40);
1139 hcol22->SetMaximum(100);
1140 hcol22->SetMinimum(40);
1141}
1142End_Macro
1143
1144Note that the behavior of `COLZ` is not symmetric: it does not draw values below the specified minimum,
1145but does draw values above the specified maximum by clipping them to the maximum color. In contrast, `COLZ0`
1146clips color on both lower and upper sides. Both `COLZ0` and `COLZ` exclude drawing empty bins (`content == error == 0`),
1147if the set minimum is not negative.
1148
1149\since **ROOT version 6.09/01:**
1150
1151When the option SAME (or "SAMES") is used with the option COL, the boxes' color
1152are computed taking the previous plots into account. The range along the Z axis
1153is imposed by the first plot (the one without option SAME); therefore the order
1154in which the plots are done is relevant. Same as [in the `BOX` option](\ref HP13), one can use
1155`SAME0` (or `SAMES0`) to opt out of this imposition.
1156
1157Begin_Macro(source)
1158{
1159 auto c = new TCanvas("c","Example of col plots with option SAME",200,10,700,500);
1160 auto h1 = new TH2F("h1","h1",40,-3,3,40,-3,3);
1161 auto h2 = new TH2F("h2","h2",40,-3,3,40,-3,3);
1162 auto h3 = new TH2F("h3","h3",40,-3,3,40,-3,3);
1163 auto h4 = new TH2F("h4","h4",40,-3,3,40,-3,3);
1164 h1->SetBit(TH1::kNoStats);
1165 for (Int_t i=0;i<5000;i++) {
1166 double x,y;
1167 gRandom->Rannor(x,y);
1168 if(x>0 && y>0) h1->Fill(x,y,4);
1169 if(x<0 && y<0) h2->Fill(x,y,3);
1170 if(x>0 && y<0) h3->Fill(x,y,2);
1171 if(x<0 && y>0) h4->Fill(x,y,1);
1172 }
1173 h1->Draw("colz");
1174 h2->Draw("col same");
1175 h3->Draw("col same");
1176 h4->Draw("col same");
1177}
1178End_Macro
1179
1180The option `COL` can be combined with the option `POL`:
1181
1182Begin_Macro(source)
1183{
1184 auto c1 = new TCanvas("c1","c1",600,400);
1185 auto hcol1 = new TH2F("hcol1","Option COLor combined with POL",40,-4,4,40,-4,4);
1186 float px, py;
1187 for (Int_t i = 0; i < 25000; i++) {
1188 gRandom->Rannor(px,py);
1189 hcol1->Fill(px,py);
1190 }
1191 hcol1->Draw("COLZPOL");
1192}
1193End_Macro
1194
1195\since **ROOT version 6.07/03:**
1196
1197A second rendering technique is also available with the COL2 and COLZ2 options.
1198
1199These options provide potential performance improvements compared to the standard
1200COL option. The performance comparison of the COL2 to the COL option depends on
1201the histogram and the size of the rendering region in the current pad. In general,
1202a small (approx. less than 100 bins per axis), sparsely populated TH2 will render
1203faster with the COL option.
1204
1205However, for larger histograms (approx. more than 100 bins per axis)
1206that are not sparse, the COL2 option will provide up to 20 times performance improvements.
1207For example, a 1000x1000 bin TH2 that is not sparse will render an order of magnitude
1208faster with the COL2 option.
1209
1210The COL2 option will also scale its performance based on the size of the
1211pixmap the histogram image is being rendered into. It also is much better optimized for
1212sessions where the user is forwarding X11 windows through an `ssh` connection.
1213
1214For the most part, the COL2 and COLZ2 options are a drop in replacement to the COL
1215and COLZ options. There is one major difference and that concerns the treatment of
1216bins with zero content. The COL2 and COLZ2 options color these bins the color of zero.
1217
1218COL2 option renders the histogram as a bitmap. Therefore it cannot be saved in vector
1219graphics file format like PostScript or PDF (an empty image will be generated). It can
1220be saved only in bitmap files like PNG format for instance.
1221
1222
1223\anchor HP140
1224### The CANDLE and VIOLIN options
1225
1226The mechanism behind Candle plots and Violin plots is very similar. Because of this they are
1227implemented in the same class TCandle. The keywords CANDLE or VIOLIN will initiate the drawing of
1228the corresponding plots. Followed by the keyword the user can select a plot direction (X or V for
1229vertical projections, or Y or H for horizontal projections) and/or predefined definitions
1230(1-6 for candles, 1-2 for violins). The order doesn't matter. Default is X and 1.
1231
1232Instead of using the predefined representations, the candle and violin parameters can be
1233changed individually. In that case the option have the following form:
1234
1235 CANDLEX(<option-string>)
1236 CANDLEY(<option-string>)
1237 VIOLINX(<option-string>)
1238 VIOLINY(<option-string>).
1239
1240All zeros at the beginning of `option-string` can be omitted.
1241
1242`option-string` consists eight values, defined as follow:
1243
1244 "CANDLEX(zhpawMmb)"
1245
1246Where:
1247
1248 - `b = 0`; no box drawn
1249 - `b = 1`; the box is drawn. As the candle-plot is also called a box-plot it
1250 makes sense in the very most cases to always draw the box
1251 - `b = 2`; draw a filled box with border
1252
1253 - `m = 0`; no median drawn
1254 - `m = 1`; median is drawn as a line
1255 - `m = 2`; median is drawn with errors (notches)
1256 - `m = 3`; median is drawn as a circle
1257
1258 - `M = 0`; no mean drawn
1259 - `M = 1`; mean is drawn as a dashed line
1260 - `M = 3`; mean is drawn as a circle
1261
1262 - `w = 0`; no whisker drawn
1263 - `w = 1`; whisker is drawn to end of distribution.
1264 - `w = 2`; whisker is drawn to max 1.5*iqr
1265
1266 - `a = 0`; no anchor drawn
1267 - `a = 1`; the anchors are drawn
1268
1269 - `p = 0`; no points drawn
1270 - `p = 1`; only outliers are drawn
1271 - `p = 2`; all datapoints are drawn
1272 - `p = 3`: all datapoints are drawn scattered
1273
1274 - `h = 0`; no histogram is drawn
1275 - `h = 1`; histogram at the left or bottom side is drawn
1276 - `h = 2`; histogram at the right or top side is drawn
1277 - `h = 3`; histogram at left and right or top and bottom (violin-style) is drawn
1278
1279 - `z = 0`; no zero indicator line is drawn
1280 - `z = 1`; zero indicator line is drawn.
1281
1282As one can see all individual options for both candle and violin plots can be accessed by this
1283mechanism. In deed the keywords CANDLE(<option-string>) and VIOLIN(<option-string>) have the same
1284meaning. So you can parametrise an option-string for a candle plot and use the keywords VIOLIN and
1285vice versa, if you wish.
1286
1287Using a logarithmic x- or y-axis is possible for candle and violin charts.
1288
1289\since **ROOT version 6.11/01**
1290
1291a logarithmic z-axis is possible, too but will only affect violin charts of course.
1292
1293\anchor HP140a
1294#### The CANDLE option
1295
1296<a href="http://en.wikipedia.org/wiki/Box_plot">A Candle plot</a> (also known as
1297a "box plot" or "whisker plot") was invented in 1977 by John Tukey. It is a convenient
1298way to describe graphically a data distribution (D) with only five numbers:
1299
1300 1. The minimum value of the distribution D (bottom or left whisker).
1301 2. The lower quartile (Q1): 25% of the data points in D are less than Q1 (bottom of the box).
1302 3. The median (M): 50% of the data points in D are less than M.
1303 4. The upper quartile (Q3): 75% of the data points in D are less than Q3 (top of the box).
1304 5. The maximum value of the distribution D (top or right whisker).
1305
1306In this implementation a TH2 is considered as a collection of TH1 along
1307X (option `CANDLE` or `CANDLEX`) or Y (option `CANDLEY`).
1308Each TH1 is represented as one candle.
1309
1310Begin_Macro(source)
1311../../../tutorials/hist/hist052_Graphics_candle_plot_whiskers.C
1312End_Macro
1313
1314The candle reduces the information coming from a whole distribution into few values.
1315Independently from the number of entries or the significance of the underlying distribution
1316a candle will always look like a candle. So candle plots should be used carefully in
1317particular with unknown distributions. The definition of a candle is based on
1318__unbinned data__. Here, candles are created from binned data. Because of this, the
1319deviation is connected to the bin width used. The calculation of the quantiles
1320normally done on unbinned data also. Because data are binned, this will
1321only work the best possible way within the resolution of one bin
1322
1323Because of all these facts one should take care that:
1324
1325 - there are enough points per candle
1326 - the bin width is small enough (more bins will increase the maximum
1327 available resolution of the quantiles although there will be some
1328 bins with no entries)
1329 - never make a candle-plot if the underlying distribution is double-distributed
1330 - only create candles of distributions that are more-or-less gaussian (the
1331 MPV should be not too far away from the mean).
1332
1333#### What a candle is made of
1334
1335\since **ROOT version 6.07/05**
1336
1337##### The box
1338The box displays the position of the inter-quantile-range of the underlying
1339distribution. The box contains 25% of the distribution below the median
1340and 25% of the distribution above the median. If the underlying distribution is large
1341enough and gaussian shaped the end-points of the box represent \f$ 0.6745\times\sigma \f$
1342(Where \f$ \sigma \f$ is the standard deviation of the gaussian). The width and
1343the position of the box can be modified by SetBarWidth() and SetBarOffset().
1344The +-25% quantiles are calculated by the GetQuantiles() methods.
1345
1346\since **ROOT version 6.11/01**
1347
1348Using the static function TCandle::SetBoxRange(double) the box definition will be
1349overwritten. E.g. using a box range of 0.68 will redefine the area of the lower box edge
1350to the upper box edge in order to cover 68% of the distribution illustrated by that candle.
1351The static function will affect all candle-charts in the running program.
1352Default is 0.5.
1353
1354Using the static function TCandle::SetScaledCandle(bool) the width of the box (and the
1355whole candle) can be influenced. Deactivated, the width is constant (to be set by
1356SetBarWidth() ). Activated, the width of the boxes will be scaled to each other based on the
1357amount of data in the corresponding candle, the maximum width can be influenced by
1358SetBarWidth(). The static function will affect all candle-charts in the running program.
1359Default is false. Scaling between multiple candle-charts (using "same" or THStack) is not
1360supported, yet
1361
1362##### The Median
1363For a sorted list of numbers, the median is the value in the middle of the list.
1364E.g. if a sorted list is made of five numbers "1,2,3,6,7" 3 will be the median
1365because it is in the middle of the list. If the number of entries is even the
1366average of the two values in the middle will be used. As histograms are binned
1367data, the situation is a bit more complex. The following example shows this:
1368
1369~~~ {.cpp}
1370void quantiles() {
1371 auto h = new TH1I("h","h",10,0,10);
1372 //h->Fill(3);
1373 //h->Fill(3);
1374 h->Fill(4);
1375 h->Draw();
1376 double p = 0.;
1377 double q = 0.;
1378 h->GetQuantiles(1,&q,&p);
1379
1380 cout << "Median is: " << q << std::endl;
1381}
1382~~~
1383
1384Here the bin-width is 1.0. If the two Fill(3) are commented out, as there are currently,
1385the example will return a calculated median of 4.5, because that's the bin center
1386of the bin in which the value 4.0 has been dropped. If the two Fill(3) are not
1387commented out, it will return 3.75, because the algorithm tries to evenly distribute
1388the individual values of a bin with bin content > 0. It means the sorted list
1389would be "3.25, 3.75, 4.5".
1390
1391The consequence is a median of 3.75. This shows how important it is to use a
1392small enough bin-width when using candle-plots on binned data.
1393If the distribution is large enough and gaussian shaped the median will be exactly
1394equal to the mean.
1395The median can be shown as a line or as a circle or not shown at all.
1396
1397In order to show the significance of the median notched candle plots apply a "notch" or
1398narrowing of the box around the median. The significance is defined by
1399\f$ 1.57\times\frac{iqr}{N} \f$ and will be represented as the size of the notch
1400(where iqr is the size of the box and N is the number of entries of the whole
1401distribution). Candle plots like these are usually called "notched candle plots".
1402
1403In case the significance of the median is greater that the size of the box, the
1404box will have an unnatural shape. Usually it means the chart has not enough data,
1405or that representing this uncertainty is not useful
1406
1407##### The Mean
1408The mean can be drawn as a dashed line or as a circle or not drawn at all.
1409The mean is the arithmetic average of the values in the distribution.
1410It is calculated using GetMean(). Because histograms are
1411binned data, the mean value can differ from a calculation on the raw-data.
1412If the distribution is large enough and gaussian shaped the mean will be
1413exactly the median.
1414
1415##### The Whiskers
1416The whiskers represent the part of the distribution not covered by the box.
1417The upper 25% and the lower 25% of the distribution are located within the whiskers.
1418Two representations are available.
1419
1420 - A simple one (using w=1) defining the lower whisker from the lowest data value
1421 to the bottom of the box, and the upper whisker from the top of the box to the
1422 highest data value. In this representation the whisker-lines are dashed.
1423 - A more complex one having a further restriction. The whiskers are still connected
1424 to the box but their length cannot exceed \f$ 1.5\times iqr \f$. So it might
1425 be that the outermost part of the underlying distribution will not be covered
1426 by the whiskers. Usually these missing parts will be represented by the outliers
1427 (see points). Of course the upper and the lower whisker may differ in length.
1428 In this representation the whiskers are drawn as solid lines.
1429
1430\since **ROOT version 6.11/01**
1431
1432Using the static function TCandle::SetWhiskerRange(double) the whisker definition w=1
1433will be overwritten. E.g. using a whisker-range of 0.95 and w=1 will redefine the area of
1434the lower whisker to the upper whisker in order to cover 95% of the distribution inside
1435that candle. The static function will affect all candle-charts in the running program.
1436Default is 1.
1437
1438If the distribution is large enough and gaussian shaped, the maximum length of
1439the whisker will be located at \f$ \pm 2.698 \sigma \f$ (when using the
14401.5*iqr-definition (w=2), where \f$ \sigma \f$ is the standard deviation
1441(see picture above). In that case 99.3% of the total distribution will be covered
1442by the box and the whiskers, whereas 0.7% are represented by the outliers.
1443
1444##### The Anchors
1445The anchors have no special meaning in terms of statistical calculation. They mark
1446the end of the whiskers and they have the width of the box. Both representation
1447with and without anchors are common.
1448
1449##### The Points
1450Depending on the configuration the points can have different meanings:
1451 - If p=1 the points represent the outliers. If they are shown, it means
1452 some parts of the underlying distribution are not covered by the whiskers.
1453 This can only occur when the whiskers are set to option w=2. Here the whiskers
1454 can have a maximum length of \f$ 1.5 \times iqr \f$. So any points outside the
1455 whiskers will be drawn as outliers. The outliers will be represented by crosses.
1456 - If p=2 all points in the distribution will be painted as crosses. This is
1457 useful for small datasets only (up to 10 or 20 points per candle).
1458 The outliers are shown along the candle. Because the underlying distribution
1459 is binned, is frequently occurs that a bin contains more than one value.
1460 Because of this the points will be randomly scattered within their bin along
1461 the candle axis. If the bin content for a bin is exactly 1 (usually
1462 this happens for the outliers) if will be drawn in the middle of the bin along
1463 the candle axis. As the maximum number of points per candle is limited by kNMax/2
1464 on very large datasets scaling will be performed automatically. In that case one
1465 would loose all outliers because they have usually a bin content of 1 (and a
1466 bin content between 0 and 1 after the scaling). Because of this all bin contents
1467 between 0 and 1 - after the scaling - will be forced to be 1.
1468 - As the drawing of all values on large datasets can lead to big amounts of crosses,
1469 one can show all values as a scatter plot instead by choosing p=3. The points will be
1470 drawn as dots and will be scattered within the width of the candle. The color
1471 of the points will be the color of the candle-chart.
1472
1473##### Other Options
1474Is is possible to combine all options of candle and violin plots with each other. E.g. a box-plot
1475with a histogram.
1476
1477#### How to use the candle-plots drawing option
1478
1479There are six predefined candle-plot representations:
1480
1481 - "CANDLEX1": Standard candle (whiskers cover the whole distribution)
1482 - "CANDLEX2": Standard candle with better whisker definition + outliers.
1483 It is a good compromise
1484 - "CANDLEX3": Like candle2 but with a mean as a circle.
1485 It is easier to distinguish mean and median
1486 - "CANDLEX4": Like candle3 but showing the uncertainty of the median as well
1487 (notched candle plots).
1488 For bigger datasets per candle
1489 - "CANDLEX5": Like candle2 but showing all data points.
1490 For very small datasets
1491 - "CANDLEX6": Like candle2 but showing all datapoints scattered.
1492 For huge datasets
1493
1494
1495The following picture shows how the six predefined representations look.
1496
1497Begin_Macro
1498{
1499 auto c1 = new TCanvas("c1","c1",700,800);
1500 c1->Divide(2,3);
1501 gStyle->SetOptStat(kFALSE);
1502
1503 auto hcandle = new TH2F("hcandle"," ",10,-4,4,40,-20,20);
1504 float px, py;
1505 for (Int_t i = 0; i < 15000; i++) {
1506 gRandom->Rannor(px,py);
1507 hcandle->Fill(px,5*py);
1508 }
1509 hcandle->SetMarkerSize(0.5);
1510
1511 TH2F *h2;
1512 for (Int_t i=1; i<7; i++) {
1513 c1->cd(i);
1514 h2 = (TH2F*)hcandle->DrawClone(Form("CANDLE%d",i));
1515 h2->SetTitle(Form("CANDLE%d",i));
1516 }
1517}
1518End_Macro
1519
1520
1521#### Example 1
1522Box and improved whisker, no mean, no median, no anchor no outliers
1523
1524 h1->Draw("CANDLEX(2001)");
1525
1526#### Example 2
1527A Candle-definition like "CANDLEX2" (New standard candle with better whisker definition + outliers)
1528
1529 h1->Draw("CANDLEX(112111)");
1530
1531#### Example 3
1532The following example shows how several candle plots can be super-imposed using
1533the option SAME. Note that the bar-width and bar-offset are active on candle plots.
1534Also the color, the line width, the size of the points and so on can be changed by the
1535standard attribute setting methods such as SetLineColor() SetLineWidth().
1536
1537Begin_Macro(source)
1538../../../tutorials/hist/hist049_Graphics_candle_plot.C
1539End_Macro
1540
1541\anchor HP140b
1542#### The VIOLIN option
1543
1544<a href="http://en.wikipedia.org/wiki/Violin_plot">A violin plot</a> is a candle plot
1545that also encodes the pdf information at each point.
1546
1547
1548Quartiles and mean are also represented at each point, with a marker
1549and two lines.
1550
1551In this implementation a TH2 is considered as a collection of TH1 along
1552X (option `VIOLIN` or `VIOLINX`) or Y (option `VIOLINY`).
1553
1554#### What a violin is made of
1555
1556\since **ROOT version 6.09/02**
1557
1558##### The histogram
1559The histogram is typically drawn to both directions with respect to the middle-line of the
1560corresponding bin. This can be achieved by using h=3. It is possible to draw a histogram only to
1561one side (h=1, or h=2).
1562The maximum number of bins in the histogram is limited to 500, if the number of bins in the used
1563histogram is higher it will be rebinned automatically. The maximum height of the histogram can
1564be modified by using SetBarWidth() and the position can be changed with SetBarOffset().
1565A solid fill style is recommended.
1566
1567\since **ROOT version 6.11/01**
1568
1569Using the static function TCandle::SetScaledViolin(bool) the height of the histogram or the
1570violin can be influenced. Activated, the height of the bins of the individual violins will be
1571scaled with respect to each other, the maximum height can be influenced by SetBarWidth().
1572Deactivated, the height of the bin with the maximum content of each individual violin is
1573set to a constant value using SetBarWidth(). The static function will affect all violin-charts
1574in the running program. Default is true. Scaling between multiple violin-charts
1575(using "same" or THStack) is not supported, yet.
1576
1577##### The zero indicator line
1578Typical for violin charts is a line in the background over the whole histogram indicating
1579the bins with zero entries. The zero indicator line can be activated with z=1. The line color
1580will always be the same as the fill-color of the histogram.
1581
1582##### The Mean
1583The Mean is illustrated with the same mechanism as used for candle plots. Usually a circle is used.
1584
1585##### Whiskers
1586The whiskers are illustrated by the same mechanism as used for candle plots. There is only one
1587difference. When using the simple whisker definition (w=1) and the zero indicator line (z=1), then
1588the whiskers will be forced to be solid (usually hashed)
1589
1590##### Points
1591The points are illustrated by the same mechanism as used for candle plots. E.g. VIOLIN2 uses
1592better whisker definition (w=2) and outliers (p=1).
1593
1594##### Other options
1595It is possible to combine all options of candle or violin plots with each other. E.g. a violin plot
1596including a box-plot.
1597
1598#### How to use the violin-plots drawing option
1599
1600There are two predefined violin-plot representations:
1601 - "VIOLINX1": Standard violin (histogram, mean, whisker over full distribution,
1602 zero indicator line)
1603 - "VIOLINX2": Line VIOLINX1 both with better whisker definition + outliers.
1604
1605A solid fill style is recommended for this plot (as opposed to a hollow or
1606hashed style).
1607
1608Begin_Macro(source)
1609{
1610 auto c1 = new TCanvas("c1","c1",600,400);
1611 Int_t nx(6), ny(40);
1612 double xmin(0.0), xmax(+6.0), ymin(0.0), ymax(+4.0);
1613 auto hviolin = new TH2F("hviolin", "Option VIOLIN example", nx, xmin, xmax, ny, ymin, ymax);
1614 TF1 f1("f1", "gaus", +0,0 +4.0);
1615 double x,y;
1616 for (Int_t iBin=1; iBin<hviolin->GetNbinsX(); ++iBin) {
1617 double xc = hviolin->GetXaxis()->GetBinCenter(iBin);
1618 f1.SetParameters(1, 2.0+TMath::Sin(1.0+xc), 0.2+0.1*(xc-xmin)/xmax);
1619 for(Int_t i=0; i<10000; ++i){
1620 x = xc;
1621 y = f1.GetRandom();
1622 hviolin->Fill(x, y);
1623 }
1624 }
1625 hviolin->SetFillColor(kGray);
1626 hviolin->SetMarkerStyle(20);
1627 hviolin->SetMarkerSize(0.5);
1628 hviolin->Draw("VIOLIN");
1629 c1->Update();
1630}
1631End_Macro
1632
1633The next example illustrates a time development of a certain value:
1634
1635Begin_Macro(source)
1636../../../tutorials/hist/hist047_Graphics_candle_decay.C
1637End_Macro
1638
1639
1640\anchor HP15
1641### The TEXT and TEXTnn Option
1642
1643
1644For each bin the content is printed. The text attributes are:
1645
1646- text font = current TStyle font (`gStyle->SetTextFont()`).
1647- text size = 0.02*padheight*markersize (if `h` is the histogram drawn
1648 with the option `TEXT` the marker size can be changed with
1649 `h->SetMarkerSize(markersize)`).
1650- text color = marker color.
1651
1652By default the format `g` is used. This format can be redefined
1653by calling `gStyle->SetPaintTextFormat()`.
1654
1655It is also possible to use `TEXTnn` in order to draw the text with
1656the angle `nn` (`0 < nn <= 90`).
1657
1658For 2D histograms the text is plotted in the center of each non empty cells.
1659It is possible to plot empty cells by calling `gStyle->SetHistMinimumZero()`
1660or providing MIN0 draw option. For 1D histogram the text is plotted at a y
1661position equal to the bin content.
1662
1663For 2D histograms when the option "E" (errors) is combined with the option
1664text ("TEXTE"), the error for each bin is also printed.
1665
1666Begin_Macro(source)
1667{
1668 auto c01 = new TCanvas("c01","c01",700,400);
1669 c01->Divide(2,1);
1670 auto htext1 = new TH1F("htext1","Option TEXT on 1D histograms ",10,-4,4);
1671 auto htext2 = new TH2F("htext2","Option TEXT on 2D histograms ",10,-4,4,10,-20,20);
1672 float px, py;
1673 for (Int_t i = 0; i < 25000; i++) {
1674 gRandom->Rannor(px,py);
1675 htext1->Fill(px,0.1);
1676 htext2->Fill(px,5*py,0.1);
1677 }
1678 gStyle->SetPaintTextFormat("4.1f m");
1679 htext2->SetMarkerSize(1.8);
1680 c01->cd(1);
1681 htext2->Draw("TEXT45");
1682 c01->cd(2);
1683 htext1->Draw();
1684 htext1->Draw("HIST TEXT0 SAME");
1685}
1686End_Macro
1687
1688\since **ROOT version 6.07/07:**
1689
1690In case several histograms are drawn on top ot each other (using option `SAME`),
1691the text can be shifted using `SetBarOffset()`. It specifies an offset for the
1692text position in each cell, in percentage of the bin width.
1693
1694Begin_Macro(source)
1695{
1696 auto c03 = new TCanvas("c03","c03",700,400);
1697 gStyle->SetOptStat(0);
1698 auto htext3 = new TH2F("htext3","Several 2D histograms drawn with option TEXT",10,-4,4,10,-20,20);
1699 auto htext4 = new TH2F("htext4","htext4",10,-4,4,10,-20,20);
1700 auto htext5 = new TH2F("htext5","htext5",10,-4,4,10,-20,20);
1701 float px, py;
1702 for (Int_t i = 0; i < 25000; i++) {
1703 gRandom->Rannor(px,py);
1704 htext3->Fill(4*px,20*py,0.1);
1705 htext4->Fill(4*px,20*py,0.5);
1706 htext5->Fill(4*px,20*py,1.0);
1707 }
1708 htext4->SetMarkerSize(1.8);
1709 htext5->SetMarkerSize(1.8);
1710 htext5->SetMarkerColor(kRed);
1711 htext4->SetBarOffset(0.2);
1712 htext5->SetBarOffset(-0.2);
1713 htext3->Draw("COL");
1714 htext4->Draw("TEXT SAME");
1715 htext5->Draw("TEXT SAME");
1716}
1717End_Macro
1718
1719In the case of profile histograms it is possible to print the number
1720of entries instead of the bin content. It is enough to combine the
1721option "E" (for entries) with the option "TEXT".
1722
1723Begin_Macro(source)
1724{
1725 auto c02 = new TCanvas("c02","c02",700,400);
1726 c02->Divide(2,1);
1727 gStyle->SetPaintTextFormat("g");
1728
1729 auto profile = new TProfile("profile","profile",10,0,10);
1730 profile->SetMarkerSize(2.2);
1731 profile->Fill(0.5,1);
1732 profile->Fill(1.5,2);
1733 profile->Fill(2.5,3);
1734 profile->Fill(3.5,4);
1735 profile->Fill(4.5,5);
1736 profile->Fill(5.5,5);
1737 profile->Fill(6.5,4);
1738 profile->Fill(7.5,3);
1739 profile->Fill(8.5,2);
1740 profile->Fill(9.5,1);
1741 c02->cd(1); profile->Draw("HIST TEXT0");
1742 c02->cd(2); profile->Draw("HIST TEXT0E");
1743}
1744End_Macro
1745
1746\anchor HP16
1747### The CONTour options
1748
1749
1750The following contour options are supported:
1751
1752| Option | Description |
1753|----------|-----------------------------------------------------------------------------|
1754| "CONT" | Draw a contour plot (same as CONT0). |
1755| "CONT0" | Draw a contour plot using surface colors to distinguish contours. |
1756| "CONT1" | Draw a contour plot using the line colors to distinguish contours. |
1757| "CONT2" | Draw a contour plot using the line styles (1 to 5) to distinguish contours. |
1758| "CONT3" | Draw a contour plot using the same line style for all contours. |
1759| "CONT4" | Draw a contour plot using surface colors (`SURF` option at theta = 0). |
1760
1761
1762The following example shows a 2D histogram plotted with the option
1763`CONTZ`. The option `CONT` draws a contour plot using surface
1764colors to distinguish contours. Combined with the option `CONT` (or
1765`CONT0`), the option `Z` allows to display the color palette
1766defined by `gStyle->SetPalette()`.
1767
1768Begin_Macro(source)
1769{
1770 auto c1 = new TCanvas("c1","c1",600,400);
1771 auto hcontz = new TH2F("hcontz","Option CONTZ example ",40,-4,4,40,-20,20);
1772 float px, py;
1773 for (Int_t i = 0; i < 25000; i++) {
1774 gRandom->Rannor(px,py);
1775 hcontz->Fill(px-1,5*py);
1776 hcontz->Fill(2+0.5*px,2*py-10.,0.1);
1777 }
1778 hcontz->Draw("CONTZ");
1779}
1780End_Macro
1781
1782The following example shows a 2D histogram plotted with the option
1783`CONT1Z`. The option `CONT1` draws a contour plot using the
1784line colors to distinguish contours. Combined with the option `CONT1`,
1785the option `Z` allows to display the color palette defined by
1786`gStyle->SetPalette()`.
1787
1788Begin_Macro(source)
1789{
1790 auto c1 = new TCanvas("c1","c1",600,400);
1791 auto hcont1 = new TH2F("hcont1","Option CONT1Z example ",40,-4,4,40,-20,20);
1792 float px, py;
1793 for (Int_t i = 0; i < 25000; i++) {
1794 gRandom->Rannor(px,py);
1795 hcont1->Fill(px-1,5*py);
1796 hcont1->Fill(2+0.5*px,2*py-10.,0.1);
1797 }
1798 hcont1->Draw("CONT1Z");
1799}
1800End_Macro
1801
1802The following example shows a 2D histogram plotted with the option
1803`CONT2`. The option `CONT2` draws a contour plot using the
1804line styles (1 to 5) to distinguish contours.
1805
1806Begin_Macro(source)
1807{
1808 auto c1 = new TCanvas("c1","c1",600,400);
1809 auto hcont2 = new TH2F("hcont2","Option CONT2 example ",40,-4,4,40,-20,20);
1810 float px, py;
1811 for (Int_t i = 0; i < 25000; i++) {
1812 gRandom->Rannor(px,py);
1813 hcont2->Fill(px-1,5*py);
1814 hcont2->Fill(2+0.5*px,2*py-10.,0.1);
1815 }
1816 hcont2->Draw("CONT2");
1817}
1818End_Macro
1819
1820The following example shows a 2D histogram plotted with the option
1821`CONT3`. The option `CONT3` draws contour plot using the same line style for
1822all contours.
1823
1824Begin_Macro(source)
1825{
1826 auto c1 = new TCanvas("c1","c1",600,400);
1827 auto hcont3 = new TH2F("hcont3","Option CONT3 example ",40,-4,4,40,-20,20);
1828 float px, py;
1829 for (Int_t i = 0; i < 25000; i++) {
1830 gRandom->Rannor(px,py);
1831 hcont3->Fill(px-1,5*py);
1832 hcont3->Fill(2+0.5*px,2*py-10.,0.1);
1833 }
1834 hcont3->SetLineStyle(kDotted);
1835 hcont3->Draw("CONT3");
1836}
1837End_Macro
1838
1839The following example shows a 2D histogram plotted with the option
1840`CONT4`. The option `CONT4` draws a contour plot using surface
1841colors to distinguish contours (`SURF` option at theta = 0). Combined
1842with the option `CONT` (or `CONT0`), the option `Z`
1843allows to display the color palette defined by `gStyle->SetPalette()`.
1844
1845Begin_Macro(source)
1846{
1847 auto c1 = new TCanvas("c1","c1",600,400);
1848 auto hcont4 = new TH2F("hcont4","Option CONT4Z example ",40,-4,4,40,-20,20);
1849 float px, py;
1850 for (Int_t i = 0; i < 25000; i++) {
1851 gRandom->Rannor(px,py);
1852 hcont4->Fill(px-1,5*py);
1853 hcont4->Fill(2+0.5*px,2*py-10.,0.1);
1854 }
1855 hcont4->Draw("CONT4Z");
1856}
1857End_Macro
1858
1859The default number of contour levels is 20 equidistant levels and can be changed
1860with `TH1::SetContour()` or `TStyle::SetNumberContours()`.
1861
1862\anchor HP16a
1863#### The LIST option
1864
1865When option `LIST` is specified together with option
1866`CONT`, the points used to draw the contours are saved in
1867`TGraph` objects:
1868
1869 h->Draw("CONT LIST");
1870 gPad->Update();
1871
1872The contour are saved in `TGraph` objects once the pad is painted.
1873Therefore to use this functionality in a macro, `gPad->Update()`
1874should be performed after the histogram drawing. Once the list is
1875built, the contours are accessible in the following way:
1876
1877 TObjArray *contours = (TObjArray*)gROOT->GetListOfSpecials()->FindObject("contours");
1878 Int_t ncontours = contours->GetSize();
1879 TList *list = (TList*)contours->At(i);
1880
1881Where `i` is a contour number, and list contains a list of
1882`TGraph` objects.
1883For one given contour, more than one disjoint polyline may be generated.
1884The number of TGraphs per contour is given by:
1885
1886 list->GetSize();
1887
1888To access the first graph in the list one should do:
1889
1890 TGraph *gr1 = (TGraph*)list->First();
1891
1892
1893The following example (hist102_TH2_contour_list.C) shows how to use this functionality.
1894
1895Begin_Macro(source)
1896../../../tutorials/hist/hist102_TH2_contour_list.C
1897End_Macro
1898
1899\anchor HP16b
1900#### The AITOFF, MERCATOR, SINUSOIDAL and PARABOLIC options
1901
1902The following options select the `CONT4` option and are useful for
1903sky maps or exposure maps (earth.C).
1904
1905| Option | Description |
1906|--------------|---------------------------------------------------------------|
1907| "AITOFF" | Draw a contour via an AITOFF projection.|
1908| "MERCATOR" | Draw a contour via an Mercator projection.|
1909| "SINUSOIDAL" | Draw a contour via an Sinusoidal projection.|
1910| "PARABOLIC" | Draw a contour via an Parabolic projection.|
1911
1912Begin_Macro(source)
1913../../../tutorials/visualisation/graphics/earth.C
1914End_Macro
1915
1916
1917\anchor HP17
1918### The LEGO options
1919
1920
1921In a lego plot the cell contents are drawn as 3-d boxes. The height of each box
1922is proportional to the cell content. The lego aspect is control with the
1923following options:
1924
1925| Option | Description |
1926|----------|-------------------------------------------------------------------|
1927| "LEGO" | Draw a lego plot using the hidden lines removal technique.|
1928| "LEGO1" | Draw a lego plot using the hidden surface removal technique.|
1929| "LEGO2" | Draw a lego plot using colors to show the cell contents.|
1930| "LEGO3" | Draw a lego plot with hidden surface removal, like LEGO1 but the border lines of each lego-bar are not drawn.|
1931| "LEGO4" | Draw a lego plot with hidden surface removal, like LEGO1 but without the shadow effect on each lego-bar.|
1932| "0" | When used with any LEGO option, the empty bins are not drawn.|
1933
1934
1935See the limitations with [the option "SAME"](\ref HP060a).
1936
1937Line attributes can be used in lego plots to change the edges' style.
1938
1939The following example shows a 2D histogram plotted with the option
1940`LEGO`. The option `LEGO` draws a lego plot using the hidden
1941lines removal technique.
1942
1943Begin_Macro(source)
1944{
1945 auto c2 = new TCanvas("c2","c2",600,400);
1946 auto hlego = new TH2F("hlego","Option LEGO example ",40,-4,4,40,-20,20);
1947 float px, py;
1948 for (Int_t i = 0; i < 25000; i++) {
1949 gRandom->Rannor(px,py);
1950 hlego->Fill(px-1,5*py);
1951 hlego->Fill(2+0.5*px,2*py-10.,0.1);
1952 }
1953 hlego->Draw("LEGO");
1954}
1955End_Macro
1956
1957The following example shows a 2D histogram plotted with the option
1958`LEGO1`. The option `LEGO1` draws a lego plot using the
1959hidden surface removal technique. Combined with any `LEGOn` option, the
1960option `0` allows to not drawn the empty bins.
1961
1962Begin_Macro(source)
1963{
1964 auto c2 = new TCanvas("c2","c2",600,400);
1965 auto hlego1 = new TH2F("hlego1","Option LEGO1 example (with option 0) ",40,-4,4,40,-20,20);
1966 float px, py;
1967 for (Int_t i = 0; i < 25000; i++) {
1968 gRandom->Rannor(px,py);
1969 hlego1->Fill(px-1,5*py);
1970 hlego1->Fill(2+0.5*px,2*py-10.,0.1);
1971 }
1972 hlego1->SetFillColor(kYellow);
1973 hlego1->Draw("LEGO1 0");
1974}
1975End_Macro
1976
1977The following example shows a 2D histogram plotted with the option
1978`LEGO3`. Like the option `LEGO1`, the option `LEGO3`
1979draws a lego plot using the hidden surface removal technique but doesn't draw
1980the border lines of each individual lego-bar. This is very useful for histograms
1981having many bins. With such histograms the option `LEGO1` gives a black
1982image because of the border lines. This option also works with stacked legos.
1983
1984Begin_Macro(source)
1985{
1986 auto c2 = new TCanvas("c2","c2",600,400);
1987 auto hlego3 = new TH2F("hlego3","Option LEGO3 example",40,-4,4,40,-20,20);
1988 float px, py;
1989 for (Int_t i = 0; i < 25000; i++) {
1990 gRandom->Rannor(px,py);
1991 hlego3->Fill(px-1,5*py);
1992 hlego3->Fill(2+0.5*px,2*py-10.,0.1);
1993 }
1994 hlego3->SetFillColor(kRed);
1995 hlego3->Draw("LEGO3");
1996}
1997End_Macro
1998
1999The following example shows a 2D histogram plotted with the option
2000`LEGO2`. The option `LEGO2` draws a lego plot using colors to
2001show the cell contents. Combined with the option `LEGO2`, the option
2002`Z` allows to display the color palette defined by
2003`gStyle->SetPalette()`.
2004
2005Begin_Macro(source)
2006{
2007 auto c2 = new TCanvas("c2","c2",600,400);
2008 auto hlego2 = new TH2F("hlego2","Option LEGO2Z example ",40,-4,4,40,-20,20);
2009 float px, py;
2010 for (Int_t i = 0; i < 25000; i++) {
2011 gRandom->Rannor(px,py);
2012 hlego2->Fill(px-1,5*py);
2013 hlego2->Fill(2+0.5*px,2*py-10.,0.1);
2014 }
2015 hlego2->Draw("LEGO2Z");
2016}
2017End_Macro
2018
2019
2020
2021\anchor HP18
2022### The "SURFace" options
2023
2024
2025In a surface plot, cell contents are represented as a mesh.
2026The height of the mesh is proportional to the cell content.
2027
2028| Option | Description |
2029|----------|-------------------------------------------------------------------|
2030| "SURF" | Draw a surface plot using the hidden line removal technique.|
2031| "SURF1" | Draw a surface plot using the hidden surface removal technique.|
2032| "SURF2" | Draw a surface plot using colors to show the cell contents.|
2033| "SURF3" | Same as `SURF` with an additional filled contour plot on top.|
2034| "SURF4" | Draw a surface using the Gouraud shading technique.|
2035| "SURF5" | Used with one of the options CYL, PSR and CYL this option allows to draw a filled contour plot.|
2036| "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.|
2037| "SURF7" | Same as `SURF2` with an additional line contour plot on top.|
2038
2039
2040
2041See the limitations with [the option "SAME"](\ref HP060a).
2042
2043The following example shows a 2D histogram plotted with the option
2044`SURF`. The option `SURF` draws a lego plot using the hidden
2045lines removal technique.
2046
2047Begin_Macro(source)
2048{
2049 auto c2 = new TCanvas("c2","c2",600,400);
2050 auto hsurf = new TH2F("hsurf","Option SURF example ",30,-4,4,30,-20,20);
2051 float px, py;
2052 for (Int_t i = 0; i < 25000; i++) {
2053 gRandom->Rannor(px,py);
2054 hsurf->Fill(px-1,5*py);
2055 hsurf->Fill(2+0.5*px,2*py-10.,0.1);
2056 }
2057 hsurf->Draw("SURF");
2058}
2059End_Macro
2060
2061The following example shows a 2D histogram plotted with the option
2062`SURF1`. The option `SURF1` draws a surface plot using the
2063hidden surface removal technique. Combined with the option `SURF1`,
2064the option `Z` allows to display the color palette defined by
2065`gStyle->SetPalette()`.
2066
2067Begin_Macro(source)
2068{
2069 auto c2 = new TCanvas("c2","c2",600,400);
2070 auto hsurf1 = new TH2F("hsurf1","Option SURF1 example ",30,-4,4,30,-20,20);
2071 float px, py;
2072 for (Int_t i = 0; i < 25000; i++) {
2073 gRandom->Rannor(px,py);
2074 hsurf1->Fill(px-1,5*py);
2075 hsurf1->Fill(2+0.5*px,2*py-10.,0.1);
2076 }
2077 hsurf1->Draw("SURF1");
2078}
2079End_Macro
2080
2081The following example shows a 2D histogram plotted with the option
2082`SURF2`. The option `SURF2` draws a surface plot using colors
2083to show the cell contents. Combined with the option `SURF2`, the option
2084`Z` allows to display the color palette defined by
2085`gStyle->SetPalette()`.
2086
2087Begin_Macro(source)
2088{
2089 auto c2 = new TCanvas("c2","c2",600,400);
2090 auto hsurf2 = new TH2F("hsurf2","Option SURF2 example ",30,-4,4,30,-20,20);
2091 float px, py;
2092 for (Int_t i = 0; i < 25000; i++) {
2093 gRandom->Rannor(px,py);
2094 hsurf2->Fill(px-1,5*py);
2095 hsurf2->Fill(2+0.5*px,2*py-10.,0.1);
2096 }
2097 hsurf2->Draw("SURF2");
2098}
2099End_Macro
2100
2101The following example shows a 2D histogram plotted with the option
2102`SURF3`. The option `SURF3` draws a surface plot using the
2103hidden line removal technique with, in addition, a filled contour view drawn on the
2104top. Combined with the option `SURF3`, the option `Z` allows
2105to display the color palette defined by `gStyle->SetPalette()`.
2106
2107Begin_Macro(source)
2108{
2109 auto c2 = new TCanvas("c2","c2",600,400);
2110 auto hsurf3 = new TH2F("hsurf3","Option SURF3 example ",30,-4,4,30,-20,20);
2111 float px, py;
2112 for (Int_t i = 0; i < 25000; i++) {
2113 gRandom->Rannor(px,py);
2114 hsurf3->Fill(px-1,5*py);
2115 hsurf3->Fill(2+0.5*px,2*py-10.,0.1);
2116 }
2117 hsurf3->Draw("SURF3");
2118}
2119End_Macro
2120
2121The following example shows a 2D histogram plotted with the option
2122`SURF4`. The option `SURF4` draws a surface using the Gouraud
2123shading technique.
2124
2125Begin_Macro(source)
2126{
2127 auto c2 = new TCanvas("c2","c2",600,400);
2128 auto hsurf4 = new TH2F("hsurf4","Option SURF4 example ",30,-4,4,30,-20,20);
2129 float px, py;
2130 for (Int_t i = 0; i < 25000; i++) {
2131 gRandom->Rannor(px,py);
2132 hsurf4->Fill(px-1,5*py);
2133 hsurf4->Fill(2+0.5*px,2*py-10.,0.1);
2134 }
2135 hsurf4->SetFillColor(kOrange);
2136 hsurf4->Draw("SURF4");
2137}
2138End_Macro
2139
2140The following example shows a 2D histogram plotted with the option
2141`SURF5 CYL`. Combined with the option `SURF5`, the option
2142`Z` allows to display the color palette defined by `gStyle->SetPalette()`.
2143
2144Begin_Macro(source)
2145{
2146 auto c2 = new TCanvas("c2","c2",600,400);
2147 auto hsurf5 = new TH2F("hsurf4","Option SURF5 example ",30,-4,4,30,-20,20);
2148 float px, py;
2149 for (Int_t i = 0; i < 25000; i++) {
2150 gRandom->Rannor(px,py);
2151 hsurf5->Fill(px-1,5*py);
2152 hsurf5->Fill(2+0.5*px,2*py-10.,0.1);
2153 }
2154 hsurf5->Draw("SURF5 CYL");
2155}
2156End_Macro
2157
2158The following example shows a 2D histogram plotted with the option
2159`SURF7`. The option `SURF7` draws a surface plot using the
2160hidden surfaces removal technique with, in addition, a line contour view drawn on the
2161top. Combined with the option `SURF7`, the option `Z` allows
2162to display the color palette defined by `gStyle->SetPalette()`.
2163
2164Begin_Macro(source)
2165{
2166 auto c2 = new TCanvas("c2","c2",600,400);
2167 auto hsurf7 = new TH2F("hsurf3","Option SURF7 example ",30,-4,4,30,-20,20);
2168 float px, py;
2169 for (Int_t i = 0; i < 25000; i++) {
2170 gRandom->Rannor(px,py);
2171 hsurf7->Fill(px-1,5*py);
2172 hsurf7->Fill(2+0.5*px,2*py-10.,0.1);
2173 }
2174 hsurf7->Draw("SURF7");
2175}
2176End_Macro
2177
2178As shown in the following example, when a contour plot is painted on top of a
2179surface plot using the option `SAME`, the contours appear in 3D on the
2180surface.
2181
2182Begin_Macro(source)
2183{
2184 auto c20=new TCanvas("c20","c20",600,400);
2185 int NBins = 50;
2186 double d = 2;
2187 auto hsc = new TH2F("hsc", "Surface and contour with option SAME ", NBins, -d, d, NBins, -d, d);
2188 for (int bx = 1; bx <= NBins; ++bx) {
2189 for (int by = 1; by <= NBins; ++by) {
2190 double x = hsc->GetXaxis()->GetBinCenter(bx);
2191 double y = hsc->GetYaxis()->GetBinCenter(by);
2192 hsc->SetBinContent(bx, by, exp(-x*x)*exp(-y*y));
2193 }
2194 }
2195 hsc->Draw("surf2");
2196 hsc->Draw("CONT1 SAME");
2197}
2198End_Macro
2199
2200
2201\anchor HP19
2202### Cylindrical, Polar, Spherical and PseudoRapidity/Phi options
2203
2204
2205Legos and surfaces plots are represented by default in Cartesian coordinates.
2206Combined with any `LEGOn` or `SURFn` options the following
2207options allow to draw a lego or a surface in other coordinates systems.
2208
2209| Option | Description |
2210|----------|-------------------------------------------------------------------|
2211| "CYL" | Use Cylindrical coordinates. The X coordinate is mapped on the angle and the Y coordinate on the cylinder length.|
2212| "POL" | Use Polar coordinates. The X coordinate is mapped on the angle and the Y coordinate on the radius.|
2213| "SPH" | Use Spherical coordinates. The X coordinate is mapped on the latitude and the Y coordinate on the longitude.|
2214| "PSR" | Use PseudoRapidity/Phi coordinates. The X coordinate is mapped on Phi.|
2215
2216
2217
2218<b>WARNING:</b> Axis are not drawn with these options.
2219
2220The following example shows the same histogram as a lego plot is the four
2221different coordinates systems.
2222
2223Begin_Macro(source)
2224{
2225 auto c3 = new TCanvas("c3","c3",600,400);
2226 c3->Divide(2,2);
2227 auto hlcc = new TH2F("hlcc","Cylindrical coordinates",20,-4,4,20,-20,20);
2228 float px, py;
2229 for (Int_t i = 0; i < 25000; i++) {
2230 gRandom->Rannor(px,py);
2231 hlcc->Fill(px-1,5*py);
2232 hlcc->Fill(2+0.5*px,2*py-10.,0.1);
2233 }
2234 hlcc->SetFillColor(kYellow);
2235 c3->cd(1); hlcc->Draw("LEGO1 CYL");
2236 c3->cd(2); auto hlpc = (TH2F*) hlcc->DrawClone("LEGO1 POL");
2237 hlpc->SetTitle("Polar coordinates");
2238 c3->cd(3); auto hlsc = (TH2F*) hlcc->DrawClone("LEGO1 SPH");
2239 hlsc->SetTitle("Spherical coordinates");
2240 c3->cd(4); auto hlprpc = (TH2F*) hlcc->DrawClone("LEGO1 PSR");
2241 hlprpc->SetTitle("PseudoRapidity/Phi coordinates");
2242}
2243End_Macro
2244
2245The following example shows the same histogram as a surface plot is the four different coordinates systems.
2246
2247Begin_Macro(source)
2248{
2249 auto c4 = new TCanvas("c4","c4",600,400);
2250 c4->Divide(2,2);
2251 auto hscc = new TH2F("hscc","Cylindrical coordinates",20,-4,4,20,-20,20);
2252 float px, py;
2253 for (Int_t i = 0; i < 25000; i++) {
2254 gRandom->Rannor(px,py);
2255 hscc->Fill(px-1,5*py);
2256 hscc->Fill(2+0.5*px,2*py-10.,0.1);
2257 }
2258 c4->cd(1); hscc->Draw("SURF1 CYL");
2259 c4->cd(2); auto hspc = (TH2F*) hscc->DrawClone("SURF1 POL");
2260 hspc->SetTitle("Polar coordinates");
2261 c4->cd(3); auto hssc = (TH2F*) hscc->DrawClone("SURF1 SPH");
2262 hssc->SetTitle("Spherical coordinates");
2263 c4->cd(4); auto hsprpc = (TH2F*) hscc->DrawClone("SURF1 PSR");
2264 hsprpc->SetTitle("PseudoRapidity/Phi coordinates");
2265}
2266End_Macro
2267
2268
2269\anchor HP20
2270### Base line for bar-charts and lego plots
2271
2272
2273By default the base line used to draw the boxes for bar-charts and lego plots is
2274the histogram minimum. It is possible to force this base line to be 0, using MIN0 draw
2275option or with the command:
2276
2277 gStyle->SetHistMinimumZero();
2278
2279Begin_Macro(source)
2280{
2281 auto c5 = new TCanvas("c5","c5",700,400);
2282 c5->Divide(2,1);
2283 auto hz1 = new TH1F("hz1","Bar-chart drawn from 0",20,-3,3);
2284 auto hz2 = new TH2F("hz2","Lego plot drawn from 0",20,-3,3,20,-3,3);
2285 Int_t i;
2286 double x,y;
2287 hz1->SetFillColor(kBlue);
2288 hz2->SetFillColor(kBlue);
2289 for (i=0;i<10000;i++) {
2290 x = gRandom->Gaus(0,1);
2291 y = gRandom->Gaus(0,1);
2292 if (x>0) {
2293 hz1->Fill(x,1);
2294 hz2->Fill(x,y,1);
2295 } else {
2296 hz1->Fill(x,-1);
2297 hz2->Fill(x,y,-2);
2298 }
2299 }
2300 c5->cd(1); hz1->Draw("bar2 min0");
2301 c5->cd(2); hz2->Draw("lego1 min0");
2302}
2303End_Macro
2304
2305This option also works for horizontal plots. The example given in the section
2306["The bar chart option"](\ref HP100) appears as follow:
2307
2308Begin_Macro(source)
2309{
2310 int i;
2311 const Int_t nx = 8;
2312 string os_X[nx] = {"8","32","128","512","2048","8192","32768","131072"};
2313 float d_35_0[nx] = {0.75, -3.30, -0.92, 0.10, 0.08, -1.69, -1.29, -2.37};
2314 float d_35_1[nx] = {1.01, -3.02, -0.65, 0.37, 0.34, -1.42, -1.02, -2.10};
2315
2316 auto cbh = new TCanvas("cbh","cbh",400,600);
2317 cbh->SetGrid();
2318
2319 auto h1bh = new TH1F("h1bh","Option HBAR centered on 0",nx,0,nx);
2320 h1bh->SetFillColor(4);
2321 h1bh->SetBarWidth(0.4);
2322 h1bh->SetBarOffset(0.1);
2323 h1bh->SetStats(0);
2324 h1bh->SetMinimum(-5);
2325 h1bh->SetMaximum(5);
2326
2327 for (i=1; i<=nx; i++) {
2328 h1bh->Fill(os_X[i-1].c_str(), d_35_0[i-1]);
2329 h1bh->GetXaxis()->SetBinLabel(i,os_X[i-1].c_str());
2330 }
2331
2332 h1bh->Draw("hbar min0");
2333
2334 auto h2bh = new TH1F("h2bh","h2bh",nx,0,nx);
2335 h2bh->SetFillColor(38);
2336 h2bh->SetBarWidth(0.4);
2337 h2bh->SetBarOffset(0.5);
2338 h2bh->SetStats(0);
2339 for (i=1;i<=nx;i++) h2bh->Fill(os_X[i-1].c_str(), d_35_1[i-1]);
2340
2341 h2bh->Draw("hbar min0 same");
2342}
2343End_Macro
2344
2345
2346\anchor HP20a
2347### TH2Poly Drawing
2348
2349
2350The following options are supported:
2351
2352| Option | Description |
2353|----------|-------------------------------------------------------------------|
2354| "SCAT" | Draw a scatter plot (legacy draw option).|
2355| "COL" | Draw a color plot. All the bins are painted even the empty bins (default).|
2356| "COLZ" | Same as "COL". In addition the color palette is also drawn.|
2357| "0" | When used with any COL options, the empty bins are not drawn.|
2358| "TEXT" | Draw bin contents as text (format set via `gStyle->SetPaintTextFormat`).|
2359| "TEXTN" | Draw bin names as text.|
2360| "TEXTnn" | Draw bin contents as text at angle nn (0 < nn <= 90).|
2361| "L" | Draw the bins boundaries as lines. The lines attributes are the TGraphs ones.|
2362| "P" | Draw the bins boundaries as markers. The markers attributes are the TGraphs ones.|
2363| "F" | Draw the bins boundaries as filled polygons. The filled polygons attributes are the TGraphs ones.|
2364
2365
2366
2367`TH2Poly` can be drawn as a color plot (option COL). `TH2Poly` bins can have any
2368shapes. The bins are defined as graphs. The following macro is a very simple
2369example showing how to book a TH2Poly and draw it.
2370
2371Begin_Macro(source)
2372{
2373 auto ch2p1 = new TCanvas("ch2p1","ch2p1",600,400);
2374 auto h2p = new TH2Poly();
2375 h2p->SetName("h2poly_name");
2376 h2p->SetTitle("h2poly_title");
2377 double px1[] = {0, 5, 6};
2378 double py1[] = {0, 0, 5};
2379 double px2[] = {0, -1, -1, 0};
2380 double py2[] = {0, 0, -1, 3};
2381 double px3[] = {4, 3, 0, 1, 2.4};
2382 double py3[] = {4, 3.7, 1, 3.7, 2.5};
2383 h2p->AddBin(3, px1, py1);
2384 h2p->AddBin(4, px2, py2);
2385 h2p->AddBin(5, px3, py3);
2386 h2p->Fill(0.1, 0.01, 3);
2387 h2p->Fill(-0.5, -0.5, 7);
2388 h2p->Fill(-0.7, -0.5, 1);
2389 h2p->Fill(1, 3, 1.5);
2390 double fx[] = {0.1, -0.5, -0.7, 1};
2391 double fy[] = {0.01, -0.5, -0.5, 3};
2392 double fw[] = {3, 1, 1, 1.5};
2393 h2p->FillN(4, fx, fy, fw);
2394 h2p->Draw("col");
2395}
2396End_Macro
2397
2398Rectangular bins are a frequent case. The special version of
2399the `AddBin` method allows to define them more easily like
2400shown in the following example (hist037_TH2Poly_boxes.C).
2401
2402Begin_Macro(source)
2403../../../tutorials/hist/hist037_TH2Poly_boxes.C
2404End_Macro
2405
2406One `TH2Poly` bin can be a list of polygons. Such bins are defined
2407by calling `AddBin` with a `TMultiGraph`. The following example
2408shows a such case:
2409
2410Begin_Macro(source)
2411{
2412 auto ch2p2 = new TCanvas("ch2p2","ch2p2",600,400);
2413
2414 Int_t i, bin;
2415 const Int_t nx = 48;
2416 const char *states [nx] = {
2417 "alabama", "arizona", "arkansas", "california",
2418 "colorado", "connecticut", "delaware", "florida",
2419 "georgia", "idaho", "illinois", "indiana",
2420 "iowa", "kansas", "kentucky", "louisiana",
2421 "maine", "maryland", "massachusetts", "michigan",
2422 "minnesota", "mississippi", "missouri", "montana",
2423 "nebraska", "nevada", "new_hampshire", "new_jersey",
2424 "new_mexico", "new_york", "north_carolina", "north_dakota",
2425 "ohio", "oklahoma", "oregon", "pennsylvania",
2426 "rhode_island", "south_carolina", "south_dakota", "tennessee",
2427 "texas", "utah", "vermont", "virginia",
2428 "washington", "west_virginia", "wisconsin", "wyoming"
2429 };
2430 Double_t pop[nx] = {
2431 4708708, 6595778, 2889450, 36961664, 5024748, 3518288, 885122, 18537969,
2432 9829211, 1545801, 12910409, 6423113, 3007856, 2818747, 4314113, 4492076,
2433 1318301, 5699478, 6593587, 9969727, 5266214, 2951996, 5987580, 974989,
2434 1796619, 2643085, 1324575, 8707739, 2009671, 19541453, 9380884, 646844,
2435 11542645, 3687050, 3825657, 12604767, 1053209, 4561242, 812383, 6296254,
2436 24782302, 2784572, 621760, 7882590, 6664195, 1819777, 5654774, 544270
2437 };
2438
2439 Double_t lon1 = -130;
2440 Double_t lon2 = -65;
2441 Double_t lat1 = 24;
2442 Double_t lat2 = 50;
2443 auto p = new TH2Poly("USA","USA Population",lon1,lon2,lat1,lat2);
2444
2445 TFile::SetCacheFileDir(".");
2446 auto f = TFile::Open("http://root.cern/files/usa.root", "CACHEREAD");
2447
2448 TMultiGraph *mg;
2449 TKey *key;
2450 TIter nextkey(gDirectory->GetListOfKeys());
2451 while ((key = (TKey*)nextkey())) {
2452 TObject *obj = key->ReadObj();
2453 if (obj->InheritsFrom("TMultiGraph")) {
2454 mg = (TMultiGraph*)obj;
2455 bin = p->AddBin(mg);
2456 }
2457 }
2458
2459 for (i=0; i<nx; i++) p->Fill(states[i], pop[i]);
2460
2461 gStyle->SetOptStat(11);
2462 p->Draw("COLZ L");
2463}
2464End_Macro
2465
2466`TH2Poly` histograms can also be plotted using the GL interface using
2467the option "GLLEGO".
2468
2469\since **ROOT version 6.09/01**
2470
2471In some cases it can be useful to not draw the empty bins. the option "0"
2472combined with the option "COL" and "COLZ" allows to do that.
2473
2474Begin_Macro(source)
2475{
2476 auto chc = new TCanvas("chc","chc",600,400);
2477
2478 auto hc = new TH2Poly();
2479 hc->Honeycomb(0,0,.1,25,25);
2480 hc->SetName("hc");
2481 hc->SetTitle("Option COLZ 0");
2482 TRandom ran;
2483 for (int i = 0; i<300; i++) hc->Fill(ran.Gaus(2.,1), ran.Gaus(2.,1));
2484 hc->Draw("colz 0");
2485}
2486End_Macro
2487
2488\anchor HP21
2489### The SPEC option
2490
2491
2492This option allows to use the `TSpectrum2Painter` tools. See the full
2493documentation in `TSpectrum2Painter::PaintSpectrum`.
2494
2495
2496\anchor HP22
2497### Option "Z" : Adding the color palette on the right side of the pad
2498
2499
2500When this option is specified, a color palette with an axis indicating the value
2501of the corresponding color is drawn on the right side of the picture. In case,
2502not enough space is left, one can increase the size of the right margin by
2503calling `TPad::SetRightMargin()`. The attributes used to display the
2504palette axis values are taken from the Z axis of the object. For example, to
2505set the labels size on the palette axis do:
2506
2507 hist->GetZaxis()->SetLabelSize().
2508
2509<b>WARNING:</b> The palette axis is always drawn vertically.
2510
2511
2512\anchor HP23
2513### Setting the color palette
2514
2515
2516To change the color palette `TStyle::SetPalette` should be used, eg:
2517
2518 gStyle->SetPalette(ncolors,colors);
2519
2520For example the option `COL` draws a 2D histogram with cells
2521represented by a box filled with a color index which is a function
2522of the cell content.
2523If the cell content is N, the color index used will be the color number
2524in `colors[N]`, etc. If the maximum cell content is greater than
2525`ncolors`, all cell contents are scaled to `ncolors`.
2526
2527If ` ncolors <= 0`, a default palette (see below) of 50 colors is
2528defined. This palette is recommended for pads, labels ...
2529
2530`if ncolors == 1 && colors == 0`, then a Pretty Palette with a
2531Spectrum Violet->Red is created with 50 colors. That's the default rain bow
2532palette.
2533
2534Other pre-defined palettes with 255 colors are available when `colors == 0`.
2535The following value of `ncolors` give access to:
2536
2537
2538 if ncolors = 51 and colors=0, a Deep Sea palette is used.
2539 if ncolors = 52 and colors=0, a Grey Scale palette is used.
2540 if ncolors = 53 and colors=0, a Dark Body Radiator palette is used.
2541 if ncolors = 54 and colors=0, a two-color hue palette palette is used.(dark blue through neutral gray to bright
2542yellow) if ncolors = 55 and colors=0, a Rain Bow palette is used. if ncolors = 56 and colors=0, an inverted Dark Body
2543Radiator palette is used.
2544
2545
2546If `ncolors > 0 && colors == 0`, the default palette is used with a maximum of ncolors.
2547
2548The default palette defines:
2549
2550- index 0 to 9 : shades of grey
2551- index 10 to 19 : shades of brown
2552- index 20 to 29 : shades of blue
2553- index 30 to 39 : shades of red
2554- index 40 to 49 : basic colors
2555
2556The color numbers specified in the palette can be viewed by selecting
2557the item `colors` in the `VIEW` menu of the canvas tool bar.
2558The red, green, and blue components of a color can be changed thanks to
2559`TColor::SetRGB()`.
2560
2561\since **ROOT version 6.19/01**
2562
2563As default labels and ticks are drawn by `TGAxis` at equidistant (lin or log)
2564points as controlled by SetNdivisions.
2565If option "CJUST" is given labels and ticks are justified at the
2566color boundaries defined by the contour levels.
2567For more details see `TPaletteAxis`
2568
2569\anchor HP24
2570### Drawing a sub-range of a 2D histogram; the [cutg] option
2571
2572
2573Using a `TCutG` object, it is possible to draw a sub-range of a 2D
2574histogram. One must create a graphical cut (mouse or C++) and specify the name
2575of the cut between `[]` in the `Draw()` option.
2576For example (fit2a.C), with a `TCutG` named `cutg`, one can call:
2577
2578 myhist->Draw("surf1 [cutg]");
2579
2580To invert the cut, it is enough to put a `-` in front of its name:
2581
2582 myhist->Draw("surf1 [-cutg]");
2583
2584It is possible to apply several cuts (`,` means logical AND):
2585
2586 myhist->Draw("surf1 [cutg1,cutg2]");
2587
2588Begin_Macro(source)
2589../../../tutorials/fit/fit2a.C
2590End_Macro
2591
2592\anchor HP25
2593### Drawing options for 3D histograms
2594
2595
2596| Option | Description |
2597|----------|-------------------------------------------------------------------|
2598| "SCAT" | Draw a scatter plot (legacy draw option).|
2599| "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)`|
2600| "BOX" | Draw a for each cell with volume proportional to the content's absolute value. An hidden line removal algorithm is used|
2601| "BOX1" | Same as BOX but an hidden surface removal algorithm is used|
2602| "BOX2" | Same as "COL". The boxes' colors are picked in the current palette according to the bins' contents (default)|
2603| "BOX2Z" | Same as "BOX2". In addition the color palette is also drawn.|
2604| "BOX3" | Same as BOX1, but the border lines of each lego-bar are not drawn.|
2605
2606Note that instead of `BOX` one can also use `LEGO`.
2607
2608By default, 3D histograms are drawn as a colored box plots.
2609
2610The following example shows a 3D histogram plotted as a scatter plot.
2611
2612Begin_Macro(source)
2613{
2614 auto c06 = new TCanvas("c06","c06",600,400);
2615 gStyle->SetOptStat(kFALSE);
2616 auto h3scat = new TH3F("h3scat","Option SCAT",15,-2,2,15,-2,2,15,0,4);
2617 double x, y, z;
2618 for (Int_t i=0;i<10000;i++) {
2619 gRandom->Rannor(x, y);
2620 z = x*x + y*y;
2621 h3scat->Fill(x,y,z);
2622 }
2623 h3scat->Draw("SCAT"); // This a legacy draw option
2624}
2625End_Macro
2626
2627The following example shows a 3D histogram plotted with the option `BOX`.
2628
2629Begin_Macro(source)
2630{
2631 auto c16 = new TCanvas("c16","c16",600,400);
2632 gStyle->SetOptStat(kFALSE);
2633 auto h3box = new TH3F("h3box","Option BOX",15,-2,2,15,-2,2,15,0,4);
2634 double x, y, z;
2635 for (Int_t i=0;i<10000;i++) {
2636 gRandom->Rannor(x, y);
2637 z = x*x + y*y;
2638 h3box->Fill(x,y,z);
2639 }
2640 h3box->Draw("BOX");
2641}
2642End_Macro
2643
2644The following example shows a 3D histogram plotted with the option `BOX1`.
2645
2646Begin_Macro(source)
2647{
2648 auto c36 = new TCanvas("c36","c36",600,400);
2649 gStyle->SetOptStat(kFALSE);
2650 auto h3box = new TH3F("h3box","Option BOX1",10,-2.,2.,10,-2.,2.,10,-0.5,2.);
2651 double x, y, z;
2652 for (Int_t i=0;i<10000;i++) {
2653 gRandom->Rannor(x, y);
2654 z = abs(sin(x)/x + cos(y)*y);
2655 h3box->Fill(x,y,z);
2656 }
2657 h3box->SetFillColor(9);
2658 h3box->Draw("BOX1");
2659}
2660End_Macro
2661
2662The following example shows a 3D histogram plotted with the option `BOX2`.
2663
2664Begin_Macro(source)
2665{
2666 auto c56 = new TCanvas("c56","c56",600,400);
2667 gStyle->SetOptStat(kFALSE);
2668 auto h3box = new TH3F("h3box","Option BOX2 (default)",10,-2.,2.,10,-2.,2.,10,-0.5,2.);
2669 double x, y, z;
2670 for (Int_t i=0;i<10000;i++) {
2671 gRandom->Rannor(x, y);
2672 z = abs(sin(x)/x + cos(y)*y);
2673 h3box->Fill(x,y,z);
2674 }
2675 h3box->Draw("BOX2 Z");
2676}
2677End_Macro
2678
2679The following example shows a 3D histogram plotted with the option `BOX3`.
2680
2681Begin_Macro(source)
2682{
2683 auto c46 = new TCanvas("c46","c46",600,400);
2684 c46->SetFillColor(38);
2685 gStyle->SetOptStat(kFALSE);
2686 auto h3box = new TH3F("h3box","Option BOX3",15,-2,2,15,-2,2,15,0,4);
2687 double x, y, z;
2688 for (Int_t i=0;i<10000;i++) {
2689 gRandom->Rannor(x, y);
2690 z = x*x + y*y;
2691 h3box->Fill(x,y,z);
2692 }
2693 h3box->Draw("BOX3");
2694}
2695End_Macro
2696
2697For all the `BOX` options each bin is drawn as a 3D box with a volume proportional
2698to the absolute value of the bin content. The bins with a negative content are
2699drawn with a X on each face of the box as shown in the following example:
2700
2701Begin_Macro(source)
2702{
2703 auto c = new TCanvas("c","c",600,400);
2704 gStyle->SetOptStat(kFALSE);
2705 auto h3box = new TH3F("h3box","Option BOX1 with negative bins",3, 0., 4., 3, 0.,4., 3, 0., 4.);
2706 h3box->Fill(0., 2., 2., 10.);
2707 h3box->Fill(2., 2., 2., 5.);
2708 h3box->Fill(2., 2., .5, 2.);
2709 h3box->Fill(2., 2., 3., -1.);
2710 h3box->Fill(3., 2., 2., -10.);
2711 h3box->SetFillColor(8);
2712 h3box->Draw("box1");
2713}
2714End_Macro
2715
2716The following example shows a 3D histogram plotted with the option `ISO`.
2717
2718Begin_Macro(source)
2719{
2720 auto c26 = new TCanvas("c26","c26",600,400);
2721 gStyle->SetOptStat(kFALSE);
2722 auto h3iso = new TH3F("h3iso","Option ISO",15,-2,2,15,-2,2,15,0,4);
2723 double x, y, z;
2724 for (Int_t i=0;i<10000;i++) {
2725 gRandom->Rannor(x, y);
2726 z = x*x + y*y;
2727 h3iso->Fill(x,y,z);
2728 }
2729 h3iso->SetFillColor(kCyan);
2730 h3iso->Draw("ISO");
2731}
2732End_Macro
2733
2734
2735\anchor HP26
2736### Drawing option for histograms' stacks
2737
2738
2739Stacks of histograms are managed with the `THStack`. A `THStack`
2740is a collection of `TH1` (or derived) objects. For painting only the
2741`THStack` containing `TH1` only or
2742`THStack` containing `TH2` only will be considered.
2743
2744By default, histograms are shown stacked:
2745
27461. The first histogram is paint.
27472. The sum of the first and second, etc...
2748
2749If the option `NOSTACK` is specified, the histograms are all paint in
2750the same pad as if the option `SAME` had been specified. This allows to
2751compute X and Y scales common to all the histograms, like
2752`TMultiGraph` does for graphs.
2753
2754If the option `PADS` is specified, the current pad/canvas is
2755subdivided into a number of pads equal to the number of histograms and each
2756histogram is paint into a separate pad.
2757
2758The following example shows various types of stacks (hist023_THStack_simple.C).
2759
2760Begin_Macro(source)
2761../../../tutorials/hist/hist023_THStack_simple.C
2762End_Macro
2763
2764The option `nostackb` allows to draw the histograms next to each
2765other as bar charts:
2766
2767Begin_Macro(source)
2768{
2769 auto cst0 = new TCanvas("cst0","cst0",600,400);
2770 auto hs = new THStack("hs","Stacked 1D histograms: option #font[82]{\"nostackb\"}");
2771
2772 auto h1 = new TH1F("h1","h1",10,-4,4);
2773 h1->FillRandom("gaus",20000);
2774 h1->SetFillColor(kRed);
2775 hs->Add(h1);
2776
2777 auto h2 = new TH1F("h2","h2",10,-4,4);
2778 h2->FillRandom("gaus",15000);
2779 h2->SetFillColor(kBlue);
2780 hs->Add(h2);
2781
2782 auto h3 = new TH1F("h3","h3",10,-4,4);
2783 h3->FillRandom("gaus",10000);
2784 h3->SetFillColor(kGreen);
2785 hs->Add(h3);
2786
2787 hs->Draw("nostackb");
2788 hs->GetXaxis()->SetNdivisions(-10);
2789 cst0->SetGridx();
2790}
2791End_Macro
2792
2793If at least one of the histograms in the stack has errors, the whole stack is
2794visualized by default with error bars. To visualize it without errors the
2795option `HIST` should be used.
2796
2797Begin_Macro(source)
2798{
2799 auto cst1 = new TCanvas("cst1","cst1",700,400);
2800 cst1->Divide(2,1);
2801
2802 auto hst11 = new TH1F("hst11", "", 20, -10, 10);
2803 hst11->Sumw2();
2804 hst11->FillRandom("gaus", 1000);
2805 hst11->SetFillColor(kViolet);
2806 hst11->SetLineColor(kViolet);
2807
2808 auto hst12 = new TH1F("hst12", "", 20, -10, 10);
2809 hst12->FillRandom("gaus", 500);
2810 hst12->SetFillColor(kBlue);
2811 hst12->SetLineColor(kBlue);
2812
2813 THStack st1("st1", "st1");
2814 st1.Add(hst11);
2815 st1.Add(hst12);
2816
2817 cst1->cd(1); st1.Draw();
2818 cst1->cd(2); st1.Draw("hist");
2819}
2820End_Macro
2821
2822\anchor HP27
2823### Drawing of 3D implicit functions
2824
2825
28263D implicit functions (`TF3`) can be drawn as iso-surfaces.
2827The implicit function f(x,y,z) = 0 is drawn in cartesian coordinates.
2828In the following example the options "FB" and "BB" suppress the
2829"Front Box" and "Back Box" around the plot.
2830
2831Begin_Macro(source)
2832{
2833 auto c2 = new TCanvas("c2","c2",600,400);
2834 auto f3 = new TF3("f3","sin(x*x+y*y+z*z-36)",-2,2,-2,2,-2,2);
2835 f3->SetClippingBoxOn(0,0,0);
2836 f3->SetFillColor(30);
2837 f3->SetLineColor(15);
2838 f3->Draw("FBBB");
2839}
2840End_Macro
2841
2842
2843\anchor HP28
2844### Associated functions drawing
2845
2846
2847An associated function is created by `TH1::Fit`. More than on fitted
2848function can be associated with one histogram (see `TH1::Fit`).
2849
2850A `TF1` object `f1` can be added to the list of associated
2851functions of an histogram `h` without calling `TH1::Fit`
2852simply doing:
2853
2854 h->GetListOfFunctions()->Add(f1);
2855
2856or
2857
2858 h->GetListOfFunctions()->Add(f1,someoption);
2859
2860To retrieve a function by name from this list, do:
2861
2862 TF1 *f1 = (TF1*)h->GetListOfFunctions()->FindObject(name);
2863
2864or
2865
2866 TF1 *f1 = h->GetFunction(name);
2867
2868Associated functions are automatically painted when an histogram is drawn.
2869To avoid the painting of the associated functions the option `HIST`
2870should be added to the list of the options used to paint the histogram.
2871
2872
2873\anchor HP29
2874### Drawing using OpenGL
2875
2876
2877The class `TGLHistPainter` allows to paint data set using the OpenGL 3D
2878graphics library. The plotting options start with `GL` keyword.
2879In addition, in order to inform canvases that OpenGL should be used to render
28803D representations, the following option should be set:
2881
2882 gStyle->SetCanvasPreferGL(true);
2883
2884
2885\anchor HP29a
2886#### General information: plot types and supported options
2887
2888The following types of plots are provided:
2889
2890For lego plots the supported options are:
2891
2892| Option | Description |
2893|----------|-------------------------------------------------------------------|
2894| "GLLEGO" | Draw a lego plot. It works also for `TH2Poly`.|
2895| "GLLEGO2"| Bins with color levels.|
2896| "GLLEGO3"| Cylindrical bars.|
2897
2898
2899
2900Lego painter in cartesian supports logarithmic scales for X, Y, Z.
2901In polar only Z axis can be logarithmic, in cylindrical only Y.
2902
2903For surface plots (`TF2` and `TH2`) the supported options are:
2904
2905| Option | Description |
2906|-----------|------------------------------------------------------------------|
2907| "GLSURF" | Draw a surface.|
2908| "GLSURF1" | Surface with color levels|
2909| "GLSURF2" | The same as "GLSURF1" but without polygon outlines.|
2910| "GLSURF3" | Color level projection on top of plot (works only in cartesian coordinate system).|
2911| "GLSURF4" | Same as "GLSURF" but without polygon outlines.|
2912
2913
2914
2915The surface painting in cartesian coordinates supports logarithmic scales along
2916X, Y, Z axis. In polar coordinates only the Z axis can be logarithmic,
2917in cylindrical coordinates only the Y axis.
2918
2919Additional options to SURF and LEGO - Coordinate systems:
2920
2921| Option | Description |
2922|----------|-------------------------------------------------------------------|
2923| " " | Default, cartesian coordinates system.|
2924| "POL" | Polar coordinates system.|
2925| "CYL" | Cylindrical coordinates system.|
2926| "SPH" | Spherical coordinates system.|
2927
2928
2929
2930\anchor HP290
2931#### TH3 as color boxes
2932
2933The supported option is:
2934
2935| Option | Description |
2936|----------|-------------------------------------------------------------------|
2937| "GLCOL" | H3 is drawn using semi-transparent colored boxes. See glvox1.C .|
2938
2939
2940
2941\anchor HP29b
2942#### TH3 as boxes (spheres)
2943
2944The supported options are:
2945
2946| Option | Description |
2947|----------|-------------------------------------------------------------------|
2948| "GLBOX" | TH3 as a set of boxes, size of box is proportional to bin content.|
2949| "GLBOX1" | The same as "glbox", but spheres are drawn instead of boxes.|
2950
2951
2952
2953\anchor HP29c
2954#### TH3 as iso-surface(s)
2955
2956The supported option is:
2957
2958| Option | Description |
2959|----------|-------------------------------------------------------------------|
2960| "GLISO" | TH3 is drawn using iso-surfaces.|
2961
2962
2963
2964\anchor HP29d
2965#### TF3 (implicit function)
2966
2967The supported option is:
2968
2969| Option | Description |
2970|----------|-------------------------------------------------------------------|
2971| "GL" | Draw a TF3.|
2972
2973
2974
2975\anchor HP29e
2976#### Parametric surfaces
2977
2978glparametric.C shows how to create parametric equations and visualize the surface.
2979
2980\anchor HP29f
2981#### Interaction with the plots
2982
2983All the interactions are implemented via standard methods
2984`DistancetoPrimitive()` and `ExecuteEvent()`. That's why all the
2985interactions with the OpenGL plots are possible only when the mouse cursor is
2986in the plot's area (the plot's area is the part of a the pad occupied by
2987gl-produced picture). If the mouse cursor is not above gl-picture, the standard
2988pad interaction is performed.
2989
2990\anchor HP29g
2991#### Selectable parts
2992
2993Different parts of the plot can be selected:
2994
2995- xoz, yoz, xoy back planes: When such a plane selected, it's highlighted in green
2996 if the dynamic slicing by this plane is supported, and it's highlighted in red,
2997 if the dynamic slicing is not supported.
2998- The plot itself:
2999 On surfaces, the selected surface is outlined in red. (TF3 and
3000 ISO are not outlined). On lego plots, the selected bin is
3001 highlighted. The bin number and content are displayed in pad's
3002 status bar. In box plots, the box or sphere is highlighted and
3003 the bin info is displayed in pad's status bar.
3004
3005
3006\anchor HP29h
3007#### Rotation and zooming
3008
3009
3010- Rotation:
3011 When the plot is selected, it can be rotated by pressing and
3012 holding the left mouse button and move the cursor.
3013- Zoom/Unzoom:
3014 Mouse wheel or 'j', 'J', 'k', 'K' keys.
3015
3016
3017\anchor HP29i
3018#### Panning
3019
3020The selected plot can be moved in a pad's area by pressing and
3021holding the left mouse button and the shift key.
3022
3023\anchor HP29j
3024#### Box cut
3025
3026Surface, iso, box, TF3 and parametric painters support box cut by
3027pressing the 'c' or 'C' key when the mouse cursor is in a plot's
3028area. That will display a transparent box, cutting away part of the
3029surface (or boxes) in order to show internal part of plot. This box
3030can be moved inside the plot's area (the full size of the box is
3031equal to the plot's surrounding box) by selecting one of the box
3032cut axes and pressing the left mouse button to move it.
3033
3034\anchor HP29k
3035#### Plot specific interactions (dynamic slicing etc.)
3036
3037Currently, all gl-plots support some form of slicing. When back plane
3038is selected (and if it's highlighted in green) you can press and hold
3039left mouse button and shift key and move this back plane inside
3040plot's area, creating the slice. During this "slicing" plot becomes
3041semi-transparent. To remove all slices (and projected curves for
3042surfaces) double click with left mouse button in a plot's area.
3043
3044\anchor HP29l
3045#### Surface with option "GLSURF"
3046
3047The surface profile is displayed on the slicing plane.
3048The profile projection is drawn on the back plane
3049by pressing `'p'` or `'P'` key.
3050
3051\anchor HP29m
3052#### TF3
3053
3054The contour plot is drawn on the slicing plane. For TF3 the color
3055scheme can be changed by pressing 's' or 'S'.
3056
3057\anchor HP29n
3058#### Box
3059
3060The contour plot corresponding to slice plane position is drawn in real time.
3061
3062\anchor HP29o
3063#### Iso
3064
3065Slicing is similar to "GLBOX" option.
3066
3067\anchor HP29p
3068#### Parametric plot
3069
3070No slicing. Additional keys: 's' or 'S' to change color scheme -
3071about 20 color schemes supported ('s' for "scheme"); 'l' or 'L' to
3072increase number of polygons ('l' for "level" of details), 'w' or 'W'
3073to show outlines ('w' for "wireframe").
3074
3075\anchor HP30
3076#### Highlight mode for histogram
3077
3078\since **ROOT version 6.15/01**
3079
3080\image html hlHisto3_top.gif "Highlight mode"
3081
3082Highlight mode is implemented for `TH1` (and for `TGraph`) class. When
3083highlight mode is on, mouse movement over the bin will be represented
3084graphically. Bin will be highlighted as "bin box" (presented by box
3085object). Moreover, any highlight (change of bin) emits signal
3086`TCanvas::Highlighted()` which allows the user to react and call their own
3087function. For a better understanding see also the tutorial `hist043` to `hist046`
3088located in `$ROOTSYS/tutorials/hist/`.
3089
3090Highlight mode is switched on/off by `TH1::SetHighlight()` function
3091or interactively from `TH1` context menu. `TH1::IsHighlight()` to verify
3092whether the highlight mode enabled or disabled, default it is disabled.
3093
3094~~~ {.cpp}
3095 root [0] .x $ROOTSYS/tutorials/hsimple.C
3096 root [1] hpx->SetHighlight(kTRUE) // or interactively from TH1 context menu
3097 root [2] hpx->IsHighlight()
3098 (bool) true
3099~~~
3100
3101\image html hlsimple_nofun.gif "Highlight mode for histogram"
3102
3103\anchor HP30a
3104#### Highlight mode and user function
3105
3106The user can use (connect) `TCanvas::Highlighted()` signal, which is always
3107emitted if there is a highlight bin and call user function via signal
3108and slot communication mechanism. `TCanvas::Highlighted()` is similar
3109`TCanvas::Picked()`
3110
3111- when selected object (histogram as a whole) is different from previous
3112then emit `Picked()` signal
3113- when selected (highlighted) bin from histogram is different from previous
3114then emit `Highlighted()` signal
3115
3116Any user function (or functions) has to be defined
3117`UserFunction(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)`.
3118In example (see below) has name `PrintInfo()`. All parameters of user
3119function are taken from
3120
3121 void TCanvas::Highlighted(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)
3122
3123- `pad` is pointer to pad with highlighted histogram
3124- `obj` is pointer to highlighted histogram
3125- `x` is highlighted x bin for 1D histogram
3126- `y` is highlighted y bin for 2D histogram (for 1D histogram not in use)
3127
3128Example how to create a connection from any `TCanvas` object to a user
3129`UserFunction()` slot (see also `TQObject::Connect()` for additional info)
3130
3131 TQObject::Connect("TCanvas", "Highlighted(TVirtualPad*,TObject*,Int_t,Int_t)",
3132 0, 0, "UserFunction(TVirtualPad*,TObject*,Int_t,Int_t)");
3133
3134or use non-static "simplified" function
3135`TCanvas::HighlightConnect(const char *slot)`
3136
3137 c1->HighlightConnect("UserFunction(TVirtualPad*,TObject*,Int_t,Int_t)");
3138
3139NOTE the signal and slot string must have a form
3140"(TVirtualPad*,TObject*,Int_t,Int_t)"
3141
3142 root [0] .x $ROOTSYS/tutorials/hsimple.C
3143 root [1] hpx->SetHighlight(kTRUE)
3144 root [2] .x hlprint.C
3145
3146file `hlprint.C`
3147~~~ {.cpp}
3148void PrintInfo(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)
3149{
3150 auto h = (TH1F *)obj;
3151 if (!h->IsHighlight()) // after highlight disabled
3152 h->SetTitle("highlight disable");
3153 else
3154 h->SetTitle(TString::Format("bin[%03d] (%5.2f) content %g", x,
3155 h->GetBinCenter(x), h->GetBinContent(x)));
3156 pad->Update();
3157}
3158
3159void hlprint()
3160{
3161 if (!gPad) return;
3162 gPad->GetCanvas()->HighlightConnect("PrintInfo(TVirtualPad*,TObject*,Int_t,Int_t)");
3163}
3164~~~
3165
3166\image html hlsimple.gif "Highlight mode and simple user function"
3167
3168For more complex demo please see for example tree200_temperature.C file.
3169
3170*/
3171
3173
3176
3177const Int_t kNMAX = 2000;
3178
3179const Int_t kMAXCONTOUR = 104;
3181
3182static std::unique_ptr<TBox> gXHighlightBox, gYHighlightBox; // highlight X and Y box
3183
3205
3206
3207////////////////////////////////////////////////////////////////////////////////
3208/// Default constructor.
3209
3211{
3212 fH = nullptr;
3213 fXaxis = nullptr;
3214 fYaxis = nullptr;
3215 fZaxis = nullptr;
3216 fFunctions = nullptr;
3217 fNcuts = 0;
3218 fStack = nullptr;
3219 fShowProjection = 0;
3220 fShowProjection2 = 0;
3221 fShowOption = "";
3222 for (int i=0; i<kMaxCuts; i++) {
3223 fCuts[i] = nullptr;
3224 fCutsOpt[i] = 0;
3225 }
3226 fXHighlightBin = -1;
3227 fYHighlightBin = -1;
3228 fCurrentF3 = nullptr;
3229
3230 gStringEntries = gEnv->GetValue("Hist.Stats.Entries", "Entries");
3231 gStringMean = gEnv->GetValue("Hist.Stats.Mean", "Mean");
3232 gStringMeanX = gEnv->GetValue("Hist.Stats.MeanX", "Mean x");
3233 gStringMeanY = gEnv->GetValue("Hist.Stats.MeanY", "Mean y");
3234 gStringMeanZ = gEnv->GetValue("Hist.Stats.MeanZ", "Mean z");
3235 gStringStdDev = gEnv->GetValue("Hist.Stats.StdDev", "Std Dev");
3236 gStringStdDevX = gEnv->GetValue("Hist.Stats.StdDevX", "Std Dev x");
3237 gStringStdDevY = gEnv->GetValue("Hist.Stats.StdDevY", "Std Dev y");
3238 gStringStdDevZ = gEnv->GetValue("Hist.Stats.StdDevZ", "Std Dev z");
3239 gStringUnderflow = gEnv->GetValue("Hist.Stats.Underflow", "Underflow");
3240 gStringOverflow = gEnv->GetValue("Hist.Stats.Overflow", "Overflow");
3241 gStringIntegral = gEnv->GetValue("Hist.Stats.Integral", "Integral");
3242 gStringIntegralBinWidth = gEnv->GetValue("Hist.Stats.IntegralBinWidth", "Integral(w)");
3243 gStringSkewness = gEnv->GetValue("Hist.Stats.Skewness", "Skewness");
3244 gStringSkewnessX = gEnv->GetValue("Hist.Stats.SkewnessX", "Skewness x");
3245 gStringSkewnessY = gEnv->GetValue("Hist.Stats.SkewnessY", "Skewness y");
3246 gStringSkewnessZ = gEnv->GetValue("Hist.Stats.SkewnessZ", "Skewness z");
3247 gStringKurtosis = gEnv->GetValue("Hist.Stats.Kurtosis", "Kurtosis");
3248 gStringKurtosisX = gEnv->GetValue("Hist.Stats.KurtosisX", "Kurtosis x");
3249 gStringKurtosisY = gEnv->GetValue("Hist.Stats.KurtosisY", "Kurtosis y");
3250 gStringKurtosisZ = gEnv->GetValue("Hist.Stats.KurtosisZ", "Kurtosis z");
3251}
3252
3253////////////////////////////////////////////////////////////////////////////////
3254/// destructor.
3255
3259
3260////////////////////////////////////////////////////////////////////////////////
3261/// Compute the distance from the point px,py to a line.
3262///
3263/// Compute the closest distance of approach from point px,py to elements of
3264/// an histogram. The distance is computed in pixels units.
3265///
3266/// Algorithm: Currently, this simple model computes the distance from the mouse
3267/// to the histogram contour only.
3268
3270{
3271
3272 Double_t defaultLabelSize = 0.04; // See TAttAxis.h for source of this value
3273
3274 const Int_t big = 9999;
3275 const Int_t kMaxDiff = 7;
3276
3277 if (fPie)
3278 return fPie->DistancetoPrimitive(px, py);
3279
3280 Double_t x = gPad->AbsPixeltoX(px);
3281 Double_t x1 = gPad->AbsPixeltoX(px+1);
3282
3283 Int_t puxmin = gPad->XtoAbsPixel(gPad->GetUxmin());
3284 Int_t puymin = gPad->YtoAbsPixel(gPad->GetUymin());
3285 Int_t puxmax = gPad->XtoAbsPixel(gPad->GetUxmax());
3286 Int_t puymax = gPad->YtoAbsPixel(gPad->GetUymax());
3287 Int_t curdist = big;
3289 Bool_t dsame;
3290 TObject *PadPointer = gPad->GetPadPointer();
3291 if (!PadPointer) return 0;
3292 TString doption = PadPointer->GetDrawOption();
3293 Double_t factor = 1;
3294 if (fH->GetNormFactor() != 0) {
3295 factor = fH->GetNormFactor()/fH->GetSumOfWeights();
3296 }
3297 // return if point is not in the histogram area
3298
3299 // If a 3D view exists, check distance to axis
3300 TView *view = gPad->GetView();
3301 Int_t d1,d2,d3;
3302 if (view && Hoption.Contour != 14) {
3303 Double_t ratio;
3304 d3 = view->GetDistancetoAxis(3, px, py, ratio);
3305 if (d3 <= kMaxDiff) {gPad->SetSelected(fZaxis); return 0;}
3306 d1 = view->GetDistancetoAxis(1, px, py, ratio);
3307 if (d1 <= kMaxDiff) {gPad->SetSelected(fXaxis); return 0;}
3308 d2 = view->GetDistancetoAxis(2, px, py, ratio);
3309 if (d2 <= kMaxDiff) {gPad->SetSelected(fYaxis); return 0;}
3310 if ( px > puxmin && px < puxmax && py > puymax && py < puymin) curdist = 1;
3311 goto FUNCTIONS;
3312 }
3313 // check if point is close to an axis
3314 doption.ToLower();
3315 dsame = kFALSE;
3316 if (doption.Contains("same")) dsame = kTRUE;
3317
3319 if (doption.Contains("y+")) {
3321 if (px <= xyaxis+dyaxis && px >= xyaxis && py >puymax && py < puymin) {
3322 if (!dsame) {
3323 if (gPad->IsVertical()) gPad->SetSelected(fYaxis);
3324 else gPad->SetSelected(fXaxis);
3325 return 0;
3326 }
3327 }
3328 } else {
3330 if (px >= xyaxis-dyaxis && px <= xyaxis && py >puymax && py < puymin) {
3331 if (!dsame) {
3332 if (gPad->IsVertical()) gPad->SetSelected(fYaxis);
3333 else gPad->SetSelected(fXaxis);
3334 return 0;
3335 }
3336 }
3337 }
3338
3340 if (doption.Contains("x+")) {
3342 if (py >= yxaxis-dxaxis && py <= yxaxis && px <puxmax && px > puxmin) {
3343 if (!dsame) {
3344 if (gPad->IsVertical()) gPad->SetSelected(fXaxis);
3345 else gPad->SetSelected(fYaxis);
3346 return 0;
3347 }
3348 }
3349 } else {
3351 if (yxaxis < puymin) yxaxis = puymin;
3353 if (!dsame) {
3354 if (gPad->IsVertical()) gPad->SetSelected(fXaxis);
3355 else gPad->SetSelected(fYaxis);
3356 return 0;
3357 }
3358 }
3359 }
3360
3361 if (fH->IsHighlight()) { // only if highlight is enable
3362 if ((px > puxmin) && (py < puymin) && (px < puxmax) && (py > puymax))
3363 HighlightBin(px, py);
3364 }
3365
3366 // if object is 2D or 3D return this object
3367 if (fH->GetDimension() == 2) {
3368 if (fH->InheritsFrom(TH2Poly::Class())) {
3369 TH2Poly *th2 = (TH2Poly*)fH;
3371 gPad->GetRangeAxis(xmin, ymin, xmax, ymax);
3372 Double_t pxu = gPad->AbsPixeltoX(px);
3373 Double_t pyu = gPad->AbsPixeltoY(py);
3374 if ((pxu>xmax) || (pxu < xmin) || (pyu>ymax) || (pyu < ymin)) {
3375 curdist = big;
3376 goto FUNCTIONS;
3377 } else {
3378 Int_t bin = th2->FindBin(pxu, pyu);
3379 if (bin>0) curdist = 1;
3380 else curdist = big;
3381 goto FUNCTIONS;
3382 }
3383 }
3384 Int_t delta2 = 5; //Give a margin of delta2 pixels to be in the 2-d area
3385 if ( px > puxmin + delta2
3386 && px < puxmax - delta2
3387 && py > puymax + delta2
3388 && py < puymin - delta2) {curdist =1; goto FUNCTIONS;}
3389 }
3390
3391 // point is inside histogram area. Find channel number
3392 if (gPad->IsVertical()) {
3393 Int_t bin = fXaxis->FindFixBin(gPad->PadtoX(x));
3394 Int_t binsup = fXaxis->FindFixBin(gPad->PadtoX(x1));
3395 Double_t binval = factor*fH->GetBinContent(bin);
3396 Int_t pybin = gPad->YtoAbsPixel(gPad->YtoPad(binval));
3397 if (binval == 0 && pybin < puymin) pybin = 10000;
3398 // special case if more than one bin for the pixel
3399 if (binsup-bin>1) {
3403 for (Int_t ibin=bin+1; ibin<binsup; ibin++) {
3407 }
3408 Int_t pybinmin = gPad->YtoAbsPixel(gPad->YtoPad(binvalmax));
3409 Int_t pybinmax = gPad->YtoAbsPixel(gPad->YtoPad(binvalmin));
3411 }
3412 if (bin != binsup) { // Mouse on bin border
3414 Int_t pybinsub = gPad->YtoAbsPixel(gPad->YtoPad(binsupval));
3415 if (py <= TMath::Max(pybinsub,pybin) && py >= TMath::Min(pybinsub,pybin) && pybin != 10000) return 0;
3416 }
3417 if (TMath::Abs(py - pybin) <= kMaxDiff) return TMath::Abs(py - pybin);
3418 } else {
3419 Double_t y = gPad->AbsPixeltoY(py);
3420 Double_t y1 = gPad->AbsPixeltoY(py+1);
3421 Int_t bin = fXaxis->FindFixBin(gPad->PadtoY(y));
3422 Int_t binsup = fXaxis->FindFixBin(gPad->PadtoY(y1));
3423 Double_t binval = factor*fH->GetBinContent(bin);
3424 Int_t pxbin = gPad->XtoAbsPixel(gPad->XtoPad(binval));
3425 if (binval == 0 && pxbin > puxmin) pxbin = 10000;
3426 // special case if more than one bin for the pixel
3427 if (binsup-bin>1) {
3431 for (Int_t ibin=bin+1; ibin<binsup; ibin++) {
3435 }
3436 Int_t pxbinmin = gPad->XtoAbsPixel(gPad->XtoPad(binvalmax));
3437 Int_t pxbinmax = gPad->XtoAbsPixel(gPad->XtoPad(binvalmin));
3439 }
3440 if (TMath::Abs(px - pxbin) <= kMaxDiff) return TMath::Abs(px - pxbin);
3441 }
3442 // Loop on the list of associated functions and user objects
3443FUNCTIONS:
3444 TObject *f;
3445 TIter next(fFunctions);
3446 while ((f = (TObject*) next())) {
3447 Int_t dist;
3448 if (f->InheritsFrom(TF1::Class())) dist = f->DistancetoPrimitive(-px,py);
3449 else dist = f->DistancetoPrimitive(px,py);
3450 if (dist < kMaxDiff) {gPad->SetSelected(f); return dist;}
3451 }
3452 return curdist;
3453}
3454
3455////////////////////////////////////////////////////////////////////////////////
3456/// Display a panel with all histogram drawing options.
3457
3459{
3460
3461 gCurrentHist = fH;
3462 if (!gPad) {
3463 Error("DrawPanel", "need to draw histogram first");
3464 return;
3465 }
3467 editor->Show();
3468 gROOT->ProcessLine(TString::Format("((TCanvas*)0x%zx)->Selected((TVirtualPad*)0x%zx,(TObject*)0x%zx,1)",
3469 (size_t)gPad->GetCanvas(), (size_t)gPad, (size_t)fH).Data());
3470}
3471
3472////////////////////////////////////////////////////////////////////////////////
3473/// Execute the actions corresponding to `event`.
3474///
3475/// This function is called when a histogram is clicked with the locator at
3476/// the pixel position px,py.
3477
3479{
3480
3481 if (!gPad) return;
3482
3483 static Int_t bin, px1, py1, px2, py2, pyold;
3484 static std::unique_ptr<TBox> zoombox;
3486
3487 Int_t bin1, bin2;
3488 Double_t xlow, xup, ylow, binval, x, baroffset, barwidth, binwidth;
3489 Bool_t opaque = gPad->OpaqueMoving();
3490
3491 if (!gPad->IsEditable()) return;
3492
3493 if (fPie) {
3494 fPie->ExecuteEvent(event, px, py);
3495 return;
3496 }
3497 // come here if we have a lego/surface in the pad
3498 TView *view = gPad->GetView();
3499
3500 if (!fShowProjection && view && !view->TestBit(kCannotRotate)) {
3501 view->ExecuteRotateView(event, px, py);
3502 return;
3503 }
3504
3505 TAxis *xaxis = fH->GetXaxis();
3506 TAxis *yaxis = fH->GetYaxis();
3507 Int_t dimension = fH->GetDimension();
3508
3509 // In case of option SAME the axis must be the ones of the first drawn histogram
3510 TString IsSame = fH->GetDrawOption();
3511 IsSame.ToLower();
3512 if (IsSame.Index("same")>=0) {
3513 TH1 *h1;
3514 TIter next(gPad->GetListOfPrimitives());
3515 while ((h1 = (TH1 *)next())) {
3516 if (!h1->InheritsFrom(TH1::Class())) continue;
3517 xaxis = h1->GetXaxis();
3518 yaxis = h1->GetYaxis();
3519 break;
3520 }
3521 }
3522
3523 Double_t factor = 1;
3524 if (fH->GetNormFactor() != 0) {
3525 factor = fH->GetNormFactor()/fH->GetSumOfWeights();
3526 }
3527
3528 switch (event) {
3529
3530 case kButton1Down:
3531
3532 if (!opaque) gVirtualX->SetLineColor(-1);
3533 fH->TAttLine::Modify();
3534
3535 if (opaque && dimension ==2) {
3536 zbx1 = gPad->AbsPixeltoX(px);
3537 zbx2 = gPad->AbsPixeltoX(px);
3538 zby1 = gPad->AbsPixeltoY(py);
3539 zby2 = gPad->AbsPixeltoY(py);
3540 px1 = px;
3541 py1 = py;
3542 if (gPad->GetLogx()) {
3543 zbx1 = TMath::Power(10,zbx1);
3544 zbx2 = TMath::Power(10,zbx2);
3545 }
3546 if (gPad->GetLogy()) {
3547 zby1 = TMath::Power(10,zby1);
3548 zby2 = TMath::Power(10,zby2);
3549 }
3550 if (zoombox) Error("ExecuteEvent", "Last zoom box was not deleted");
3551 zoombox = std::make_unique<TBox>(zbx1, zby1, zbx2, zby2);
3552 Int_t ci = TColor::GetColor("#7d7dff");
3553 TColor *zoomcolor = gROOT->GetColor(ci);
3554 if (!TCanvas::SupportAlpha() || !zoomcolor) zoombox->SetFillStyle(3002);
3555 else zoomcolor->SetAlpha(0.5);
3556 zoombox->SetFillColor(ci);
3557 zoombox->Draw();
3558 gPad->Modified();
3559 gPad->Update();
3560 }
3561 // No break !!!
3562
3563 case kMouseMotion:
3564
3565 if (fShowProjection) {ShowProjection3(px,py); break;}
3566
3567 gPad->SetCursor(kPointer);
3568 if (dimension ==1) {
3569 if (Hoption.Bar) {
3570 baroffset = fH->GetBarOffset();
3571 barwidth = fH->GetBarWidth();
3572 } else {
3573 baroffset = 0;
3574 barwidth = 1;
3575 }
3576 x = gPad->AbsPixeltoX(px);
3577 bin = fXaxis->FindFixBin(gPad->PadtoX(x));
3578 binwidth = fXaxis->GetBinWidth(bin);
3579 xlow = gPad->XtoPad(fXaxis->GetBinLowEdge(bin) + baroffset*binwidth);
3580 xup = gPad->XtoPad(xlow + barwidth*binwidth);
3581 ylow = gPad->GetUymin();
3582 px1 = gPad->XtoAbsPixel(xlow);
3583 px2 = gPad->XtoAbsPixel(xup);
3584 py1 = gPad->YtoAbsPixel(ylow);
3585 py2 = py;
3586 pyold = py;
3587 if (gROOT->GetEditHistograms()) gPad->SetCursor(kArrowVer);
3588 }
3589
3590 break;
3591
3592 case kButton1Motion:
3593
3594 if (dimension ==1) {
3595 if (gROOT->GetEditHistograms()) {
3596 if (!opaque) {
3597 gVirtualX->DrawBox(px1, py1, px2, py2,TVirtualX::kHollow); // Draw the old box
3598 py2 += py - pyold;
3599 gVirtualX->DrawBox(px1, py1, px2, py2,TVirtualX::kHollow); // Draw the new box
3600 pyold = py;
3601 } else {
3602 py2 += py - pyold;
3603 pyold = py;
3604 binval = gPad->PadtoY(gPad->AbsPixeltoY(py2))/factor;
3605 fH->SetBinContent(bin,binval);
3606 gPad->Modified(kTRUE);
3607 }
3608 }
3609 }
3610
3611 if (opaque && dimension ==2) {
3612 if (TMath::Abs(px1-px)>5 && TMath::Abs(py1-py)>5) {
3613 zbx2 = gPad->AbsPixeltoX(px);
3614 zby2 = gPad->AbsPixeltoY(py);
3615 if (gPad->GetLogx()) zbx2 = TMath::Power(10,zbx2);
3616 if (gPad->GetLogy()) zby2 = TMath::Power(10,zby2);
3617 if (zoombox) {
3618 zoombox->SetX2(zbx2);
3619 zoombox->SetY2(zby2);
3620 }
3621 gPad->Modified();
3622 gPad->Update();
3623 }
3624 }
3625
3626 break;
3627
3628 case kWheelUp:
3629
3630 if (dimension ==2) {
3631 bin1 = xaxis->GetFirst()+1;
3632 bin2 = xaxis->GetLast()-1;
3633 bin1 = TMath::Max(bin1, 1);
3634 bin2 = TMath::Min(bin2, xaxis->GetNbins());
3635 if (bin2>bin1) xaxis->SetRange(bin1,bin2);
3636 bin1 = yaxis->GetFirst()+1;
3637 bin2 = yaxis->GetLast()-1;
3638 bin1 = TMath::Max(bin1, 1);
3639 bin2 = TMath::Min(bin2, yaxis->GetNbins());
3640 if (bin2>bin1) yaxis->SetRange(bin1,bin2);
3641 }
3642 gPad->Modified();
3643 gPad->Update();
3644
3645 break;
3646
3647 case kWheelDown:
3648
3649 if (dimension == 2) {
3650 bin1 = xaxis->GetFirst()-1;
3651 bin2 = xaxis->GetLast()+1;
3652 bin1 = TMath::Max(bin1, 1);
3653 bin2 = TMath::Min(bin2, xaxis->GetNbins());
3654 const bool resetXaxisRange = bin1 == 1 && xaxis->GetFirst() == 1 && bin2 == xaxis->GetNbins() && xaxis->GetLast() == xaxis->GetNbins();
3655 if (bin2>bin1) xaxis->SetRange(bin1,bin2);
3656 if (resetXaxisRange) xaxis->ResetBit(TAxis::kAxisRange);
3657 bin1 = yaxis->GetFirst()-1;
3658 bin2 = yaxis->GetLast()+1;
3659 bin1 = TMath::Max(bin1, 1);
3660 bin2 = TMath::Min(bin2, yaxis->GetNbins());
3661 const bool resetYaxisRange = bin1 == 1 && yaxis->GetFirst() == 1 && bin2 == yaxis->GetNbins() && yaxis->GetLast() == yaxis->GetNbins();
3662 if (bin2>bin1) yaxis->SetRange(bin1,bin2);
3663 if (resetYaxisRange) yaxis->ResetBit(TAxis::kAxisRange);
3664 }
3665 gPad->Modified();
3666 gPad->Update();
3667
3668 break;
3669
3670 case kButton1Up:
3671 if (dimension ==1) {
3672 if (gROOT->GetEditHistograms()) {
3673 binval = gPad->PadtoY(gPad->AbsPixeltoY(py2))/factor;
3674 fH->SetBinContent(bin,binval);
3675 PaintInit(); // recalculate Hparam structure and recalculate range
3676 }
3677
3678 // might resize pad pixmap so should be called before any paint routine
3680 }
3681 if (opaque && dimension ==2) {
3682 if (zoombox) {
3683 Double_t x1 = TMath::Min(zoombox->GetX1(), zoombox->GetX2());
3684 Double_t x2 = TMath::Max(zoombox->GetX1(), zoombox->GetX2());
3685 Double_t y1 = TMath::Min(zoombox->GetY1(), zoombox->GetY2());
3686 Double_t y2 = TMath::Max(zoombox->GetY1(), zoombox->GetY2());
3687 x1 = TMath::Max(x1,xaxis->GetXmin());
3688 x2 = TMath::Min(x2,xaxis->GetXmax());
3689 y1 = TMath::Max(y1,yaxis->GetXmin());
3690 y2 = TMath::Min(y2,yaxis->GetXmax());
3691 if (x1<x2 && y1<y2) {
3692 xaxis->SetRangeUser(x1, x2);
3693 yaxis->SetRangeUser(y1, y2);
3694 }
3695 zoombox.reset();
3696 }
3697 }
3698 gPad->Modified(kTRUE);
3699 if (opaque) gVirtualX->SetLineColor(-1);
3700
3701 break;
3702
3703 case kButton1Locate:
3704
3705 ExecuteEvent(kButton1Down, px, py);
3706
3707 while (true) {
3708 px = py = 0;
3709 event = gVirtualX->RequestLocator(1, 1, px, py);
3710
3712
3713 if (event != -1) { // button is released
3714 ExecuteEvent(kButton1Up, px, py);
3715 return;
3716 }
3717 }
3718 }
3719}
3720
3721////////////////////////////////////////////////////////////////////////////////
3722/// Get a contour (as a list of TGraphs) using the Delaunay triangulation.
3723
3725{
3726 // Check if fH contains a TGraphDelaunay2D
3728 TGraphDelaunay2D *dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
3729 // try with the old painter
3730 TGraphDelaunay *dtOld = nullptr;
3731 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
3732
3733 if (!dt && !dtOld) return nullptr;
3734
3735 gCurrentHist = fH;
3736
3737 if (!fGraph2DPainter)
3738 ((THistPainter*)this)->fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
3739
3740 return fGraph2DPainter->GetContourList(contour);
3741}
3742
3743////////////////////////////////////////////////////////////////////////////////
3744/// Display the histogram info (bin number, contents, integral up to bin
3745/// corresponding to cursor position px,py.
3746
3748{
3749
3750 if (!gPad) return (char*)"";
3751
3752 Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
3753 Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
3754 Double_t x1 = gPad->PadtoX(gPad->AbsPixeltoX(px+1));
3756 drawOption.ToLower();
3759 if (fH->GetDimension() == 2) {
3760 if (gPad->GetView() || drawOption.Index("cont") >= 0) {
3761 uxmin=gPad->GetUxmin();
3762 uxmax=gPad->GetUxmax();
3765 x = xmin +(xmax-xmin)*(x-uxmin)/(uxmax-uxmin);
3766 uymin=gPad->GetUymin();
3767 uymax=gPad->GetUymax();
3770 y = ymin +(ymax-ymin)*(y-uymin)/(uymax-uymin);
3771 }
3772 }
3774 if (gPad->IsVertical()) {
3775 binx = fXaxis->FindFixBin(x);
3776 if (drawOption.Index("same") >= 0) {
3777 TH1 *h1;
3778 TIter next(gPad->GetListOfPrimitives());
3779 while ((h1 = (TH1 *)next())) {
3780 if (!h1->InheritsFrom(TH1::Class())) continue;
3781 binmin = h1->GetXaxis()->GetFirst();
3782 break;
3783 }
3784 } else {
3785 binmin = fXaxis->GetFirst();
3786 }
3788 // special case if more than 1 bin in x per pixel
3789 if (binx1-binx>1 && fH->GetDimension() == 1) {
3792 for (Int_t ibin=binx+1; ibin<binx1; ibin++) {
3796 binnear=ibin;
3797 }
3798 }
3799 binx = binnear;
3800 }
3801 } else {
3802 x1 = gPad->PadtoY(gPad->AbsPixeltoY(py+1));
3803 binx = fXaxis->FindFixBin(y);
3804 if (drawOption.Index("same") >= 0) {
3805 TH1 *h1;
3806 TIter next(gPad->GetListOfPrimitives());
3807 while ((h1 = (TH1 *)next())) {
3808 if (!h1->InheritsFrom(TH1::Class())) continue;
3809 binmin = h1->GetXaxis()->GetFirst();
3810 break;
3811 }
3812 } else {
3813 binmin = fXaxis->GetFirst();
3814 }
3816 // special case if more than 1 bin in x per pixel
3817 if (binx1-binx>1 && fH->GetDimension() == 1) {
3820 for (Int_t ibin=binx+1; ibin<binx1; ibin++) {
3824 binnear=ibin;
3825 }
3826 }
3827 binx = binnear;
3828 }
3829 }
3830 if (fH->GetDimension() == 1) {
3832 TProfile *tp = (TProfile*)fH;
3833 fObjectInfo.Form("(x=%g, y=%g, binx=%d, binc=%g, bine=%g, binn=%d)",
3835 (Int_t) tp->GetBinEntries(binx));
3836 }
3837 else {
3838 Double_t integ = 0;
3839 for (Int_t bin=binmin;bin<=binx;bin++) {integ += fH->GetBinContent(bin);}
3840 fObjectInfo.Form("(x=%g, y=%g, binx=%d, binc=%g, Sum=%g)",
3842 }
3843 } else if (fH->GetDimension() == 2) {
3844 if (fH->InheritsFrom(TH2Poly::Class())) {
3845 TH2Poly *th2 = (TH2Poly*)fH;
3846 biny = th2->FindBin(x,y);
3847 fObjectInfo.Form("%s (x=%g, y=%g, bin=%d, binc=%g)",
3848 th2->GetBinTitle(biny),x,y,biny,th2->GetBinContent(biny));
3849 }
3850 else if (fH->InheritsFrom(TProfile2D::Class())) {
3852 biny = fYaxis->FindFixBin(y);
3853 Int_t bin = fH->GetBin(binx,biny);
3854 fObjectInfo.Form("(x=%g, y=%g, binx=%d, biny=%d, binc=%g, bine=%g, binn=%d)",
3855 x, y, binx, biny, fH->GetBinContent(bin),
3856 fH->GetBinError(bin), (Int_t) tp->GetBinEntries(bin));
3857 } else {
3858 biny = fYaxis->FindFixBin(y);
3859 fObjectInfo.Form("(x=%g, y=%g, binx=%d, biny=%d, binc=%g bine=%g)",
3862 }
3863 } else {
3864 // 3d case: retrieving the x,y,z bin is not yet implemented
3865 // print just the x,y info
3866 fObjectInfo.Form("(x=%g, y=%g)",x,y);
3867 }
3868
3869 return (char *)fObjectInfo.Data();
3870}
3871
3872////////////////////////////////////////////////////////////////////////////////
3873/// Set highlight (enable/disable) mode for fH
3874
3876{
3877 if (fH->IsHighlight()) return;
3878
3879 fXHighlightBin = -1;
3880 fYHighlightBin = -1;
3881 // delete previous highlight box
3882 if (gXHighlightBox) gXHighlightBox.reset();
3883 if (gYHighlightBox) gYHighlightBox.reset();
3884 // emit Highlighted() signal (user can check on disabled)
3885 if (gPad->GetCanvas()) gPad->GetCanvas()->Highlighted(gPad, fH, fXHighlightBin, fYHighlightBin);
3886}
3887
3888////////////////////////////////////////////////////////////////////////////////
3889/// Check on highlight bin
3890
3892{
3893 // call from DistancetoPrimitive (only if highlight is enable)
3894
3895 Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
3896 Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
3899 if (!gPad->IsVertical()) binx = fXaxis->FindFixBin(y);
3900
3902 if (binx != fXHighlightBin) {
3904 changedBin = kTRUE;
3905 } else if (fH->GetDimension() == 1) return;
3906 if (biny != fYHighlightBin) {
3908 changedBin = kTRUE;
3909 }
3910 if (!changedBin) return;
3911
3912 // Info("HighlightBin", "histo: %p '%s'\txbin: %d, ybin: %d",
3913 // (void *)fH, fH->GetName(), fXHighlightBin, fYHighlightBin);
3914
3915 // paint highlight bin as box (recursive calls PaintHighlightBin)
3916 gPad->Modified(kTRUE);
3917 gPad->Update();
3918
3919 // emit Highlighted() signal
3920 if (gPad->GetCanvas()) gPad->GetCanvas()->Highlighted(gPad, fH, fXHighlightBin, fYHighlightBin);
3921}
3922
3923////////////////////////////////////////////////////////////////////////////////
3924/// Paint highlight bin as TBox object
3925
3927{
3928 // call from PaintTitle
3929
3930 if (!fH->IsHighlight()) return;
3931
3932 Double_t uxmin = gPad->GetUxmin();
3933 Double_t uxmax = gPad->GetUxmax();
3934 Double_t uymin = gPad->GetUymin();
3935 Double_t uymax = gPad->GetUymax();
3936 if (gPad->GetLogx()) {
3937 uxmin = TMath::Power(10.0, uxmin);
3938 uxmax = TMath::Power(10.0, uxmax);
3939 }
3940 if (gPad->GetLogy()) {
3941 uymin = TMath::Power(10.0, uymin);
3942 uymax = TMath::Power(10.0, uymax);
3943 }
3944
3945 // testing specific possibility (after zoom, draw with "same", log, etc.)
3947 if (gPad->IsVertical()) {
3949 if ((hcenter < uxmin) || (hcenter > uxmax)) return;
3950 } else {
3952 if ((hcenter < uymin) || (hcenter > uymax)) return;
3953 }
3954 if (fH->GetDimension() == 2) {
3956 if ((hcenter < uymin) || (hcenter > uymax)) return;
3957 }
3958
3959 // paint X highlight bin (for 1D or 2D)
3961 if (gPad->IsVertical()) {
3964 hby1 = uymin;
3965 hby2 = uymax;
3966 } else {
3967 hbx1 = uxmin;
3968 hbx2 = uxmax;
3971 }
3972
3973 if (!gXHighlightBox) {
3974 gXHighlightBox = std::make_unique<TBox>(hbx1, hby1, hbx2, hby2);
3975 gXHighlightBox->SetBit(kCannotPick);
3976 gXHighlightBox->SetFillColor(TColor::GetColor("#9797ff"));
3977 if (!TCanvas::SupportAlpha()) gXHighlightBox->SetFillStyle(3001);
3978 else gROOT->GetColor(gXHighlightBox->GetFillColor())->SetAlpha(0.5);
3979 }
3980 gXHighlightBox->SetX1(hbx1);
3981 gXHighlightBox->SetX2(hbx2);
3982 gXHighlightBox->SetY1(hby1);
3983 gXHighlightBox->SetY2(hby2);
3984 gXHighlightBox->Paint();
3985
3986 // Info("PaintHighlightBin", "histo: %p '%s'\txbin: %d, ybin: %d",
3987 // (void *)fH, fH->GetName(), fXHighlightBin, fYHighlightBin);
3988
3989 // paint Y highlight bin (only for 2D)
3990 if (fH->GetDimension() != 2) return;
3991 hbx1 = uxmin;
3992 hbx2 = uxmax;
3995
3996 if (!gYHighlightBox) {
3997 gYHighlightBox = std::make_unique<TBox>(hbx1, hby1, hbx2, hby2);
3998 gYHighlightBox->SetBit(kCannotPick);
3999 gYHighlightBox->SetFillColor(gXHighlightBox->GetFillColor());
4000 gYHighlightBox->SetFillStyle(gXHighlightBox->GetFillStyle());
4001 }
4002 gYHighlightBox->SetX1(hbx1);
4003 gYHighlightBox->SetX2(hbx2);
4004 gYHighlightBox->SetY1(hby1);
4005 gYHighlightBox->SetY2(hby2);
4006 gYHighlightBox->Paint();
4007}
4008
4009////////////////////////////////////////////////////////////////////////////////
4010/// Return `kTRUE` if the cell `ix`, `iy` is inside one of the graphical cuts.
4011
4013{
4014
4015 for (Int_t i=0;i<fNcuts;i++) {
4018 if (fCutsOpt[i] > 0) {
4019 if (!fCuts[i]->IsInside(x,y)) return kFALSE;
4020 } else {
4021 if (fCuts[i]->IsInside(x,y)) return kFALSE;
4022 }
4023 }
4024 return kTRUE;
4025}
4026
4027////////////////////////////////////////////////////////////////////////////////
4028/// Return `kTRUE` if the point `x`, `y` is inside one of the graphical cuts.
4029
4031{
4032
4033 for (Int_t i=0;i<fNcuts;i++) {
4034 if (fCutsOpt[i] > 0) {
4035 if (!fCuts[i]->IsInside(x,y)) return kFALSE;
4036 } else {
4037 if (fCuts[i]->IsInside(x,y)) return kFALSE;
4038 }
4039 }
4040 return kTRUE;
4041}
4042
4043////////////////////////////////////////////////////////////////////////////////
4044/// Decode string `choptin` and fill Hoption structure.
4045
4047{
4048
4049 char *l;
4050 char chopt[128];
4052 strlcpy(chopt,choptin,128);
4055
4063 Hoption.Candle = 0;
4064
4065 // special 2D options
4066 Hoption.List = 0;
4067 Hoption.Zscale = 0;
4068 Hoption.FrontBox = 1;
4069 Hoption.BackBox = 1;
4071
4072 Hoption.Zero = 0;
4073
4075
4076 //check for graphical cuts
4077 MakeCuts(chopt);
4078
4079 for (Int_t i=0;i<nch;i++) chopt[i] = toupper(chopt[i]);
4080 if (hdim > 1) Hoption.Color = 1; // Default drawing option for 2D and 3D histograms
4081 if (!nch) Hoption.Hist = 1;
4082 if (fFunctions->First()) Hoption.Func = 1;
4083 if (fH->GetSumw2N() && hdim == 1) Hoption.Error = 2;
4084
4085 char *l1 = strstr(chopt,"PFC"); // Automatic Fill Color
4086 char *l2 = strstr(chopt,"PLC"); // Automatic Line Color
4087 char *l3 = strstr(chopt,"PMC"); // Automatic Marker Color
4088 if (l1 || l2 || l3) {
4089 Int_t i = gPad->NextPaletteColor();
4090 if (l1) {memcpy(l1," ",3); fH->SetFillColor(i);}
4091 if (l2) {memcpy(l2," ",3); fH->SetLineColor(i);}
4092 if (l3) {memcpy(l3," ",3); fH->SetMarkerColor(i);}
4093 Hoption.Hist = 1; // Make sure something is drawn in case there is no drawing option specified.
4094 }
4095
4096 l = strstr(chopt,"MIN0");
4097 if (l) {
4098 Hoption.MinimumZero = 1;
4099 memcpy(l," ",4);
4100 }
4101
4102 l = strstr(chopt,"SPEC");
4103 if (l) {
4104 Hoption.Color = 0;
4105 memcpy(l," ",4);
4106 Int_t bs=0;
4107 l = strstr(chopt,"BF(");
4108 if (l) {
4109 if (sscanf(&l[3],"%d",&bs) > 0) {
4110 Int_t i=0;
4111 while (l[i]!=')') {
4112 l[i] = ' ';
4113 i++;
4114 }
4115 l[i] = ' ';
4116 }
4117 }
4118 Hoption.Spec = TMath::Max(1600,bs);
4119 return 1;
4120 }
4121
4122 l = strstr(chopt,"GL");
4123 if (l) {
4124 memcpy(l," ",2);
4125 }
4126 l = strstr(chopt,"X+");
4127 if (l) {
4128 Hoption.AxisPos = 10;
4129 memcpy(l," ",2);
4130 }
4131 l = strstr(chopt,"Y+");
4132 if (l) {
4133 Hoption.AxisPos += 1;
4134 memcpy(l," ",2);
4135 }
4136 if ((Hoption.AxisPos == 10 || Hoption.AxisPos == 1) && (nch == 2)) Hoption.Hist = 1;
4137 if (Hoption.AxisPos == 11 && nch == 4) Hoption.Hist = 1;
4138
4139 l = strstr(chopt,"SAMES");
4140 if (l) {
4141 if (nch == 5) Hoption.Hist = 1;
4142 Hoption.Same = 2;
4143 memcpy(l," ",5);
4144 if (l[5] == '0') { Hoption.Same += 10; l[5] = ' '; }
4145 }
4146 l = strstr(chopt,"SAME");
4147 if (l) {
4148 if (nch == 4) Hoption.Hist = 1;
4149 Hoption.Same = 1;
4150 memcpy(l," ",4);
4151 if (l[4] == '0') { Hoption.Same += 10; l[4] = ' '; }
4152 }
4153
4154 l = strstr(chopt,"SCAT");
4155 if (l) {
4156 Warning("MakeChopt","option SCAT is deprecated.");
4157 Hoption.Scat = 1;
4158 memcpy(l," ",4);
4159 Hoption.Color = 0;
4160 }
4161
4162 l = strstr(chopt,"PIE");
4163 if (l) {
4164 Hoption.Pie = 1;
4165 memcpy(l," ",3);
4166 }
4167
4168
4169 l = strstr(chopt,"CANDLE");
4170 if (l) {
4172 Hoption.Candle = candle.ParseOption(l);
4173 Hoption.Color = 0;
4174 }
4175
4176 l = strstr(chopt,"VIOLIN");
4177 if (l) {
4179 Hoption.Candle = candle.ParseOption(l);
4180 Hoption.Color = 0;
4181 }
4182
4183 l = strstr(chopt,"LEGO");
4184 if (l) {
4185 Hoption.Color = 0;
4186 Hoption.Lego = 1; memcpy(l," ",4);
4187 if (l[4] == '1') { Hoption.Lego = 11; l[4] = ' '; }
4188 if (l[4] == '2') { Hoption.Lego = 12; l[4] = ' '; }
4189 if (l[4] == '3') { Hoption.Lego = 13; l[4] = ' '; }
4190 if (l[4] == '4') { Hoption.Lego = 14; l[4] = ' '; }
4191 if (l[4] == '9') { Hoption.Lego = 19; l[4] = ' '; }
4192 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4193 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4194 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4195 }
4196
4197 l = strstr(chopt,"SURF");
4198 if (l) {
4199 Hoption.Color = 0;
4200 Hoption.Surf = 1; memcpy(l," ",4);
4201 if (l[4] == '1') { Hoption.Surf = 11; l[4] = ' '; }
4202 if (l[4] == '2') { Hoption.Surf = 12; l[4] = ' '; }
4203 if (l[4] == '3') { Hoption.Surf = 13; l[4] = ' '; }
4204 if (l[4] == '4') { Hoption.Surf = 14; l[4] = ' '; }
4205 if (l[4] == '5') { Hoption.Surf = 15; l[4] = ' '; }
4206 if (l[4] == '6') { Hoption.Surf = 16; l[4] = ' '; }
4207 if (l[4] == '7') { Hoption.Surf = 17; l[4] = ' '; }
4208 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4209 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4210 }
4211
4212 l = strstr(chopt,"TF3");
4213 if (l) {
4214 memcpy(l," ",3);
4215 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4216 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4217 }
4218
4219 l = strstr(chopt,"ISO");
4220 if (l) {
4221 memcpy(l," ",3);
4222 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4223 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4224 Hoption.Color = 0;
4225 }
4226
4227 l = strstr(chopt,"LIST"); if (l) { Hoption.List = 1; memcpy(l," ",4);}
4228
4229 l = strstr(chopt,"CONT");
4230 if (l) {
4231 memcpy(l," ",4);
4232 if (hdim>1) {
4233 Hoption.Color = 0;
4234 Hoption.Contour = 1;
4235 if (l[4] == '1') { Hoption.Contour = 11; l[4] = ' '; }
4236 if (l[4] == '2') { Hoption.Contour = 12; l[4] = ' '; }
4237 if (l[4] == '3') { Hoption.Contour = 13; l[4] = ' '; }
4238 if (l[4] == '4') { Hoption.Contour = 14; l[4] = ' '; }
4239 if (l[4] == '5') { Hoption.Contour = 15; l[4] = ' '; }
4240 } else {
4241 Hoption.Hist = 1;
4242 }
4243 }
4244 l = strstr(chopt,"HBAR");
4245 if (l) {
4246 Hoption.Hist = 0;
4247 Hoption.Bar = 20; memcpy(l," ",4);
4248 if (l[4] == '1') { Hoption.Bar = 21; l[4] = ' '; }
4249 if (l[4] == '2') { Hoption.Bar = 22; l[4] = ' '; }
4250 if (l[4] == '3') { Hoption.Bar = 23; l[4] = ' '; }
4251 if (l[4] == '4') { Hoption.Bar = 24; l[4] = ' '; }
4252 }
4253 l = strstr(chopt,"BAR");
4254 if (l) {
4255 Hoption.Hist = 0;
4256 Hoption.Bar = 10; memcpy(l," ",3);
4257 if (l[3] == '1') { Hoption.Bar = 11; l[3] = ' '; }
4258 if (l[3] == '2') { Hoption.Bar = 12; l[3] = ' '; }
4259 if (l[3] == '3') { Hoption.Bar = 13; l[3] = ' '; }
4260 if (l[3] == '4') { Hoption.Bar = 14; l[3] = ' '; }
4261 }
4262
4263 l = strstr(chopt,"ARR" );
4264 if (l) {
4265 memcpy(l," ", 3);
4266 if (hdim>1) {
4267 Hoption.Arrow = 1;
4268 Hoption.Color = 0;
4269 l = strstr(chopt,"COL"); if (l) { Hoption.Arrow = 2; memcpy(l," ",3); }
4270 l = strstr(chopt,"Z"); if (l) { Hoption.Zscale = 1; memcpy(l," ",1); }
4271 } else {
4272 Hoption.Hist = 1;
4273 }
4274 }
4275 l = strstr(chopt,"BOX" );
4276 if (l) {
4277 memcpy(l," ", 3);
4278 if (hdim>1) {
4279 Hoption.Color = 0;
4280 Hoption.Box = 1;
4281 if (l[3] == '1') { Hoption.Box = 11; l[3] = ' '; }
4282 if (l[3] == '2') { Hoption.Box = 12; l[3] = ' '; }
4283 if (l[3] == '3') { Hoption.Box = 13; l[3] = ' '; }
4284 } else {
4285 Hoption.Hist = 1;
4286 }
4287 }
4288 l = strstr(chopt,"TEXT");
4289 if (l) {
4290 Int_t angle;
4291 if (sscanf(&l[4],"%d",&angle) > 0) {
4292 if (angle < 0) angle=0;
4293 if (angle > 90) angle=90;
4294 Hoption.Text = 1000+angle;
4295 } else {
4296 Hoption.Text = 1;
4297 }
4298 memcpy(l," ", 4);
4299 l = strstr(chopt,"N");
4300 if (l && fH->InheritsFrom(TH2Poly::Class())) Hoption.Text = 3000 + (Hoption.Text != 1 ? Hoption.Text : 0);
4301 Hoption.Color = 0;
4302 }
4303 l = strstr(chopt,"COLZ");
4304 if (l) {
4305 memcpy(l," ",4);
4306 if (hdim > 1) {
4308 Hoption.Color = 1;
4309 Hoption.Zscale = 1;
4310 if (l[4] == '2') { Hoption.Color = 3; l[4] = ' '; }
4311 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4312 l = strstr(chopt,"1"); if (l) { Hoption.Color = 2; memcpy(l," ",1); }
4313 } else {
4314 Hoption.Hist = 1;
4315 }
4316 }
4317 l = strstr(chopt,"COL" );
4318 if (l) {
4319 memcpy(l," ", 3);
4320 if (hdim > 1) {
4322 Hoption.Color = 1;
4323 if (l[3] == '2') { Hoption.Color = 3; l[3] = ' '; }
4324 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4325 l = strstr(chopt,"1"); if (l) { Hoption.Color = 2; memcpy(l," ",1); }
4326 } else {
4327 Hoption.Hist = 1;
4328 }
4329 }
4330 l = strstr(chopt,"FUNC"); if (l) { Hoption.Func = 2; memcpy(l," ",4); Hoption.Hist = 0; }
4331 l = strstr(chopt,"HIST"); if (l) { Hoption.Hist = 2; memcpy(l," ",4); Hoption.Func = 0; Hoption.Error = 0;}
4332 l = strstr(chopt,"AXIS"); if (l) { Hoption.Axis = 1; memcpy(l," ",4); }
4333 l = strstr(chopt,"AXIG"); if (l) { Hoption.Axis = 2; memcpy(l," ",4); }
4334 l = strstr(chopt,"SCAT"); if (l) { Hoption.Scat = 1; memcpy(l," ",4); }
4335 l = strstr(chopt,"POL"); if (l) { Hoption.System = kPOLAR; memcpy(l," ",3); }
4336 l = strstr(chopt,"CYL"); if (l) { Hoption.System = kCYLINDRICAL; memcpy(l," ",3); }
4337 l = strstr(chopt,"SPH"); if (l) { Hoption.System = kSPHERICAL; memcpy(l," ",3); }
4338 l = strstr(chopt,"PSR"); if (l) { Hoption.System = kRAPIDITY; memcpy(l," ",3); }
4339
4340 l = strstr(chopt,"TRI");
4341 if (l) {
4342 if (!explicitColor) Hoption.Color = 0;
4343 Hoption.Tri = 1; memcpy(l," ",3);
4344 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4345 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4346 l = strstr(chopt,"ERR"); if (l) memcpy(l," ",3);
4347 }
4348
4349 l = strstr(chopt,"AITOFF");
4350 if (l) {
4351 Hoption.Proj = 1; memcpy(l," ",6); //Aitoff projection
4352 }
4353 l = strstr(chopt,"MERCATOR");
4354 if (l) {
4355 Hoption.Proj = 2; memcpy(l," ",8); //Mercator projection
4356 }
4357 l = strstr(chopt,"SINUSOIDAL");
4358 if (l) {
4359 Hoption.Proj = 3; memcpy(l," ",10); //Sinusoidal projection
4360 }
4361 l = strstr(chopt,"PARABOLIC");
4362 if (l) {
4363 Hoption.Proj = 4; memcpy(l," ",9); //Parabolic projection
4364 }
4365 l = strstr(chopt,"MOLLWEIDE");
4366 if (l) {
4367 Hoption.Proj = 5; memcpy(l," ",9); //Mollweide projection
4368 }
4369 if (Hoption.Proj > 0) {
4370 if (!explicitColor) Hoption.Color = 0;
4371 Hoption.Contour = 14;
4372 }
4373
4374 if (strstr(chopt,"A")) Hoption.Axis = -1;
4375 if (strstr(chopt,"B")) Hoption.Bar = 1;
4376 if (strstr(chopt,"C") && !strstr(chopt,"CJUST")) { Hoption.Curve =1; Hoption.Hist = -1;}
4377 if (strstr(chopt,"F")) Hoption.Fill =1;
4378 if (strstr(chopt,"][")) {Hoption.Off =1; Hoption.Hist =1;}
4379 if (strstr(chopt,"F2")) Hoption.Fill =2;
4380 if (strstr(chopt,"L")) { Hoption.Line =1; Hoption.Hist = -1;}
4381 if (strstr(chopt,"P")) { Hoption.Mark =1; Hoption.Hist = -1;}
4382 if (strstr(chopt,"Z")) Hoption.Zscale =1;
4383 if (strstr(chopt,"*")) Hoption.Star =1;
4384 if (strstr(chopt,"H")) Hoption.Hist =2;
4385 if (strstr(chopt,"P0")) Hoption.Mark =10;
4386
4387 if (fH->InheritsFrom(TH2Poly::Class())) {
4389 }
4390
4391 if (strstr(chopt,"E")) {
4392 if (hdim == 1) {
4393 Hoption.Error = 1;
4394 if (strstr(chopt,"E1")) Hoption.Error = 11;
4395 if (strstr(chopt,"E2")) Hoption.Error = 12;
4396 if (strstr(chopt,"E3")) Hoption.Error = 13;
4397 if (strstr(chopt,"E4")) Hoption.Error = 14;
4398 if (strstr(chopt,"E5")) Hoption.Error = 15;
4399 if (strstr(chopt,"E6")) Hoption.Error = 16;
4400 if (strstr(chopt,"E0")) Hoption.Error += 40;
4401 if (strstr(chopt,"X0")) {
4402 if (Hoption.Error == 1) Hoption.Error += 20;
4403 Hoption.Error += 10;
4404 }
4406 Hoption.Text += 2000;
4407 Hoption.Error = 0;
4408 }
4409 } else {
4410 if (Hoption.Error == 0) {
4411 Hoption.Error = 100;
4412 if (!explicitColor) Hoption.Color = 0;
4413 }
4414 if (Hoption.Text) {
4415 Hoption.Text += 2000;
4416 Hoption.Error = 0;
4417 }
4418 }
4419 }
4420
4421 if (Hoption.Surf == 15) {
4423 Hoption.Surf = 13;
4424 Warning("MakeChopt","option SURF5 is not supported in Cartesian and Polar modes");
4425 }
4426 }
4427
4428 // Copy options from current style
4429 Hoption.Logx = gPad->GetLogx();
4430 Hoption.Logy = gPad->GetLogy();
4431 Hoption.Logz = gPad->GetLogz();
4432
4433 // Check options incompatibilities
4434 if (Hoption.Bar == 1) Hoption.Hist = -1;
4435 return 1;
4436}
4437
4438////////////////////////////////////////////////////////////////////////////////
4439/// Decode string `choptin` and fill Graphical cuts structure.
4440
4442{
4443
4444 fNcuts = 0;
4445 char *left = (char*)strchr(choptin,'[');
4446 if (!left) return 0;
4447 char *right = (char*)strchr(choptin,']');
4448 if (!right) return 0;
4449 Int_t nch = right-left;
4450 if (nch < 2) return 0;
4451 char *cuts = left+1;
4452 *right = 0;
4453 char *comma, *minus;
4454 Int_t i;
4455 while (true) {
4456 comma = strchr(cuts,',');
4457 if (comma) *comma = 0;
4458 minus = strchr(cuts,'-');
4459 if (minus) cuts = minus+1;
4460 while (*cuts == ' ') cuts++;
4461 Int_t nc = strlen(cuts);
4462 while (cuts[nc-1] == ' ') {cuts[nc-1] = 0; nc--;}
4463 TIter next(gROOT->GetListOfSpecials());
4464 TCutG *cut=nullptr;
4465 TObject *obj;
4466 while ((obj = next())) {
4467 if (!obj->InheritsFrom(TCutG::Class())) continue;
4468 if (strcmp(obj->GetName(),cuts)) continue;
4469 cut = (TCutG*)obj;
4470 break;
4471 }
4472 if (cut) {
4473 fCuts[fNcuts] = cut;
4474 fCutsOpt[fNcuts] = 1;
4475 if (minus) fCutsOpt[fNcuts] = -1;
4476 fNcuts++;
4477 }
4478 if (!comma) break;
4479 cuts = comma+1;
4480 }
4481 for (i=0;i<=nch;i++) left[i] = ' ';
4482 return fNcuts;
4483}
4484
4485////////////////////////////////////////////////////////////////////////////////
4486/// [Control routine to paint any kind of histograms](\ref HP00)
4487
4489{
4490
4491 if (fH->GetBuffer()) fH->BufferEmpty(-1);
4492
4493 //For iOS: put the histogram on the top of stack of pickable objects.
4495
4496 gPad->SetVertical(kTRUE);
4497
4499 gCurrentHist = fH;
4500 TH1 *hsave = fH;
4502
4503 if (!MakeChopt(option)) return; //check options and fill Hoption structure
4504
4505 // Paint using TSpectrum2Painter
4506 if (Hoption.Spec) {
4507 if (!TableInit()) return;
4508 if (!TClass::GetClass("TSpectrum2Painter")) gSystem->Load("libSpectrumPainter");
4509 gROOT->ProcessLineFast(TString::Format("TSpectrum2Painter::PaintSpectrum((TH2F*)0x%zx,\"%s\",%d)",
4510 (size_t)fH, option, Hoption.Spec).Data());
4511 return;
4512 }
4513
4514 // Deflate the labels in case of alphanumeric labels
4518
4519 if (Hoption.Pie) {
4520 if (fH->GetDimension() == 1) {
4521 if (!fPie)
4522 fPie = std::make_unique<TPie>(fH);
4523 fPie->Paint(option);
4524 } else {
4525 Error("Paint", "Option PIE is for 1D histograms only");
4526 }
4527 return;
4528 } else {
4529 fPie.reset();
4530 }
4531
4532 fXbuf.resize(kNMAX);
4533 fYbuf.resize(kNMAX);
4534 if (fH->GetDimension() > 2) {
4535 PaintH3(option);
4537 if (Hoption.Func) {
4542 Hoption = hoptsave;
4543 Hparam = hparsave;
4544 }
4546 fXbuf.clear();
4547 fYbuf.clear();
4548 return;
4549 }
4550 TView *view = gPad->GetView();
4551 if (view) {
4552 if (!Hoption.Lego && !Hoption.Surf && !Hoption.Tri) {
4553 delete view;
4554 gPad->SetView(nullptr);
4555 }
4556 }
4557 if (fH->GetDimension() > 1 || Hoption.Lego || Hoption.Surf) {
4558 // In case of 1D histogram, Z axis becomes Y axis.
4559 Int_t logysav=0, logzsav=0;
4560 if (fH->GetDimension() == 1) {
4563 Hoption.Logz = 0;
4564 if (Hoption.Logy) {
4565 Hoption.Logz = 1;
4566 Hoption.Logy = 0;
4567 }
4568 }
4570 if (Hoption.Func) {
4575 Hoption = hoptsave;
4576 Hparam = hparsave;
4577 }
4580 fXbuf.clear();
4581 fYbuf.clear();
4582 if (fH->GetDimension() == 1) {
4585 }
4586 return;
4587 }
4588
4589 if (Hoption.Bar >= 20) {
4591 fXbuf.clear();
4592 fYbuf.clear();
4593 return;
4594 }
4595
4596 gPad->RangeAxisChanged(); //emit RangeAxisChanged() signal to sync axes
4597 // fill Hparam structure with histo parameters
4598 if (!PaintInit()) {
4599 fXbuf.clear();
4600 fYbuf.clear();
4601 return;
4602 }
4603
4604 // Picture surround (if new page) and page number (if requested).
4605 // Histogram surround (if not option "Same").
4606 PaintFrame();
4607
4608 // Paint histogram axis only
4609 Bool_t gridx = gPad->GetGridx();
4610 Bool_t gridy = gPad->GetGridy();
4611 if (Hoption.Axis > 0) {
4612 if (Hoption.Axis > 1) PaintAxis(kTRUE); //axis with grid
4613 else {
4614 if (gridx) gPad->SetGridx(0);
4615 if (gridy) gPad->SetGridy(0);
4617 if (gridx) gPad->SetGridx(1);
4618 if (gridy) gPad->SetGridy(1);
4619 }
4620 if ((Hoption.Same%10) ==1) Hoption.Same += 1;
4621 goto paintstat;
4622 }
4623 if (gridx || gridy) PaintAxis(kTRUE); // Draw the grid only
4624
4625 // test for options BAR or HBAR
4626 if (Hoption.Bar >= 10) {
4628 }
4629
4630 // do not draw histogram if error bars required
4631 if (!Hoption.Error) {
4632 if (Hoption.Hist && Hoption.Bar<10) PaintHist(option);
4633 }
4634
4635 // test for error bars or option E
4636 if (Hoption.Error) {
4638 if (Hoption.Hist == 2) PaintHist(option);
4639 }
4640
4642
4643 // test for associated function
4644 if (Hoption.Func) {
4649 Hoption = hoptsave;
4650 Hparam = hparsave;
4651 }
4652
4653 if (gridx) gPad->SetGridx(0);
4654 if (gridy) gPad->SetGridy(0);
4656 if (gridx) gPad->SetGridx(1);
4657 if (gridy) gPad->SetGridy(1);
4658
4659 PaintTitle(); // Draw histogram title
4660
4661 // Draw box with histogram statistics and/or fit parameters
4662paintstat:
4663 if ((Hoption.Same%10) != 1 && !fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
4664 TIter next(fFunctions);
4665 TObject *obj = nullptr;
4666 while ((obj = next())) {
4667 if (obj->InheritsFrom(TF1::Class())) break;
4668 obj = nullptr;
4669 }
4670
4671 //Stat is painted twice (first, it will be in canvas' list of primitives),
4672 //second, it will be here, this is not required on iOS.
4673 //Condition is ALWAYS true on a platform different from iOS.
4674 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode())
4675 PaintStat(gStyle->GetOptStat(),(TF1*)obj);
4676 }
4679 fXbuf.clear();
4680 fYbuf.clear();
4681}
4682
4683////////////////////////////////////////////////////////////////////////////////
4684/// [Control function to draw a table as an arrow plot](\ref HP12)
4685
4687{
4689 Double_t dx, dy, x1, x2, y1, y2, xc, yc, dxn, dyn;
4692 Double_t xrg = gPad->GetUxmin();
4693 Double_t yrg = gPad->GetUymin();
4694 Double_t xln = gPad->GetUxmax() - xrg;
4695 Double_t yln = gPad->GetUymax() - yrg;
4696 Double_t cx = (xln/Double_t(ncx))/2.;
4697 Double_t cy = (yln/Double_t(ncy))/2.;
4698 Double_t dn = 1.E-30;
4699
4700 auto arrow = new TArrow();
4701 arrow->SetAngle(30);
4702 arrow->SetFillStyle(1001);
4703 arrow->SetFillColor(fH->GetLineColor());
4704 arrow->SetLineColor(fH->GetLineColor());
4705 arrow->SetLineWidth(fH->GetLineWidth());
4706
4707 // Initialize the levels on the Z axis
4708 Int_t ncolors=0, ndivz=0;
4709 Double_t scale=0.;
4710 if (Hoption.Arrow>1) {
4711 ncolors = gStyle->GetNumberOfColors();
4712 Int_t ndiv = fH->GetContour();
4713 if (ndiv == 0 ) {
4714 ndiv = gStyle->GetNumberContours();
4715 fH->SetContour(ndiv);
4716 }
4717 ndivz = TMath::Abs(ndiv);
4718 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
4720 }
4721
4722 for (Int_t id=1;id<=2;id++) {
4723 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
4726 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
4727 xk = fXaxis->GetBinLowEdge(i);
4728 xstep = fXaxis->GetBinWidth(i);
4729 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
4730 if (i == Hparam.xfirst) {
4731 dx = fH->GetBinContent(i+1, j) - fH->GetBinContent(i, j);
4732 } else if (i == Hparam.xlast) {
4733 dx = fH->GetBinContent(i, j) - fH->GetBinContent(i-1, j);
4734 } else {
4735 dx = 0.5*(fH->GetBinContent(i+1, j) - fH->GetBinContent(i-1, j));
4736 }
4737 if (j == Hparam.yfirst) {
4738 dy = fH->GetBinContent(i, j+1) - fH->GetBinContent(i, j);
4739 } else if (j == Hparam.ylast) {
4740 dy = fH->GetBinContent(i, j) - fH->GetBinContent(i, j-1);
4741 } else {
4742 dy = 0.5*(fH->GetBinContent(i, j+1) - fH->GetBinContent(i, j-1));
4743 }
4744 if (id == 1) {
4747 } else if (id == 2) {
4748 xc = xrg + xln*(Double_t(i - Hparam.xfirst+1)-0.5)/Double_t(ncx);
4749 dxn = cx*dx/dn;
4750 x1 = xc - dxn;
4751 x2 = xc + dxn;
4752 yc = yrg + yln*(Double_t(j - Hparam.yfirst+1)-0.5)/Double_t(ncy);
4753 dyn = cy*dy/dn;
4754 y1 = yc - dyn;
4755 y2 = yc + dyn;
4756 if (Hoption.Arrow>1) {
4757 int color = Int_t(0.01+(fH->GetBinContent(i, j)-fH->GetMinimum())*scale);
4758 Int_t theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
4759 if (theColor > ncolors-1) theColor = ncolors-1;
4760 arrow->SetFillColor(gStyle->GetColorPalette(theColor));
4761 arrow->SetLineColor(gStyle->GetColorPalette(theColor));
4762 }
4763 if (TMath::Abs(x2-x1) > 0. || TMath::Abs(y2-y1) > 0.) {
4764 arrow->PaintArrow(x1, y1, x2, y2, 0.015, "|>");
4765 } else {
4766 arrow->PaintArrow(x1, y1, x2, y2, 0.005, "|>");
4767 }
4768 }
4769 }
4770 }
4771 }
4772
4774}
4775
4776////////////////////////////////////////////////////////////////////////////////
4777/// Draw axis (2D case) of an histogram.
4778///
4779/// If `drawGridOnly` is `TRUE`, only the grid is painted (if needed). This allows
4780/// to draw the grid and the axis separately. In `THistPainter::Paint` this
4781/// feature is used to make sure that the grid is drawn in the background and
4782/// the axis tick marks in the foreground of the pad.
4783
4785{
4786
4787 //On iOS, grid should not be pickable and can not be highlighted.
4788 //Condition is never true on a platform different from iOS.
4789 if (drawGridOnly && (gPad->PadInHighlightMode() || gPad->PadInSelectionMode()))
4790 return;
4791
4792 if (Hoption.Axis == -1) return;
4793 if (Hoption.Same && Hoption.Axis <= 0) return;
4794
4795 // Repainting alphanumeric labels axis on a plot done with
4796 // the option HBAR (horizontal) needs some adjustments.
4797 TAxis *xaxis = nullptr;
4798 TAxis *yaxis = nullptr;
4799 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4800 if (fXaxis->GetLabels() || fYaxis->GetLabels()) { // One axis has alphanumeric labels
4801 TIter next(gPad->GetListOfPrimitives());
4802 TObject *obj;
4803 // Check if the first TH1 of THStack in the pad is drawn with the option HBAR
4804 while ((obj = next())) {
4805 if (!obj->InheritsFrom(TH1::Class()) &&
4806 !obj->InheritsFrom(THStack::Class())) continue;
4807 TString opt = obj->GetDrawOption();
4808 opt.ToLower();
4809 // if drawn with HBAR, the axis should be inverted and the pad set to horizontal
4810 if (strstr(opt,"hbar")) {
4811 gPad->SetVertical(kFALSE);
4812 xaxis = fXaxis;
4813 yaxis = fYaxis;
4814 if (!strcmp(xaxis->GetName(),"xaxis")) {
4815 fXaxis = yaxis;
4816 fYaxis = xaxis;
4817 }
4818 }
4819 break;
4820 }
4821 }
4822 }
4823
4824 static char chopt[10] = "";
4825 Double_t gridl = 0;
4826 Int_t ndiv, ndivx, ndivy, nx1, nx2, ndivsave;
4827 Int_t useHparam = 0;
4831
4832 Double_t axmin = gPad->GetUxmin();
4833 Double_t axmax = gPad->GetUxmax();
4834 Double_t aymin = gPad->GetUymin();
4835 Double_t aymax = gPad->GetUymax();
4836 char *cw = nullptr;
4837 TGaxis axis;
4838
4839 // In case of option 'cont4' or in case of option 'same' over a 'cont4 plot'
4840 // Hparam must be use for the axis limits.
4841 if (Hoption.Contour == 14) useHparam = 1;
4842 if (Hoption.Same) {
4843 TObject *obj;
4844 TIter next(gPad->GetListOfPrimitives());
4845 while ((obj=next())) {
4846 if (strstr(obj->GetDrawOption(),"cont4")) {
4847 useHparam = 1;
4848 break;
4849 }
4850 }
4851 }
4852
4853 // Paint X axis
4854
4855 //To make X-axis selectable on iOS device.
4856 if (gPad->PadInSelectionMode())
4857 gPad->PushSelectableObject(fXaxis);
4858
4859 //This condition is ALWAYS true, unless it works on iOS (can be false on iOS).
4860 if (gPad->PadInSelectionMode() || !gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && gPad->GetSelected() == fXaxis)) {
4862 if (ndivx > 1000) {
4863 nx2 = ndivx/100;
4864 nx1 = TMath::Max(1, ndivx%100);
4865 ndivx = 100*nx2 + Int_t(Float_t(nx1)*gPad->GetAbsWNDC());
4866 }
4867 axis.SetTextAngle(0);
4869
4870 chopt[0] = 0;
4871 strlcat(chopt, "SDH",10);
4872 if (ndivx < 0) strlcat(chopt, "N",10);
4873 if (gPad->GetGridx()) {
4874 gridl = (aymax-aymin)/(gPad->GetY2() - gPad->GetY1());
4875 strlcat(chopt, "W",10);
4876 }
4877
4878 // Define X-Axis limits
4879 if (Hoption.Logx) {
4880 strlcat(chopt, "G",10);
4881 ndiv = TMath::Abs(ndivx);
4882 if (useHparam) {
4885 } else {
4886 umin = TMath::Power(10,axmin);
4887 umax = TMath::Power(10,axmax);
4888 }
4889 } else {
4890 ndiv = TMath::Abs(ndivx);
4891 if (useHparam) {
4892 umin = Hparam.xmin;
4893 umax = Hparam.xmax;
4894 } else {
4895 umin = axmin;
4896 umax = axmax;
4897 }
4898 }
4899
4900 // Display axis as time
4901 if (fXaxis->GetTimeDisplay()) {
4902 strlcat(chopt,"t",10);
4903 if (strlen(fXaxis->GetTimeFormatOnly()) == 0) {
4905 }
4906 }
4907
4908 // The main X axis can be on the bottom or on the top of the pad
4910 if (xAxisPos == 1) {
4911 // Main X axis top
4912 xAxisYPos1 = aymax;
4913 xAxisYPos2 = aymin;
4914 } else {
4915 // Main X axis bottom
4916 xAxisYPos1 = aymin;
4917 xAxisYPos2 = aymax;
4918 }
4919
4920 // Paint the main X axis (always)
4921 uminsave = umin;
4922 umaxsave = umax;
4923 ndivsave = ndiv;
4924 axis.SetOption(chopt);
4925 if (xAxisPos) {
4926 strlcat(chopt, "-",10);
4927 gridl = -gridl;
4928 }
4929 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4930 axis.SetLabelSize(0.);
4931 axis.SetTitle("");
4932 }
4935 umin, umax, ndiv, chopt, gridl, drawGridOnly);
4936
4937 // Paint additional X axis (if needed)
4938 // On iOS, this additional X axis is neither pickable, nor highlighted.
4939 // Additional checks PadInSelectionMode etc. does not effect non-iOS platform.
4940 if (gPad->GetTickx() && !gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
4941 if (xAxisPos) {
4942 cw=strstr(chopt,"-");
4943 *cw='z';
4944 } else {
4945 strlcat(chopt, "-",10);
4946 }
4947 if (gPad->GetTickx() < 2) strlcat(chopt, "U",10);
4948 if ((cw=strstr(chopt,"W"))) *cw='z';
4949 axis.SetTitle("");
4953 }
4954 }//End of "if pad in selection mode etc".
4955
4956 // Paint Y axis
4957 //On iOS, Y axis must pushed into the stack of selectable objects.
4958 if (gPad->PadInSelectionMode())
4959 gPad->PushSelectableObject(fYaxis);
4960
4961 //This conditions is ALWAYS true on a platform, different from iOS (on iOS can be true, can be false).
4962 if (gPad->PadInSelectionMode() || !gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && gPad->GetSelected() == fYaxis)) {
4965
4966 chopt[0] = 0;
4967 strlcat(chopt, "SDH",10);
4968 if (ndivy < 0) strlcat(chopt, "N",10);
4969 if (gPad->GetGridy()) {
4970 gridl = (axmax-axmin)/(gPad->GetX2() - gPad->GetX1());
4971 strlcat(chopt, "W",10);
4972 }
4973
4974 // Define Y-Axis limits
4975 if (Hoption.Logy) {
4976 strlcat(chopt, "G",10);
4977 ndiv = TMath::Abs(ndivy);
4978 if (useHparam) {
4981 } else {
4982 umin = TMath::Power(10,aymin);
4983 umax = TMath::Power(10,aymax);
4984 }
4985 } else {
4986 ndiv = TMath::Abs(ndivy);
4987 if (useHparam) {
4988 umin = Hparam.ymin;
4989 umax = Hparam.ymax;
4990 } else {
4991 umin = aymin;
4992 umax = aymax;
4993 }
4994 }
4995
4996 // Display axis as time
4997 if (fYaxis->GetTimeDisplay()) {
4998 strlcat(chopt,"t",10);
4999 if (strlen(fYaxis->GetTimeFormatOnly()) == 0) {
5001 }
5002 }
5003
5004 // The main Y axis can be on the left or on the right of the pad
5006 if (yAxisPos == 1) {
5007 // Main Y axis left
5008 yAxisXPos1 = axmax;
5009 yAxisXPos2 = axmin;
5010 } else {
5011 // Main Y axis right
5012 yAxisXPos1 = axmin;
5013 yAxisXPos2 = axmax;
5014 }
5015
5016 // Paint the main Y axis (always)
5017 uminsave = umin;
5018 umaxsave = umax;
5019 ndivsave = ndiv;
5020 axis.SetOption(chopt);
5021 if (yAxisPos) {
5022 strlcat(chopt, "+L",10);
5023 gridl = -gridl;
5024 }
5025 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
5026 axis.SetLabelSize(0.);
5027 axis.SetTitle("");
5028 }
5031 umin, umax, ndiv, chopt, gridl, drawGridOnly);
5032
5033 // Paint the additional Y axis (if needed)
5034 // Additional checks for pad mode are required on iOS: this "second" axis is
5035 // neither pickable, nor highlighted. Additional checks have no effect on non-iOS platform.
5036 if (gPad->GetTicky() && !gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
5037 if (gPad->GetTicky() < 2) {
5038 strlcat(chopt, "U",10);
5040 } else {
5041 strlcat(chopt, "+L",10);
5042 }
5043 if ((cw=strstr(chopt,"W"))) *cw='z';
5044 axis.SetTitle("");
5048 }
5049 }//End of "if pad is in selection mode etc."
5050
5051 // Reset the axis if they have been inverted in case of option HBAR
5052 if (xaxis) {
5053 fXaxis = xaxis;
5054 fYaxis = yaxis;
5055 }
5056}
5057
5058////////////////////////////////////////////////////////////////////////////////
5059/// [Draw a bar-chart in a normal pad.](\ref HP10)
5060
5062{
5063
5064 Int_t bar = Hoption.Bar - 10;
5068 TBox box;
5070 if (hcolor == gPad->GetFrameFillColor()) ++hcolor;
5072 box.SetFillColor(hcolor);
5073 box.SetFillStyle(hstyle);
5074 box.SetLineStyle(fH->GetLineStyle());
5075 box.SetLineColor(fH->GetLineColor());
5076 box.SetLineWidth(fH->GetLineWidth());
5077 for (Int_t bin=fXaxis->GetFirst();bin<=fXaxis->GetLast();bin++) {
5078 y = fH->GetBinContent(bin);
5079 xmin = gPad->XtoPad(fXaxis->GetBinLowEdge(bin));
5080 xmax = gPad->XtoPad(fXaxis->GetBinUpEdge(bin));
5081 ymin = gPad->GetUymin();
5082 ymax = gPad->YtoPad(y);
5083 if (ymax < gPad->GetUymin()) continue;
5084 if (ymax > gPad->GetUymax()) ymax = gPad->GetUymax();
5085 if (ymin < gPad->GetUymin()) ymin = gPad->GetUymin();
5086 if (Hoption.MinimumZero && ymin < 0)
5087 ymin=TMath::Min(0.,gPad->GetUymax());
5088 w = (xmax-xmin)*width;
5089 xmin += offset*(xmax-xmin);
5090 xmax = xmin + w;
5091 if (bar < 1) {
5092 box.PaintBox(xmin,ymin,xmax,ymax);
5093 } else {
5094 umin = xmin + bar*(xmax-xmin)/10.;
5095 umax = xmax - bar*(xmax-xmin)/10.;
5096 box.SetFillColor(TColor::GetColorBright(hcolor)); //bright
5097 box.PaintBox(xmin,ymin,umin,ymax);
5098 box.SetFillColor(hcolor);
5099 box.PaintBox(umin,ymin,umax,ymax);
5100 box.SetFillColor(TColor::GetColorDark(hcolor)); //dark
5101 box.PaintBox(umax,ymin,xmax,ymax);
5102 }
5103 }
5104}
5105
5106////////////////////////////////////////////////////////////////////////////////
5107/// [Draw a bar char in a rotated pad (X vertical, Y horizontal)](\ref HP10)
5108
5110{
5111
5112 gPad->SetVertical(kFALSE);
5113
5114 PaintInitH();
5115
5116 TAxis *xaxis = fXaxis;
5117 TAxis *yaxis = fYaxis;
5118 if (!strcmp(xaxis->GetName(),"xaxis")) {
5119 fXaxis = yaxis;
5120 fYaxis = xaxis;
5121 }
5122
5123 PaintFrame();
5125
5126 Int_t bar = Hoption.Bar - 20;
5130 TBox box;
5132 if (hcolor == gPad->GetFrameFillColor()) ++hcolor;
5134 box.SetFillColor(hcolor);
5135 box.SetFillStyle(hstyle);
5136 box.SetLineStyle(fH->GetLineStyle());
5137 box.SetLineColor(fH->GetLineColor());
5138 box.SetLineWidth(fH->GetLineWidth());
5139 for (Int_t bin=fYaxis->GetFirst();bin<=fYaxis->GetLast();bin++) {
5140 ymin = gPad->YtoPad(fYaxis->GetBinLowEdge(bin));
5141 ymax = gPad->YtoPad(fYaxis->GetBinUpEdge(bin));
5142 xmin = gPad->GetUxmin();
5143 xmax = gPad->XtoPad(fH->GetBinContent(bin));
5144 if (xmax < gPad->GetUxmin()) continue;
5145 if (xmax > gPad->GetUxmax()) xmax = gPad->GetUxmax();
5146 if (xmin < gPad->GetUxmin()) xmin = gPad->GetUxmin();
5147 if (Hoption.MinimumZero && xmin < 0)
5148 xmin=TMath::Min(0.,gPad->GetUxmax());
5149 w = (ymax-ymin)*width;
5150 ymin += offset*(ymax-ymin);
5151 ymax = ymin + w;
5152 if (bar < 1) {
5153 box.PaintBox(xmin,ymin,xmax,ymax);
5154 } else {
5155 umin = ymin + bar*(ymax-ymin)/10.;
5156 umax = ymax - bar*(ymax-ymin)/10.;
5157 box.SetFillColor(TColor::GetColorDark(hcolor)); //dark
5158 box.PaintBox(xmin,ymin,xmax,umin);
5159 box.SetFillColor(hcolor);
5160 box.PaintBox(xmin,umin,xmax,umax);
5161 box.SetFillColor(TColor::GetColorBright(hcolor)); //bright
5162 box.PaintBox(xmin,umax,xmax,ymax);
5163 }
5164 }
5165
5166 PaintTitle();
5167
5168 // Draw box with histogram statistics and/or fit parameters
5169 if ((Hoption.Same%10) != 1 && !fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
5170 TIter next(fFunctions);
5171 TObject *obj = nullptr;
5172 while ((obj = next())) {
5173 if (obj->InheritsFrom(TF1::Class())) break;
5174 obj = nullptr;
5175 }
5176 PaintStat(gStyle->GetOptStat(),(TF1*)obj);
5177 }
5178
5179 fXaxis = xaxis;
5180 fYaxis = yaxis;
5181}
5182
5183////////////////////////////////////////////////////////////////////////////////
5184/// [Control function to draw a 2D histogram as a box plot](\ref HP13)
5185
5187{
5188
5191 if (fH->GetFillColor() == 0) fH->SetFillStyle(0);
5192 if (Hoption.Box == 11) fH->SetFillStyle(1001);
5193 fH->TAttLine::Modify();
5194 fH->TAttFill::Modify();
5195
5196 Double_t z, xk,xstep, yk, ystep, xcent, ycent, xlow, xup, ylow, yup;
5197 Double_t ux1 = gPad->PixeltoX(1);
5198 Double_t ux0 = gPad->PixeltoX(0);
5199 Double_t uy1 = gPad->PixeltoY(1);
5200 Double_t uy0 = gPad->PixeltoY(0);
5201 Double_t dxmin = 0.51*(gPad->PadtoX(ux1)-gPad->PadtoX(ux0));
5202 Double_t dymin = 0.51*(gPad->PadtoY(uy0)-gPad->PadtoY(uy1));
5203
5204 Double_t zmin = TMath::Max(fH->GetMinimum(),0.);
5207 Double_t zminlin = zmin, zmaxlin = zmax;
5208
5209 // In case of option SAME, zmin and zmax values are taken from the
5210 // first plotted 2D histogram.
5211 if (Hoption.Same > 0 && Hoption.Same < 10) {
5212 TH2 *h2;
5213 TIter next(gPad->GetListOfPrimitives());
5214 while ((h2 = (TH2 *)next())) {
5215 if (!h2->InheritsFrom(TH2::Class())) continue;
5216 zmin = TMath::Max(h2->GetMinimum(), 0.);
5217 zmax = TMath::Max(TMath::Abs(h2->GetMaximum()),
5218 TMath::Abs(h2->GetMinimum()));
5219 zminlin = zmin;
5220 zmaxlin = zmax;
5221 if (Hoption.Logz) {
5222 if (zmin <= 0) {
5223 zmin = TMath::Log10(zmax*0.001);
5224 } else {
5225 zmin = TMath::Log10(zmin);
5226 }
5227 zmax = TMath::Log10(zmax);
5228 }
5229 break;
5230 }
5231 } else {
5232 if (Hoption.Logz) {
5233 if (zmin > 0) {
5234 zmin = TMath::Log10(zmin);
5235 zmax = TMath::Log10(zmax);
5236 } else {
5237 return;
5238 }
5239 }
5240 }
5241
5242 Double_t zratio, dz = zmax - zmin;
5244 if (fH->GetMinimum()<0) kZminNeg = kTRUE;
5246
5247 // Define the dark and light colors the "button style" boxes.
5248 Color_t color = fH->GetFillColor();
5249 Color_t light=0, dark=0;
5250 if (Hoption.Box == 11) {
5252 dark = TColor::GetColorDark(color);
5253 }
5254
5255 // Loop over all the bins and draw the boxes
5256 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
5259 ycent = 0.5*ystep;
5260 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
5261 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
5262 xk = fXaxis->GetBinLowEdge(i);
5263 xstep = fXaxis->GetBinWidth(i);
5264 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
5265 xcent = 0.5*xstep;
5266 z = Hparam.factor*fH->GetBinContent(bin);
5267 kZNeg = kFALSE;
5268
5269 if (TMath::Abs(z) < zminlin) continue; // Can be the case with ...
5270 if (TMath::Abs(z) > zmaxlin) z = zmaxlin; // ... option Same
5271 if (kZminNeg && z==0) continue; // Do not draw empty bins if case of histo with negative bins.
5272
5273 if (z < 0) {
5274 if (Hoption.Logz) continue;
5275 z = -z;
5276 kZNeg = kTRUE;
5277 }
5278 if (Hoption.Logz) {
5279 if (z != 0) z = TMath::Log10(z);
5280 else z = zmin;
5281 }
5282
5283 if (dz == 0) continue;
5284 zratio = TMath::Sqrt((z-zmin)/dz);
5285 if (zratio == 0) continue;
5286
5287 xup = xcent*zratio + xk + xcent;
5288 xlow = 2*(xk + xcent) - xup;
5289 if (xup-xlow < dxmin) xup = xlow+dxmin;
5290 if (Hoption.Logx) {
5291 if (xup > 0) xup = TMath::Log10(xup);
5292 else continue;
5293 if (xlow > 0) xlow = TMath::Log10(xlow);
5294 else continue;
5295 }
5296
5297 yup = ycent*zratio + yk + ycent;
5298 ylow = 2*(yk + ycent) - yup;
5299 if (yup-ylow < dymin) yup = ylow+dymin;
5300 if (Hoption.Logy) {
5301 if (yup > 0) yup = TMath::Log10(yup);
5302 else continue;
5303 if (ylow > 0) ylow = TMath::Log10(ylow);
5304 else continue;
5305 }
5306
5307 xlow = TMath::Max(xlow, gPad->GetUxmin());
5308 ylow = TMath::Max(ylow, gPad->GetUymin());
5309 xup = TMath::Min(xup , gPad->GetUxmax());
5310 yup = TMath::Min(yup , gPad->GetUymax());
5311
5312 if (xlow >= xup) continue;
5313 if (ylow >= yup) continue;
5314
5315 if (Hoption.Box == 1) {
5316 fH->SetFillColor(color);
5317 fH->TAttFill::Modify();
5318 gPad->PaintBox(xlow, ylow, xup, yup);
5319 if (kZNeg) {
5320 gPad->PaintLine(xlow, ylow, xup, yup);
5321 gPad->PaintLine(xlow, yup, xup, ylow);
5322 }
5323 } else if (Hoption.Box == 11) {
5324 // Draw the center of the box
5325 fH->SetFillColor(color);
5326 fH->TAttFill::Modify();
5327 gPad->PaintBox(xlow, ylow, xup, yup);
5328
5329 // Draw top&left part of the box
5330 Double_t x[7], y[7];
5331 Double_t bwidth = 0.1;
5332 x[0] = xlow; y[0] = ylow;
5333 x[1] = xlow + bwidth*(xup-xlow); y[1] = ylow + bwidth*(yup-ylow);
5334 x[2] = x[1]; y[2] = yup - bwidth*(yup-ylow);
5335 x[3] = xup - bwidth*(xup-xlow); y[3] = y[2];
5336 x[4] = xup; y[4] = yup;
5337 x[5] = xlow; y[5] = yup;
5338 x[6] = xlow; y[6] = ylow;
5339 if (kZNeg) fH->SetFillColor(dark);
5340 else fH->SetFillColor(light);
5341 fH->TAttFill::Modify();
5342 gPad->PaintFillArea(7, x, y);
5343
5344 // Draw bottom&right part of the box
5345 x[0] = xlow; y[0] = ylow;
5346 x[1] = xlow + bwidth*(xup-xlow); y[1] = ylow + bwidth*(yup-ylow);
5347 x[2] = xup - bwidth*(xup-xlow); y[2] = y[1];
5348 x[3] = x[2]; y[3] = yup - bwidth*(yup-ylow);
5349 x[4] = xup; y[4] = yup;
5350 x[5] = xup; y[5] = ylow;
5351 x[6] = xlow; y[6] = ylow;
5352 if (kZNeg) fH->SetFillColor(light);
5353 else fH->SetFillColor(dark);
5354 fH->TAttFill::Modify();
5355 gPad->PaintFillArea(7, x, y);
5356 }
5357 }
5358 }
5359
5363 fH->TAttFill::Modify();
5364}
5365
5366
5367
5368////////////////////////////////////////////////////////////////////////////////
5369/// [Control function to draw a 2D histogram as a candle (box) plot or violin plot](\ref HP14)
5370
5372{
5373 TH1D *hproj = nullptr;
5374 TH2D *h2 = (TH2D*)fH;
5375
5378 myCandle.SetMarkerColor(fH->GetLineColor());
5379 myCandle.SetLineColor(fH->GetLineColor());
5380 myCandle.SetLineWidth(fH->GetLineWidth());
5381 myCandle.SetFillColor(fH->GetFillColor());
5382 myCandle.SetFillStyle(fH->GetFillStyle());
5383 myCandle.SetMarkerSize(fH->GetMarkerSize());
5384 myCandle.SetMarkerStyle(fH->GetMarkerStyle());
5386
5387 Bool_t swapXY = myCandle.IsHorizontal();
5388 const Double_t standardCandleWidth = 0.66;
5389 const Double_t standardHistoWidth = 0.8;
5390
5391 double allMaxContent = 0, allMaxIntegral = 0;
5392 if (myCandle.IsViolinScaled())
5393 allMaxContent = h2->GetBinContent(h2->GetMaximumBin());
5394
5395 if (!swapXY) { // Vertical candle
5396 //Determining the slice with the maximum integral - if necessary
5397 if (myCandle.IsCandleScaled())
5398 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast; i++) {
5399 hproj = h2->ProjectionY("_px", i, i);
5400 if (hproj->Integral() > allMaxIntegral) allMaxIntegral = hproj->Integral();
5401 }
5402 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast; i++) {
5404 Double_t binWidth = fXaxis->GetBinWidth(i);
5405 hproj = h2->ProjectionY("_px", i, i);
5406 if (hproj->GetEntries() != 0) {
5408 Double_t offset = fH->GetBarOffset()*binWidth;
5409 double myMaxContent = hproj->GetBinContent(hproj->GetMaximumBin());
5410 double myIntegral = hproj->Integral();
5412 if (candleWidth > 0.999 && candleWidth < 1.001) {
5415 }
5416 if (Hoption.Logz && myMaxContent > 0) {
5418 if (myCandle.IsViolinScaled() && myMaxContent > 0 && allMaxContent > 0)
5420 } else if (myCandle.IsViolinScaled() && (allMaxContent > 0))
5422 if (myCandle.IsCandleScaled() && (allMaxIntegral > 0))
5424
5425 myCandle.SetAxisPosition(binPosX+binWidth/2. + offset);
5426 myCandle.SetCandleWidth(candleWidth*binWidth);
5427 myCandle.SetHistoWidth(histoWidth*binWidth);
5428 myCandle.SetHistogram(hproj);
5429 myCandle.Paint();
5430 }
5431 }
5432 } else { // Horizontal candle
5433 //Determining the slice with the maximum integral - if necessary
5434 if (myCandle.IsCandleScaled())
5435 for (Int_t i=Hparam.yfirst; i<=Hparam.ylast; i++) {
5436 hproj = h2->ProjectionX("_py", i, i);
5437 if (hproj->Integral() > allMaxIntegral) allMaxIntegral = hproj->Integral();
5438 }
5439 for (Int_t i=Hparam.yfirst; i<=Hparam.ylast; i++) {
5441 Double_t binWidth = fYaxis->GetBinWidth(i);
5442 hproj = h2->ProjectionX("_py", i, i);
5443 if (hproj->GetEntries() != 0) {
5445 Double_t offset = fH->GetBarOffset()*binWidth;
5446 double myMaxContent = hproj->GetBinContent(hproj->GetMaximumBin());
5447 double myIntegral = hproj->Integral();
5449 if (candleWidth > 0.999 && candleWidth < 1.001) {
5452 }
5453 if (Hoption.Logz && myMaxContent > 0) {
5455 if (myCandle.IsViolinScaled() && myMaxContent > 0 && allMaxContent > 0)
5457 } else if (myCandle.IsViolinScaled() && (allMaxContent > 0))
5459 if (myCandle.IsCandleScaled() && (allMaxIntegral > 0))
5461
5462 myCandle.SetAxisPosition(binPosY+binWidth/2. + offset);
5463 myCandle.SetCandleWidth(candleWidth*binWidth);
5464 myCandle.SetHistoWidth(histoWidth*binWidth);
5465 myCandle.SetHistogram(hproj);
5466 myCandle.Paint();
5467 }
5468 }
5469 }
5470 delete hproj;
5471}
5472
5473
5474
5475////////////////////////////////////////////////////////////////////////////////
5476/// Returns the rendering regions for an axis to use in the COL2 option
5477///
5478/// The algorithm analyses the size of the axis compared to the size of
5479/// the rendering region. It figures out the boundaries to use for each color
5480/// of the rendering region. Only one axis is computed here.
5481///
5482/// This allows for a single computation of the boundaries before iterating
5483/// through all of the bins.
5484///
5485/// \param pAxis the axis to consider
5486/// \param nPixels the number of pixels to render axis into
5487/// \param isLog whether the axis is log scale
5488
5489std::vector<THistRenderingRegion>
5491{
5492 std::vector<THistRenderingRegion> regions;
5493
5494 enum STRATEGY { Bins, Pixels } strategy;
5495
5496 Int_t nBins = (pAxis->GetLast() - pAxis->GetFirst() + 1);
5497
5498 if (nBins >= nPixels) {
5499 // more bins than pixels... we should loop over pixels and sample
5500 strategy = Pixels;
5501 } else {
5502 // fewer bins than pixels... we should loop over bins
5503 strategy = Bins;
5504 }
5505
5506 if (isLog) {
5507
5508 Double_t xMin = pAxis->GetBinLowEdge(pAxis->GetFirst());
5509 Int_t binOffset=0;
5510 while (xMin <= 0 && ((pAxis->GetFirst()+binOffset) != pAxis->GetLast()) ) {
5511 binOffset++;
5512 xMin = pAxis->GetBinLowEdge(pAxis->GetFirst()+binOffset);
5513 }
5514 if (xMin <= 0) {
5515 // this should cause an error if we have
5516 return regions;
5517 }
5518 Double_t xMax = pAxis->GetBinUpEdge(pAxis->GetLast());
5519
5520 if (strategy == Bins) {
5521 // logarithmic plot. we find the pixel for the bin
5522 // pixel = eta * log10(V) - alpha
5523 // where eta = nPixels/(log10(Vmax)-log10(Vmin))
5524 // and alpha = nPixels*log10(Vmin)/(log10(Vmax)-log10(Vmin))
5525 // and V is axis value
5527 Double_t offset = -1.0 * eta * TMath::Log10(xMin);
5528
5529 for (Int_t bin=pAxis->GetFirst()+binOffset; bin<=pAxis->GetLast(); bin++) {
5530
5531 // linear plot. we simply need to find the appropriate bin
5532 // for the
5533 Double_t xLowValue = pAxis->GetBinLowEdge(bin);
5534 Double_t xUpValue = pAxis->GetBinUpEdge(bin);
5537 THistRenderingRegion region = {std::make_pair(xPx0, xPx1),
5538 std::make_pair(bin, bin+1)};
5539 regions.push_back(region);
5540 }
5541
5542 } else {
5543
5544 // loop over pixels
5545
5547
5548 for (Int_t pixelIndex=0; pixelIndex<(nPixels-1); pixelIndex++) {
5549 // linear plot
5550 Int_t binLow = pAxis->FindBin(xMin*TMath::Power(10.0, beta*pixelIndex));
5551 Int_t binHigh = pAxis->FindBin(xMin*TMath::Power(10.0, beta*(pixelIndex+1)));
5552 THistRenderingRegion region = { std::make_pair(pixelIndex, pixelIndex+1),
5553 std::make_pair(binLow, binHigh)};
5554 regions.push_back(region);
5555 }
5556 }
5557 } else {
5558 // standard linear plot
5559
5560 if (strategy == Bins) {
5561 // loop over bins
5562 for (Int_t bin=pAxis->GetFirst(); bin<=pAxis->GetLast(); bin++) {
5563
5564 // linear plot. we simply need to find the appropriate bin
5565 // for the
5566 Int_t xPx0 = ((bin - pAxis->GetFirst()) * nPixels)/nBins;
5567 Int_t xPx1 = xPx0 + nPixels/nBins;
5568
5569 // make sure we don't compute beyond our bounds
5570 if (xPx1>= nPixels) xPx1 = nPixels-1;
5571
5572 THistRenderingRegion region = {std::make_pair(xPx0, xPx1),
5573 std::make_pair(bin, bin+1)};
5574 regions.push_back(region);
5575 }
5576 } else {
5577 // loop over pixels
5579 // linear plot
5580 Int_t binLow = (nBins*pixelIndex)/nPixels + pAxis->GetFirst();
5581 Int_t binHigh = binLow + nBins/nPixels;
5582 THistRenderingRegion region = { std::make_pair(pixelIndex, pixelIndex+1),
5583 std::make_pair(binLow, binHigh)};
5584 regions.push_back(region);
5585 }
5586 }
5587 }
5588
5589 return regions;
5590}
5591
5592////////////////////////////////////////////////////////////////////////////////
5593/// [Rendering scheme for the COL2 and COLZ2 options] (\ref HP14)
5594
5596{
5597
5598 if (Hoption.System != kCARTESIAN) {
5599 Error("THistPainter::PaintColorLevelsFast(Option_t*)",
5600 "Only cartesian coordinates supported by 'COL2' option. Using 'COL' option instead.");
5601 PaintColorLevels(nullptr);
5602 return;
5603 }
5604
5605 Double_t z;
5606
5607 // Use existing max or min values. If either is already set
5608 // the appropriate value to use.
5609 Double_t zmin = fH->GetMinimumStored();
5610 Double_t zmax = fH->GetMaximumStored();
5611 Double_t originalZMin = zmin;
5612 Double_t originalZMax = zmax;
5613 if ((zmin == -1111) && (zmax == -1111)) {
5614 fH->GetMinimumAndMaximum(zmin, zmax);
5615 fH->SetMinimum(zmin);
5616 fH->SetMaximum(zmax);
5617 } else if (zmin == -1111) {
5618 zmin = fH->GetMinimum();
5619 fH->SetMinimum(zmin);
5620 } else if (zmax == -1111) {
5621 zmax = fH->GetMaximum();
5622 fH->SetMaximum(zmax);
5623 }
5624
5625 Double_t dz = zmax - zmin;
5626 if (dz <= 0) { // Histogram filled with a constant value
5627 zmax += 0.1*TMath::Abs(zmax);
5628 zmin -= 0.1*TMath::Abs(zmin);
5629 dz = zmax - zmin;
5630 }
5631
5632 if (Hoption.Logz) {
5633 if (zmin > 0) {
5634 zmin = TMath::Log10(zmin);
5635 zmax = TMath::Log10(zmax);
5636 dz = zmax - zmin;
5637 } else {
5638 Error("THistPainter::PaintColorLevelsFast(Option_t*)",
5639 "Cannot plot logz because bin content is less than 0.");
5640 return;
5641 }
5642 }
5643
5644 // Initialize the levels on the Z axis
5645 Int_t ndiv = fH->GetContour();
5646 if (ndiv == 0 ) {
5647 ndiv = gStyle->GetNumberContours();
5648 fH->SetContour(ndiv);
5649 }
5650 std::vector<Double_t> colorBounds(ndiv);
5651 std::vector<Double_t> contours(ndiv, 0);
5652 if (!fH->TestBit(TH1::kUserContour)) {
5653 fH->SetContour(ndiv);
5654 } else {
5655 fH->GetContour(contours.data());
5656 }
5657
5658 Double_t step = 1.0/ndiv;
5659 for (Int_t i=0; i<ndiv; ++i) {
5660 colorBounds[i] = step*i;
5661 }
5662
5663 auto pFrame = gPad->GetFrame();
5664 Int_t px0 = gPad->XtoPixel(pFrame->GetX1());
5665 Int_t px1 = gPad->XtoPixel(pFrame->GetX2());
5666 Int_t py0 = gPad->YtoPixel(pFrame->GetY1());
5667 Int_t py1 = gPad->YtoPixel(pFrame->GetY2());
5668 Int_t nXPixels = px1-px0;
5669 Int_t nYPixels = py0-py1; // y=0 is at the top of the screen
5670
5671 std::vector<Double_t> buffer(nXPixels*nYPixels, 0);
5672
5675 if (xRegions.empty() || yRegions.empty()) {
5676 Error("THistPainter::PaintColorLevelFast(Option_t*)",
5677 "Encountered error while computing rendering regions.");
5678 return;
5679 }
5680
5683 Double_t minValue = 1.;
5684 Double_t maxValue = 0.;
5685 for (auto& yRegion : yRegions) {
5686 for (auto& xRegion : xRegions ) {
5687
5688 const auto& xBinRange = xRegion.fBinRange;
5689 const auto& yBinRange = yRegion.fBinRange;
5690
5691 // sample the range
5692 z = fH->GetBinContent(xBinRange.second-1, yBinRange.second-1);
5693
5694 if (Hoption.Logz) {
5695 if (z > 0) z = TMath::Log10(z);
5696 else z = zmin;
5697 }
5698
5699 // obey the user's max and min values if they were set
5700 if (z > zmax) z = zmax;
5701 if (z < zmin) z = zmin;
5702
5704 // contours are absolute values
5705 auto index = TMath::BinarySearch(contours.size(), contours.data(), z);
5706 z = colorBounds[index];
5707 } else {
5708 Int_t index = 0;
5709 if (dz != 0) {
5710 index = 0.001 + ((z - zmin)/dz)*ndiv;
5711 }
5712
5713 if (index == static_cast<Int_t>(colorBounds.size())) {
5714 index--;
5715 }
5716
5717 // Do a little bookkeeping to use later for getting libAfterImage to produce
5718 // the correct colors
5719 if (index == 0) {
5720 minExists = kTRUE;
5721 } else if (index == static_cast<Int_t>(colorBounds.size()-1)) {
5722 maxExists = kTRUE;
5723 }
5724
5725 z = colorBounds[index];
5726
5727 if (z < minValue) {
5728 minValue = z;
5729 }
5730 if (z > maxValue) {
5731 maxValue = z;
5732 }
5733 }
5734
5735 // fill in the actual pixels
5736 const auto& xPixelRange = xRegion.fPixelRange;
5737 const auto& yPixelRange = yRegion.fPixelRange;
5738 for (Int_t xPx = xPixelRange.first; xPx <= xPixelRange.second; ++xPx) {
5739 for (Int_t yPx = yPixelRange.first; yPx <= yPixelRange.second; ++yPx) {
5741 buffer[pixel] = z;
5742 }
5743 }
5744 } // end px loop
5745 } // end py loop
5746
5747 // This is a bit of a hack to ensure that we span the entire color range and
5748 // don't screw up the colors for a sparse histogram. No one will notice that I set a
5749 // single pixel on the edge of the image to a different color. This is even more
5750 // true because the chosen pixels will be covered by the axis.
5751 if (minValue != maxValue) {
5752 if ( !minExists) {
5753 buffer.front() = 0;
5754 }
5755
5756 if ( !maxExists) {
5757 buffer[buffer.size()-nXPixels] = 0.95;
5758 }
5759 }
5760
5761 // Generate the TImage
5764 pImage->SetImageQuality(TAttImage::kImgBest);
5765 pImage->SetImage(buffer.data(), nXPixels, nYPixels, pPalette);
5766 delete pPalette;
5767
5768 Window_t wid = static_cast<Window_t>(gVirtualX->GetWindowID(gPad->GetPixmapID()));
5769 pImage->PaintImage(wid, px0, py1, 0, 0, nXPixels, nYPixels);
5770 delete pImage;
5771
5773
5774 // Reset the maximum and minimum values to their original values
5775 // when this function was called. If we don't do this, an initial
5776 // value of -1111 will be replaced with the true max or min values.
5779}
5780
5781////////////////////////////////////////////////////////////////////////////////
5782/// [Control function to draw a 2D histogram as a color plot.](\ref HP14)
5783
5785{
5786 Double_t z, e, zc, xk, xstep, yk, ystep, xlow, xup, ylow, yup;
5787
5788 Double_t zmin = fH->GetMinimum();
5789 Double_t zmax = fH->GetMaximum();
5790
5791 Double_t dz = zmax - zmin;
5792 if (dz <= 0) { // Histogram filled with a constant value
5793 zmax += 0.1*TMath::Abs(zmax);
5794 zmin -= 0.1*TMath::Abs(zmin);
5795 dz = zmax - zmin;
5796 }
5797
5798 // In case of option SAME, zmin and zmax values are taken from the
5799 // first plotted 2D histogram.
5800 if (Hoption.Same > 0 && Hoption.Same < 10) {
5801 TH2 *h2;
5802 TIter next(gPad->GetListOfPrimitives());
5803 while ((h2 = (TH2 *)next())) {
5804 if (!h2->InheritsFrom(TH2::Class())) continue;
5805 zmin = h2->GetMinimum();
5806 zmax = h2->GetMaximum();
5807 fH->SetMinimum(zmin);
5808 fH->SetMaximum(zmax);
5809 if (Hoption.Logz) {
5810 if (zmin <= 0) {
5811 zmin = TMath::Log10(zmax*0.001);
5812 } else {
5813 zmin = TMath::Log10(zmin);
5814 }
5815 zmax = TMath::Log10(zmax);
5816 }
5817 dz = zmax - zmin;
5818 break;
5819 }
5820 } else {
5821 if (Hoption.Logz) {
5822 if (zmin > 0) {
5823 zmin = TMath::Log10(zmin);
5824 zmax = TMath::Log10(zmax);
5825 dz = zmax - zmin;
5826 } else {
5827 return;
5828 }
5829 }
5830 }
5831
5834 fH->SetFillStyle(1001);
5835 fH->TAttFill::Modify();
5836
5837 // Initialize the levels on the Z axis
5838 Int_t ncolors = gStyle->GetNumberOfColors();
5839 Int_t ndiv = fH->GetContour();
5840 if (ndiv == 0 ) {
5841 ndiv = gStyle->GetNumberContours();
5842 fH->SetContour(ndiv);
5843 }
5844 Int_t ndivz = TMath::Abs(ndiv);
5845 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
5846 Double_t scale = (dz ? ndivz / dz : 1.0);
5847
5848 Int_t color;
5849 TProfile2D* prof2d = dynamic_cast<TProfile2D*>(fH);
5850 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
5853 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
5854 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
5855 xk = fXaxis->GetBinLowEdge(i);
5856 xstep = fXaxis->GetBinWidth(i);
5857 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
5858 z = fH->GetBinContent(bin);
5859 e = fH->GetBinError(bin);
5860 // if fH is a profile histogram do not draw empty bins
5861 if (prof2d) {
5862 const Double_t binEntries = prof2d->GetBinEntries(bin);
5863 if (binEntries == 0)
5864 continue;
5865 } else {
5866 // don't draw the empty bins for non-profile histograms
5867 // with positive content
5868 if (z == 0 && e == 0) {
5869 if (zmin >= 0 || Hoption.Logz) continue;
5870 if (Hoption.Color == 2) continue;
5871 }
5872 }
5873
5874 if (Hoption.Logz) {
5875 if (z > 0) z = TMath::Log10(z);
5876 else z = zmin;
5877 }
5878 if (z < zmin && !Hoption.Zero) continue;
5879 xup = xk + xstep;
5880 xlow = xk;
5881 if (Hoption.Logx) {
5882 if (xup > 0) xup = TMath::Log10(xup);
5883 else continue;
5884 if (xlow > 0) xlow = TMath::Log10(xlow);
5885 else continue;
5886 }
5887 yup = yk + ystep;
5888 ylow = yk;
5889 if (Hoption.Logy) {
5890 if (yup > 0) yup = TMath::Log10(yup);
5891 else continue;
5892 if (ylow > 0) ylow = TMath::Log10(ylow);
5893 else continue;
5894 }
5895 if (xup < gPad->GetUxmin()) continue;
5896 if (yup < gPad->GetUymin()) continue;
5897 if (xlow > gPad->GetUxmax()) continue;
5898 if (ylow > gPad->GetUymax()) continue;
5899 if (xlow < gPad->GetUxmin()) xlow = gPad->GetUxmin();
5900 if (ylow < gPad->GetUymin()) ylow = gPad->GetUymin();
5901 if (xup > gPad->GetUxmax()) xup = gPad->GetUxmax();
5902 if (yup > gPad->GetUymax()) yup = gPad->GetUymax();
5903
5905 zc = fH->GetContourLevelPad(0);
5906 if (z < zc) continue;
5907 color = -1;
5908 for (Int_t k=0; k<ndiv; k++) {
5909 zc = fH->GetContourLevelPad(k);
5910 if (z < zc) {
5911 continue;
5912 } else {
5913 color++;
5914 }
5915 }
5916 } else {
5917 color = Hoption.Zero ? Int_t(0.01+(std::max(z, zmin)-zmin)*scale) : Int_t(0.01+(z-zmin)*scale);
5918 }
5919
5920 Int_t theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
5921 if (theColor > ncolors-1) theColor = ncolors-1;
5923 if (Hoption.System != kPOLAR) {
5925 fH->TAttFill::Modify();
5926 gPad->PaintBox(xlow, ylow, xup, yup);
5927 } else {
5928 Double_t midx = (gPad->GetUxmin() + gPad->GetUxmax()) / 2,
5929 midy = (gPad->GetUymin() + gPad->GetUymax()) / 2,
5930 a1 = (xlow - gPad->GetUxmin()) / (gPad->GetUxmax() - gPad->GetUxmin()) * 360,
5931 a2 = (xup - gPad->GetUxmin()) / (gPad->GetUxmax() - gPad->GetUxmin()) * 360,
5932 rx = gPad->GetUxmax() - gPad->GetUxmin(),
5933 ry = gPad->GetUymax() - gPad->GetUymin(),
5934 r1 = (ylow - gPad->GetUymin()) / (gPad->GetUymax() - gPad->GetUymin()) * rx / 2,
5935 r2 = (yup - gPad->GetUymin()) / (gPad->GetUymax() - gPad->GetUymin()) * rx / 2;
5936
5937 TCrown crown(midx, midy, r1, r2, a1, a2);
5938 crown.SetYXRatio(rx > 0 ? ry / rx : 1);
5939 crown.SetFillColor(fillColor);
5940 crown.SetLineColor(fH->GetLineColor());
5941 crown.SetLineWidth(fH->GetLineWidth());
5942 crown.SetLineStyle(fH->GetLineStyle());
5943 crown.Paint();
5944 }
5945 }
5946 }
5947
5949
5952 fH->TAttFill::Modify();
5953
5954}
5955
5956////////////////////////////////////////////////////////////////////////////////
5957/// [Control function to draw a 2D histogram as a contour plot.](\ref HP16)
5958
5960{
5961
5962 Int_t i, j, count, ncontour, icol, n, lj, m, ix, jx, ljfill;
5963 Int_t itars, mode, ir[4];
5964 Double_t xsave, ysave, thesave,phisave,x[4], y[4], zc[4];
5965
5966 if (Hoption.Contour == 14) {
5967 Hoption.Surf = 12;
5968 Hoption.Axis = 1;
5969 thesave = gPad->GetTheta();
5970 phisave = gPad->GetPhi();
5971 gPad->SetPhi(0.);
5972 gPad->SetTheta(90.);
5974 gPad->SetPhi(phisave);
5975 gPad->SetTheta(thesave);
5976 TView *view = gPad->GetView();
5977 if (view) view->SetBit(kCannotRotate); //tested in ExecuteEvent
5978 PaintAxis();
5979 return;
5980 }
5981
5982 if (Hoption.Same) {
5983 // If the contour is painted on a 3d plot, the contour lines are
5984 // paint in 3d too.
5985 TObject *obj;
5986 TIter next(gPad->GetListOfPrimitives());
5987 while ((obj=next())) {
5988 if (strstr(obj->GetDrawOption(),"surf") ||
5989 strstr(obj->GetDrawOption(),"lego") ||
5990 strstr(obj->GetDrawOption(),"tri")) {
5991 Hoption.Surf = 16;
5993 return;
5994 }
5995 }
5996 }
5997
5998 if (Hoption.Contour == 15) {
5999 TGraphDelaunay2D *dt = nullptr;
6000 TGraphDelaunay *dtOld = nullptr;
6002 dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
6003 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
6004 if (!dt && !dtOld) return;
6005 if (!fGraph2DPainter)
6006 fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
6007 fGraph2DPainter->Paint(option);
6008 return;
6009 }
6010
6011 gPad->SetBit(TGraph::kClipFrame);
6012
6013 std::vector<Double_t> levels(2*kMAXCONTOUR);
6014 std::vector<Double_t> xarr(2*kMAXCONTOUR);
6015 std::vector<Double_t> yarr(2*kMAXCONTOUR);
6016 std::vector<Int_t> itarr(2*kMAXCONTOUR);
6017
6018 Int_t npmax = 0;
6019 for (i=0;i<2*kMAXCONTOUR;i++) itarr[i] = 0;
6020
6021 ncontour = fH->GetContour();
6022 if (ncontour == 0) {
6025 }
6026 if (ncontour > kMAXCONTOUR) {
6027 Warning("PaintContour", "maximum number of contours is %d, asked for %d",
6030 }
6032
6033 for (i=0;i<ncontour;i++) levels[i] = fH->GetContourLevelPad(i);
6037 if (Hoption.Contour == 13) {
6038 fH->TAttLine::Modify();
6039 }
6040
6041 std::vector<std::unique_ptr<TPolyLine>> polys;
6042 TObjArray *contours = nullptr;
6043 TList *list = nullptr;
6044 TGraph *graph = nullptr;
6045 std::vector<Int_t> np;
6046 if (Hoption.Contour == 1 || (Hoption.List && (Hoption.Contour == 11 || Hoption.Contour == 12 || Hoption.Contour == 13))) {
6047 np.resize(ncontour);
6048 for (i=0;i<ncontour;i++)
6049 np[i] = 0;
6050 for (i=0;i<ncontour;i++)
6051 polys.emplace_back(std::make_unique<TPolyLine>(100));
6052 if (Hoption.List == 1) {
6053 contours = (TObjArray*)gROOT->GetListOfSpecials()->FindObject("contours");
6054 if (contours) {
6055 gROOT->GetListOfSpecials()->Remove(contours);
6056 count = contours->GetSize();
6057 for (i=0;i<count;i++) {
6058 list = (TList*)contours->At(i);
6059 if (list) list->Delete();
6060 }
6061 contours->Delete();
6062 delete contours;
6063 }
6065 contours->SetName("contours");
6066 gROOT->GetListOfSpecials()->Add(contours);
6067 for (i=0;i<ncontour;i++) {
6068 list = new TList();
6069 contours->Add(list);
6070 }
6071 }
6072 }
6074 Int_t ncolors = gStyle->GetNumberOfColors();
6076
6077 Int_t k,ipoly;
6078 for (j=Hparam.yfirst; j<Hparam.ylast; j++) {
6079 y[0] = fYaxis->GetBinCenter(j);
6080 y[1] = y[0];
6081 y[2] = fYaxis->GetBinCenter(j+1);
6082 y[3] = y[2];
6083 for (i=Hparam.xfirst; i<Hparam.xlast; i++) {
6084 zc[0] = fH->GetBinContent(i, j);
6085 zc[1] = fH->GetBinContent(i+1, j);
6086 zc[2] = fH->GetBinContent(i+1, j+1);
6087 zc[3] = fH->GetBinContent(i, j+1);
6088 if (!IsInside(fXaxis->GetBinCenter(i),fYaxis->GetBinCenter(j))) continue;
6089 if (Hoption.Logz) {
6090 if (zc[0] > 0) zc[0] = TMath::Log10(zc[0]);
6091 else zc[0] = Hparam.zmin;
6092 if (zc[1] > 0) zc[1] = TMath::Log10(zc[1]);
6093 else zc[1] = Hparam.zmin;
6094 if (zc[2] > 0) zc[2] = TMath::Log10(zc[2]);
6095 else zc[2] = Hparam.zmin;
6096 if (zc[3] > 0) zc[3] = TMath::Log10(zc[3]);
6097 else zc[3] = Hparam.zmin;
6098 }
6099 for (k=0;k<4;k++) {
6100 ir[k] = TMath::BinarySearch(ncontour, levels.data(), zc[k]);
6101 }
6102 if (ir[0] != ir[1] || ir[1] != ir[2] || ir[2] != ir[3] || ir[3] != ir[0]) {
6103 x[0] = fXaxis->GetBinCenter(i);
6104 x[3] = x[0];
6105 x[1] = fXaxis->GetBinCenter(i+1);
6106 x[2] = x[1];
6107 if (zc[0] <= zc[1]) n = 0; else n = 1;
6108 if (zc[2] <= zc[3]) m = 2; else m = 3;
6109 if (zc[n] > zc[m]) n = m;
6110 n++;
6111 lj=1;
6112 for (ix=1;ix<=4;ix++) {
6113 m = n%4 + 1;
6114 ljfill = PaintContourLine(zc[n-1],ir[n-1],x[n-1],y[n-1],zc[m-1],
6115 ir[m-1],x[m-1],y[m-1], xarr.data()+lj-1,yarr.data()+lj-1,itarr.data()+lj-1, levels.data());
6116 lj += 2*ljfill;
6117 n = m;
6118 }
6119
6120 if (zc[0] <= zc[1]) n = 0; else n = 1;
6121 if (zc[2] <= zc[3]) m = 2; else m = 3;
6122 if (zc[n] > zc[m]) n = m;
6123 n++;
6124 lj=2;
6125 for (ix=1;ix<=4;ix++) {
6126 if (n == 1) m = 4;
6127 else m = n-1;
6128 ljfill = PaintContourLine(zc[n-1],ir[n-1],x[n-1],y[n-1],zc[m-1],
6129 ir[m-1],x[m-1],y[m-1],xarr.data()+lj-1,yarr.data()+lj-1,itarr.data()+lj-1, levels.data());
6130 lj += 2*ljfill;
6131 n = m;
6132 }
6133
6134 // Re-order endpoints
6135
6136 count = 0;
6137 for (ix=1; ix<=lj-5; ix +=2) {
6138 //count = 0;
6139 while (itarr[ix-1] != itarr[ix]) {
6140 xsave = xarr[ix];
6141 ysave = yarr[ix];
6142 itars = itarr[ix];
6143 for (jx=ix; jx<=lj-5; jx +=2) {
6144 xarr[jx] = xarr[jx+2];
6145 yarr[jx] = yarr[jx+2];
6146 itarr[jx] = itarr[jx+2];
6147 }
6148 xarr[lj-3] = xsave;
6149 yarr[lj-3] = ysave;
6150 itarr[lj-3] = itars;
6151 if (count > 100) break;
6152 count++;
6153 }
6154 }
6155
6156 if (count > 100) continue;
6157 for (ix=1; ix<=lj-2; ix +=2) {
6158 theColor = Int_t((itarr[ix-1]+0.99)*Float_t(ncolors)/Float_t(ndivz));
6160 if (Hoption.Contour == 11) {
6162 }
6163 if (Hoption.Contour == 12) {
6164 mode = icol%5;
6165 if (mode == 0) mode = 5;
6167 }
6168 if (Hoption.Contour != 1) {
6169 fH->TAttLine::Modify();
6170 gPad->PaintPolyLine(2,xarr.data()+ix-1,yarr.data()+ix-1);
6171 if ((Hoption.Contour != 11 && Hoption.Contour != 12 && Hoption.Contour != 13) || !Hoption.List)
6172 continue;
6173 }
6174
6175 ipoly = itarr[ix-1];
6176 if (ipoly >=0 && ipoly <ncontour) {
6177 polys[ipoly]->SetPoint(np[ipoly] ,xarr[ix-1],yarr[ix-1]);
6178 polys[ipoly]->SetPoint(np[ipoly]+1,xarr[ix], yarr[ix]);
6179 np[ipoly] += 2;
6180 if (npmax < np[ipoly]) npmax = np[ipoly];
6181 }
6182 }
6183 } // end of if (ir[0]
6184 } //end of for (i
6185 } //end of for (j
6186
6188 std::vector<Double_t> xp, yp;
6190 Int_t istart;
6191 Int_t first = ncontour;
6192 std::vector<Int_t> polysort;
6194 if (Hoption.Contour != 1) {
6195 if (!Hoption.List || (Hoption.Contour != 11 && Hoption.Contour != 12 && Hoption.Contour != 13))
6196 goto theEND;
6197 }
6198
6199 //The 2 points line generated above are now sorted/merged to generate
6200 //a list of consecutive points.
6201 // If the option "List" has been specified, the list of points is saved
6202 // in the form of TGraph objects in the ROOT list of special objects.
6203 xmin = gPad->GetUxmin();
6204 ymin = gPad->GetUymin();
6205 xp.resize(2*npmax);
6206 yp.resize(2*npmax);
6207 polysort.resize(ncontour);
6208 //find first positive contour
6209 for (ipoly=0;ipoly<ncontour;ipoly++) {
6210 if (levels[ipoly] >= 0) {first = ipoly; break;}
6211 }
6212 //store negative contours from 0 to minimum, then all positive contours
6213 k = 0;
6214 for (ipoly=first-1;ipoly>=0;ipoly--) {polysort[k] = ipoly; k++;}
6215 for (ipoly=first;ipoly<ncontour;ipoly++) {polysort[k] = ipoly; k++;}
6216 // if Contour==1 we can now draw sorted contours, otherwise (11,12,13) just store
6217 contListNb = 0;
6218 if (Hoption.Contour == 1) fH->SetFillStyle(1001);
6219 for (k=0;k<ncontour;k++) {
6220 ipoly = polysort[k];
6221 if (Hoption.List) list = (TList*)contours->At(contListNb);
6222 contListNb++;
6223 if (np[ipoly] == 0)
6224 continue;
6225 Double_t *xx = polys[ipoly]->GetX();
6226 Double_t *yy = polys[ipoly]->GetY();
6227 istart = 0;
6228 while (true) {
6229 iminus = npmax;
6230 iplus = iminus+1;
6231 xp[iminus]= xx[istart]; yp[iminus] = yy[istart];
6232 xp[iplus] = xx[istart+1]; yp[iplus] = yy[istart+1];
6233 xx[istart] = xmin; yy[istart] = ymin;
6234 xx[istart+1] = xmin; yy[istart+1] = ymin;
6235 while (true) {
6236 nadd = 0;
6237 for (i=2;i<np[ipoly];i+=2) {
6238 if ((iplus < 2*npmax-1) && (xx[i] == xp[iplus]) && (yy[i] == yp[iplus])) {
6239 iplus++;
6240 xp[iplus] = xx[i+1]; yp[iplus] = yy[i+1];
6241 xx[i] = xmin; yy[i] = ymin;
6242 xx[i+1] = xmin; yy[i+1] = ymin;
6243 nadd++;
6244 }
6245 if ((iminus > 0) && (xx[i+1] == xp[iminus]) && (yy[i+1] == yp[iminus])) {
6246 iminus--;
6247 xp[iminus] = xx[i]; yp[iminus] = yy[i];
6248 xx[i] = xmin; yy[i] = ymin;
6249 xx[i+1] = xmin; yy[i+1] = ymin;
6250 nadd++;
6251 }
6252 }
6253 if (nadd == 0) break;
6254 }
6255 theColor = Int_t((ipoly+0.99)*Float_t(ncolors)/Float_t(ndivz));
6257 if (Hoption.Contour == 1) {
6258 if (ndivz > 1) fH->SetFillColor(icol);
6259 fH->TAttFill::Modify();
6260 gPad->PaintFillArea(iplus-iminus+1,xp.data()+iminus,yp.data()+iminus);
6261 }
6262 if (Hoption.List) {
6263 graph = new TGraph(iplus-iminus+1,xp.data()+iminus,yp.data()+iminus);
6264 if (Hoption.Contour == 1)
6265 graph->SetFillColor(icol);
6266 else if (Hoption.Contour == 11)
6267 graph->SetLineColor(icol);
6268 else if (Hoption.Contour == 12) {
6269 mode = icol%5;
6270 if (mode == 0) mode = 5;
6271 graph->SetLineStyle(mode);
6272 }
6273 graph->SetLineWidth(fH->GetLineWidth());
6274 list->Add(graph);
6275 }
6276 //check if more points are left
6277 istart = 0;
6278 for (i=2;i<np[ipoly];i+=2) {
6279 if (xx[i] != xmin && yy[i] != ymin) {
6280 istart = i;
6281 break;
6282 }
6283 }
6284 if (istart == 0) break;
6285 }
6286 }
6287
6288theEND:
6289 gPad->ResetBit(TGraph::kClipFrame);
6294}
6295
6296////////////////////////////////////////////////////////////////////////////////
6297/// Fill the matrix `xarr` and `yarr` for Contour Plot.
6298
6302{
6303
6304 Bool_t vert;
6306 Int_t n, i, icount;
6307
6308 if (x1 == x2) {
6309 vert = kTRUE;
6310 tlen = y2 - y1;
6311 } else {
6312 vert = kFALSE;
6313 tlen = x2 - x1;
6314 }
6315
6316 n = icont1 +1;
6317 tdif = elev2 - elev1;
6318 i = 0;
6319 icount = 0;
6320 while (n <= icont2 && i <= kMAXCONTOUR/2 -3) {
6321 //elev = fH->GetContourLevel(n);
6322 elev = levels[n];
6323 diff = elev - elev1;
6324 pdif = diff/tdif;
6325 xlen = tlen*pdif;
6326 if (vert) {
6327 if (Hoption.Logx)
6328 xarr[i] = TMath::Log10(x1);
6329 else
6330 xarr[i] = x1;
6331 if (Hoption.Logy)
6332 yarr[i] = TMath::Log10(y1 + xlen);
6333 else
6334 yarr[i] = y1 + xlen;
6335 } else {
6336 if (Hoption.Logx)
6337 xarr[i] = TMath::Log10(x1 + xlen);
6338 else
6339 xarr[i] = x1 + xlen;
6340 if (Hoption.Logy)
6341 yarr[i] = TMath::Log10(y1);
6342 else
6343 yarr[i] = y1;
6344 }
6345 itarr[i] = n;
6346 icount++;
6347 i +=2;
6348 n++;
6349 }
6350 return icount;
6351}
6352
6353////////////////////////////////////////////////////////////////////////////////
6354/// [Draw 1D histograms error bars.](\ref HP09)
6355
6357{
6358
6359 // On iOS, we do not highlight histogram, if it's not picked at the moment
6360 // (but part of histogram (axis or pavestat) was picked, that's why this code
6361 // is called at all. This conditional statement never executes on non-iOS platform.
6362 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH) return;
6363
6364 const Int_t kBASEMARKER=8;
6365 Double_t xp, yp, ex1, ex2, ey1, ey2;
6366 Double_t delta;
6368 Double_t xi1, xi2, xi3, xi4, yi1, yi2, yi3, yi4;
6370 Double_t logxmin = 0;
6371 Double_t logymin = 0;
6372 Double_t offset = 0.;
6373 Double_t width = 0.;
6374 Int_t i, k, npoints, first, last, fixbin;
6375 Int_t if1 = 0;
6376 Int_t if2 = 0;
6379 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};
6380 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};
6381
6382 std::vector<Double_t> xline, yline;
6384 if (Hoption.Error >= 40) {Hoption.Error -=40; option0 = 1;}
6385 if (Int_t(Hoption.Error/10) == 2) {optionEX0 = 1; Hoption.Error -= 10;}
6386 if (Hoption.Error == 31) {optionEX0 = 1; Hoption.Error = 1;}
6387 if (Hoption.Error == 11) option1 = 1;
6388 if (Hoption.Error == 12) option2 = 1;
6389 if (Hoption.Error == 13) option3 = 1;
6390 if (Hoption.Error == 14) {option4 = 1; option3 = 1;}
6391 if (Hoption.Error == 15) {optionI0 = 1; option3 = 1;}
6392 if (Hoption.Error == 16) {optionI0 = 1; option4 = 1; option3 = 1;}
6393 if (option2+option3 == 0) optionE = 1;
6394 if (Hoption.Error == 0) optionE = 0;
6395 if (fXaxis->GetXbins()->fN) fixbin = 0;
6396 else fixbin = 1;
6397
6398 offset = fH->GetBarOffset();
6399 width = fH->GetBarWidth();
6400
6402 if (optionEX0) {
6403 xerror = 0;
6404 } else {
6405 xerror = gStyle->GetErrorX();
6406 }
6408 if (errormarker == 1) symbolsize = 0.01;
6410 if (errormarker >= 20 && errormarker <= 49) {
6411 sbasex *= cxx[errormarker-20];
6412 sbasey *= cyy[errormarker-20];
6413 }
6414 // set the graphics attributes
6415
6416 fH->TAttLine::Modify();
6417 fH->TAttFill::Modify();
6418 fH->TAttMarker::Modify();
6419
6420 // set the first and last bin
6421
6422 Double_t factor = Hparam.factor;
6423 first = Hparam.xfirst;
6424 last = Hparam.xlast;
6425 npoints = last - first +1;
6426 xmin = gPad->GetUxmin();
6427 xmax = gPad->GetUxmax();
6428 ymin = gPad->GetUymin();
6429 ymax = gPad->GetUymax();
6430
6431
6432 if (option3) {
6433 xline.resize(2*npoints);
6434 yline.resize(2*npoints);
6435 if ((npoints > 0) && (xline.empty() || yline.empty())) {
6436 Error("PaintErrors", "too many points, out of memory");
6437 return;
6438 }
6439 if1 = 1;
6440 if2 = 2*npoints;
6441 }
6442
6443 // compute the offset of the error bars due to the symbol size
6444 s2x = gPad->PixeltoX(Int_t(0.5*sbasex)) - gPad->PixeltoX(0);
6445 s2y =-gPad->PixeltoY(Int_t(0.5*sbasey)) + gPad->PixeltoY(0);
6446
6447 // compute size of the lines at the end of the error bars
6449 bxsize = gPad->PixeltoX(dxend) - gPad->PixeltoX(0);
6450 bysize =-gPad->PixeltoY(dxend) + gPad->PixeltoY(0);
6451
6452
6453 if (fixbin) {
6455 else xp = Hparam.xmin + 0.5*Hparam.xbinsize;
6456 } else {
6457 delta = fH->GetBinWidth(first);
6458 xp = fH->GetBinLowEdge(first) + 0.5*delta;
6459 }
6460
6461 // if errormarker = 0 or symbolsize = 0. no symbol is drawn
6464
6465 // ---------------------- Loop over the points---------------------
6466 for (k=first; k<=last; k++) {
6467
6468 // get the data
6469 // xp = X position of the current point
6470 // yp = Y position of the current point
6471 // ex1 = Low X error
6472 // ex2 = Up X error
6473 // ey1 = Low Y error
6474 // ey2 = Up Y error
6475 // (xi,yi) = Error bars coordinates
6476
6477 // apply offset on errors for bar histograms
6478 Double_t xminTmp = gPad->XtoPad(fXaxis->GetBinLowEdge(k));
6479 Double_t xmaxTmp = gPad->XtoPad(fXaxis->GetBinUpEdge(k));
6480 if (Hoption.Logx) {
6483 }
6486 xmaxTmp = xminTmp + w;
6487 xp = (xminTmp+xmaxTmp)/2.;
6488
6489 if (Hoption.Logx) {
6490 if (xp <= 0) goto L30;
6491 if (xp < logxmin) goto L30;
6492 if (xp > TMath::Power(10,xmax)) break;
6493 } else {
6494 if (xp < xmin) goto L30;
6495 if (xp > xmax) break;
6496 }
6497 yp = factor*fH->GetBinContent(k);
6498 if (optionI0 && yp==0) goto L30;
6499 if (fixbin) {
6501 } else {
6502 delta = fH->GetBinWidth(k);
6503 ex1 = xerror*delta;
6504 }
6505 if (fH->GetBinErrorOption() == TH1::kNormal) {
6506 ey1 = factor*fH->GetBinError(k);
6507 ey2 = ey1;
6508 } else {
6509 ey1 = factor*fH->GetBinErrorLow(k);
6510 ey2 = factor*fH->GetBinErrorUp(k);
6511 }
6512 ex2 = ex1;
6513
6514 xi4 = xp;
6515 xi3 = xp;
6516 xi2 = xp + ex2;
6517 xi1 = xp - ex1;
6518
6519 yi1 = yp;
6520 yi2 = yp;
6521 yi3 = yp - ey1;
6522 yi4 = yp + ey2;
6523
6524 // take the LOG if necessary
6525 if (Hoption.Logx) {
6530 }
6531 if (Hoption.Logy) {
6536 }
6537
6538 // test if error bars are not outside the limits
6539 // otherwise they are truncated
6540
6545
6546 // test if the marker is on the frame limits. If "Yes", the
6547 // marker will not be drawn and the error bars will be readjusted.
6548
6549 drawmarker = kTRUE;
6550 if (!option0 && !option3) {
6551 if (Hoption.Logy && yp < logymin) goto L30;
6552 if (yi1 < ymin || yi1 > ymax) goto L30;
6553 if (Hoption.Error != 0 && yp == 0 && ey1 <= 0) drawmarker = kFALSE;
6554 }
6556
6557 // draw the error rectangles
6558 if (option2) {
6559 if (yi3 >= ymax) goto L30;
6560 if (yi4 <= ymin) goto L30;
6561 gPad->PaintBox(xi1,yi3,xi2,yi4);
6562 }
6563
6564 // keep points for fill area drawing
6565 if (option3) {
6566 xline[if1-1] = xi3;
6567 xline[if2-1] = xi3;
6568 yline[if1-1] = yi4;
6569 yline[if2-1] = yi3;
6570 if1++;
6571 if2--;
6572 }
6573
6574 // draw the error bars
6575 if (Hoption.Logy && yp < logymin) drawmarker = kFALSE;
6576 if (optionE && drawmarker) {
6577 if ((yi3 < yi1 - s2y) && (yi3 < ymax)) gPad->PaintLine(xi3,yi3,xi4,TMath::Min(yi1 - s2y,ymax));
6578 if ((yi1 + s2y < yi4) && (yi4 > ymin)) gPad->PaintLine(xi3,TMath::Max(yi1 + s2y, ymin),xi4,yi4);
6579 // don't duplicate the horizontal line
6580 if (Hoption.Hist != 2) {
6582 if (xi1 < xi3 - s2x) gPad->PaintLine(xi1,yi1,xi3 - s2x,yi2);
6583 if (xi3 + s2x < xi2) gPad->PaintLine(xi3 + s2x,yi1,xi2,yi2);
6584 }
6585 }
6586 }
6587 if (optionE && !drawmarker && (ey1 != 0 || ey2 !=0)) {
6588 if ((yi3 < yi1) && (yi3 < ymax)) gPad->PaintLine(xi3,yi3,xi4,TMath::Min(yi1,ymax));
6589 if ((yi1 < yi4) && (yi4 > ymin)) gPad->PaintLine(xi3,TMath::Max(yi1,ymin),xi4,yi4);
6590 // don't duplicate the horizontal line
6591 if (Hoption.Hist != 2) {
6593 if (xi1 < xi3) gPad->PaintLine(xi1,yi1,xi3,yi2);
6594 if (xi3 < xi2) gPad->PaintLine(xi3,yi1,xi2,yi2);
6595 }
6596 }
6597 }
6598
6599 // draw line at the end of the error bars
6600
6601 if (option1 && drawmarker) {
6602
6603 if (yi3 < yi1-s2y && yi3 < ymax && yi3 > ymin) gPad->PaintLine(xi3 - bxsize, yi3 , xi3 + bxsize, yi3);
6604 if (yi4 > yi1+s2y && yi4 < ymax && yi4 > ymin) gPad->PaintLine(xi3 - bxsize, yi4 , xi3 + bxsize, yi4);
6606 if (xi1 < xi3-s2x) gPad->PaintLine(xi1 , yi1 - bysize, xi1 , yi1 + bysize);
6607 if (xi2 > xi3+s2x) gPad->PaintLine(xi2 , yi1 - bysize, xi2 , yi1 + bysize);
6608 }
6609 }
6610
6611 // draw the marker
6612
6613 if (drawmarker) gPad->PaintPolyMarker(1, &xi3, &yi1);
6614
6615L30:
6616 if (fixbin) xp += Hparam.xbinsize;
6617 else {
6618 if (k < last) {
6619 delta = fH->GetBinWidth(k+1);
6620 xp = fH->GetBinLowEdge(k+1) + 0.5*delta;
6621 }
6622 }
6623 } //end of for loop
6624
6625 // draw the filled area
6626
6627 if (option3) {
6628 TGraph graph;
6629 graph.SetLineStyle(fH->GetLineStyle());
6630 graph.SetLineColor(fH->GetLineColor());
6631 graph.SetLineWidth(fH->GetLineWidth());
6632 graph.SetFillStyle(fH->GetFillStyle());
6633 graph.SetFillColor(fH->GetFillColor());
6634 Int_t logx = gPad->GetLogx();
6635 Int_t logy = gPad->GetLogy();
6636 gPad->SetLogx(0);
6637 gPad->SetLogy(0);
6638
6639 // In some cases the number of points in the fill area is smaller than
6640 // 2*npoints. In such cases the array xline and yline must be arranged
6641 // before being plotted. The next loop does that.
6642 if (if2 > npoints) {
6643 for (i=1; i<if1; i++) {
6644 xline[if1-2+i] = xline[if2-1+i];
6645 yline[if1-2+i] = yline[if2-1+i];
6646 }
6647 npoints = if1-1;
6648 }
6649 if (option4) graph.PaintGraph(2*npoints,xline.data(),yline.data(),"FC");
6650 else graph.PaintGraph(2*npoints,xline.data(),yline.data(),"F");
6651 gPad->SetLogx(logx);
6652 gPad->SetLogy(logy);
6653 }
6654}
6655
6656////////////////////////////////////////////////////////////////////////////////
6657/// Draw 2D histograms errors.
6658
6660{
6661
6662 fH->TAttMarker::Modify();
6663 fH->TAttLine::Modify();
6664
6665 // Define the 3D view
6666 fXbuf[0] = Hparam.xmin;
6667 fYbuf[0] = Hparam.xmax;
6668 fXbuf[1] = Hparam.ymin;
6669 fYbuf[1] = Hparam.ymax;
6670 fXbuf[2] = Hparam.zmin;
6671 fYbuf[2] = Hparam.zmax*(1. + gStyle->GetHistTopMargin());
6672 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
6673 TView *view = gPad ? gPad->GetView() : nullptr;
6674 if (!view) {
6675 Error("Paint2DErrors", "no TView in current pad");
6676 return;
6677 }
6678 Double_t thedeg = 90 - gPad->GetTheta();
6679 Double_t phideg = -90 - gPad->GetPhi();
6680 Double_t psideg = view->GetPsi();
6681 Int_t irep;
6682 view->SetView(phideg, thedeg, psideg, irep);
6683
6684 // Set color/style for back box
6685 fLego->SetFillStyle(gPad->GetFrameFillStyle());
6686 fLego->SetFillColor(gPad->GetFrameFillColor());
6687 fLego->TAttFill::Modify();
6688 Int_t backcolor = gPad->GetFrameFillColor();
6689 if (Hoption.System != kCARTESIAN) backcolor = 0;
6690 view->PadRange(backcolor);
6691 fLego->SetFillStyle(fH->GetFillStyle());
6692 fLego->SetFillColor(fH->GetFillColor());
6693 fLego->TAttFill::Modify();
6694
6695 // Paint the Back Box if needed
6696 if (Hoption.BackBox && !Hoption.Same && !Hoption.Lego && !Hoption.Surf) {
6697 fLego->InitMoveScreen(-1.1,1.1);
6698 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
6700 fLego->BackBox(90);
6701 }
6702
6703 // Paint the Errors
6704 Double_t x, ex, x1, x2;
6705 Double_t y, ey, y1, y2;
6706 Double_t z, ez1, ez2, z1, z2;
6707 Double_t temp1[3],temp2[3];
6709 if (Hoption.Error == 110) {
6710 xyerror = 0;
6711 } else {
6713 }
6714
6716 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
6717 y = fYaxis->GetBinCenter(j);
6719 y1 = y-ey;
6720 y2 = y+ey;
6721 if (Hoption.Logy) {
6722 if (y > 0) y = TMath::Log10(y);
6723 else continue;
6724 if (y1 > 0) y1 = TMath::Log10(y1);
6725 else y1 = Hparam.ymin;
6726 if (y2 > 0) y2 = TMath::Log10(y2);
6727 else y2 = Hparam.ymin;
6728 }
6731 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
6732 xk = fXaxis->GetBinLowEdge(i);
6733 xstep = fXaxis->GetBinWidth(i);
6734 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
6735 Int_t bin = fH->GetBin(i,j);
6736 x = fXaxis->GetBinCenter(i);
6738 x1 = x-ex;
6739 x2 = x+ex;
6740 if (Hoption.Logx) {
6741 if (x > 0) x = TMath::Log10(x);
6742 else continue;
6743 if (x1 > 0) x1 = TMath::Log10(x1);
6744 else x1 = Hparam.xmin;
6745 if (x2 > 0) x2 = TMath::Log10(x2);
6746 else x2 = Hparam.xmin;
6747 }
6748 z = fH->GetBinContent(bin);
6749 if (fH->GetBinErrorOption() == TH1::kNormal) {
6750 ez1 = fH->GetBinError(bin);
6751 ez2 = ez1;
6752 }
6753 else {
6754 ez1 = fH->GetBinErrorLow(bin);
6755 ez2 = fH->GetBinErrorUp(bin);
6756 }
6757 z1 = z - ez1;
6758 z2 = z + ez2;
6759 if (Hoption.Logz) {
6760 if (z > 0) z = TMath::Log10(z);
6761 else z = Hparam.zmin;
6762 if (z1 > 0) z1 = TMath::Log10(z1);
6763 else z1 = Hparam.zmin;
6764 if (z2 > 0) z2 = TMath::Log10(z2);
6765 else z2 = Hparam.zmin;
6766
6767 }
6768 if (z <= Hparam.zmin) continue;
6769 if (z > Hparam.zmax) z = Hparam.zmax;
6770
6771 temp1[0] = x1;
6772 temp1[1] = y;
6773 temp1[2] = z;
6774 temp2[0] = x2;
6775 temp2[1] = y;
6776 temp2[2] = z;
6777 gPad->PaintLine3D(temp1, temp2);
6778 temp1[0] = x;
6779 temp1[1] = y1;
6780 temp1[2] = z;
6781 temp2[0] = x;
6782 temp2[1] = y2;
6783 temp2[2] = z;
6784 gPad->PaintLine3D(temp1, temp2);
6785 temp1[0] = x;
6786 temp1[1] = y;
6787 temp1[2] = z1;
6788 temp2[0] = x;
6789 temp2[1] = y;
6790 temp2[2] = z2;
6791 gPad->PaintLine3D(temp1, temp2);
6792 temp1[0] = x;
6793 temp1[1] = y;
6794 temp1[2] = z;
6795 view->WCtoNDC(temp1, &temp2[0]);
6796 gPad->PaintPolyMarker(1, &temp2[0], &temp2[1]);
6797 }
6798 }
6799
6800 // Paint the Front Box if needed
6801 if (Hoption.FrontBox) {
6802 fLego->InitMoveScreen(-1.1,1.1);
6804 fLego->FrontBox(90);
6805 }
6806
6807 // Paint the Axis if needed
6808 if (!Hoption.Axis && !Hoption.Same && !Hoption.Lego && !Hoption.Surf) {
6809 TGaxis axis;
6810 PaintLegoAxis(&axis, 90);
6811 }
6812
6813 fLego.reset();
6814}
6815
6816////////////////////////////////////////////////////////////////////////////////
6817/// Calculate range and clear pad (canvas).
6818
6820{
6821
6822 if (Hoption.Same) return;
6823
6825
6826 if (Hoption.Lego || Hoption.Surf || Hoption.Tri ||
6827 Hoption.Contour == 14 || Hoption.Error >= 100) {
6828 TObject *frame = gPad->FindObject("TFrame");
6829 if (frame) gPad->Remove(frame);
6830 return;
6831 }
6832
6833 //The next statement is always executed on non-iOS platform,
6834 //on iOS depends on pad mode.
6835 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode())
6836 gPad->PaintPadFrame(Hparam.xmin,Hparam.ymin,Hparam.xmax,Hparam.ymax);
6837}
6838
6839////////////////////////////////////////////////////////////////////////////////
6840/// [Paint functions associated to an histogram.](\ref HP28")
6841
6843{
6844 auto lnk = fFunctions->FirstLink();
6845
6846 while (lnk) {
6847 auto obj = lnk->GetObject();
6849 if (obj->InheritsFrom(TF2::Class())) {
6850 if (!obj->TestBit(TF2::kNotDraw)) {
6851 if (Hoption.Lego || Hoption.Surf || Hoption.Error >= 100) {
6852 TF2 *f2 = (TF2*)obj;
6853 f2->SetMinimum(fH->GetMinimum());
6854 f2->SetMaximum(fH->GetMaximum());
6855 f2->SetRange(fH->GetXaxis()->GetXmin(), fH->GetYaxis()->GetXmin(), fH->GetXaxis()->GetXmax(), fH->GetYaxis()->GetXmax() );
6856 f2->Paint("surf same");
6857 } else {
6858 obj->Paint("cont3 same");
6859 }
6860 }
6861 } else if (obj->InheritsFrom(TF1::Class())) {
6862 if (!obj->TestBit(TF1::kNotDraw)) obj->Paint("lsame");
6863 } else {
6864 //Let's make this 'function' selectable on iOS device (for example, it can be TPaveStat).
6865 gPad->PushSelectableObject(obj);
6866
6867 //The next statement is ALWAYS executed on non-iOS platform, on iOS it depends on pad's mode
6868 //and picked object.
6869 if (!gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && obj == gPad->GetSelected()))
6870 obj->Paint(lnk->GetOption());
6871 }
6872 lnk = lnk->Next();
6873 }
6874}
6875
6876////////////////////////////////////////////////////////////////////////////////
6877/// [Control routine to draw 1D histograms](\ref HP01b)
6878
6880{
6881
6882 //On iOS: do not highlight hist, if part of it was selected.
6883 //Never executes on non-iOS platform.
6884 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
6885 return;
6886
6887 static char chopth[17];
6888
6890 Int_t i, j, first, last, nbins, fixbin;
6891 Double_t c1, yb;
6892 yb = 0;
6893
6894 strlcpy(chopth, " ",17);
6895
6898 Double_t baroffset = fH->GetBarOffset();
6899 Double_t barwidth = fH->GetBarWidth();
6902 gStyle->SetBarOffset(baroffset);
6903 gStyle->SetBarWidth(barwidth);
6904
6905 // Create "LIFE" structure to keep current histogram status
6906
6907 first = Hparam.xfirst;
6908 last = Hparam.xlast;
6909 nbins = last - first + 1;
6910
6911 std::vector<Double_t> keepx, keepy;
6912 if (fXaxis->GetXbins()->fN) fixbin = 0;
6913 else fixbin = 1;
6914 if (fixbin) keepx.resize(2);
6915 else keepx.resize(nbins+1);
6916 keepy.resize(nbins);
6917 Double_t logymin = 0;
6919
6920 // Loop on histogram bins
6921
6922 for (j=first; j<=last;j++) {
6924 if (TMath::Abs(ymax-ymin) > 0) {
6926 else yb = c1;
6927 }
6928 if (!Hoption.Line) {
6929 yb = TMath::Max(yb, ymin);
6930 yb = TMath::Min(yb, ymax);
6931 }
6932 keepy[j-first] = yb;
6933 }
6934
6935 // Draw histogram according to value of FillStyle and FillColor
6936
6937 if (fixbin) { keepx[0] = Hparam.xmin; keepx[1] = Hparam.xmax; }
6938 else {
6939 for (i=0; i<nbins; i++) keepx[i] = fXaxis->GetBinLowEdge(i+first);
6940 keepx[nbins] = fXaxis->GetBinUpEdge(nbins-1+first);
6941 }
6942
6943 // Prepare Fill area (systematic with option "Bar").
6944
6946 htype = oldhtype;
6947 if (Hoption.Bar) {
6948 if (htype == 0 || htype == 1000) htype = 1001;
6949 }
6950
6952
6953 // Code option for GrapHist
6954
6955 if (Hoption.Line) chopth[0] = 'L';
6956 if (Hoption.Star) chopth[1] = '*';
6957 if (Hoption.Mark) chopth[2] = 'P';
6958 if (Hoption.Mark == 10) chopth[3] = '0';
6960 if (Hoption.Curve) chopth[3] = 'C';
6961 if (Hoption.Hist > 0) chopth[4] = 'H';
6962 else if (Hoption.Bar) chopth[5] = 'B';
6963 if (Hoption.Logy) chopth[6] = '1';
6964 if (fH->GetFillColor() && htype) {
6965 if (Hoption.Hist > 0 || Hoption.Curve || Hoption.Line) {
6966 chopth[7] = 'F';
6967 }
6968 }
6969 }
6970 if (!fixbin && strlen(chopth)) {
6971 chopth[8] = 'N';
6972 }
6973
6974 if (Hoption.Fill == 2) chopth[13] = '2';
6975
6976 // Option LOGX
6977
6978 if (Hoption.Logx) {
6979 chopth[9] = 'G';
6980 chopth[10] = 'X';
6981 if (fixbin) {
6982 keepx[0] = TMath::Power(10,keepx[0]);
6983 keepx[1] = TMath::Power(10,keepx[1]);
6984 }
6985 }
6986
6987 if (Hoption.Off) {
6988 chopth[11] = ']';
6989 chopth[12] = '[';
6990 }
6991
6992 // Draw the histogram
6993
6994 TGraph graph;
6995 graph.SetLineWidth(lw);
6996 graph.SetLineStyle(fH->GetLineStyle());
6997 graph.SetLineColor(fH->GetLineColor());
6998 graph.SetFillStyle(htype);
6999 graph.SetFillColor(fH->GetFillColor());
7001 graph.SetMarkerSize(fH->GetMarkerSize());
7004
7005 graph.PaintGrapHist(nbins, keepx.data(), keepy.data() ,chopth);
7006
7009
7011}
7012
7013////////////////////////////////////////////////////////////////////////////////
7014/// [Control function to draw a 3D histograms.](\ref HP01d)
7015
7017{
7018
7019 TString cmd;
7020 TString opt = option;
7021 opt.ToLower();
7022 Int_t irep;
7023 Float_t NEntries = fH->GetEntries();
7024
7025 if (fCurrentF3 || strstr(opt,"tf3")) {
7026 PaintTF3();
7027 return;
7028 }
7029
7030 if (NEntries > 0) {
7031 if (Hoption.Box || Hoption.Lego || Hoption.Color) {
7032 if (Hoption.Box == 11 || Hoption.Lego == 11) {
7033 PaintH3Box(1);
7034 } else if (Hoption.Box == 12 || Hoption.Lego == 12 || Hoption.Color == 1) {
7035 PaintH3Box(2);
7036 } else if (Hoption.Box == 13 || Hoption.Lego == 13) {
7037 PaintH3Box(3);
7038 } else {
7040 }
7041 return;
7042 }
7043
7044 if (strstr(opt,"iso")) {
7045 PaintH3Iso();
7046 return;
7047 }
7048 }
7049
7050 TView *view = gPad ? gPad->GetView() : nullptr;
7051 if (!view) return;
7052
7053 if (strstr(opt,"fb")) Hoption.FrontBox = 0;
7054 if (strstr(opt,"bb")) Hoption.BackBox = 0;
7055
7056 Double_t thedeg = 90 - gPad->GetTheta();
7057 Double_t phideg = -90 - gPad->GetPhi();
7058 Double_t psideg = view->GetPsi();
7059 view->SetView(phideg, thedeg, psideg, irep);
7060
7061 if(NEntries > 0) { // Paint as 3D scatter plot
7062 cmd.Form("TPolyMarker3D::PaintH3((TH1 *)0x%zx,\"%s\");",(size_t)fH,option);
7063 gROOT->ProcessLine(cmd.Data());
7064 } else {
7065 TAxis* xAxis = fH->GetXaxis();
7066 TAxis* yAxis = fH->GetYaxis();
7067 TAxis* zAxis = fH->GetZaxis();
7068 Double_t xmin = xAxis->GetXmin();
7069 Double_t xmax = xAxis->GetXmax();
7070 Double_t ymin = yAxis->GetXmin();
7071 Double_t ymax = yAxis->GetXmax();
7072 Double_t zmin = zAxis->GetXmin();
7073 Double_t zmax = zAxis->GetXmax();
7074 view->SetRange(xmin, ymin, zmin, xmax, ymax, zmax); // Set the axis limits (Xmin, Ymin, Zmin, Xmax, Ymax, Zmax)
7075 }
7076
7077 if (Hoption.Same) return;
7078
7079 // Draw axis
7080 view->SetOutlineToCube();
7081 TSeqCollection *ol = view->GetOutline();
7082 if (ol && Hoption.BackBox && Hoption.FrontBox) ol->Paint(option);
7084
7085 if (!Hoption.Axis && !Hoption.Same) {
7086 TGaxis axis;
7087 PaintLegoAxis(&axis, 90);
7088 }
7089
7090 // Draw palette. In case of 4D plot with TTree::Draw() the palette should
7091 // be painted with the option colz.
7092 if (fH->GetDrawOption() && strstr(opt,"colz")) {
7093 Int_t ndiv = fH->GetContour();
7094 if (ndiv == 0 ) {
7095 ndiv = gStyle->GetNumberContours();
7096 fH->SetContour(ndiv);
7097 }
7098 PaintPalette();
7099 }
7100
7101 // Draw title
7102 PaintTitle();
7103
7104 //Draw stats and fit results
7105 TF1 *fit = nullptr;
7106 TIter next(fFunctions);
7107 while (auto obj = next()) {
7108 if (obj->InheritsFrom(TF1::Class())) {
7109 fit = (TF1*)obj;
7110 break;
7111 }
7112 }
7113 if ((Hoption.Same%10) != 1) {
7114 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7116 }
7117 }
7118
7119}
7120
7121////////////////////////////////////////////////////////////////////////////////
7122/// Compute histogram parameters used by the drawing routines.
7123
7125{
7126
7127 if (fH->GetDimension() > 1 || Hoption.Lego || Hoption.Surf) return 1;
7128
7129 Int_t i;
7130 static const char *where = "PaintInit";
7132 Int_t maximum = 0;
7133 Int_t minimum = 0;
7134 if (fH->GetMaximumStored() != -1111) maximum = 1;
7135 if (fH->GetMinimumStored() != -1111) minimum = 1;
7136
7137 // Compute X axis parameters
7138
7139 Int_t last = fXaxis->GetLast();
7140 Int_t first = fXaxis->GetFirst();
7143 Hparam.xlast = last;
7144 Hparam.xfirst = first;
7147
7148 // if log scale in X, replace xmin,max by the log
7149 if (Hoption.Logx) {
7150 if (Hparam.xmax<=0) {
7151 Error(where, "cannot set X axis to log scale");
7152 return 0;
7153 }
7154 if (Hparam.xlowedge <=0 ) {
7155 if (Hoption.Same) {
7156 TH1* h1 = nullptr;
7157 TObject *obj;
7158 TIter next(gPad->GetListOfPrimitives());
7159 while ((obj = (TObject *)next())) {
7160 if (obj->InheritsFrom(TH1::Class())) { h1 = (TH1*)(obj) ; break; }
7161 if (obj->InheritsFrom(THStack::Class())) { h1 = ((THStack*)(obj))->GetHistogram() ; break; }
7162 if (obj->InheritsFrom(TGraph::Class())) { h1 = ((TGraph*)(obj))->GetHistogram() ; break; }
7163 if (obj->InheritsFrom(TMultiGraph::Class())) { h1 = ((TMultiGraph*)(obj))->GetHistogram(); break; }
7164 if (obj->InheritsFrom(TGraph2D::Class())) { h1 = ((TGraph2D*)(obj))->GetHistogram(); break; }
7165 if (obj->InheritsFrom(TF1::Class())) { h1 = ((TF1*)(obj))->GetHistogram(); break; }
7166 }
7167 if (h1) {
7169 } else {
7170 Error(where, "undefined user's coordinates. Cannot use option SAME");
7171 return 0;
7172 }
7173 } else {
7174 for (i=first; i<=last; i++) {
7175 Double_t binLow = fXaxis->GetBinLowEdge(i);
7176 if (binLow>0) {
7177 Hparam.xlowedge = binLow;
7178 break;
7179 }
7180 if (binLow == 0 && fH->GetBinContent(i) !=0) {
7181 Hparam.xlowedge = fXaxis->GetBinUpEdge(i)*0.001;
7182 break;
7183 }
7184 }
7185 if (Hparam.xlowedge<=0) {
7186 Error(where, "cannot set X axis to log scale");
7187 return 0;
7188 }
7189 }
7191 }
7196 if (Hparam.xlast > last) Hparam.xlast = last;
7197 if (Hparam.xfirst < first) Hparam.xfirst = first;
7198 }
7199
7200 // Compute Y axis parameters
7201 Double_t bigp = TMath::Power(10,32);
7202 Double_t ymax = -bigp;
7203 Double_t ymin = bigp;
7204 Double_t c1, e1;
7205 Double_t xv[1];
7206 Double_t fval;
7207 TObject *f;
7208 TF1 *f1;
7209 Double_t allchan = 0;
7210 Int_t nonNullErrors = 0;
7211 TIter next(fFunctions);
7212 for (i=first; i<=last;i++) {
7213 c1 = fH->GetBinContent(i);
7215 if (Hoption.Logy) {
7216 if (c1 > 0) ymin = TMath::Min(ymin,c1);
7217 } else {
7219 }
7220 if (Hoption.Error) {
7222 e1 = fH->GetBinError(i);
7223 else
7224 e1 = fH->GetBinErrorUp(i);
7225 if (e1 > 0) nonNullErrors++;
7228 e1 = fH->GetBinErrorLow(i);
7229
7230 if (Hoption.Logy) {
7231 if (c1-e1>0.01*TMath::Abs(c1)) ymin = TMath::Min(ymin,c1-e1);
7232 } else {
7234 }
7235 }
7236 if (Hoption.Func) {
7237 xv[0] = fXaxis->GetBinCenter(i);
7238 while ((f = (TObject*) next())) {
7239 if (f->IsA() == TF1::Class()) {
7240 f1 = (TF1*)f;
7241 if (xv[0] < f1->GetXmin() || xv[0] > f1->GetXmax()) continue;
7242 fval = f1->Eval(xv[0],0,0);
7243 if (f1->GetMaximumStored() != -1111) fval = TMath::Min(f1->GetMaximumStored(), fval);
7245 if (Hoption.Logy) {
7246 if (c1 > 0 && fval > 0.3*c1) ymin = TMath::Min(ymin,fval);
7247 }
7248 }
7249 }
7250 next.Reset();
7251 }
7252 allchan += c1;
7253 }
7254 if (!nonNullErrors) {
7255 if (Hoption.Error) {
7256 if (!Hoption.Mark && !Hoption.Line && !Hoption.Star && !Hoption.Curve) Hoption.Hist = 2;
7257 Hoption.Error=0;
7258 }
7259 }
7260
7261
7262 // Take into account maximum , minimum
7263
7264 if (Hoption.Logy && ymin <= 0) {
7265 if (ymax >= 1) ymin = TMath::Max(.005,ymax*1e-10);
7266 else ymin = 0.001*ymax;
7267 }
7268
7269 Double_t xm = ymin;
7270 if (maximum) ymax = fH->GetMaximumStored();
7271 if (minimum) xm = fH->GetMinimumStored();
7272 if (Hoption.Logy && xm < 0) {
7273 Error(where, "log scale requested with a negative argument (%f)", xm);
7274 return 0;
7275 } else if (Hoption.Logy && xm>=0 && ymax==0) { // empty histogram in log scale
7276 ymin = 0.01;
7277 ymax = 10.;
7278 } else {
7279 ymin = xm;
7280 }
7281
7282 if (ymin >= ymax) {
7283 if (Hoption.Logy) {
7284 if (ymax > 0) ymin = 0.001*ymax;
7285 else {
7286 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", ymax);
7287 return 0;
7288 }
7289 }
7290 else {
7291 if (ymin > 0) {
7292 ymin = 0;
7293 ymax *= 2;
7294 } else if (ymin < 0) {
7295 ymax = 0;
7296 ymin *= 2;
7297 } else {
7298 ymin = 0;
7299 ymax = 1;
7300 }
7301 }
7302 }
7303
7304 // In some cases, mainly because of precision issues, ymin and ymax could almost equal.
7305 if (TMath::AreEqualRel(ymin,ymax,1E-15)) {
7306 ymin = ymin*(1-1E-14);
7307 ymax = ymax*(1+1E-14);
7308 }
7309
7310 // take into account normalization factor
7311 Hparam.allchan = allchan;
7312 Double_t factor = allchan;
7313 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
7314 if (allchan) factor /= allchan;
7315 if (factor == 0) factor = 1;
7316 Hparam.factor = factor;
7317 ymax = factor*ymax;
7318 ymin = factor*ymin;
7319 //just in case the norm factor is negative
7320 // this may happen with a positive norm factor and a negative integral !
7321 if (ymax < ymin) {
7322 Double_t temp = ymax;
7323 ymax = ymin;
7324 ymin = temp;
7325 }
7326
7327 // For log scales, histogram coordinates are LOG10(ymin) and
7328 // LOG10(ymax). Final adjustment (if not option "Same"
7329 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
7330 // Maximum and Minimum are not defined.
7331 if (Hoption.Logy) {
7332 if (ymin <=0 || ymax <=0) {
7333 Error(where, "Cannot set Y axis to log scale");
7334 return 0;
7335 }
7337 if (!minimum) ymin += TMath::Log10(0.5);
7339 if (!maximum) ymax += TMath::Log10(2*(0.9/0.95));
7340 if (!Hoption.Same) {
7341 Hparam.ymin = ymin;
7342 Hparam.ymax = ymax;
7343 }
7344 return 1;
7345 }
7346
7347 // final adjustment of ymin for linear scale.
7348 // if minimum is not set , then ymin is set to zero if >0
7349 // or to ymin - margin if <0.
7350 if (!minimum) {
7351 if (Hoption.MinimumZero) {
7352 if (ymin >= 0) ymin = 0;
7353 else ymin -= yMARGIN*(ymax-ymin);
7354 } else {
7356 if (ymin >= 0 && (ymin-dymin <= 0)) ymin = 0;
7357 else ymin -= dymin;
7358 }
7359 }
7360
7361 // final adjustment of YMAXI for linear scale (if not option "Same"):
7362 // decrease histogram height to MAX% of allowed height if HMAXIM
7363 // has not been called.
7364 if (!maximum) {
7365 ymax += yMARGIN*(ymax-ymin);
7366 }
7367
7368 Hparam.ymin = ymin;
7369 Hparam.ymax = ymax;
7370 return 1;
7371}
7372
7373////////////////////////////////////////////////////////////////////////////////
7374/// Compute histogram parameters used by the drawing routines for a rotated pad.
7375
7377{
7378
7379 static const char *where = "PaintInitH";
7381 Int_t maximum = 0;
7382 Int_t minimum = 0;
7383 if (fH->GetMaximumStored() != -1111) maximum = 1;
7384 if (fH->GetMinimumStored() != -1111) minimum = 1;
7385
7386 // Compute X axis parameters
7387
7388 Int_t last = fXaxis->GetLast();
7389 Int_t first = fXaxis->GetFirst();
7392 Hparam.xlast = last;
7393 Hparam.xfirst = first;
7396
7397 // if log scale in Y, replace ymin,max by the log
7398 if (Hoption.Logy) {
7399 if (Hparam.xlowedge <=0 ) {
7402 }
7403 if (Hparam.ymin <=0 || Hparam.ymax <=0) {
7404 Error(where, "cannot set Y axis to log scale");
7405 return 0;
7406 }
7411 if (Hparam.xlast > last) Hparam.xlast = last;
7412 }
7413
7414 // Compute Y axis parameters
7415 Double_t bigp = TMath::Power(10,32);
7416 Double_t xmax = -bigp;
7417 Double_t xmin = bigp;
7418 Double_t c1, e1;
7419 Double_t xv[1];
7420 Double_t fval;
7421 Int_t i;
7422 TObject *f;
7423 TF1 *f1;
7424 Double_t allchan = 0;
7425 TIter next(fFunctions);
7426 for (i=first; i<=last;i++) {
7427 c1 = fH->GetBinContent(i);
7430 if (Hoption.Error) {
7431 e1 = fH->GetBinError(i);
7434 }
7435 if (Hoption.Func) {
7436 xv[0] = fXaxis->GetBinCenter(i);
7437 while ((f = (TObject*) next())) {
7438 if (f->IsA() == TF1::Class()) {
7439 f1 = (TF1*)f;
7440 if (xv[0] < f1->GetXmin() || xv[0] > f1->GetXmax()) continue;
7441 fval = f1->Eval(xv[0],0,0);
7443 if (Hoption.Logy) {
7444 if (fval > 0.3*c1) xmin = TMath::Min(xmin,fval);
7445 }
7446 }
7447 }
7448 next.Reset();
7449 }
7450 allchan += c1;
7451 }
7452
7453 // Take into account maximum , minimum
7454
7455 if (Hoption.Logx && xmin <= 0) {
7456 if (xmax >= 1) xmin = TMath::Max(.5,xmax*1e-10);
7457 else xmin = 0.001*xmax;
7458 }
7459 Double_t xm = xmin;
7460 if (maximum) xmax = fH->GetMaximumStored();
7461 if (minimum) xm = fH->GetMinimumStored();
7462 if (Hoption.Logx && xm <= 0) {
7463 Error(where, "log scale requested with zero or negative argument (%f)", xm);
7464 return 0;
7465 }
7466 else xmin = xm;
7467 if (xmin >= xmax) {
7468 if (Hoption.Logx) {
7469 if (xmax > 0) xmin = 0.001*xmax;
7470 else {
7471 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", xmax);
7472 return 0;
7473 }
7474 }
7475 else {
7476 if (xmin > 0) {
7477 xmin = 0;
7478 xmax *= 2;
7479 } else if (xmin < 0) {
7480 xmax = 0;
7481 xmin *= 2;
7482 } else {
7483 xmin = 0;
7484 xmax = 1;
7485 }
7486 }
7487 }
7488
7489 // take into account normalization factor
7490 Hparam.allchan = allchan;
7491 Double_t factor = allchan;
7492 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
7493 if (allchan) factor /= allchan;
7494 if (factor == 0) factor = 1;
7495 Hparam.factor = factor;
7496 xmax = factor*xmax;
7497 xmin = factor*xmin;
7498
7499 // For log scales, histogram coordinates are LOG10(ymin) and
7500 // LOG10(ymax). Final adjustment (if not option "Same"
7501 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
7502 // Maximum and Minimum are not defined.
7503 if (Hoption.Logx) {
7504 if (xmin <=0 || xmax <=0) {
7505 Error(where, "Cannot set Y axis to log scale");
7506 return 0;
7507 }
7509 if (!minimum) xmin += TMath::Log10(0.5);
7511 if (!maximum) xmax += TMath::Log10(2*(0.9/0.95));
7512 if (!Hoption.Same) {
7513 Hparam.xmin = xmin;
7514 Hparam.xmax = xmax;
7515 }
7516 return 1;
7517 }
7518
7519 // final adjustment of ymin for linear scale.
7520 // if minimum is not set , then ymin is set to zero if >0
7521 // or to ymin - margin if <0.
7522 if (!minimum) {
7523 if (xmin >= 0) xmin = 0;
7524 else xmin -= yMARGIN*(xmax-xmin);
7525 }
7526
7527 // final adjustment of YMAXI for linear scale (if not option "Same"):
7528 // decrease histogram height to MAX% of allowed height if HMAXIM
7529 // has not been called.
7530 if (!maximum) {
7531 xmax += yMARGIN*(xmax-xmin);
7532 }
7533 Hparam.xmin = xmin;
7534 Hparam.xmax = xmax;
7535 return 1;
7536}
7537
7538////////////////////////////////////////////////////////////////////////////////
7539/// [Control function to draw a 3D histogram with boxes.](\ref HP25)
7540
7542{
7543 // Predefined box structure
7544 Double_t wxyz[8][3] = { {-1,-1,-1}, {1,-1,-1}, {1,1,-1}, {-1,1,-1},
7545 {-1,-1, 1}, {1,-1, 1}, {1,1, 1}, {-1,1, 1} };
7546 Int_t iface[6][4] = { {0,3,2,1}, {4,5,6,7},
7547 {0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7} };
7548
7549 // Define dimensions of world space
7550 TAxis *xaxis = fH->GetXaxis();
7551 TAxis *yaxis = fH->GetYaxis();
7552 TAxis *zaxis = fH->GetZaxis();
7553
7554 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7555 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7556 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7557 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7558 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7559 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7560
7561 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7562
7563 // Set view
7564 TView *view = gPad ? gPad->GetView() : nullptr;
7565 if (!view) {
7566 Error("PaintH3", "no TView in current pad");
7567 return;
7568 }
7569 Double_t thedeg = 90 - gPad->GetTheta();
7570 Double_t phideg = -90 - gPad->GetPhi();
7571 Double_t psideg = view->GetPsi();
7572 Int_t irep;
7573 view->SetView(phideg, thedeg, psideg, irep);
7574
7575 Int_t backcolor = gPad->GetFrameFillColor();
7576 view->PadRange(backcolor);
7577
7578 // Draw back surfaces of frame box
7579 fLego->InitMoveScreen(-1.1,1.1);
7580 if (Hoption.BackBox) {
7581 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
7583 fLego->BackBox(90);
7584 }
7585
7587
7588 // Define order of drawing
7589 Double_t *tnorm = view->GetTnorm();
7590 if (!tnorm) return;
7591 Int_t incrx = (tnorm[ 8] < 0.) ? -1 : +1;
7592 Int_t incry = (tnorm[ 9] < 0.) ? -1 : +1;
7593 Int_t incrz = (tnorm[10] < 0.) ? -1 : +1;
7594 Int_t ix1 = (incrx == +1) ? xaxis->GetFirst() : xaxis->GetLast();
7595 Int_t iy1 = (incry == +1) ? yaxis->GetFirst() : yaxis->GetLast();
7596 Int_t iz1 = (incrz == +1) ? zaxis->GetFirst() : zaxis->GetLast();
7597 Int_t ix2 = (incrx == +1) ? xaxis->GetLast() : xaxis->GetFirst();
7598 Int_t iy2 = (incry == +1) ? yaxis->GetLast() : yaxis->GetFirst();
7599 Int_t iz2 = (incrz == +1) ? zaxis->GetLast() : zaxis->GetFirst();
7600
7601 // Set graphic attributes (colour, style, etc.)
7606
7607 fH->SetFillStyle(1001);
7608 fH->TAttFill::Modify();
7609 fH->TAttLine::Modify();
7610 Int_t ncolors = gStyle->GetNumberOfColors();
7612
7613 // Create bin boxes and draw
7617
7618 Double_t pmin[3], pmax[3], sxyz[8][3];
7619 for (Int_t ix = ix1; ix !=ix2+incrx; ix += incrx) {
7620 pmin[0] = xaxis->GetBinLowEdge(ix);
7621 pmax[0] = xaxis->GetBinUpEdge(ix);
7622 for (Int_t iy = iy1; iy != iy2+incry; iy += incry) {
7623 pmin[1] = yaxis->GetBinLowEdge(iy);
7624 pmax[1] = yaxis->GetBinUpEdge(iy);
7625 for (Int_t iz = iz1; iz != iz2+incrz; iz += incrz) {
7626 pmin[2] = zaxis->GetBinLowEdge(iz);
7627 pmax[2] = zaxis->GetBinUpEdge(iz);
7628 Double_t w = fH->GetBinContent(fH->GetBin(ix,iy,iz));
7629 Bool_t neg = kFALSE;
7630 Int_t n = 5;
7631 if (w<0) {
7632 w = -w;
7633 neg = kTRUE;
7634 }
7635 if (w < wmin) continue;
7636 if (w > wmax) w = wmax;
7637 Double_t scale = (TMath::Power((w-wmin)/(wmax-wmin),1./3.))/2.;
7638 if (scale == 0) continue;
7639 for (Int_t i=0; i<3; ++i) {
7640 Double_t c = (pmax[i] + pmin[i])*0.5;
7641 Double_t d = (pmax[i] - pmin[i])*scale;
7642 for (Int_t k=0; k<8; ++k) { // set bin box vertices
7643 sxyz[k][i] = wxyz[k][i]*d + c;
7644 }
7645 }
7646 for (Int_t k=0; k<8; ++k) { // transform to normalized space
7647 view->WCtoNDC(&sxyz[k][0],&sxyz[k][0]);
7648 }
7649 Double_t x[8], y[8]; // draw bin box faces
7650 for (Int_t k=0; k<6; ++k) {
7651 for (Int_t i=0; i<4; ++i) {
7652 Int_t iv = iface[k][i];
7653 x[i] = sxyz[iv][0];
7654 y[i] = sxyz[iv][1];
7655 }
7656 x[4] = x[0] ; y[4] = y[0];
7657 if (neg) {
7658 x[5] = x[2] ; y[5] = y[2];
7659 x[6] = x[3] ; y[6] = y[3];
7660 x[7] = x[1] ; y[7] = y[1];
7661 n = 8;
7662 } else {
7663 n = 5;
7664 }
7665 Double_t z = (x[2]-x[0])*(y[3]-y[1]) - (y[2]-y[0])*(x[3]-x[1]);
7666 if (z <= 0.) continue;
7667 if (iopt == 2) {
7668 theColor = ncolors*((w-wmin)/(wmax-wmin)) -1;
7670 } else {
7671 if (k == 3 || k == 5) {
7673 } else if (k == 0 || k == 1) {
7675 } else {
7677 }
7678 }
7679 fH->TAttFill::Modify();
7680 gPad->PaintFillArea(4, x, y);
7681 if (iopt != 3)gPad->PaintPolyLine(n, x, y);
7682 }
7683 }
7684 }
7685 }
7686
7687 // Draw front surfaces of frame box
7688 if (Hoption.FrontBox) fLego->FrontBox(90);
7689
7690 // Draw axis and title
7691 if (!Hoption.Axis && !Hoption.Same) {
7692 TGaxis axis;
7693 PaintLegoAxis(&axis, 90);
7694 }
7695 PaintTitle();
7696
7697 // Draw palette. if needed.
7698 if (Hoption.Zscale) {
7699 Int_t ndiv = fH->GetContour();
7700 if (ndiv == 0 ) {
7701 ndiv = gStyle->GetNumberContours();
7702 fH->SetContour(ndiv);
7703 }
7704 PaintPalette();
7705 }
7706
7707 //Draw stats and fit results
7708 TF1 *fit = nullptr;
7709 TIter next(fFunctions);
7710 while (auto obj = next()) {
7711 if (obj->InheritsFrom(TF1::Class())) {
7712 fit = (TF1*)obj;
7713 break;
7714 }
7715 }
7716 if ((Hoption.Same%10) != 1) {
7717 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7719 }
7720 }
7721
7722 fLego.reset();
7723
7726 fH->TAttFill::Modify();
7727}
7728
7729////////////////////////////////////////////////////////////////////////////////
7730/// [Control function to draw a 3D histogram with boxes.](\ref HP25)
7731
7733{
7734 // Predefined box structure
7735 Double_t wxyz[8][3] = {
7736 {-1,-1,-1}, {1,-1,-1}, {1,1,-1}, {-1,1,-1}, // bottom vertices
7737 {-1,-1, 1}, {1,-1, 1}, {1,1, 1}, {-1,1, 1} // top vertices
7738 };
7739 Int_t iface[6][4] = {
7740 {0,3,2,1}, {4,5,6,7}, // bottom and top faces
7741 {0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7} // side faces
7742 };
7743 Double_t normal[6][3] = {
7744 {0,0,-1}, {0,0,1}, // Z-, Z+
7745 {0,-1,0}, {1,0,0}, {0,1,0}, {-1,0,0} // Y-, X+, Y+, X-
7746 };
7747
7748 // Define dimensions of world space
7749 TAxis *xaxis = fH->GetXaxis();
7750 TAxis *yaxis = fH->GetYaxis();
7751 TAxis *zaxis = fH->GetZaxis();
7752
7753 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7754 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7755 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7756 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7757 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7758 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7759
7760 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7761
7762 // Set view
7763 TView *view = gPad ? gPad->GetView() : nullptr;
7764 if (!view) {
7765 Error("PaintH3", "no TView in current pad");
7766 return;
7767 }
7768 Double_t thedeg = 90 - gPad->GetTheta();
7769 Double_t phideg = -90 - gPad->GetPhi();
7770 Double_t psideg = view->GetPsi();
7771 Int_t irep;
7772 view->SetView(phideg, thedeg, psideg, irep);
7773
7774 Int_t backcolor = gPad->GetFrameFillColor();
7775 view->PadRange(backcolor);
7776
7777 // Draw front surfaces of frame box
7778 if (Hoption.FrontBox) {
7779 fLego->InitMoveScreen(-1.1,1.1);
7781 }
7782
7783 // Initialize hidden line removal algorithm "raster screen"
7784 fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
7785
7786 // Define order of drawing
7787 Double_t *tnorm = view->GetTnorm();
7788 if (!tnorm) return;
7789 Int_t incrx = (tnorm[ 8] < 0.) ? +1 : -1;
7790 Int_t incry = (tnorm[ 9] < 0.) ? +1 : -1;
7791 Int_t incrz = (tnorm[10] < 0.) ? +1 : -1;
7792 Int_t ix1 = (incrx == +1) ? xaxis->GetFirst() : xaxis->GetLast();
7793 Int_t iy1 = (incry == +1) ? yaxis->GetFirst() : yaxis->GetLast();
7794 Int_t iz1 = (incrz == +1) ? zaxis->GetFirst() : zaxis->GetLast();
7795 Int_t ix2 = (incrx == +1) ? xaxis->GetLast() : xaxis->GetFirst();
7796 Int_t iy2 = (incry == +1) ? yaxis->GetLast() : yaxis->GetFirst();
7797 Int_t iz2 = (incrz == +1) ? zaxis->GetLast() : zaxis->GetFirst();
7798
7799 // Set line attributes (colour, style, etc.)
7800 fH->TAttLine::Modify();
7801
7802 // Create bin boxes and draw
7803 const Int_t NTMAX = 100;
7804 Double_t tt[NTMAX][2];
7808 Double_t pmin[3], pmax[3], sxyz[8][3], pp[4][2];
7809 for (Int_t ix = ix1; ix !=ix2+incrx; ix += incrx) {
7810 pmin[0] = xaxis->GetBinLowEdge(ix);
7811 pmax[0] = xaxis->GetBinUpEdge(ix);
7812 for (Int_t iy = iy1; iy != iy2+incry; iy += incry) {
7813 pmin[1] = yaxis->GetBinLowEdge(iy);
7814 pmax[1] = yaxis->GetBinUpEdge(iy);
7815 for (Int_t iz = iz1; iz != iz2+incrz; iz += incrz) {
7816 pmin[2] = zaxis->GetBinLowEdge(iz);
7817 pmax[2] = zaxis->GetBinUpEdge(iz);
7818 Double_t w = fH->GetBinContent(fH->GetBin(ix,iy,iz));
7819 Bool_t neg = kFALSE;
7820 if (w<0) {
7821 w = -w;
7822 neg = kTRUE;
7823 }
7824 if (w < wmin) continue;
7825 if (w > wmax) w = wmax;
7826 Double_t scale = (TMath::Power((w-wmin)/(wmax-wmin),1./3.))/2.;
7827 if (scale == 0) continue;
7828 for (Int_t i=0; i<3; ++i) {
7829 Double_t c = (pmax[i] + pmin[i])*0.5;
7830 Double_t d = (pmax[i] - pmin[i])*scale;
7831 for (Int_t k=0; k<8; ++k) { // set bin box vertices
7832 sxyz[k][i] = wxyz[k][i]*d + c;
7833 }
7834 }
7835 for (Int_t k=0; k<8; ++k) { // transform to normalized space
7836 view->WCtoNDC(&sxyz[k][0],&sxyz[k][0]);
7837 }
7838 for (Int_t k=0; k<6; ++k) { // draw box faces
7839 Double_t zn;
7840 view->FindNormal(normal[k][0], normal[k][1], normal[k][2], zn);
7841 if (zn <= 0) continue;
7842 for (Int_t i=0; i<4; ++i) {
7843 Int_t ip = iface[k][i];
7844 pp[i][0] = sxyz[ip][0];
7845 pp[i][1] = sxyz[ip][1];
7846 }
7847 for (Int_t i=0; i<4; ++i) {
7848 Int_t i1 = i;
7849 Int_t i2 = (i == 3) ? 0 : i + 1;
7850 Int_t nt;
7851 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7852 Double_t xdel = pp[i2][0] - pp[i1][0];
7853 Double_t ydel = pp[i2][1] - pp[i1][1];
7854 Double_t x[2], y[2];
7855 for (Int_t it = 0; it < nt; ++it) {
7856 x[0] = pp[i1][0] + xdel*tt[it][0];
7857 y[0] = pp[i1][1] + ydel*tt[it][0];
7858 x[1] = pp[i1][0] + xdel*tt[it][1];
7859 y[1] = pp[i1][1] + ydel*tt[it][1];
7860 gPad->PaintPolyLine(2, x, y);
7861 }
7862 }
7863 if (neg) {
7864 Int_t i1 = 0;
7865 Int_t i2 = 2;
7866 Int_t nt;
7867 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7868 Double_t xdel = pp[i2][0] - pp[i1][0];
7869 Double_t ydel = pp[i2][1] - pp[i1][1];
7870 Double_t x[2], y[2];
7871 for (Int_t it = 0; it < nt; ++it) {
7872 x[0] = pp[i1][0] + xdel*tt[it][0];
7873 y[0] = pp[i1][1] + ydel*tt[it][0];
7874 x[1] = pp[i1][0] + xdel*tt[it][1];
7875 y[1] = pp[i1][1] + ydel*tt[it][1];
7876 gPad->PaintPolyLine(2, x, y);
7877 }
7878 i1 = 1;
7879 i2 = 3;
7880 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7881 xdel = pp[i2][0] - pp[i1][0];
7882 ydel = pp[i2][1] - pp[i1][1];
7883 for (Int_t it = 0; it < nt; ++it) {
7884 x[0] = pp[i1][0] + xdel*tt[it][0];
7885 y[0] = pp[i1][1] + ydel*tt[it][0];
7886 x[1] = pp[i1][0] + xdel*tt[it][1];
7887 y[1] = pp[i1][1] + ydel*tt[it][1];
7888 gPad->PaintPolyLine(2, x, y);
7889 }
7890 }
7891 fLego->FillPolygonBorder(4, &pp[0][0]); // update raster screen
7892 }
7893 }
7894 }
7895 }
7896
7897 // Draw frame box
7898 if (Hoption.BackBox) {
7899 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
7901 fLego->BackBox(90);
7902 }
7903
7904 if (Hoption.FrontBox) fLego->FrontBox(90);
7905
7906 // Draw axis and title
7907 if (!Hoption.Axis && !Hoption.Same) {
7908 TGaxis axis;
7909 PaintLegoAxis(&axis, 90);
7910 }
7911 PaintTitle();
7912
7913 //Draw stats and fit results
7914 TF1 *fit = nullptr;
7915 TIter next(fFunctions);
7916 while (auto obj = next()) {
7917 if (obj->InheritsFrom(TF1::Class())) {
7918 fit = (TF1*)obj;
7919 break;
7920 }
7921 }
7922 if ((Hoption.Same%10) != 1) {
7923 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7925 }
7926 }
7927
7928 fLego.reset();
7929}
7930
7931////////////////////////////////////////////////////////////////////////////////
7932/// [Control function to draw a 3D histogram with Iso Surfaces.](\ref HP25)
7933
7935{
7936
7937 const Double_t ydiff = 1;
7938 const Double_t yligh1 = 10;
7939 const Double_t qa = 0.15;
7940 const Double_t qd = 0.15;
7941 const Double_t qs = 0.8;
7943 Int_t i, irep;
7944 Int_t nbcol = 28;
7945 Int_t icol1 = 201;
7946 Int_t ic1 = icol1;
7947 Int_t ic2 = ic1+nbcol;
7948 Int_t ic3 = ic2+nbcol;
7949
7950 TAxis *xaxis = fH->GetXaxis();
7951 TAxis *yaxis = fH->GetYaxis();
7952 TAxis *zaxis = fH->GetZaxis();
7953
7954 Int_t nx = fH->GetNbinsX();
7955 Int_t ny = fH->GetNbinsY();
7956 Int_t nz = fH->GetNbinsZ();
7957
7958 std::vector<Double_t> x(nx);
7959 std::vector<Double_t> y(ny);
7960 std::vector<Double_t> z(nz);
7961
7962 for (i=0; i<nx; i++) x[i] = xaxis->GetBinCenter(i+1);
7963 for (i=0; i<ny; i++) y[i] = yaxis->GetBinCenter(i+1);
7964 for (i=0; i<nz; i++) z[i] = zaxis->GetBinCenter(i+1);
7965
7966 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7967 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7968 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7969 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7970 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7971 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7972
7973 Double_t s[3];
7974 s[0] = fH->GetSumOfWeights()/(fH->GetNbinsX()*fH->GetNbinsY()*fH->GetNbinsZ());
7975 s[1] = 0.5*s[0];
7976 s[2] = 1.5*s[0];
7977
7978 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7979
7980 TView *view = gPad ? gPad->GetView() : nullptr;
7981 if (!view) {
7982 Error("PaintH3Iso", "no TView in current pad");
7983 return;
7984 }
7985 Double_t thedeg = 90 - gPad->GetTheta();
7986 Double_t phideg = -90 - gPad->GetPhi();
7987 Double_t psideg = view->GetPsi();
7988 view->SetView(phideg, thedeg, psideg, irep);
7989
7990 Int_t backcolor = gPad->GetFrameFillColor();
7991 if (Hoption.System != kCARTESIAN) backcolor = 0;
7992 view->PadRange(backcolor);
7993
7994 Double_t dcol = 0.5/Double_t(nbcol);
7995 TColor *colref = gROOT->GetColor(fH->GetFillColor());
7996 if (!colref) {
7997 return;
7998 }
7999 Float_t r, g, b, hue, light, satur;
8000 colref->GetRGB(r,g,b);
8002 TColor *acol;
8003 for (Int_t col=0;col<nbcol;col++) {
8004 acol = gROOT->GetColor(col+icol1);
8005 TColor::HLStoRGB(hue, .4+col*dcol, satur, r, g, b);
8006 if (acol) acol->SetRGB(r, g, b);
8007 }
8008
8009 fLego->InitMoveScreen(-1.1,1.1);
8010
8011 if (Hoption.BackBox) {
8012 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
8014 fLego->BackBox(90);
8015 }
8016
8017 fLego->LightSource(0, ydiff, 0, 0, 0, irep);
8018 fLego->LightSource(1, yligh1, 1, 1, 1, irep);
8019 fLego->SurfaceProperty(qa, qd, qs, 1, irep);
8020 fmin = ydiff*qa;
8021 fmax = ydiff*qa + (yligh1+0.1)*(qd+qs);
8022 fLego->SetIsoSurfaceParameters(fmin, fmax, nbcol, ic1, ic2, ic3);
8023
8024 fLego->IsoSurface(1, s, nx, ny, nz, x.data(), y.data(), z.data(), "BF");
8025
8026 if (Hoption.FrontBox) {
8027 fLego->InitMoveScreen(-1.1,1.1);
8029 fLego->FrontBox(90);
8030 }
8031 if (!Hoption.Axis && !Hoption.Same) {
8032 TGaxis axis;
8033 PaintLegoAxis(&axis, 90);
8034 }
8035
8036 PaintTitle();
8037
8038 //Draw stats and fit results
8039 TF1 *fit = nullptr;
8040 TIter next(fFunctions);
8041 while (auto obj = next()) {
8042 if (obj->InheritsFrom(TF1::Class())) {
8043 fit = (TF1*)obj;
8044 break;
8045 }
8046 }
8047 if ((Hoption.Same%10) != 1) {
8048 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
8050 }
8051 }
8052
8053 fLego.reset();
8054}
8055
8056////////////////////////////////////////////////////////////////////////////////
8057/// [Control function to draw a 2D histogram as a lego plot.](\ref HP17)
8058
8060{
8061
8062 Int_t raster = 1;
8063 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
8064 Int_t nx = Hparam.xlast - Hparam.xfirst + 1;
8065 Int_t ny = Hparam.ylast - Hparam.yfirst + 1;
8066 Double_t zmin = Hparam.zmin;
8067 Double_t zmax = Hparam.zmax;
8072 Double_t dangle = 10*3.141592/180; //Delta angle for Rapidity option
8073 Double_t deltaz = TMath::Abs(zmin);
8074 if (deltaz == 0) deltaz = 1;
8075 if (zmin >= zmax) {
8076 zmin -= 0.5*deltaz;
8077 zmax += 0.5*deltaz;
8078 }
8079 Double_t z1c = zmin;
8080 Double_t z2c = zmin + (zmax-zmin)*(1+gStyle->GetHistTopMargin());
8081
8082 // Compute the lego limits and instantiate a lego object
8083 fXbuf[0] = -1;
8084 fYbuf[0] = 1;
8085 fXbuf[1] = -1;
8086 fYbuf[1] = 1;
8087 if (Hoption.System == kPOLAR) {
8088 fXbuf[2] = z1c;
8089 fYbuf[2] = z2c;
8090 } else if (Hoption.System == kCYLINDRICAL) {
8091 if (Hoption.Logy) {
8092 if (ylab1 > 0) fXbuf[2] = TMath::Log10(ylab1);
8093 else fXbuf[2] = 0;
8094 if (ylab2 > 0) fYbuf[2] = TMath::Log10(ylab2);
8095 else fYbuf[2] = 0;
8096 } else {
8097 fXbuf[2] = ylab1;
8098 fYbuf[2] = ylab2;
8099 }
8100 z1c = 0; z2c = 1;
8101 } else if (Hoption.System == kSPHERICAL) {
8102 fXbuf[2] = -1;
8103 fYbuf[2] = 1;
8104 z1c = 0; z2c = 1;
8105 } else if (Hoption.System == kRAPIDITY) {
8106 fXbuf[2] = -1/TMath::Tan(dangle);
8107 fYbuf[2] = 1/TMath::Tan(dangle);
8108 } else {
8109 fXbuf[0] = xlab1;
8110 fYbuf[0] = xlab2;
8111 fXbuf[1] = ylab1;
8112 fYbuf[1] = ylab2;
8113 fXbuf[2] = z1c;
8114 fYbuf[2] = z2c;
8115 raster = 0;
8116 }
8117
8118 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data(), Hoption.System);
8119
8120 Int_t nids = -1;
8121 TH1 * hid = nullptr;
8122 Color_t colormain = -1, colordark = -1;
8124
8125 // LEGO3 is like LEGO1 except that the black lines around each lego are not drawn.
8126 if (Hoption.Lego == 13) {
8127 Hoption.Lego = 11;
8128 fLego->SetMesh(0);
8129 }
8130 // LEGO4 is like LEGO1 except no shadows are drawn.
8131 if (Hoption.Lego == 14) {
8132 Hoption.Lego = 11;
8134 }
8135
8136 // Initialize the levels on the Z axis
8137 Int_t ndiv = fH->GetContour();
8138 if (ndiv == 0 ) {
8139 ndiv = gStyle->GetNumberContours();
8140 fH->SetContour(ndiv);
8141 }
8142 Int_t ndivz = TMath::Abs(ndiv);
8143 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
8144
8145 // Initialize colors
8146 if (!fStack) {
8147 fLego->SetEdgeAtt(fH->GetLineColor(),fH->GetLineStyle(),fH->GetLineWidth(),0);
8148 } else {
8149 for (Int_t id=0;id<=fStack->GetSize();id++) {
8150 hid = (TH1*)fStack->At((id==0)?id:id-1);
8151 fLego->SetEdgeAtt(hid->GetLineColor(),hid->GetLineStyle(),hid->GetLineWidth(),id);
8152 }
8153 }
8154
8155 if (Hoption.Lego == 11) {
8156 nids = 1;
8157 if (fStack) nids = fStack->GetSize();
8158 hid = fH;
8159 for (Int_t id=0;id<=nids;id++) {
8160 if (id > 0 && fStack) hid = (TH1*)fStack->At(id-1);
8161 colormain = hid->GetFillColor();
8162 if (colormain == 1) colormain = 17; //avoid drawing with black
8164 else colordark = colormain;
8165 fLego->SetColorMain(colormain,id);
8166 fLego->SetColorDark(colordark,id);
8167 if (id <= 1) fLego->SetColorMain(colormain,-1); // Set Bottom color
8168 if (id == nids) fLego->SetColorMain(colormain,99); // Set Top color
8169 }
8170 }
8171
8172 // Now ready to draw the lego plot
8173 Int_t irep = 0;
8174
8175 TView *view = gPad ? gPad->GetView() : nullptr;
8176 if (!view) {
8177 Error("PaintLego", "no TView in current pad");
8178 return;
8179 }
8180
8181 Double_t thedeg = 90 - gPad->GetTheta();
8182 Double_t phideg = -90 - gPad->GetPhi();
8183 Double_t psideg = view->GetPsi();
8184 view->SetView(phideg, thedeg, psideg, irep);
8185
8186 fLego->SetLineColor(kBlack); // zgrid color for lego1 & lego2
8187 fLego->SetFillStyle(fH->GetFillStyle());
8188
8189 // Set color/style for back box
8190 fLego->SetFillStyle(gPad->GetFrameFillStyle());
8191 fLego->SetFillColor(gPad->GetFrameFillColor());
8192 fLego->TAttFill::Modify();
8193
8194 Int_t backcolor = gPad->GetFrameFillColor();
8195 if (Hoption.System != kCARTESIAN) backcolor = 0;
8196 view->PadRange(backcolor);
8197
8198 fLego->SetFillStyle(fH->GetFillStyle());
8199 fLego->SetFillColor(fH->GetFillColor());
8200 fLego->TAttFill::Modify();
8201
8202 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
8203
8204 if (raster) fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
8205 else fLego->InitMoveScreen(-1.1,1.1);
8206
8207 if (Hoption.Lego == 19) {
8209 if (Hoption.BackBox) fLego->BackBox(90);
8210 if (Hoption.FrontBox) fLego->FrontBox(90);
8211 if (!Hoption.Axis) { TGaxis axis; PaintLegoAxis(&axis, 90); }
8212 return;
8213 }
8214
8215 if (Hoption.Lego == 11 || Hoption.Lego == 12) {
8218 fLego->BackBox(90);
8219 }
8220 }
8221
8222 if (Hoption.Lego == 12) DefineColorLevels(ndivz);
8223
8224 fLego->SetLegoFunction(&TPainter3dAlgorithms::LegoFunction);
8226 if (Hoption.Lego == 11) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode3);
8227 if (Hoption.Lego == 12) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode2);
8228 if (Hoption.System == kPOLAR) {
8229 if (Hoption.Lego == 1) fLego->LegoPolar(1,nx,ny,"FB");
8230 if (Hoption.Lego == 11) fLego->LegoPolar(1,nx,ny,"BF");
8231 if (Hoption.Lego == 12) fLego->LegoPolar(1,nx,ny,"BF");
8232 } else if (Hoption.System == kCYLINDRICAL) {
8233 if (Hoption.Lego == 1) fLego->LegoCylindrical(1,nx,ny,"FB");
8234 if (Hoption.Lego == 11) fLego->LegoCylindrical(1,nx,ny,"BF");
8235 if (Hoption.Lego == 12) fLego->LegoCylindrical(1,nx,ny,"BF");
8236 } else if (Hoption.System == kSPHERICAL) {
8237 if (Hoption.Lego == 1) fLego->LegoSpherical(0,1,nx,ny,"FB");
8238 if (Hoption.Lego == 11) fLego->LegoSpherical(0,1,nx,ny,"BF");
8239 if (Hoption.Lego == 12) fLego->LegoSpherical(0,1,nx,ny,"BF");
8240 } else if (Hoption.System == kRAPIDITY) {
8241 if (Hoption.Lego == 1) fLego->LegoSpherical(1,1,nx,ny,"FB");
8242 if (Hoption.Lego == 11) fLego->LegoSpherical(1,1,nx,ny,"BF");
8243 if (Hoption.Lego == 12) fLego->LegoSpherical(1,1,nx,ny,"BF");
8244 } else {
8245 if (Hoption.Lego == 1) {
8247 fLego->LegoCartesian(90,nx,ny,"FB");}
8248 if (Hoption.Lego == 11) fLego->LegoCartesian(90,nx,ny,"BF");
8249 if (Hoption.Lego == 12) fLego->LegoCartesian(90,nx,ny,"BF");
8250 }
8251
8252 if (Hoption.Lego == 1 || Hoption.Lego == 11) {
8255 fLego->BackBox(90);
8256 }
8257 }
8258 if (Hoption.System == kCARTESIAN) {
8259 fLego->InitMoveScreen(-1.1,1.1);
8261 if (Hoption.FrontBox) fLego->FrontBox(90);
8262 }
8263 if (!Hoption.Axis && !Hoption.Same) {
8264 TGaxis axis;
8265 PaintLegoAxis(&axis, 90);
8266 }
8268 fLego.reset();
8269}
8270
8271////////////////////////////////////////////////////////////////////////////////
8272/// Draw the axis for legos and surface plots.
8273
8275{
8276
8277 static Double_t epsil = 0.001;
8278
8281 Double_t r[24] /* was [3][8] */;
8282 Int_t ndivx, ndivy, ndivz, i;
8283 Double_t x1[3], x2[3], y1[3], y2[3], z1[3], z2[3], av[24] /* was [3][8] */;
8284 static char chopax[8], chopay[8], chopaz[8];
8285 Int_t ix1, ix2, iy1, iy2, iz1, iz2;
8286 Double_t rad;
8287
8288 TView *view = gPad ? gPad->GetView() : nullptr;
8289 if (!view) {
8290 Error("PaintLegoAxis", "no TView in current pad");
8291 return;
8292 }
8293
8294 // In polar coordinates, draw a short line going from the external circle
8295 // corresponding to r = 1 up to r = 1.1
8296 if (Hoption.System == kPOLAR) {
8297 r[0] = 1;
8298 r[1] = 0;
8299 r[2] = 0;
8300 view->WCtoNDC(r, x1);
8301 r[0] = 1.1;
8302 r[1] = 0;
8303 r[2] = 0;
8304 view->WCtoNDC(r, x2);
8305 gPad->PaintLine(x1[0],x1[1],x2[0],x2[1]);
8306 return;
8307 }
8308
8309 if (Hoption.System != kCARTESIAN) return;
8310
8311 rad = TMath::ATan(1.) * 4. /180.;
8312 cosa = TMath::Cos(ang*rad);
8313 sina = TMath::Sin(ang*rad);
8314
8315 view->AxisVertex(ang, av, ix1, ix2, iy1, iy2, iz1, iz2);
8316 for (i = 1; i <= 8; ++i) {
8317 r[i*3 - 3] = av[i*3 - 3] + av[i*3 - 2]*cosa;
8318 r[i*3 - 2] = av[i*3 - 2]*sina;
8319 r[i*3 - 1] = av[i*3 - 1];
8320 }
8321
8322 view->WCtoNDC(&r[ix1*3 - 3], x1);
8323 view->WCtoNDC(&r[ix2*3 - 3], x2);
8324 view->WCtoNDC(&r[iy1*3 - 3], y1);
8325 view->WCtoNDC(&r[iy2*3 - 3], y2);
8326 view->WCtoNDC(&r[iz1*3 - 3], z1);
8327 view->WCtoNDC(&r[iz2*3 - 3], z2);
8328
8329 view->SetAxisNDC(x1, x2, y1, y2, z1, z2);
8330
8331 Double_t *rmin = view->GetRmin();
8332 Double_t *rmax = view->GetRmax();
8333 if (!rmin || !rmax) return;
8334
8335 // Initialize the axis options
8336 if (x1[0] > x2[0]) strlcpy(chopax, "SDH=+",8);
8337 else strlcpy(chopax, "SDH=-",8);
8338 if (y1[0] > y2[0]) strlcpy(chopay, "SDH=+",8);
8339 else strlcpy(chopay, "SDH=-",8);
8340 if (z2[1] > z1[1]) strlcpy(chopaz, "SDH=+",8);
8341 else strlcpy(chopaz, "SDH=-",8);
8342
8343 // Option LOG is required ?
8344 if (Hoption.Logx) strlcat(chopax,"G",8);
8345 if (Hoption.Logy) strlcat(chopay,"G",8);
8346 if (Hoption.Logz) strlcat(chopaz,"G",8);
8347
8348 // Initialize the number of divisions. If the
8349 // number of divisions is negative, option 'N' is required.
8353 if (ndivx < 0) {
8355 strlcat(chopax, "N",8);
8356 }
8357 if (ndivy < 0) {
8359 strlcat(chopay, "N",8);
8360 }
8361 if (ndivz < 0) {
8363 strlcat(chopaz, "N",8);
8364 }
8365
8366 // Set Axis attributes.
8367 // The variable SCALE rescales the VSIZ
8368 // in order to have the same label size for all angles.
8369
8370 axis->SetLineWidth(1);
8371
8372 // X axis drawing
8373 if (TMath::Abs(x1[0] - x2[0]) >= epsil || TMath::Abs(x1[1] - x2[1]) > epsil) {
8376 if (Hoption.Logx && !fH->InheritsFrom(TH3::Class())) {
8377 bmin = TMath::Power(10, rmin[0]);
8378 bmax = TMath::Power(10, rmax[0]);
8379 } else {
8380 bmin = rmin[0];
8381 bmax = rmax[0];
8382 }
8383 // Option time display is required ?
8384 if (fXaxis->GetTimeDisplay()) {
8385 strlcat(chopax,"t",8);
8386 if (strlen(fXaxis->GetTimeFormatOnly()) == 0) {
8388 } else {
8390 }
8391 }
8392 axis->SetOption(chopax);
8393 axis->PaintAxis(x1[0], x1[1], x2[0], x2[1], bmin, bmax, ndivx, chopax);
8394 }
8395
8396 // Y axis drawing
8397 if (TMath::Abs(y1[0] - y2[0]) >= epsil || TMath::Abs(y1[1] - y2[1]) > epsil) {
8400 if (fYaxis->GetTitleOffset() == 0) axis->SetTitleOffset(1.5);
8401
8402 if (fH->GetDimension() < 2) {
8403 strlcpy(chopay, "V=+UN",8);
8404 ndivy = 0;
8405 }
8406 if (TMath::Abs(y1[0] - y2[0]) < epsil) {
8407 y2[0] = y1[0];
8408 }
8409 if (Hoption.Logy && !fH->InheritsFrom(TH3::Class())) {
8410 bmin = TMath::Power(10, rmin[1]);
8411 bmax = TMath::Power(10, rmax[1]);
8412 } else {
8413 bmin = rmin[1];
8414 bmax = rmax[1];
8415 }
8416 // Option time display is required ?
8417 if (fYaxis->GetTimeDisplay()) {
8418 strlcat(chopay,"t",8);
8419 if (strlen(fYaxis->GetTimeFormatOnly()) == 0) {
8421 } else {
8423 }
8424 }
8425 axis->SetOption(chopay);
8426 axis->PaintAxis(y1[0], y1[1], y2[0], y2[1], bmin, bmax, ndivy, chopay);
8427 }
8428
8429 // Z axis drawing
8430 if (TMath::Abs(z1[0] - z2[0]) >= 100*epsil || TMath::Abs(z1[1] - z2[1]) > 100*epsil) {
8432 if (Hoption.Logz && !fH->InheritsFrom(TH3::Class())) {
8433 bmin = TMath::Power(10, rmin[2]);
8434 bmax = TMath::Power(10, rmax[2]);
8435 } else {
8436 bmin = rmin[2];
8437 bmax = rmax[2];
8438 }
8439 // Option time display is required ?
8440 if (fZaxis->GetTimeDisplay()) {
8441 strlcat(chopaz,"t",8);
8442 if (strlen(fZaxis->GetTimeFormatOnly()) == 0) {
8444 } else {
8446 }
8447 }
8448 axis->SetOption(chopaz);
8450 if (ztit.Index(";")>0) {
8451 ztit.Remove(ztit.Index(";"),ztit.Length());
8452 axis->SetTitle(ztit.Data());
8453 }
8454 axis->PaintAxis(z1[0], z1[1], z2[0], z2[1], bmin, bmax, ndivz, chopaz);
8455 }
8456
8457 //fH->SetLineStyle(1); /// otherwise fEdgeStyle[i] gets overwritten!
8458}
8459
8460////////////////////////////////////////////////////////////////////////////////
8461/// [Paint the color palette on the right side of the pad.](\ref HP22)
8462
8464{
8466 TView *view = gPad ? gPad->GetView() : nullptr;
8467 if (palette) {
8468 if (view) {
8469 if (!palette->TestBit(TPaletteAxis::kHasView)) {
8471 delete palette; palette = nullptr;
8472 }
8473 } else {
8474 if (palette->TestBit(TPaletteAxis::kHasView)) {
8476 delete palette; palette = nullptr;
8477 }
8478 }
8479 // make sure the histogram member of the palette is setup correctly. It may not be after a Clone()
8480 if (palette && !palette->GetHistogram()) palette->SetHistogram(fH);
8481 }
8482
8483 if (!palette) {
8484 Double_t xup = gPad->GetUxmax();
8485 Double_t x2 = gPad->PadtoX(gPad->GetX2());
8486 Double_t ymin = gPad->PadtoY(gPad->GetUymin());
8487 Double_t ymax = gPad->PadtoY(gPad->GetUymax());
8488 Double_t xr = 0.05*(gPad->GetX2() - gPad->GetX1());
8489 Double_t xmin = gPad->PadtoX(xup +0.1*xr);
8490 Double_t xmax = gPad->PadtoX(xup + xr);
8491 if (xmax > x2) xmax = gPad->PadtoX(gPad->GetX2()-0.01*xr);
8494 palette->Paint();
8495 }
8496}
8497
8498////////////////////////////////////////////////////////////////////////////////
8499/// [Control function to draw a 2D histogram as a scatter plot.](\ref HP11)
8500
8502{
8503
8504 fH->TAttMarker::Modify();
8505
8506 Int_t k, marker;
8507 Double_t dz, z, xk,xstep, yk, ystep;
8508 Double_t scale = 1;
8510 Double_t zmax = fH->GetMaximum();
8511 Double_t zmin = fH->GetMinimum();
8512 if (zmin == 0 && zmax == 0) return;
8513 if (zmin == zmax) {
8514 zmax += 0.1*TMath::Abs(zmax);
8515 zmin -= 0.1*TMath::Abs(zmin);
8516 }
8518 if (Hoption.Logz) {
8519 if (zmin > 0) zmin = TMath::Log10(zmin);
8520 else zmin = 0;
8521 if (zmax > 0) zmax = TMath::Log10(zmax);
8522 else zmax = 0;
8523 if (zmin == 0 && zmax == 0) return;
8524 dz = zmax - zmin;
8525 scale = 100/dz;
8526 if (ncells > 10000) scale /= 5;
8527 ltest = kTRUE;
8528 } else {
8529 dz = zmax - zmin;
8530 if (dz >= kNMAX || zmax < 1) {
8531 scale = (kNMAX-1)/dz;
8532 if (ncells > 10000) scale /= 5;
8533 ltest = kTRUE;
8534 }
8535 }
8536 if (fH->GetMinimumStored() == -1111) {
8538 if (Hoption.MinimumZero) {
8539 if (zmin >= 0) zmin = 0;
8540 else zmin -= yMARGIN*(zmax-zmin);
8541 } else {
8542 Double_t dzmin = yMARGIN*(zmax-zmin);
8543 if (zmin >= 0 && (zmin-dzmin <= 0)) zmin = 0;
8544 else zmin -= dzmin;
8545 }
8546 }
8547
8548 TString opt = option;
8549 opt.ToLower();
8550 if (opt.Contains("scat=")) {
8551 char optscat[100];
8552 strlcpy(optscat,opt.Data(),100);
8553 char *oscat = strstr(optscat,"scat=");
8554 char *blank = strstr(oscat," "); if (blank) *blank = 0;
8555 sscanf(oscat+5,"%lg",&scale);
8556 }
8557 // use an independent instance of a random generator
8558 // instead of gRandom to avoid conflicts and
8559 // to get same random numbers when drawing the same histogram
8561 marker=0;
8562 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
8565 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
8566 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
8567 xk = fXaxis->GetBinLowEdge(i);
8568 xstep = fXaxis->GetBinWidth(i);
8569 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
8570 z = fH->GetBinContent(bin);
8571 if (z < zmin) z = zmin;
8572 if (z > zmax) z = zmax;
8573 if (Hoption.Logz) {
8574 if (z > 0) z = TMath::Log10(z) - zmin;
8575 } else {
8576 z -= zmin;
8577 }
8578 if (z <= 0) continue;
8579 k = Int_t(z*scale);
8580 if (ltest) k++;
8581 if (k > 0) {
8582 for (Int_t loop=0; loop<k; loop++) {
8583 if (k+marker >= kNMAX) {
8584 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
8585 marker=0;
8586 }
8587 fXbuf[marker] = (random.Rndm()*xstep) + xk;
8588 fYbuf[marker] = (random.Rndm()*ystep) + yk;
8589 if (Hoption.Logx) {
8590 if (fXbuf[marker] > 0) fXbuf[marker] = TMath::Log10(fXbuf[marker]);
8591 else break;
8592 }
8593 if (Hoption.Logy) {
8594 if (fYbuf[marker] > 0) fYbuf[marker] = TMath::Log10(fYbuf[marker]);
8595 else break;
8596 }
8597 if (fXbuf[marker] < gPad->GetUxmin()) break;
8598 if (fYbuf[marker] < gPad->GetUymin()) break;
8599 if (fXbuf[marker] > gPad->GetUxmax()) break;
8600 if (fYbuf[marker] > gPad->GetUymax()) break;
8601 marker++;
8602 }
8603 }
8604 }
8605 }
8606 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
8607
8609}
8610
8611////////////////////////////////////////////////////////////////////////////////
8612/// Static function to paint special objects like vectors and matrices.
8613/// This function is called via `gROOT->ProcessLine` to paint these objects
8614/// without having a direct dependency of the graphics or histogramming
8615/// system.
8616
8618{
8619
8620 if (!obj) return;
8623
8624 if (obj->InheritsFrom(TMatrixFBase::Class())) {
8625 // case TMatrixF
8626 TH2F *R__TMatrixFBase = new TH2F((TMatrixFBase &)*obj);
8627 R__TMatrixFBase->SetBit(kCanDelete);
8628 R__TMatrixFBase->Draw(option);
8629
8630 } else if (obj->InheritsFrom(TMatrixDBase::Class())) {
8631 // case TMatrixD
8632 TH2D *R__TMatrixDBase = new TH2D((TMatrixDBase &)*obj);
8633 R__TMatrixDBase->SetBit(kCanDelete);
8634 R__TMatrixDBase->Draw(option);
8635
8636 } else if (obj->InheritsFrom(TVectorF::Class())) {
8637 //case TVectorF
8638 TH1F *R__TVectorF = new TH1F((TVectorF &)*obj);
8639 R__TVectorF->SetBit(kCanDelete);
8640 R__TVectorF->Draw(option);
8641
8642 } else if (obj->InheritsFrom(TVectorD::Class())) {
8643 //case TVectorD
8644 TH1D *R__TVectorD = new TH1D((TVectorD &)*obj);
8645 R__TVectorD->SetBit(kCanDelete);
8646 R__TVectorD->Draw(option);
8647 }
8648
8649 TH1::AddDirectory(status);
8650}
8651
8652////////////////////////////////////////////////////////////////////////////////
8653/// [Draw the statistics box for 1D and profile histograms.](\ref HP07)
8654
8656{
8657 TString tt, tf;
8658 Int_t dofit;
8659 TPaveStats *stats = nullptr;
8660 TIter next(fFunctions);
8661 while (auto obj = next()) {
8662 if (obj->InheritsFrom(TPaveStats::Class())) {
8663 stats = (TPaveStats*)obj;
8664 break;
8665 }
8666 }
8667
8668 if (stats && dostat) {
8669 dofit = stats->GetOptFit();
8670 dostat = stats->GetOptStat();
8671 } else {
8672 dofit = gStyle->GetOptFit();
8673 }
8674 if (!dofit) fit = nullptr;
8675 if (dofit == 1) dofit = 111;
8676 if (dostat == 1) dostat = 1111;
8677 Int_t print_name = dostat%10;
8678 Int_t print_entries = (dostat/10)%10;
8679 Int_t print_mean = (dostat/100)%10;
8680 Int_t print_stddev = (dostat/1000)%10;
8681 Int_t print_under = (dostat/10000)%10;
8682 Int_t print_over = (dostat/100000)%10;
8683 Int_t print_integral= (dostat/1000000)%10;
8684 Int_t print_skew = (dostat/10000000)%10;
8685 Int_t print_kurt = (dostat/100000000)%10;
8689 Int_t print_fval = dofit%10;
8690 Int_t print_ferrors = (dofit/10)%10;
8691 Int_t print_fchi2 = (dofit/100)%10;
8692 Int_t print_fprob = (dofit/1000)%10;
8694 if (fit) {
8695 if (print_fval < 2) nlinesf += fit->GetNumberFreeParameters();
8696 else nlinesf += fit->GetNpar();
8697 }
8699
8700 // Pavetext with statistics
8701 Bool_t done = kFALSE;
8702 if (!dostat && !fit) {
8703 if (stats) { fFunctions->Remove(stats); delete stats;}
8704 return;
8705 }
8707 if (fit) statw = 1.8*gStyle->GetStatW();
8709 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
8710 stath = 0.25*(nlines+nlinesf)*gStyle->GetStatH();
8711 }
8712 if (stats) {
8713 stats->Clear();
8714 done = kTRUE;
8715 } else {
8716 stats = new TPaveStats(
8719 gStyle->GetStatX(),
8720 gStyle->GetStatY(),"brNDC");
8721
8722 stats->SetParent(fH);
8723 stats->SetOptFit(dofit);
8724 stats->SetOptStat(dostat);
8725 stats->SetFillColor(gStyle->GetStatColor());
8726 stats->SetFillStyle(gStyle->GetStatStyle());
8728 stats->SetTextFont(gStyle->GetStatFont());
8729 if (gStyle->GetStatFont()%10 > 2)
8731 stats->SetFitFormat(gStyle->GetFitFormat());
8733 stats->SetName("stats");
8734
8736 stats->SetTextAlign(12);
8737 stats->SetBit(kCanDelete);
8738 stats->SetBit(kMustCleanup);
8739 }
8740 if (print_name) stats->AddText(fH->GetName());
8741 if (print_entries) {
8742 if (fH->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(fH->GetEntries()+0.5));
8743 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(fH->GetEntries()));
8744 stats->AddText(tt.Data());
8745 }
8746 if (print_mean) {
8747 if (print_mean == 1) {
8748 tf.Form("%s = %s%s",gStringMean.Data(),"%",stats->GetStatFormat());
8749 tt.Form(tf.Data(),fH->GetMean(1));
8750 } else {
8751 tf.Form("%s = %s%s #pm %s%s",gStringMean.Data(),"%",stats->GetStatFormat()
8752 ,"%",stats->GetStatFormat());
8753 tt.Form(tf.Data(),fH->GetMean(1),fH->GetMeanError(1));
8754 }
8755 stats->AddText(tt.Data());
8757 if (print_mean == 1) {
8758 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
8759 tt.Form(tf.Data(),fH->GetMean(2));
8760 } else {
8761 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
8762 ,"%",stats->GetStatFormat());
8763 tt.Form(tf.Data(),fH->GetMean(2),fH->GetMeanError(2));
8764 }
8765 stats->AddText(tt.Data());
8766 }
8767 }
8768 if (print_stddev) {
8769 if (print_stddev == 1) {
8770 tf.Form("%s = %s%s",gStringStdDev.Data(),"%",stats->GetStatFormat());
8771 tt.Form(tf.Data(),fH->GetStdDev(1));
8772 } else {
8773 tf.Form("%s = %s%s #pm %s%s",gStringStdDev.Data(),"%",stats->GetStatFormat()
8774 ,"%",stats->GetStatFormat());
8775 tt.Form(tf.Data(),fH->GetStdDev(1),fH->GetStdDevError(1));
8776 }
8777 stats->AddText(tt.Data());
8779 if (print_stddev == 1) {
8780 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
8781 tt.Form(tf.Data(),fH->GetStdDev(2));
8782 } else {
8783 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
8784 ,"%",stats->GetStatFormat());
8785 tt.Form(tf.Data(),fH->GetStdDev(2),fH->GetStdDevError(2));
8786 }
8787 stats->AddText(tt.Data());
8788 }
8789 }
8790 if (print_under) {
8791 tf.Form("%s = %s%s",gStringUnderflow.Data(),"%",stats->GetStatFormat());
8792 tt.Form(tf.Data(),fH->GetBinContent(0));
8793 stats->AddText(tt.Data());
8794 }
8795 if (print_over) {
8796 tf.Form("%s = %s%s",gStringOverflow.Data(),"%",stats->GetStatFormat());
8797 tt.Form(tf.Data(),fH->GetBinContent(fXaxis->GetNbins()+1));
8798 stats->AddText(tt.Data());
8799 }
8800 if (print_integral) {
8801 if (print_integral == 1) {
8802 tf.Form("%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
8803 tt.Form(tf.Data(),fH->Integral());
8804 } else {
8805 tf.Form("%s = %s%s",gStringIntegralBinWidth.Data(),"%",stats->GetStatFormat());
8806 tt.Form(tf.Data(),fH->Integral("width"));
8807 }
8808 stats->AddText(tt.Data());
8809 }
8810 if (print_skew) {
8811 if (print_skew == 1) {
8812 tf.Form("%s = %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat());
8813 tt.Form(tf.Data(),fH->GetSkewness(1));
8814 } else {
8815 tf.Form("%s = %s%s #pm %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat()
8816 ,"%",stats->GetStatFormat());
8817 tt.Form(tf.Data(),fH->GetSkewness(1),fH->GetSkewness(11));
8818 }
8819 stats->AddText(tt.Data());
8820 }
8821 if (print_kurt) {
8822 if (print_kurt == 1) {
8823 tf.Form("%s = %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat());
8824 tt.Form(tf.Data(),fH->GetKurtosis(1));
8825 } else {
8826 tf.Form("%s = %s%s #pm %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat()
8827 ,"%",stats->GetStatFormat());
8828 tt.Form(tf.Data(),fH->GetKurtosis(1),fH->GetKurtosis(11));
8829 }
8830 stats->AddText(tt.Data());
8831 }
8832
8833 // Draw Fit parameters
8834 if (fit) {
8835 Int_t ndf = fit->GetNDF();
8836 tf.Form("#chi^{2} / ndf = %s%s / %d","%",stats->GetFitFormat(),ndf);
8837 tt.Form(tf.Data(),fit->GetChisquare());
8838 if (print_fchi2) stats->AddText(tt.Data());
8839 if (print_fprob) {
8840 tf.Form("Prob = %s%s","%",stats->GetFitFormat());
8841 tt.Form(tf.Data(),TMath::Prob(fit->GetChisquare(),ndf));
8842 stats->AddText(tt.Data());
8843 }
8844 if (print_fval || print_ferrors) {
8846 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
8847 fit->GetParLimits(ipar,parmin,parmax);
8849 if (print_ferrors) {
8850 tf.Form("%-8s = %s%s #pm %s ", fit->GetParName(ipar), "%",stats->GetFitFormat(),
8851 GetBestFormat(fit->GetParameter(ipar), fit->GetParError(ipar), stats->GetFitFormat()));
8852 tt.Form(tf.Data(),fit->GetParameter(ipar)
8853 ,fit->GetParError(ipar));
8854 } else {
8855 tf.Form("%-8s = %s%s ",fit->GetParName(ipar), "%",stats->GetFitFormat());
8856 tt.Form(tf.Data(),fit->GetParameter(ipar));
8857 }
8858 stats->AddText(tt.Data());
8859 }
8860 }
8861 }
8862
8863 if (!done) fFunctions->Add(stats);
8864 stats->Paint(stats->GetOption());
8865}
8866
8867////////////////////////////////////////////////////////////////////////////////
8868/// [Draw the statistics box for 2D histograms.](\ref HP07)
8869
8871{
8872
8873 if (fH->GetDimension() != 2) return;
8874 TH2 *h2 = (TH2*)fH;
8875
8876 TString tt, tf;
8877 Int_t dofit;
8878 TPaveStats *stats = nullptr;
8879 TIter next(fFunctions);
8880 while (auto obj = next()) {
8881 if (obj->InheritsFrom(TPaveStats::Class())) {
8882 stats = (TPaveStats*)obj;
8883 break;
8884 }
8885 }
8886 if (stats && dostat) {
8887 dofit = stats->GetOptFit();
8888 dostat = stats->GetOptStat();
8889 } else {
8890 dofit = gStyle->GetOptFit();
8891 }
8892 if (dostat == 1) dostat = 1111;
8893 Int_t print_name = dostat%10;
8894 Int_t print_entries = (dostat/10)%10;
8895 Int_t print_mean = (dostat/100)%10;
8896 Int_t print_stddev = (dostat/1000)%10;
8897 Int_t print_under = (dostat/10000)%10;
8898 Int_t print_over = (dostat/100000)%10;
8899 Int_t print_integral= (dostat/1000000)%10;
8900 Int_t print_skew = (dostat/10000000)%10;
8901 Int_t print_kurt = (dostat/100000000)%10;
8903 if (print_under || print_over) nlines += 3;
8904
8905 // Pavetext with statistics
8906 if (!gStyle->GetOptFit()) fit = nullptr;
8907 Bool_t done = kFALSE;
8908 if (!dostat && !fit) {
8909 if (stats) { fFunctions->Remove(stats); delete stats;}
8910 return;
8911 }
8913 if (fit) statw = 1.8*gStyle->GetStatW();
8915 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
8916 stath = 0.25*nlines*gStyle->GetStatH();
8917 }
8918 if (fit) stath += gStyle->GetStatH();
8919 if (stats) {
8920 stats->Clear();
8921 done = kTRUE;
8922 } else {
8923 stats = new TPaveStats(
8926 gStyle->GetStatX(),
8927 gStyle->GetStatY(),"brNDC");
8928
8929 stats->SetParent(fH);
8930 stats->SetOptFit(dofit);
8931 stats->SetOptStat(dostat);
8932 stats->SetFillColor(gStyle->GetStatColor());
8933 stats->SetFillStyle(gStyle->GetStatStyle());
8935 stats->SetName("stats");
8936
8938 stats->SetTextAlign(12);
8939 stats->SetTextFont(gStyle->GetStatFont());
8940 if (gStyle->GetStatFont()%10 > 2)
8942 stats->SetFitFormat(gStyle->GetFitFormat());
8944 stats->SetBit(kCanDelete);
8945 stats->SetBit(kMustCleanup);
8946 }
8947 if (print_name) stats->AddText(h2->GetName());
8948 if (print_entries) {
8949 if (h2->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(h2->GetEntries()+0.5));
8950 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(h2->GetEntries()));
8951 stats->AddText(tt.Data());
8952 }
8953 if (print_mean) {
8954 if (print_mean == 1) {
8955 tf.Form("%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
8956 tt.Form(tf.Data(),h2->GetMean(1));
8957 stats->AddText(tt.Data());
8958 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
8959 tt.Form(tf.Data(),h2->GetMean(2));
8960 stats->AddText(tt.Data());
8961 } else {
8962 tf.Form("%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
8963 ,"%",stats->GetStatFormat());
8964 tt.Form(tf.Data(),h2->GetMean(1),h2->GetMeanError(1));
8965 stats->AddText(tt.Data());
8966 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
8967 ,"%",stats->GetStatFormat());
8968 tt.Form(tf.Data(),h2->GetMean(2),h2->GetMeanError(2));
8969 stats->AddText(tt.Data());
8970 }
8971 }
8972 if (print_stddev) {
8973 if (print_stddev == 1) {
8974 tf.Form("%s = %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat());
8975 tt.Form(tf.Data(),h2->GetStdDev(1));
8976 stats->AddText(tt.Data());
8977 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
8978 tt.Form(tf.Data(),h2->GetStdDev(2));
8979 stats->AddText(tt.Data());
8980 } else {
8981 tf.Form("%s = %s%s #pm %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat()
8982 ,"%",stats->GetStatFormat());
8983 tt.Form(tf.Data(),h2->GetStdDev(1),h2->GetStdDevError(1));
8984 stats->AddText(tt.Data());
8985 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
8986 ,"%",stats->GetStatFormat());
8987 tt.Form(tf.Data(),h2->GetStdDev(2),h2->GetStdDevError(2));
8988 stats->AddText(tt.Data());
8989 }
8990 }
8991 if (print_integral) {
8992 tf.Form("%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
8993 tt.Form(tf.Data(),fH->Integral());
8994 stats->AddText(tt.Data());
8995 }
8996 if (print_skew) {
8997 if (print_skew == 1) {
8998 tf.Form("%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
8999 tt.Form(tf.Data(),h2->GetSkewness(1));
9000 stats->AddText(tt.Data());
9001 tf.Form("%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
9002 tt.Form(tf.Data(),h2->GetSkewness(2));
9003 stats->AddText(tt.Data());
9004 } else {
9005 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
9006 ,"%",stats->GetStatFormat());
9007 tt.Form(tf.Data(),h2->GetSkewness(1),h2->GetSkewness(11));
9008 stats->AddText(tt.Data());
9009 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
9010 ,"%",stats->GetStatFormat());
9011 tt.Form(tf.Data(),h2->GetSkewness(2),h2->GetSkewness(12));
9012 stats->AddText(tt.Data());
9013 }
9014 }
9015 if (print_kurt) {
9016 if (print_kurt == 1) {
9017 tf.Form("%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
9018 tt.Form(tf.Data(),h2->GetKurtosis(1));
9019 stats->AddText(tt.Data());
9020 tf.Form("%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
9021 tt.Form(tf.Data(),h2->GetKurtosis(2));
9022 stats->AddText(tt.Data());
9023 } else {
9024 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
9025 ,"%",stats->GetStatFormat());
9026 tt.Form(tf.Data(),h2->GetKurtosis(1),h2->GetKurtosis(11));
9027 stats->AddText(tt.Data());
9028 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
9029 ,"%",stats->GetStatFormat());
9030 tt.Form(tf.Data(),h2->GetKurtosis(2),h2->GetKurtosis(12));
9031 stats->AddText(tt.Data());
9032 }
9033 }
9034 if (print_under || print_over) {
9035 //get 3*3 under/overflows for 2d hist
9036 Double_t unov[9];
9037
9038 Int_t cellsX = h2->GetXaxis()->GetNbins() + 1;
9039 Int_t cellsY = h2->GetYaxis()->GetNbins() + 1;
9040 Int_t firstX = std::max(1, h2->GetXaxis()->GetFirst());
9041 Int_t firstY = std::max(1, h2->GetYaxis()->GetFirst());
9042 Int_t lastX = std::min(h2->GetXaxis()->GetLast(), h2->GetXaxis()->GetNbins());
9043 Int_t lastY = std::min(h2->GetYaxis()->GetLast(), h2->GetYaxis()->GetNbins());
9044
9045 unov[0] = h2->Integral( 0, firstX-1, lastY+1, cellsY );
9046 unov[1] = h2->Integral(firstX , lastX , lastY+1, cellsY );
9047 unov[2] = h2->Integral(lastX+1, cellsX , lastY+1, cellsY );
9048 unov[3] = h2->Integral( 0, firstX-1, firstY , lastY );
9049 unov[4] = h2->Integral(firstX , lastX , firstY , lastY );
9050 unov[5] = h2->Integral(lastX+1, cellsX , firstY , lastY );
9051 unov[6] = h2->Integral( 0, firstX-1, 0, firstY-1);
9052 unov[7] = h2->Integral(firstX, lastX, 0, firstY-1);
9053 unov[8] = h2->Integral(lastX+1, cellsX , 0, firstY-1);
9054
9055 tt.Form("%g|%g|%g\n", unov[0], unov[1], unov[2]);
9056 stats->AddText(tt.Data());
9057 tt.Form("%g|%g|%g\n", unov[3], unov[4], unov[5]);
9058 stats->AddText(tt.Data());
9059 tt.Form("%g|%g|%g\n", unov[6], unov[7], unov[8]);
9060 stats->AddText(tt.Data());
9061 }
9062
9063 // Draw Fit parameters
9064 if (fit) {
9065 Int_t ndf = fit->GetNDF();
9066 tt.Form("#chi^{2} / ndf = %6.4g / %d",fit->GetChisquare(),ndf);
9067 stats->AddText(tt.Data());
9068 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
9069 tt.Form("%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
9070 ,fit->GetParameter(ipar)
9071 ,fit->GetParError(ipar));
9072 stats->AddText(tt.Data());
9073 }
9074 }
9075
9076 if (!done) fFunctions->Add(stats);
9077 stats->Paint(stats->GetOption());
9078}
9079
9080////////////////////////////////////////////////////////////////////////////////
9081/// [Draw the statistics box for 3D histograms.](\ref HP07)
9082
9084{
9085
9086 if (fH->GetDimension() != 3) return;
9087 TH3 *h3 = (TH3*)fH;
9088
9089 TString tt, tf;
9090 Int_t dofit;
9091 TPaveStats *stats = nullptr;
9092 TIter next(fFunctions);
9093 while (auto obj = next()) {
9094 if (obj->InheritsFrom(TPaveStats::Class())) {
9095 stats = (TPaveStats*)obj;
9096 break;
9097 }
9098 }
9099 if (stats && dostat) {
9100 dofit = stats->GetOptFit();
9101 dostat = stats->GetOptStat();
9102 } else {
9103 dofit = gStyle->GetOptFit();
9104 }
9105 if (dostat == 1) dostat = 1111;
9106 Int_t print_name = dostat%10;
9107 Int_t print_entries = (dostat/10)%10;
9108 Int_t print_mean = (dostat/100)%10;
9109 Int_t print_stddev = (dostat/1000)%10;
9110 Int_t print_under = (dostat/10000)%10;
9111 Int_t print_over = (dostat/100000)%10;
9112 Int_t print_integral= (dostat/1000000)%10;
9113 Int_t print_skew = (dostat/10000000)%10;
9114 Int_t print_kurt = (dostat/100000000)%10;
9116 if (print_under || print_over) nlines += 3;
9117
9118 // Pavetext with statistics
9119 if (!gStyle->GetOptFit()) fit = nullptr;
9120 Bool_t done = kFALSE;
9121 if (!dostat && !fit) {
9122 if (stats) { fFunctions->Remove(stats); delete stats;}
9123 return;
9124 }
9126 if (fit) statw = 1.8*gStyle->GetStatW();
9128 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
9129 stath = 0.25*nlines*gStyle->GetStatH();
9130 }
9131 if (fit) stath += gStyle->GetStatH();
9132 if (stats) {
9133 stats->Clear();
9134 done = kTRUE;
9135 } else {
9136 stats = new TPaveStats(
9139 gStyle->GetStatX(),
9140 gStyle->GetStatY(),"brNDC");
9141
9142 stats->SetParent(fH);
9143 stats->SetOptFit(dofit);
9144 stats->SetOptStat(dostat);
9145 stats->SetFillColor(gStyle->GetStatColor());
9146 stats->SetFillStyle(gStyle->GetStatStyle());
9148 stats->SetName("stats");
9149
9151 stats->SetTextAlign(12);
9152 stats->SetTextFont(gStyle->GetStatFont());
9153 stats->SetFitFormat(gStyle->GetFitFormat());
9155 stats->SetBit(kCanDelete);
9156 stats->SetBit(kMustCleanup);
9157 }
9158 if (print_name) stats->AddText(h3->GetName());
9159 if (print_entries) {
9160 if (h3->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(h3->GetEntries()+0.5));
9161 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(h3->GetEntries()+0.5));
9162 stats->AddText(tt.Data());
9163 }
9164 if (print_mean) {
9165 if (print_mean == 1) {
9166 tf.Form("%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
9167 tt.Form(tf.Data(),h3->GetMean(1));
9168 stats->AddText(tt.Data());
9169 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
9170 tt.Form(tf.Data(),h3->GetMean(2));
9171 stats->AddText(tt.Data());
9172 tf.Form("%s = %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat());
9173 tt.Form(tf.Data(),h3->GetMean(3));
9174 stats->AddText(tt.Data());
9175 } else {
9176 tf.Form("%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
9177 ,"%",stats->GetStatFormat());
9178 tt.Form(tf.Data(),h3->GetMean(1),h3->GetMeanError(1));
9179 stats->AddText(tt.Data());
9180 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
9181 ,"%",stats->GetStatFormat());
9182 tt.Form(tf.Data(),h3->GetMean(2),h3->GetMeanError(2));
9183 stats->AddText(tt.Data());
9184 tf.Form("%s = %s%s #pm %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat()
9185 ,"%",stats->GetStatFormat());
9186 tt.Form(tf.Data(),h3->GetMean(3),h3->GetMeanError(3));
9187 stats->AddText(tt.Data());
9188 }
9189 }
9190 if (print_stddev) {
9191 if (print_stddev == 1) {
9192 tf.Form("%s = %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat());
9193 tt.Form(tf.Data(),h3->GetStdDev(1));
9194 stats->AddText(tt.Data());
9195 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
9196 tt.Form(tf.Data(),h3->GetStdDev(2));
9197 stats->AddText(tt.Data());
9198 tf.Form("%s = %s%s",gStringStdDevZ.Data(),"%",stats->GetStatFormat());
9199 tt.Form(tf.Data(),h3->GetStdDev(3));
9200 stats->AddText(tt.Data());
9201 } else {
9202 tf.Form("%s = %s%s #pm %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat()
9203 ,"%",stats->GetStatFormat());
9204 tt.Form(tf.Data(),h3->GetStdDev(1),h3->GetStdDevError(1));
9205 stats->AddText(tt.Data());
9206 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
9207 ,"%",stats->GetStatFormat());
9208 tt.Form(tf.Data(),h3->GetStdDev(2),h3->GetStdDevError(2));
9209 stats->AddText(tt.Data());
9210 tf.Form("%s = %s%s #pm %s%s",gStringStdDevZ.Data(),"%",stats->GetStatFormat()
9211 ,"%",stats->GetStatFormat());
9212 tt.Form(tf.Data(),h3->GetStdDev(3),h3->GetStdDevError(3));
9213 stats->AddText(tt.Data());
9214 }
9215 }
9216 if (print_integral) {
9217 tt.Form("%s = %6.4g",gStringIntegral.Data(),h3->Integral());
9218 stats->AddText(tt.Data());
9219 }
9220 if (print_skew) {
9221 if (print_skew == 1) {
9222 tf.Form("%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
9223 tt.Form(tf.Data(),h3->GetSkewness(1));
9224 stats->AddText(tt.Data());
9225 tf.Form("%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
9226 tt.Form(tf.Data(),h3->GetSkewness(2));
9227 stats->AddText(tt.Data());
9228 tf.Form("%s = %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat());
9229 tt.Form(tf.Data(),h3->GetSkewness(3));
9230 stats->AddText(tt.Data());
9231 } else {
9232 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
9233 ,"%",stats->GetStatFormat());
9234 tt.Form(tf.Data(),h3->GetSkewness(1),h3->GetSkewness(11));
9235 stats->AddText(tt.Data());
9236 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
9237 ,"%",stats->GetStatFormat());
9238 tt.Form(tf.Data(),h3->GetSkewness(2),h3->GetSkewness(12));
9239 stats->AddText(tt.Data());
9240 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat()
9241 ,"%",stats->GetStatFormat());
9242 tt.Form(tf.Data(),h3->GetSkewness(3),h3->GetSkewness(13));
9243 stats->AddText(tt.Data());
9244 }
9245 }
9246 if (print_kurt) {
9247 if (print_kurt == 1) {
9248 tf.Form("%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
9249 tt.Form(tf.Data(),h3->GetKurtosis(1));
9250 stats->AddText(tt.Data());
9251 tf.Form("%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
9252 tt.Form(tf.Data(),h3->GetKurtosis(2));
9253 stats->AddText(tt.Data());
9254 tf.Form("%s = %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat());
9255 tt.Form(tf.Data(),h3->GetKurtosis(3));
9256 stats->AddText(tt.Data());
9257 } else {
9258 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
9259 ,"%",stats->GetStatFormat());
9260 tt.Form(tf.Data(),h3->GetKurtosis(1),h3->GetKurtosis(11));
9261 stats->AddText(tt.Data());
9262 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
9263 ,"%",stats->GetStatFormat());
9264 tt.Form(tf.Data(),h3->GetKurtosis(2),h3->GetKurtosis(12));
9265 stats->AddText(tt.Data());
9266 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat()
9267 ,"%",stats->GetStatFormat());
9268 tt.Form(tf.Data(),h3->GetKurtosis(3),h3->GetKurtosis(13));
9269 stats->AddText(tt.Data());
9270 }
9271 }
9272 if (print_under || print_over) {
9273 // no underflow - overflow printing for a 3D histogram
9274 // one would need a 3D table
9275 }
9276
9277 // Draw Fit parameters
9278 if (fit) {
9279 Int_t ndf = fit->GetNDF();
9280 tt.Form("#chi^{2} / ndf = %6.4g / %d",fit->GetChisquare(),ndf);
9281 stats->AddText(tt.Data());
9282 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
9283 tt.Form("%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
9284 ,fit->GetParameter(ipar)
9285 ,fit->GetParError(ipar));
9286 stats->AddText(tt.Data());
9287 }
9288 }
9289
9290 if (!done) fFunctions->Add(stats);
9291 stats->Paint(stats->GetOption());
9292}
9293
9294////////////////////////////////////////////////////////////////////////////////
9295/// [Control function to draw a 2D histogram as a surface plot.](\ref HP18)
9296
9298{
9299
9300 const Double_t ydiff = 1;
9301 const Double_t yligh1 = 10;
9302 const Double_t qa = 0.15;
9303 const Double_t qd = 0.15;
9304 const Double_t qs = 0.8;
9306 Int_t raster = 0;
9307 Int_t irep = 0;
9308
9309 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
9312 Double_t zmin = Hparam.zmin;
9313 Double_t zmax = Hparam.zmax;
9318 Double_t dangle = 10*3.141592/180; //Delta angle for Rapidity option
9319 Double_t deltaz = TMath::Abs(zmin);
9320 if (deltaz == 0) deltaz = 1;
9321 if (zmin >= zmax) {
9322 zmin -= 0.5*deltaz;
9323 zmax += 0.5*deltaz;
9324 }
9325 Double_t z1c = zmin;
9326 Double_t z2c = zmin + (zmax-zmin)*(1+gStyle->GetHistTopMargin());
9327 // Compute the lego limits and instantiate a lego object
9328 fXbuf[0] = -1;
9329 fYbuf[0] = 1;
9330 fXbuf[1] = -1;
9331 fYbuf[1] = 1;
9332 if (Hoption.System >= kPOLAR && (Hoption.Surf == 1 || Hoption.Surf == 13)) raster = 1;
9333 if (Hoption.System == kPOLAR) {
9334 fXbuf[2] = z1c;
9335 fYbuf[2] = z2c;
9336 } else if (Hoption.System == kCYLINDRICAL) {
9337 if (Hoption.Logy) {
9338 if (ylab1 > 0) fXbuf[2] = TMath::Log10(ylab1);
9339 else fXbuf[2] = 0;
9340 if (ylab2 > 0) fYbuf[2] = TMath::Log10(ylab2);
9341 else fYbuf[2] = 0;
9342 } else {
9343 fXbuf[2] = ylab1;
9344 fYbuf[2] = ylab2;
9345 }
9346 z1c = 0; z2c = 1;
9347 } else if (Hoption.System == kSPHERICAL) {
9348 fXbuf[2] = -1;
9349 fYbuf[2] = 1;
9350 z1c = 0; z2c = 1;
9351 } else if (Hoption.System == kRAPIDITY) {
9352 fXbuf[2] = -1/TMath::Tan(dangle);
9353 fYbuf[2] = 1/TMath::Tan(dangle);
9354 } else {
9355 fXbuf[0] = xlab1;
9356 fYbuf[0] = xlab2;
9357 fXbuf[1] = ylab1;
9358 fYbuf[1] = ylab2;
9359 fXbuf[2] = z1c;
9360 fYbuf[2] = z2c;
9361 }
9362
9363 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data(), Hoption.System);
9364 fLego->SetEdgeAtt(fH->GetLineColor(),fH->GetLineStyle(),fH->GetLineWidth(),0);
9365 fLego->SetFillColor(fH->GetFillColor());
9366
9367 // Initialize the levels on the Z axis
9368 Int_t ndiv = fH->GetContour();
9369 if (ndiv == 0 ) {
9370 ndiv = gStyle->GetNumberContours();
9371 fH->SetContour(ndiv);
9372 }
9373 Int_t ndivz = TMath::Abs(ndiv);
9374 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
9375
9376 if (Hoption.Surf == 13 || Hoption.Surf == 15) fLego->SetMesh(3);
9377 if (Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) fLego->SetMesh(0);
9378
9379 // Close the surface in case of non cartesian coordinates.
9380
9381 if (Hoption.System != kCARTESIAN) {nx++; ny++;}
9382
9383 // Now ready to draw the surface plot
9384
9385 TView *view = gPad ? gPad->GetView() : nullptr;
9386 if (!view) {
9387 Error("PaintSurface", "no TView in current pad");
9388 return;
9389 }
9390
9391 Double_t thedeg = 90 - gPad->GetTheta();
9392 Double_t phideg = -90 - gPad->GetPhi();
9393 Double_t psideg = view->GetPsi();
9394 view->SetView(phideg, thedeg, psideg, irep);
9395
9396 // Set color/style for back box
9397 if (Hoption.Same) {
9398 fLego->SetFillStyle(0);
9399 fLego->SetFillColor(1);
9400 } else {
9401 fLego->SetFillStyle(gPad->GetFrameFillStyle());
9402 fLego->SetFillColor(gPad->GetFrameFillColor());
9403 }
9404 fLego->TAttFill::Modify();
9405
9406 Int_t backcolor = gPad->GetFrameFillColor();
9407 if (Hoption.System != kCARTESIAN) backcolor = 0;
9408 view->PadRange(backcolor);
9409
9410 fLego->SetFillStyle(fH->GetFillStyle());
9411 fLego->SetFillColor(fH->GetFillColor());
9412 fLego->TAttFill::Modify();
9413
9414 // Draw the filled contour on top
9416
9418 if (Hoption.Surf == 13 || Hoption.Surf == 15) {
9420 Hoption.Surf = 23;
9421 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9423 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"BF");
9424 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9425 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9426 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9427 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"BF");
9429 fLego->SetMesh(1);
9430 }
9431
9432 if (raster) fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
9433 else fLego->InitMoveScreen(-1.1,1.1);
9434
9435 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) {
9436 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9439 fLego->BackBox(90);
9440 }
9441 }
9442
9443 // Gouraud Shading surface
9444 if (Hoption.Surf == 14) {
9445 // Set light sources
9446 fLego->LightSource(0, ydiff, 0,0,0,irep);
9447 fLego->LightSource(1, yligh1 ,1,1,1,irep);
9448 fLego->SurfaceProperty(qa, qd, qs, 1, irep);
9449 fmin = ydiff*qa;
9450 fmax = fmin + (yligh1+0.1)*(qd+qs);
9451 Int_t nbcol = 28;
9452 icol1 = 201;
9453 Double_t dcol = 0.5/Double_t(nbcol);
9454 TColor *colref = gROOT->GetColor(fH->GetFillColor());
9455 if (!colref) return;
9457 colref->GetRGB(r,g,b);
9459 TColor *acol;
9460 for (Int_t col=0;col<nbcol;col++) {
9461 acol = gROOT->GetColor(col+icol1);
9462 TColor::HLStoRGB(hue,.4+col*dcol,satur,r,g,b);
9463 if (acol) acol->SetRGB(r,g,b);
9464 }
9465 fLego->Spectrum(nbcol, fmin, fmax, icol1, 1, irep);
9466 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::GouraudFunction);
9468 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"BF");
9469 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9470 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9471 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9472 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"BF");
9473 } else if (Hoption.Surf == 15) {
9474 // The surface is not drawn in this case.
9475 } else {
9476 // Draw the surface
9477 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 16 || Hoption.Surf == 17) {
9479 } else {
9480 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9481 }
9482 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9483 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceRaster1);
9484 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode2);
9485 if (Hoption.System == kPOLAR) {
9486 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfacePolar(1,nx,ny,"FB");
9487 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfacePolar(1,nx,ny,"BF");
9488 } else if (Hoption.System == kCYLINDRICAL) {
9489 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceCylindrical(1,nx,ny,"FB");
9490 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9491 } else if (Hoption.System == kSPHERICAL) {
9492 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceSpherical(0,1,nx,ny,"FB");
9493 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9494 } else if (Hoption.System == kRAPIDITY) {
9495 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceSpherical(1,1,nx,ny,"FB");
9496 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9497 } else {
9498 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove1);
9499 if (Hoption.Surf == 16) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove3);
9500 if (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16) fLego->SurfaceCartesian(90,nx,ny,"FB");
9501 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCartesian(90,nx,ny,"BF");
9502 }
9503 }
9504
9505 // Paint the line contour on top for option SURF7
9506 if (Hoption.Surf == 17) {
9507 fLego->InitMoveScreen(-1.1,1.1);
9508 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9509 Hoption.Surf = 23;
9510 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9512 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"FB");
9513 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"FB");
9514 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"FB");
9515 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"FB");
9516 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"FB");
9517 }
9518
9519 if ((!Hoption.Same) &&
9520 (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16)) {
9523 fLego->BackBox(90);
9524 }
9525 }
9526 if (Hoption.System == kCARTESIAN) {
9527 fLego->InitMoveScreen(-1.1,1.1);
9529 if (Hoption.FrontBox) fLego->FrontBox(90);
9530 }
9531 if (!Hoption.Axis && !Hoption.Same) {
9532 TGaxis axis;
9533 PaintLegoAxis(&axis, 90);
9534 }
9535
9537
9538 fLego.reset();
9539}
9540
9541////////////////////////////////////////////////////////////////////////////////
9542/// Control function to draw a table using Delaunay triangles.
9543
9545{
9546
9547 TGraphDelaunay2D *dt = nullptr;
9548 TGraphDelaunay *dtOld = nullptr;
9549
9550 // Check if fH contains a TGraphDelaunay2D
9552 dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
9553 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
9554 if (!dt && !dtOld) return;
9555
9556 // If needed, create a TGraph2DPainter
9557 if (!fGraph2DPainter)
9558 fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
9559
9560 // Define the 3D view
9561 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
9562 if (Hoption.Same) {
9563 TView *viewsame = gPad ? gPad->GetView() : nullptr;
9564 if (!viewsame) {
9565 Error("PaintTriangles", "no TView in current pad, do not use option SAME");
9566 return;
9567 }
9568 Double_t *rmin = viewsame->GetRmin();
9569 Double_t *rmax = viewsame->GetRmax();
9570 if (!rmin || !rmax) return;
9571 fXbuf[0] = rmin[0];
9572 fYbuf[0] = rmax[0];
9573 fXbuf[1] = rmin[1];
9574 fYbuf[1] = rmax[1];
9575 fXbuf[2] = rmin[2];
9576 fYbuf[2] = rmax[2];
9577 fH->SetMaximum(rmax[2]);
9578 fH->SetMinimum(rmin[2]);
9579 fH->GetXaxis()->SetRangeUser(rmin[0],rmax[0]);
9580 fH->GetYaxis()->SetRangeUser(rmin[1],rmax[1]);
9581 } else {
9582 fXbuf[0] = Hparam.xmin;
9583 fYbuf[0] = Hparam.xmax;
9584 fXbuf[1] = Hparam.ymin;
9585 fYbuf[1] = Hparam.ymax;
9586 fXbuf[2] = Hparam.zmin;
9587 fYbuf[2] = Hparam.zmax;
9588 }
9589
9590 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
9591 TView *view = gPad ? gPad->GetView() : nullptr;
9592 if (!view) {
9593 Error("PaintTriangles", "no TView in current pad");
9594 return;
9595 }
9596 Double_t thedeg = 90 - gPad->GetTheta();
9597 Double_t phideg = -90 - gPad->GetPhi();
9598 Double_t psideg = view->GetPsi();
9599 Int_t irep;
9600 view->SetView(phideg, thedeg, psideg, irep);
9601
9602 // Set color/style for back box
9603 fLego->SetFillStyle(gPad->GetFrameFillStyle());
9604 fLego->SetFillColor(gPad->GetFrameFillColor());
9605 fLego->TAttFill::Modify();
9606 Int_t backcolor = gPad->GetFrameFillColor();
9607 if (Hoption.System != kCARTESIAN) backcolor = 0;
9608 view->PadRange(backcolor);
9609 fLego->SetFillStyle(fH->GetFillStyle());
9610 fLego->SetFillColor(fH->GetFillColor());
9611 fLego->TAttFill::Modify();
9612
9613 // Paint the Back Box if needed
9614 if (Hoption.BackBox && !Hoption.Same) {
9615 fLego->InitMoveScreen(-1.1,1.1);
9616 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9618 fLego->BackBox(90);
9619 }
9620
9621 // Paint the triangles
9622 fGraph2DPainter->Paint(option);
9623
9624 // Paint the Front Box if needed
9625 if (Hoption.FrontBox) {
9626 fLego->InitMoveScreen(-1.1,1.1);
9628 fLego->FrontBox(90);
9629 }
9630
9631 // Paint the Axis if needed
9632 if (!Hoption.Axis && !Hoption.Same) {
9633 TGaxis axis;
9634 PaintLegoAxis(&axis, 90);
9635 }
9636
9638
9639 fLego.reset();
9640}
9641
9642////////////////////////////////////////////////////////////////////////////////
9643/// Define the color levels used to paint legos, surfaces etc..
9644
9646{
9647
9648 Int_t i, irep;
9649
9650 // Initialize the color levels
9651 if (ndivz >= 100) {
9652 Warning("PaintSurface", "too many color levels, %d >= 100, reset to 99", ndivz);
9653 ndivz = 99;
9654 }
9655 std::vector<Double_t> funlevel(ndivz+1);
9656 std::vector<Int_t> colorlevel(ndivz+1);
9658 Int_t ncolors = gStyle->GetNumberOfColors();
9659 for (i = 0; i < ndivz; ++i) {
9661 theColor = Int_t((i+0.99)*Float_t(ncolors)/Float_t(ndivz));
9663 }
9664 colorlevel[ndivz] = gStyle->GetColorPalette(ncolors-1);
9665 fLego->ColorFunction(ndivz, funlevel.data(), colorlevel.data(), irep);
9666}
9667
9668////////////////////////////////////////////////////////////////////////////////
9669/// [Control function to draw 2D/3D histograms (tables).](\ref HP01c)
9670
9672{
9673
9674 // Fill Hparam structure with histo parameters
9675 if (!TableInit()) return;
9676
9677 // Draw histogram frame
9678 PaintFrame();
9679
9680 // If palette option not specified, delete a possible existing palette
9681 if (!Hoption.Zscale) {
9682 TObject *palette = fFunctions->FindObject("palette");
9683 if (palette) { fFunctions->Remove(palette); delete palette;}
9684 }
9685
9686 // Do not draw the histogram. Only the attached functions will be drawn.
9687 if (Hoption.Func == 2) {
9688 if (Hoption.Zscale) {
9689 Int_t ndiv = fH->GetContour();
9690 if (ndiv == 0 ) {
9691 ndiv = gStyle->GetNumberContours();
9692 fH->SetContour(ndiv);
9693 }
9694 PaintPalette();
9695 }
9696
9697 // Draw the histogram according to the option
9698 } else {
9699 if (fH->InheritsFrom(TH2Poly::Class()) && Hoption.Axis<=0) {
9700 if (Hoption.Fill) PaintTH2PolyBins("f");
9704 if (Hoption.Line) PaintTH2PolyBins("l");
9705 if (Hoption.Mark) PaintTH2PolyBins("P");
9706 } else if (Hoption.Axis<=0) {
9710 if (Hoption.Color) {
9713 }
9716 if (Hoption.Error >= 100) Paint2DErrors(option);
9718 }
9722 }
9723
9724 // Draw histogram title
9725 PaintTitle();
9726
9727 // Draw the axes
9728 if (!Hoption.Lego && !Hoption.Surf &&
9729 !Hoption.Tri && !(Hoption.Error >= 100)) PaintAxis(kFALSE);
9730
9731 TF1 *fit = nullptr;
9732 TIter next(fFunctions);
9733 while (auto obj = next()) {
9734 if (obj->InheritsFrom(TF1::Class())) {
9735 fit = (TF1*)obj;
9736 break;
9737 }
9738 }
9739 if ((Hoption.Same%10) != 1) {
9740 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
9741 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
9742 //ALWAYS executed on non-iOS platform.
9743 //On iOS, depends on mode.
9745 }
9746 }
9747 }
9748}
9749
9750////////////////////////////////////////////////////////////////////////////////
9751/// Control function to draw a TH2Poly bins' contours.
9752///
9753/// - option = "F" draw the bins as filled areas.
9754/// - option = "L" draw the bins as line.
9755/// - option = "P" draw the bins as markers.
9756
9758{
9759
9760 //Do not highlight the histogram, if its part was picked.
9761 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH) return;
9762
9763 TString opt = option;
9764 opt.ToLower();
9765 Bool_t line = kFALSE;
9766 Bool_t fill = kFALSE;
9767 Bool_t mark = kFALSE;
9768 if (opt.Contains("l")) line = kTRUE;
9769 if (opt.Contains("f")) fill = kTRUE;
9770 if (opt.Contains("p")) mark = kTRUE;
9771
9772 TH2PolyBin *b;
9773 Double_t z;
9774
9775 TIter next(((TH2Poly*)fH)->GetBins());
9776 TObject *obj, *poly;
9777
9778 while ((obj=next())) {
9779 b = (TH2PolyBin*)obj;
9780 z = b->GetContent();
9781 if (z==0 && Hoption.Zero) continue; // Do not draw empty bins in case of option "COL0 L"
9782 poly = b->GetPolygon();
9783
9784 // Paint the TGraph bins.
9785 if (poly->IsA() == TGraph::Class()) {
9786 TGraph *g = (TGraph*)poly;
9787 g->TAttLine::Modify();
9788 g->TAttMarker::Modify();
9789 g->TAttFill::Modify();
9790 if (line) {
9791 Int_t fs = g->GetFillStyle();
9793 g->SetFillStyle(0);
9795 g->Paint("F");
9797 g->SetFillStyle(fs);
9798 }
9799 if (fill) g->Paint("F");
9800 if (mark) g->Paint("P");
9801 }
9802
9803 // Paint the TMultiGraph bins.
9804 if (poly->IsA() == TMultiGraph::Class()) {
9806 TList *gl = mg->GetListOfGraphs();
9807 if (!gl) return;
9808 TGraph *g;
9809 TIter nextg(gl);
9810 while ((g = (TGraph*) nextg())) {
9811 g->TAttLine::Modify();
9812 g->TAttMarker::Modify();
9813 g->TAttFill::Modify();
9814 if (line) {
9815 Int_t fs = g->GetFillStyle();
9817 g->SetFillStyle(0);
9819 g->Paint("F");
9821 g->SetFillStyle(fs);
9822 }
9823 if (fill) g->Paint("F");
9824 if (mark) g->Paint("P");
9825 }
9826 }
9827 }
9828}
9829
9830////////////////////////////////////////////////////////////////////////////////
9831/// [Control function to draw a TH2Poly as a color plot.](\ref HP20a)
9832
9834{
9835
9836 //Do not highlight the histogram, if its part was picked.
9837 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
9838 return;
9839
9840 Int_t ncolors, color, theColor;
9841 Double_t z, zc;
9842 Double_t zmin = fH->GetMinimum();
9843 Double_t zmax = fH->GetMaximum();
9844 if (Hoption.Logz) {
9845 if (zmax > 0) {
9846 if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
9847 zmin = TMath::Log10(zmin);
9848 zmax = TMath::Log10(zmax);
9849 } else {
9850 return;
9851 }
9852 }
9853 Double_t dz = zmax - zmin;
9854
9855 // Initialize the levels on the Z axis
9856 ncolors = gStyle->GetNumberOfColors();
9857 Int_t ndiv = fH->GetContour();
9858 if (ndiv == 0 ) {
9859 ndiv = gStyle->GetNumberContours();
9860 fH->SetContour(ndiv);
9861 }
9862 Int_t ndivz = TMath::Abs(ndiv);
9863 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
9865
9866 TIter next(((TH2Poly*)fH)->GetBins());
9867
9868 while (auto obj = next()) {
9869 TH2PolyBin *b = (TH2PolyBin*)obj;
9870 TObject *poly = b->GetPolygon();
9871
9872 z = b->GetContent();
9873 if (z==0 && Hoption.Zero) continue;
9874 if (Hoption.Logz) {
9875 if (z > 0) z = TMath::Log10(z);
9876 else z = zmin;
9877 }
9878 if (z < zmin) continue;
9879
9880 // Define the bin color.
9882 zc = fH->GetContourLevelPad(0);
9883 if (z < zc) continue;
9884 color = -1;
9885 for (Int_t k=0; k<ndiv; k++) {
9886 zc = fH->GetContourLevelPad(k);
9887 if (z < zc) {
9888 continue;
9889 } else {
9890 color++;
9891 }
9892 }
9893 } else {
9894 color = Int_t(0.01+(z-zmin)*scale);
9895 }
9896 theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
9897 if (theColor > ncolors-1) theColor = ncolors-1;
9898
9899 // Paint the TGraph bins.
9900 if (poly->IsA() == TGraph::Class()) {
9901 TGraph *g = (TGraph*)poly;
9902 g->SetFillColor(gStyle->GetColorPalette(theColor));
9903 g->TAttFill::Modify();
9904 g->Paint("F");
9905 }
9906
9907 // Paint the TMultiGraph bins.
9908 if (poly->IsA() == TMultiGraph::Class()) {
9910 TList *gl = mg->GetListOfGraphs();
9911 if (!gl) return;
9912 TGraph *g;
9913 TIter nextg(gl);
9914 while ((g = (TGraph*) nextg())) {
9915 g->SetFillColor(gStyle->GetColorPalette(theColor));
9916 g->TAttFill::Modify();
9917 g->Paint("F");
9918 }
9919 }
9920 }
9922}
9923
9924////////////////////////////////////////////////////////////////////////////////
9925/// [Control function to draw a TH2Poly as a scatter plot.](\ref HP20a)
9926
9928{
9929
9930 //Do not highlight the histogram, if its part was selected.
9931 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
9932 return;
9933
9934 Int_t k, loop, marker=0;
9935 Double_t z, xk,xstep, yk, ystep, xp, yp;
9936 Double_t scale = 1;
9937 Double_t zmin = fH->GetMinimum();
9938 Double_t zmax = fH->GetMaximum();
9939 if (Hoption.Logz) {
9940 if (zmax > 0) {
9941 if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
9942 zmin = TMath::Log10(zmin);
9943 zmax = TMath::Log10(zmax);
9944 } else {
9945 return;
9946 }
9947 }
9948 Double_t dz = zmax - zmin;
9949 scale = (kNMAX-1)/dz;
9950
9951
9952 // use an independent instance of a random generator
9953 // instead of gRandom to avoid conflicts and
9954 // to get same random numbers when drawing the same histogram
9956
9957 TH2PolyBin *b;
9958
9959 TIter next(((TH2Poly*)fH)->GetBins());
9960 TObject *obj, *poly;
9961
9962 Double_t maxarea = 0, a;
9963 while ((obj=next())) {
9964 b = (TH2PolyBin*)obj;
9965 a = b->GetArea();
9966 if (a>maxarea) maxarea = a;
9967 }
9968
9969 next.Reset();
9970
9971 while ((obj=next())) {
9972 b = (TH2PolyBin*)obj;
9973 poly = b->GetPolygon();
9974 z = b->GetContent();
9975 if (z < zmin) z = zmin;
9976 if (z > zmax) z = zmax;
9977 if (Hoption.Logz) {
9978 if (z > 0) z = TMath::Log10(z) - zmin;
9979 } else {
9980 z -= zmin;
9981 }
9982 k = Int_t((z*scale)*(b->GetArea()/maxarea));
9983 xk = b->GetXMin();
9984 yk = b->GetYMin();
9985 xstep = b->GetXMax()-xk;
9986 ystep = b->GetYMax()-yk;
9987
9988 // Paint the TGraph bins.
9989 if (poly->IsA() == TGraph::Class()) {
9990 TGraph *g = (TGraph*)poly;
9991 if (k <= 0 || z <= 0) continue;
9992 loop = 0;
9993 while (loop<k) {
9994 if (k+marker >= kNMAX) {
9995 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
9996 marker=0;
9997 }
9998 xp = (random.Rndm()*xstep) + xk;
9999 yp = (random.Rndm()*ystep) + yk;
10000 if (g->IsInside(xp,yp)) {
10001 fXbuf[marker] = xp;
10002 fYbuf[marker] = yp;
10003 marker++;
10004 loop++;
10005 }
10006 }
10007 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10008 }
10009
10010 // Paint the TMultiGraph bins.
10011 if (poly->IsA() == TMultiGraph::Class()) {
10013 TList *gl = mg->GetListOfGraphs();
10014 if (!gl) return;
10015 if (k <= 0 || z <= 0) continue;
10016 loop = 0;
10017 while (loop<k) {
10018 if (k+marker >= kNMAX) {
10019 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10020 marker=0;
10021 }
10022 xp = (random.Rndm()*xstep) + xk;
10023 yp = (random.Rndm()*ystep) + yk;
10024 if (mg->IsInside(xp,yp)) {
10025 fXbuf[marker] = xp;
10026 fYbuf[marker] = yp;
10027 marker++;
10028 loop++;
10029 }
10030 }
10031 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10032 }
10033 }
10034 PaintTH2PolyBins("l");
10035}
10036
10037////////////////////////////////////////////////////////////////////////////////
10038/// [Control function to draw a TH2Poly as a text plot.](\ref HP20a)
10039
10041{
10042
10043 TLatex text;
10044 text.SetTextFont(gStyle->GetTextFont());
10045 text.SetTextColor(fH->GetMarkerColor());
10046 text.SetTextSize(0.02*fH->GetMarkerSize());
10047
10048 Double_t x, y, z, e, angle = 0;
10049 TString tt, tf;
10050 tf.Form("%s%s","%",gStyle->GetPaintTextFormat());
10051 if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
10052 Int_t opt = (Int_t)Hoption.Text/1000;
10053
10054 text.SetTextAlign(22);
10055 if (Hoption.Text == 1) angle = 0;
10056 text.SetTextAngle(angle);
10057 text.TAttText::Modify();
10058
10059 TH2PolyBin *b;
10060
10061 TIter next(((TH2Poly*)fH)->GetBins());
10062 TObject *obj, *p;
10063
10064 while ((obj=next())) {
10065 b = (TH2PolyBin*)obj;
10066 p = b->GetPolygon();
10067 x = (b->GetXMin()+b->GetXMax())/2;
10068 if (Hoption.Logx) {
10069 if (x > 0) x = TMath::Log10(x);
10070 else continue;
10071 }
10072 y = (b->GetYMin()+b->GetYMax())/2;
10073 if (Hoption.Logy) {
10074 if (y > 0) y = TMath::Log10(y);
10075 else continue;
10076 }
10077 z = b->GetContent();
10078 if (z < fH->GetMinimum() || (z == 0 && !Hoption.MinimumZero)) continue;
10079 if (opt==2) {
10080 e = fH->GetBinError(b->GetBinNumber());
10081 tf.Form("#splitline{%s%s}{#pm %s%s}",
10083 "%",gStyle->GetPaintTextFormat());
10084 tt.Form(tf.Data(),z,e);
10085 } else {
10086 tt.Form(tf.Data(),z);
10087 }
10088 if (opt==3) text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),p->GetName());
10089 else text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),tt.Data());
10090 }
10091
10092 PaintTH2PolyBins("l");
10093}
10094
10095////////////////////////////////////////////////////////////////////////////////
10096/// [Control function to draw a 1D/2D histograms with the bin values.](\ref HP15)
10097
10099{
10100
10101 TLatex text;
10102 text.SetTextFont(((int)gStyle->GetTextFont()/10)*10+2); // font precision must be 2
10103 text.SetTextColor(fH->GetMarkerColor());
10104 text.SetTextSize(0.02*fH->GetMarkerSize());
10105
10106 Double_t x, y, z, e, angle = 0;
10107 TString tt, tf;
10108 tf.Form("%s%s","%",gStyle->GetPaintTextFormat());
10109 if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
10110
10111 // 1D histograms
10112 if (fH->GetDimension() == 1) {
10114 Double_t yt;
10115 TProfile *hp = (TProfile*)fH;
10116 if (Hoption.Text>2000 && fH->InheritsFrom(TProfile::Class())) {
10117 Hoption.Text = Hoption.Text-2000;
10118 getentries = kTRUE;
10119 }
10120 if (Hoption.Text == 1) angle = 90;
10121 text.SetTextAlign(11);
10122 if (angle == 90) text.SetTextAlign(12);
10123 if (angle == 0) text.SetTextAlign(21);
10124 text.TAttText::Modify();
10125 Double_t dt = 0.02*(gPad->GetY2()-gPad->GetY1());
10126 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10127 if (Hoption.Bar) {
10128 x = fH->GetXaxis()->GetBinLowEdge(i)+
10129 fH->GetXaxis()->GetBinWidth(i)*
10130 (fH->GetBarOffset()+0.5*fH->GetBarWidth());
10131 } else {
10132 x = fH->GetXaxis()->GetBinCenter(i);
10133 }
10134 y = fH->GetBinContent(i);
10135 yt = y;
10136 if (Hoption.MinimumZero && y<0) y = 0;
10137 if (getentries) yt = hp->GetBinEntries(i);
10138 if (yt == 0.) continue;
10139 tt.Form(tf.Data(),yt);
10140 if (Hoption.Logx) {
10141 if (x > 0) x = TMath::Log10(x);
10142 else continue;
10143 }
10144 if (Hoption.Logy) {
10145 if (y > 0) y = TMath::Log10(y);
10146 else continue;
10147 }
10148 if (y >= gPad->GetY2()) continue;
10149 if (y <= gPad->GetY1()) continue;
10150 text.PaintLatex(x,y+0.2*dt,angle,0.02*fH->GetMarkerSize(),tt.Data());
10151 }
10152
10153 // 2D histograms
10154 } else {
10155 Double_t zmin = Hparam.zmin;
10156 if (Hoption.Logz) zmin = TMath::Power(10,Hparam.zmin);
10157
10158 text.SetTextAlign(22);
10159 if (Hoption.Text == 1) angle = 0;
10160 text.SetTextAngle(angle);
10161 text.TAttText::Modify();
10162 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
10163 y = fYaxis->GetBinCenter(j);
10164 if (Hoption.Logy) {
10165 if (y > 0) y = TMath::Log10(y);
10166 else continue;
10167 }
10168 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10169 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
10170 x = fXaxis->GetBinCenter(i);
10171 if (Hoption.Logx) {
10172 if (x > 0) x = TMath::Log10(x);
10173 else continue;
10174 }
10175 if (!IsInside(x,y)) continue;
10176 z = fH->GetBinContent(bin);
10177 if (z < zmin || (z == 0 && !Hoption.MinimumZero)) continue;
10178 if (Hoption.Text>2000) {
10179 e = fH->GetBinError(bin);
10180 tf.Form("#splitline{%s%s}{#pm %s%s}",
10182 "%",gStyle->GetPaintTextFormat());
10183 tt.Form(tf.Data(),z,e);
10184 } else {
10185 tt.Form(tf.Data(),z);
10186 }
10187 text.PaintLatex(x,y+fH->GetBarOffset()*fYaxis->GetBinWidth(j),
10188 angle,0.02*fH->GetMarkerSize(),tt.Data());
10189 }
10190 }
10191 }
10192}
10193
10194////////////////////////////////////////////////////////////////////////////////
10195/// [Control function to draw a 3D implicit functions.](\ref HP27)
10196
10198{
10199
10200 Int_t irep;
10201
10202 TAxis *xaxis = fH->GetXaxis();
10203 TAxis *yaxis = fH->GetYaxis();
10204 TAxis *zaxis = fH->GetZaxis();
10205
10206 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
10207 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
10208 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
10209 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
10210 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
10211 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
10212
10213 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
10214
10215 TView *view = gPad ? gPad->GetView() : nullptr;
10216 if (!view) {
10217 Error("PaintTF3", "no TView in current pad");
10218 return;
10219 }
10220 Double_t thedeg = 90 - gPad->GetTheta();
10221 Double_t phideg = -90 - gPad->GetPhi();
10222 Double_t psideg = view->GetPsi();
10223 view->SetView(phideg, thedeg, psideg, irep);
10224
10225 fLego->InitMoveScreen(-1.1,1.1);
10226
10227 if (Hoption.BackBox) {
10228 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
10230 fLego->BackBox(90);
10231 }
10232
10234
10235 fLego->ImplicitFunction(fCurrentF3, fXbuf.data(), fYbuf.data(), fH->GetNbinsX(),
10236 fH->GetNbinsY(),
10237 fH->GetNbinsZ(), "BF");
10238
10239 if (Hoption.FrontBox) {
10240 fLego->InitMoveScreen(-1.1,1.1);
10242 fLego->FrontBox(90);
10243 }
10244 if (!Hoption.Axis && !Hoption.Same) {
10245 TGaxis axis;
10246 PaintLegoAxis(&axis, 90);
10247 }
10248
10249 PaintTitle();
10250
10251 fLego.reset();
10252}
10253
10254/////////////////////////////////////////////////////////////new TGaxis///////////////////
10255/// Draw the histogram title
10256///
10257/// The title is drawn according to the title alignment returned by
10258/// `GetTitleAlign()`. It is a 2 digits integer): hv
10259///
10260/// where `h` is the horizontal alignment and `v` is the
10261/// vertical alignment.
10262///
10263/// - `h` can get the values 1 2 3 for left, center, and right
10264/// - `v` can get the values 1 2 3 for bottom, middle and top
10265///
10266/// for instance the default alignment is: 13 (left top)
10267
10269{
10270 // probably best place for calls PaintHighlightBin
10271 // calls after paint histo (1D or 2D) and before paint title and stats
10272 if (!gPad->GetView()) PaintHighlightBin();
10273
10274 if (Hoption.Same) return;
10275 if (fH->TestBit(TH1::kNoTitle)) return;
10276 Int_t nt = strlen(fH->GetTitle());
10277 TPaveText *title = nullptr;
10278 TObject *obj;
10279 TIter next(gPad->GetListOfPrimitives());
10280 while ((obj = next())) {
10281 if (!obj->InheritsFrom(TPaveText::Class())) continue;
10282 title = (TPaveText*)obj;
10283 if (strcmp(title->GetName(),"title")) {title = nullptr; continue;}
10284 break;
10285 }
10286 if (nt == 0 || gStyle->GetOptTitle() <= 0) {
10287 if (title) delete title;
10288 return;
10289 }
10292
10293 if (ht <= 0) {
10294 if (gStyle->GetTitleFont("")%10 == 3) {
10295 Double_t hw = TMath::Max((Double_t)gPad->XtoPixel(gPad->GetX2()),
10296 (Double_t)gPad->YtoPixel(gPad->GetY1()));
10297 ht = 1.1*(gStyle->GetTitleSize("")/hw);
10298 } else {
10299 ht = 1.1*gStyle->GetTitleFontSize();
10300 }
10301 }
10302 if (ht <= 0) ht = 0.05;
10303 if (wt <= 0) {
10304 TLatex l;
10305 l.SetTextSize(ht);
10306 l.SetTitle(fH->GetTitle());
10307 // adjustment in case the title has several lines (#splitline)
10308 ht = TMath::Max(ht, 1.2*l.GetYsize()/(gPad->GetY2() - gPad->GetY1()));
10309 Double_t wndc = l.GetXsize()/(gPad->GetX2() - gPad->GetX1());
10310 wt = TMath::Min(0.7, 0.02+wndc);
10311 }
10312 if (title) {
10313 TText *t0 = (TText*)title->GetLine(0);
10314 if (t0) {
10315 if (!strcmp(t0->GetTitle(),fH->GetTitle())) return;
10316 t0->SetTitle(fH->GetTitle());
10317 if (wt > 0) title->SetX2NDC(title->GetX1NDC()+wt);
10318 }
10319 return;
10320 }
10321
10323 if (talh < 1) talh = 1; else if (talh > 3) talh = 3;
10325 if (talv < 1) talv = 1; else if (talv > 3) talv = 3;
10327 xpos = gStyle->GetTitleX();
10328 ypos = gStyle->GetTitleY();
10329 if (talh == 2) xpos = xpos-wt/2.;
10330 if (talh == 3) xpos = xpos-wt;
10331 if (talv == 2) ypos = ypos+ht/2.;
10332 if (talv == 1) ypos = ypos+ht;
10333
10334 TPaveText *ptitle = new TPaveText(xpos, ypos-ht, xpos+wt, ypos,"blNDC");
10335
10336 // box with the histogram title
10337 ptitle->SetFillColor(gStyle->GetTitleFillColor());
10338 ptitle->SetFillStyle(gStyle->GetTitleStyle());
10339 ptitle->SetName("title");
10340 ptitle->SetBorderSize(gStyle->GetTitleBorderSize());
10341 ptitle->SetTextColor(gStyle->GetTitleTextColor());
10342 ptitle->SetTextFont(gStyle->GetTitleFont(""));
10343 if (gStyle->GetTitleFont("")%10 > 2)
10344 ptitle->SetTextSize(gStyle->GetTitleFontSize());
10345 ptitle->AddText(fH->GetTitle());
10346 ptitle->SetBit(kCanDelete);
10347 ptitle->Draw();
10348 ptitle->Paint("blNDC");
10349
10350 if(!gPad->IsEditable()) delete ptitle;
10351}
10352
10353////////////////////////////////////////////////////////////////////////////////
10354/// Process message `mess`.
10355
10356void THistPainter::ProcessMessage(const char *mess, const TObject *obj)
10357{
10358 if (!strcmp(mess,"SetF3")) {
10359 fCurrentF3 = (TF3 *)obj;
10360 }
10361}
10362
10363////////////////////////////////////////////////////////////////////////////////
10364/// Static function.
10365///
10366/// Convert Right Ascension, Declination to X,Y using an AITOFF projection.
10367/// This procedure can be used to create an all-sky map in Galactic
10368/// coordinates with an equal-area Aitoff projection. Output map
10369/// coordinates are zero longitude centered.
10370/// Also called Hammer-Aitoff projection (first presented by Ernst von Hammer in 1892)
10371///
10372/// source: GMT
10373///
10374/// code from Ernst-Jan Buis
10375
10377{
10378
10379 Double_t x, y;
10380
10382 Double_t delta = b*TMath::DegToRad();
10383 Double_t r2 = TMath::Sqrt(2.);
10384 Double_t f = 2*r2/TMath::Pi();
10385 Double_t cdec = TMath::Cos(delta);
10388 y = TMath::Sin(delta)*r2/denom;
10389 x *= TMath::RadToDeg()/f;
10390 y *= TMath::RadToDeg()/f;
10391 // x *= -1.; // for a skymap swap left<->right
10392 Al = x;
10393 Ab = y;
10394
10395 return 0;
10396}
10397
10398////////////////////////////////////////////////////////////////////////////////
10399/// Static function
10400///
10401/// Probably the most famous of the various map projections, the Mercator projection
10402/// takes its name from Mercator who presented it in 1569. It is a cylindrical, conformal projection
10403/// with no distortion along the equator.
10404/// The Mercator projection has been used extensively for world maps in which the distortion towards
10405/// the polar regions grows rather large, thus incorrectly giving the impression that, for example,
10406/// Greenland is larger than South America. In reality, the latter is about eight times the size of
10407/// Greenland. Also, the Former Soviet Union looks much bigger than Africa or South America. One may wonder
10408/// whether this illusion has had any influence on U.S. foreign policy.' (Source: GMT)
10409/// code from Ernst-Jan Buis
10410
10412{
10413
10414 Al = l;
10416 Ab = TMath::Log(aid);
10417 return 0;
10418}
10419
10420////////////////////////////////////////////////////////////////////////////////
10421/// Static function code for sinusoidal projection
10422/// from Ernst-Jan Buis
10423/// Source https://en.wikipedia.org/wiki/Sinusoidal_projection
10424
10426{
10427
10428 Al = l*cos(b*TMath::DegToRad());
10429 Ab = b;
10430 return 0;
10431}
10432
10433////////////////////////////////////////////////////////////////////////////////
10434/// Static function code for parabolic projection
10435/// from Ernst-Jan Buis
10436
10438{
10439
10440 Al = l*(2.*TMath::Cos(2*b*TMath::DegToRad()/3) - 1);
10441 Ab = 180*TMath::Sin(b*TMath::DegToRad()/3);
10442 return 0;
10443}
10444
10445////////////////////////////////////////////////////////////////////////////////
10446/// Static function.
10447///
10448/// Convert Right Ascension, Declination to X,Y using an MOLLWEIDE projection.
10449/// This procedure can be used to create an all-sky map in Galactic
10450/// coordinates with an equal-area Mollweide projection. Output map
10451/// coordinates are zero longitude centered.
10452/// It is also known as the Babinet projection, homalographic projection, homolographic projection, and elliptical projection.
10453/// Source: https://en.wikipedia.org/wiki/Mollweide_projection
10454///
10455/// code from Marco Meyer-Conde
10456
10458{
10459
10460 Double_t theta0 = b * TMath::DegToRad(), theta = theta0;
10461
10462 for (int i = 0; i < 100; i++) {
10463 Double_t num = 2 * theta + TMath::Sin(2 * theta) - TMath::Pi() * TMath::Sin(theta0);
10464 Double_t den = 4 * TMath::Power(TMath::Cos(theta), 2);
10465
10466 if (den < 1e-20) {
10467 theta = theta0;
10468 break;
10469 }
10470
10471 theta -= num / den;
10472
10473 if (TMath::Abs(num / den) < 1e-4) break;
10474 }
10475
10476 Al = l * TMath::Cos(theta);
10477 Ab = 90 * TMath::Sin(theta);
10478
10479 return 0;
10480}
10481
10482////////////////////////////////////////////////////////////////////////////////
10483/// Recompute the histogram range following graphics operations.
10484
10486{
10487
10488 if (Hoption.Same) return;
10489
10490 // Compute x,y range
10492 xmax = Hparam.xmax,
10493 ymin = Hparam.ymin,
10494 ymax = Hparam.ymax,
10495 xscale = 1;
10496
10497 std::function<Int_t(Double_t,Double_t,Double_t&,Double_t&)> func;
10498
10499 if (Hoption.Proj == 1) {
10500 func = ProjectAitoff2xy;
10501 xscale = 0.9999;
10502 } else if (Hoption.Proj == 2) {
10503 if (Hparam.ymin <= -90 || Hparam.ymax >= 90) {
10504 Warning("Mercator Projection", "Latitude out of range %f or %f", Hparam.ymin, Hparam.ymax);
10505 Hoption.Proj = 0;
10506 } else {
10509 }
10510 } else if (Hoption.Proj == 3) {
10511 func = ProjectSinusoidal2xy;
10512 } else if (Hoption.Proj == 4) {
10513 func = ProjectParabolic2xy;
10514 } else if (Hoption.Proj == 5) {
10515 func = ProjectMollweide2xy;
10516 }
10517
10518 if (func) {
10520
10524 func(Hparam.xmax, Hparam.ymin, xmax, ymin);
10525
10526 if (xmin > xmin_aid) xmin = xmin_aid;
10527 if (ymin > ymin_aid) ymin = ymin_aid;
10528 if (xmax < xmax_aid) xmax = xmax_aid;
10529 if (ymax < ymax_aid) ymax = ymax_aid;
10530 if (Hparam.ymin < 0 && Hparam.ymax > 0) {
10531 // there is an 'equator', check its range in the plot..
10532 func(Hparam.xmin*xscale, 0, xmin_aid, ymin_aid);
10533 func(Hparam.xmax*xscale, 0, xmax_aid, ymin_aid);
10534 if (xmin > xmin_aid) xmin = xmin_aid;
10535 if (xmax < xmax_aid) xmax = xmax_aid;
10536 }
10537 if (Hparam.xmin < 0 && Hparam.xmax > 0) {
10538 func(0, Hparam.ymin, xmin_aid, ymin_aid);
10539 func(0, Hparam.ymax, xmax_aid, ymax_aid);
10540 if (ymin > ymin_aid) ymin = ymin_aid;
10541 if (ymax < ymax_aid) ymax = ymax_aid;
10542 }
10543 }
10544
10545 Hparam.xmin = xmin;
10546 Hparam.xmax = xmax;
10547 Hparam.ymin = ymin;
10548 Hparam.ymax = ymax;
10549
10550 Double_t dx = xmax-xmin;
10551 Double_t dy = ymax-ymin;
10552 Double_t dxr = dx/(1 - gPad->GetLeftMargin() - gPad->GetRightMargin());
10553 Double_t dyr = dy/(1 - gPad->GetBottomMargin() - gPad->GetTopMargin());
10554
10555 // Range() could change the size of the pad pixmap and therefore should
10556 // be called before the other paint routines
10557 gPad->Range(xmin - dxr*gPad->GetLeftMargin(),
10558 ymin - dyr*gPad->GetBottomMargin(),
10559 xmax + dxr*gPad->GetRightMargin(),
10560 ymax + dyr*gPad->GetTopMargin());
10561 gPad->RangeAxis(xmin, ymin, xmax, ymax);
10562}
10563
10564////////////////////////////////////////////////////////////////////////////////
10565/// Set current histogram to `h`
10566
10568{
10569
10570 if (h == nullptr) return;
10571 fH = h;
10572 fXaxis = h->GetXaxis();
10573 fYaxis = h->GetYaxis();
10574 fZaxis = h->GetZaxis();
10576}
10577
10578////////////////////////////////////////////////////////////////////////////////
10579/// Initialize various options to draw 2D histograms.
10580
10582{
10583
10584 static const char *where = "TableInit";
10585
10586 Int_t first, last;
10588 Double_t zmin, zmax;
10589 Int_t maximum = 0;
10590 Int_t minimum = 0;
10591 if (fH->GetMaximumStored() != -1111) maximum = 1;
10592 if (fH->GetMinimumStored() != -1111) minimum = 1;
10593
10594 // ----------------- Compute X axis parameters
10595 first = fXaxis->GetFirst();
10596 last = fXaxis->GetLast();
10597 Hparam.xlast = last;
10598 Hparam.xfirst = first;
10603
10604 // if log scale in X, replace xmin,max by the log
10605 if (Hoption.Logx) {
10606 // find the first edge of a bin that is > 0
10607 if (Hparam.xlowedge <=0 ) {
10610 }
10611 if (Hparam.xmin <=0 || Hparam.xmax <=0) {
10612 Error(where, "cannot set X axis to log scale");
10613 return 0;
10614 }
10616 if (Hparam.xfirst < first) Hparam.xfirst = first;
10618 if (Hparam.xlast > last) Hparam.xlast = last;
10621 }
10622
10623 // ----------------- Compute Y axis parameters
10624 first = fYaxis->GetFirst();
10625 last = fYaxis->GetLast();
10626 Hparam.ylast = last;
10627 Hparam.yfirst = first;
10630 if (!Hparam.ybinsize) Hparam.ybinsize = 1;
10633
10634 // if log scale in Y, replace ymin,max by the log
10635 if (Hoption.Logy) {
10636 if (Hparam.ylowedge <=0 ) {
10639 }
10640 if (Hparam.ymin <=0 || Hparam.ymax <=0) {
10641 Error(where, "cannot set Y axis to log scale");
10642 return 0;
10643 }
10645 if (Hparam.yfirst < first) Hparam.yfirst = first;
10647 if (Hparam.ylast > last) Hparam.ylast = last;
10650 }
10651
10652
10653 // ----------------- Compute Z axis parameters
10654 Double_t bigp = TMath::Power(10,32);
10655 zmax = -bigp;
10656 zmin = bigp;
10657 Double_t c1, e1;
10658 Double_t allchan = 0;
10659 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
10660 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10661 c1 = fH->GetBinContent(i,j);
10662 zmax = TMath::Max(zmax,c1);
10663 if (Hoption.Error) {
10664 e1 = fH->GetBinError(i,j);
10665 zmax = TMath::Max(zmax,c1+e1);
10666 }
10667 zmin = TMath::Min(zmin,c1);
10668 allchan += c1;
10669 }
10670 }
10671
10672 // Take into account maximum , minimum
10673
10674 if (maximum) zmax = fH->GetMaximumStored();
10675 if (minimum) zmin = fH->GetMinimumStored();
10676 if (Hoption.Logz && zmax < 0) {
10677 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10678 return 0;
10679 } else if (Hoption.Logz && zmin>=0 && zmax==0) { // empty histogram in log scale
10680 zmin = 0.01;
10681 zmax = 10.;
10682 }
10683 if (zmin >= zmax) {
10684 if (Hoption.Logz) {
10685 if (zmax > 0) zmin = 0.001*zmax;
10686 else {
10687 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10688 return 0;
10689 }
10690 }
10691 }
10692
10693 // take into account normalization factor
10694 Hparam.allchan = allchan;
10695 Double_t factor = allchan;
10696 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
10697 if (allchan) factor /= allchan;
10698 if (factor == 0) factor = 1;
10699 Hparam.factor = factor;
10700 zmax = factor*zmax;
10701 zmin = factor*zmin;
10702 c1 = zmax;
10703 if (TMath::Abs(zmin) > TMath::Abs(c1)) c1 = zmin;
10704
10705 // For log scales, histogram coordinates are log10(ymin) and
10706 // log10(ymax). Final adjustment (if not option "Same")
10707 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
10708 // Maximum and Minimum are not defined.
10709 if (Hoption.Logz) {
10710 if (zmin <= 0) {
10711 zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
10712 fH->SetMinimum(zmin);
10713 }
10714 zmin = TMath::Log10(zmin);
10715 if (!minimum) zmin += TMath::Log10(0.5);
10716 zmax = TMath::Log10(zmax);
10717 if (!maximum) zmax += TMath::Log10(2*(0.9/0.95));
10718 goto LZMIN;
10719 }
10720
10721 // final adjustment of YMAXI for linear scale (if not option "Same"):
10722 // decrease histogram height to MAX% of allowed height if HMAXIM
10723 // has not been called.
10724 // MAX% is the value in percent which has been set in HPLSET
10725 // (default is 90%).
10726 if (!maximum) {
10727 zmax += yMARGIN*(zmax-zmin);
10728 }
10729
10730 // final adjustment of ymin for linear scale.
10731 // if minimum is not set , then ymin is set to zero if >0
10732 // or to ymin - yMARGIN if <0.
10733 if (!minimum) {
10734 if (Hoption.MinimumZero) {
10735 if (zmin >= 0) zmin = 0;
10736 else zmin -= yMARGIN*(zmax-zmin);
10737 } else {
10738 Double_t dzmin = yMARGIN*(zmax-zmin);
10739 if (zmin >= 0 && (zmin-dzmin <= 0)) zmin = 0;
10740 else zmin -= dzmin;
10741 }
10742 }
10743
10744LZMIN:
10745 Hparam.zmin = zmin;
10746 Hparam.zmax = zmax;
10747
10748 // Set bar offset and width
10751
10752 return 1;
10753}
10754
10755////////////////////////////////////////////////////////////////////////////////
10756/// This function returns the best format to print the error value (e)
10757/// knowing the parameter value (v) and the format (f) used to print it.
10758
10760{
10761
10762 static TString ef;
10763 TString tf, tv;
10764
10765 // print v with the format f in tv.
10766 tf.Form("%s%s","%",f);
10767 tv.Form(tf.Data(),v);
10768
10769 // Analyse tv.
10770 int ie = tv.Index("e");
10771 int iE = tv.Index("E");
10772 int id = tv.Index(".");
10773
10774 // v has been printed with the exponent notation.
10775 // There is 2 cases, the exponent is positive or negative
10776 if (ie >= 0 || iE >= 0) {
10777 if (tv.Index("+") >= 0) {
10778 if (e < 1) {
10779 ef.Form("%s.1f","%");
10780 } else {
10781 if (ie >= 0) {
10782 ef.Form("%s.%de","%",ie-id-1);
10783 } else {
10784 ef.Form("%s.%dE","%",iE-id-1);
10785 }
10786 }
10787 } else {
10788 if (ie >= 0) {
10789 ef.Form("%s.%de","%",ie-id-1);
10790 } else {
10791 ef.Form("%s.%dE","%",iE-id-1);
10792 }
10793 }
10794
10795 // There is not '.' in tv. e will be printed with one decimal digit.
10796 } else if (id < 0) {
10797 ef.Form("%s.1f","%");
10798
10799 // There is a '.' in tv and no exponent notation. e's decimal part will
10800 // have the same number of digits as v's one.
10801 } else {
10802 ef.Form("%s.%df","%",tv.Length()-id-1);
10803 }
10804
10805 return ef.Data();
10806}
10807
10808////////////////////////////////////////////////////////////////////////////////
10809/// Set projection.
10810
10812{
10813 if (fShowProjection2) {
10814 auto name2 = TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2);
10815 auto c2 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name2.Data()));
10816 if (c2) c2->Close();
10817 fShowProjection2 = 0;
10818 }
10819 if (fShowProjection) {
10820 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10821 auto c1 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name1.Data()));
10822 if (c1) c1->Close();
10823 fShowProjection = 0;
10824 }
10825
10826 if (nbins <= 0) return;
10827
10828 TString opt = option;
10829 opt.ToLower();
10830 Int_t projection = 0;
10831 if (opt.Contains("x")) projection = 1;
10832 if (opt.Contains("y")) projection = 2;
10833 if (opt.Contains("z")) projection = 3;
10834 if (opt.Contains("xy")) projection = 4;
10835 if (opt.Contains("yx")) projection = 5;
10836 if (opt.Contains("xz")) projection = 6;
10837 if (opt.Contains("zx")) projection = 7;
10838 if (opt.Contains("yz")) projection = 8;
10839 if (opt.Contains("zy")) projection = 9;
10840 if (projection < 4) fShowOption = option+1;
10841 else fShowOption = option+2;
10842 fShowProjection = projection+100*nbins;
10843 fShowProjection2 = 0;
10844 gROOT->MakeDefCanvas();
10845 gPad->SetName(TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection).Data());
10846 gPad->SetGrid();
10847}
10848
10850{
10851 if (fShowProjection2) {
10852 auto name2 = TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2);
10853 auto c2 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name2.Data()));
10854 if (c2) c2->Close();
10855 fShowProjection2 = 0;
10856 }
10857 if (fShowProjection) {
10858 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10859 auto c1 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name1.Data()));
10860 if (c1) c1->Close();
10861 fShowProjection = 0;
10862 }
10863
10864 if ((nbinsX <= 0) || (nbinsY <= 0)) return;
10865
10866
10867 TString opt = option;
10868 opt.ToLower();
10869 Int_t projection = 0;
10870 if (opt.Contains("x")) projection = 1;
10871 if (opt.Contains("y")) projection = 2;
10872 if (opt.Contains("z")) projection = 3;
10873 if (opt.Contains("xy")) projection = 4;
10874 if (opt.Contains("yx")) projection = 5;
10875 if (opt.Contains("xz")) projection = 6;
10876 if (opt.Contains("zx")) projection = 7;
10877 if (opt.Contains("yz")) projection = 8;
10878 if (opt.Contains("zy")) projection = 9;
10879 if (projection < 4) fShowOption = option+1;
10880 else fShowOption = option+2;
10883 gROOT->MakeDefCanvas();
10884 gPad->SetName(TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection).Data());
10885 gPad->SetGrid();
10886 gROOT->MakeDefCanvas();
10887 gPad->SetName(TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2).Data());
10888 gPad->SetGrid();
10889}
10890
10891
10892////////////////////////////////////////////////////////////////////////////////
10893/// Show projection onto X.
10894
10896{
10897
10898 Int_t nbins = (Int_t)fShowProjection/100;
10899 gPad->SetDoubleBuffer(0); // turn off double buffer mode
10900 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
10901
10902 // Erase old position and draw a line at current position
10903 static int pyold1 = 0;
10904 static int pyold2 = 0;
10905 float uxmin = gPad->GetUxmin();
10906 float uxmax = gPad->GetUxmax();
10907 int pxmin = gPad->XtoAbsPixel(uxmin);
10908 int pxmax = gPad->XtoAbsPixel(uxmax);
10909 Float_t upy = gPad->AbsPixeltoY(py);
10910 Float_t y = gPad->PadtoY(upy);
10911 Int_t biny1 = fH->GetYaxis()->FindBin(y);
10912 Int_t biny2 = TMath::Min(biny1+nbins-1, fH->GetYaxis()->GetNbins());
10913 Int_t py1 = gPad->YtoAbsPixel(gPad->GetLogy() ? TMath::Log10(fH->GetYaxis()->GetBinLowEdge(biny1)) : fH->GetYaxis()->GetBinLowEdge(biny1));
10914 Int_t py2 = gPad->YtoAbsPixel(gPad->GetLogy() ? TMath::Log10(fH->GetYaxis()->GetBinUpEdge(biny2)) : fH->GetYaxis()->GetBinUpEdge(biny2));
10915
10917 gVirtualX->DrawBox(pxmin,py1,pxmax,py2,TVirtualX::kFilled);
10918 pyold1 = py1;
10919 pyold2 = py2;
10920
10921 // Create or set the new canvas proj x
10923 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10924 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(name1.Data());
10925 if (c) {
10926 c->Clear();
10927 } else {
10928 fShowProjection = 0;
10929 fShowProjection2 = 0;
10930 pyold1 = 0;
10931 pyold2 = 0;
10932 return;
10933 }
10934 c->cd();
10935 c->SetLogy(ctxt.GetSaved()->GetLogz());
10936 c->SetLogx(ctxt.GetSaved()->GetLogx());
10937
10938 // Draw slice corresponding to mouse position
10939 TString prjName = TString::Format("slice_px_of_%s",fH->GetName());
10940 TH1D *hp = ((TH2*)fH)->ProjectionX(prjName, biny1, biny2);
10941 if (hp) {
10942 hp->SetFillColor(38);
10943 // apply a patch from Oliver Freyermuth to set the title in the projection
10944 // using the range of the projected Y values
10945 if (biny1 == biny2) {
10948 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
10950 if (fH->GetYaxis()->GetLabels() != nullptr) {
10951 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf] %s", biny1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetYaxis()->GetBinLabel(biny1)));
10952 } else {
10953 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf]", biny1, valuePrecision, valueFrom, valuePrecision, valueTo));
10954 }
10955 } else {
10958 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
10959 // biny1 is used here to get equal precision no matter how large the binrange is,
10960 // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
10962 if (fH->GetYaxis()->GetLabels() != nullptr) {
10963 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)));
10964 } else {
10965 hp->SetTitle(TString::Format("ProjectionX of biny=[%d,%d] [y=%.*lf..%.*lf]", biny1, biny2, valuePrecision, valueFrom, valuePrecision, valueTo));
10966 }
10967 }
10968 hp->SetXTitle(fH->GetXaxis()->GetTitle());
10969 hp->SetYTitle(((TH2*)fH)->GetZaxis()->GetTitle() ? ((TH2*)fH)->GetZaxis()->GetTitle() : "Number of Entries");
10970 hp->Draw();
10971 c->Update();
10972 }
10973}
10974
10975////////////////////////////////////////////////////////////////////////////////
10976/// Show projection onto Y.
10977
10979{
10980
10981 Int_t nbins = (Int_t)fShowProjection/100;
10982 if (fShowProjection2)
10983 nbins = (Int_t)fShowProjection2/100;
10984 gPad->SetDoubleBuffer(0); // turn off double buffer mode
10985 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
10986
10987 // Erase old position and draw a line at current position
10988 static int pxold1 = 0;
10989 static int pxold2 = 0;
10990 float uymin = gPad->GetUymin();
10991 float uymax = gPad->GetUymax();
10992 int pymin = gPad->YtoAbsPixel(uymin);
10993 int pymax = gPad->YtoAbsPixel(uymax);
10994 Float_t upx = gPad->AbsPixeltoX(px);
10995 Float_t x = gPad->PadtoX(upx);
10996 Int_t binx1 = fH->GetXaxis()->FindBin(x);
10997 Int_t binx2 = TMath::Min(binx1+nbins-1, fH->GetXaxis()->GetNbins());
10998 Int_t px1 = gPad->XtoAbsPixel(gPad->GetLogx() ? TMath::Log10(fH->GetXaxis()->GetBinLowEdge(binx1)) : fH->GetXaxis()->GetBinLowEdge(binx1));
10999 Int_t px2 = gPad->XtoAbsPixel(gPad->GetLogx() ? TMath::Log10(fH->GetXaxis()->GetBinUpEdge(binx2)) : fH->GetXaxis()->GetBinUpEdge(binx2));
11000
11002 gVirtualX->DrawBox(px1,pymin,px2,pymax,TVirtualX::kFilled);
11003 pxold1 = px1;
11004 pxold2 = px2;
11005
11006 // Create or set the new canvas proj y
11008
11009 TString name2 = fShowProjection2 ? TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2)
11010 : TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
11011
11012 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(name2.Data());
11013 if (c) {
11014 c->Clear();
11015 } else {
11016 fShowProjection = 0;
11017 fShowProjection2 = 0;
11018 pxold1 = 0;
11019 pxold2 = 0;
11020 return;
11021 }
11022 c->cd();
11023 c->SetLogy(ctxt.GetSaved()->GetLogz());
11024 c->SetLogx(ctxt.GetSaved()->GetLogy());
11025
11026 // Draw slice corresponding to mouse position
11027 TString prjName = TString::Format("slice_py_of_%s",fH->GetName());
11028 TH1D *hp = ((TH2*)fH)->ProjectionY(prjName, binx1, binx2);
11029 if (hp) {
11030 hp->SetFillColor(38);
11031 // apply a patch from Oliver Freyermuth to set the title in the projection
11032 // using the range of the projected X values
11033 if (binx1 == binx2) {
11036 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11038 if (fH->GetXaxis()->GetLabels() != nullptr) {
11039 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf] [%s]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetXaxis()->GetBinLabel(binx1)));
11040 } else {
11041 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo));
11042 }
11043 } else {
11046 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11047 // binx1 is used here to get equal precision no matter how large the binrange is,
11048 // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
11050 if (fH->GetXaxis()->GetLabels() != nullptr) {
11051 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)));
11052 } else {
11053 hp->SetTitle(TString::Format("ProjectionY of binx=[%d,%d] [x=%.*lf..%.*lf]", binx1, binx2, valuePrecision, valueFrom, valuePrecision, valueTo));
11054 }
11055 }
11056 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11057 hp->SetYTitle(((TH2*)fH)->GetZaxis()->GetTitle() ? ((TH2*)fH)->GetZaxis()->GetTitle() : "Number of Entries");
11058 hp->Draw(fShowProjection2 ? "hbar" : "");
11059 c->Update();
11060 }
11061}
11062
11063////////////////////////////////////////////////////////////////////////////////
11064/// Show projection (specified by `fShowProjection`) of a `TH3`.
11065/// The drawing option for the projection is in `fShowOption`.
11066///
11067/// First implementation; R.Brun
11068///
11069/// Full implementation: Tim Tran (timtran@jlab.org) April 2006
11070
11072{
11073
11074 Int_t nbins=(Int_t)fShowProjection/100; //decode nbins
11075 if (fH->GetDimension() < 3) {
11076 if (fShowProjection2 % 100 == 1) {
11077 ShowProjectionY(px, py);
11078 }
11079 if (fShowProjection % 100 == 1) {
11080 ShowProjectionX(px, py);
11081 return;
11082 }
11083 if (fShowProjection % 100 == 2) {
11084 ShowProjectionY(px, py);
11085 return;
11086 }
11087 }
11088
11089 gPad->SetDoubleBuffer(0); // turn off double buffer mode
11090 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
11091
11092 // Erase old position and draw a line at current position
11093 TView *view = gPad->GetView();
11094 if (!view) return;
11095 TH3 *h3 = (TH3*)fH;
11096 TAxis *xaxis = h3->GetXaxis();
11097 TAxis *yaxis = h3->GetYaxis();
11098 TAxis *zaxis = h3->GetZaxis();
11099 Double_t u[3],xx[3];
11100
11101 static TPoint line1[2];//store end points of a line, initialised 0 by default
11102 static TPoint line2[2];// second line when slice thickness > 1 bin thickness
11103 static TPoint line3[2];
11104 static TPoint line4[2];
11105 static TPoint endface1[5];
11106 static TPoint endface2[5];
11107 static TPoint rect1[5];//store vertices of the polyline (rectangle), initialsed 0 by default
11108 static TPoint rect2[5];// second rectangle when slice thickness > 1 bin thickness
11109
11110 Double_t uxmin = gPad->GetUxmin();
11111 Double_t uxmax = gPad->GetUxmax();
11112 Double_t uymin = gPad->GetUymin();
11113 Double_t uymax = gPad->GetUymax();
11114
11115 int pxmin = gPad->XtoAbsPixel(uxmin);
11116 int pxmax = gPad->XtoAbsPixel(uxmax);
11117 if (pxmin==pxmax) return;
11118 int pymin = gPad->YtoAbsPixel(uymin);
11119 int pymax = gPad->YtoAbsPixel(uymax);
11120 if (pymin==pymax) return;
11123 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(TString::Format("c_%zx_projection_%d",
11124 (size_t)fH, fShowProjection).Data());
11125 if (!c) {
11126 fShowProjection = 0;
11127 return;
11128 }
11129
11131
11132 switch ((Int_t)fShowProjection%100) {
11133 case 1:
11134 // "x"
11135 {
11136 Int_t firstY = yaxis->GetFirst();
11137 Int_t lastY = yaxis->GetLast();
11139 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11140 yaxis->SetRange(biny,biny2);
11141 Int_t firstZ = zaxis->GetFirst();
11142 Int_t lastZ = zaxis->GetLast();
11144 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11145 zaxis->SetRange(binz,binz2);
11146 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11147 if (nbins>1 && line1[0].GetX()) {
11148 gVirtualX->DrawPolyLine(2,line2);
11149 gVirtualX->DrawPolyLine(2,line3);
11150 gVirtualX->DrawPolyLine(2,line4);
11151 gVirtualX->DrawPolyLine(5,endface1);
11152 gVirtualX->DrawPolyLine(5,endface2);
11153 }
11154 xx[0] = xaxis->GetXmin();
11155 xx[2] = zaxis->GetBinCenter(binz);
11156 xx[1] = yaxis->GetBinCenter(biny);
11157 view->WCtoNDC(xx,u);
11158 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11159 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11160 xx[0] = xaxis->GetXmax();
11161 view->WCtoNDC(xx,u);
11162 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11163 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11164 gVirtualX->DrawPolyLine(2,line1);
11165 if (nbins>1) {
11166 xx[0] = xaxis->GetXmin();
11167 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11168 xx[1] = yaxis->GetBinCenter(biny);
11169 view->WCtoNDC(xx,u);
11170 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11171 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11172 xx[0] = xaxis->GetXmax();
11173 view->WCtoNDC(xx,u);
11174 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11175 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11176
11177 xx[0] = xaxis->GetXmin();
11178 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11179 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11180 view->WCtoNDC(xx,u);
11181 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11182 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11183 xx[0] = xaxis->GetXmax();
11184 view->WCtoNDC(xx,u);
11185 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11186 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11187
11188 xx[0] = xaxis->GetXmin();
11189 xx[2] = zaxis->GetBinCenter(binz);
11190 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11191 view->WCtoNDC(xx,u);
11192 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11193 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11194 xx[0] = xaxis->GetXmax();
11195 view->WCtoNDC(xx,u);
11196 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11197 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11198
11199 endface1[0].SetX(line1[0].GetX());
11200 endface1[0].SetY(line1[0].GetY());
11201 endface1[1].SetX(line2[0].GetX());
11202 endface1[1].SetY(line2[0].GetY());
11203 endface1[2].SetX(line3[0].GetX());
11204 endface1[2].SetY(line3[0].GetY());
11205 endface1[3].SetX(line4[0].GetX());
11206 endface1[3].SetY(line4[0].GetY());
11207 endface1[4].SetX(line1[0].GetX());
11208 endface1[4].SetY(line1[0].GetY());
11209
11210 endface2[0].SetX(line1[1].GetX());
11211 endface2[0].SetY(line1[1].GetY());
11212 endface2[1].SetX(line2[1].GetX());
11213 endface2[1].SetY(line2[1].GetY());
11214 endface2[2].SetX(line3[1].GetX());
11215 endface2[2].SetY(line3[1].GetY());
11216 endface2[3].SetX(line4[1].GetX());
11217 endface2[3].SetY(line4[1].GetY());
11218 endface2[4].SetX(line1[1].GetX());
11219 endface2[4].SetY(line1[1].GetY());
11220
11221 gVirtualX->DrawPolyLine(2,line2);
11222 gVirtualX->DrawPolyLine(2,line3);
11223 gVirtualX->DrawPolyLine(2,line4);
11224 gVirtualX->DrawPolyLine(5,endface1);
11225 gVirtualX->DrawPolyLine(5,endface2);
11226 }
11227 c->Clear();
11228 c->cd();
11229 TH1 *hp = h3->Project3D("x");
11230 yaxis->SetRange(firstY,lastY);
11231 zaxis->SetRange(firstZ,lastZ);
11232 if (hp) {
11233 hp->SetFillColor(38);
11234 if (nbins == 1)
11235 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny),
11236 binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
11237 else {
11238 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),
11239 binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
11240 }
11241 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11242 hp->SetYTitle("Number of Entries");
11243 hp->Draw(fShowOption.Data());
11244 }
11245 }
11246 break;
11247
11248 case 2:
11249 // "y"
11250 {
11251 Int_t firstX = xaxis->GetFirst();
11252 Int_t lastX = xaxis->GetLast();
11254 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11255 xaxis->SetRange(binx,binx2);
11256 Int_t firstZ = zaxis->GetFirst();
11257 Int_t lastZ = zaxis->GetLast();
11259 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11260 zaxis->SetRange(binz,binz2);
11261 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11262 if (nbins>1 && line1[0].GetX()) {
11263 gVirtualX->DrawPolyLine(2,line2);
11264 gVirtualX->DrawPolyLine(2,line3);
11265 gVirtualX->DrawPolyLine(2,line4);
11266 gVirtualX->DrawPolyLine(5,endface1);
11267 gVirtualX->DrawPolyLine(5,endface2);
11268 }
11269 xx[0]=xaxis->GetBinCenter(binx);
11270 xx[2] = zaxis->GetBinCenter(binz);
11271 xx[1] = yaxis->GetXmin();
11272 view->WCtoNDC(xx,u);
11273 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11274 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11275 xx[1] = yaxis->GetXmax();
11276 view->WCtoNDC(xx,u);
11277 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11278 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11279 gVirtualX->DrawPolyLine(2,line1);
11280 if (nbins>1) {
11281 xx[1] = yaxis->GetXmin();
11282 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11283 xx[0] = xaxis->GetBinCenter(binx);
11284 view->WCtoNDC(xx,u);
11285 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11286 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11287 xx[1] = yaxis->GetXmax();
11288 view->WCtoNDC(xx,u);
11289 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11290 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11291
11292 xx[1] = yaxis->GetXmin();
11293 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11294 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11295 view->WCtoNDC(xx,u);
11296 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11297 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11298 xx[1] = yaxis->GetXmax();
11299 view->WCtoNDC(xx,u);
11300 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11301 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11302
11303 xx[1] = yaxis->GetXmin();
11304 xx[2] = zaxis->GetBinCenter(binz);
11305 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11306 view->WCtoNDC(xx,u);
11307 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11308 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11309 xx[1] = yaxis->GetXmax();
11310 view->WCtoNDC(xx,u);
11311 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11312 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11313
11314 endface1[0].SetX(line1[0].GetX());
11315 endface1[0].SetY(line1[0].GetY());
11316 endface1[1].SetX(line2[0].GetX());
11317 endface1[1].SetY(line2[0].GetY());
11318 endface1[2].SetX(line3[0].GetX());
11319 endface1[2].SetY(line3[0].GetY());
11320 endface1[3].SetX(line4[0].GetX());
11321 endface1[3].SetY(line4[0].GetY());
11322 endface1[4].SetX(line1[0].GetX());
11323 endface1[4].SetY(line1[0].GetY());
11324
11325 endface2[0].SetX(line1[1].GetX());
11326 endface2[0].SetY(line1[1].GetY());
11327 endface2[1].SetX(line2[1].GetX());
11328 endface2[1].SetY(line2[1].GetY());
11329 endface2[2].SetX(line3[1].GetX());
11330 endface2[2].SetY(line3[1].GetY());
11331 endface2[3].SetX(line4[1].GetX());
11332 endface2[3].SetY(line4[1].GetY());
11333 endface2[4].SetX(line1[1].GetX());
11334 endface2[4].SetY(line1[1].GetY());
11335
11336 gVirtualX->DrawPolyLine(2,line2);
11337 gVirtualX->DrawPolyLine(2,line3);
11338 gVirtualX->DrawPolyLine(2,line4);
11339 gVirtualX->DrawPolyLine(5,endface1);
11340 gVirtualX->DrawPolyLine(5,endface2);
11341 }
11342 c->Clear();
11343 c->cd();
11344 TH1 *hp = h3->Project3D("y");
11345 xaxis->SetRange(firstX,lastX);
11346 zaxis->SetRange(firstZ,lastZ);
11347 if (hp) {
11348 hp->SetFillColor(38);
11349 if (nbins == 1)
11350 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
11351 binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
11352 else
11353 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),
11354 binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
11355 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11356 hp->SetYTitle("Number of Entries");
11357 hp->Draw(fShowOption.Data());
11358 }
11359 }
11360 break;
11361
11362 case 3:
11363 // "z"
11364 {
11365 Int_t firstX = xaxis->GetFirst();
11366 Int_t lastX = xaxis->GetLast();
11368 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11369 xaxis->SetRange(binx,binx2);
11370 Int_t firstY = yaxis->GetFirst();
11371 Int_t lastY = yaxis->GetLast();
11373 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11374 yaxis->SetRange(biny,biny2);
11375 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11376 if (nbins>1 && line1[0].GetX()) {
11377 gVirtualX->DrawPolyLine(2,line2);
11378 gVirtualX->DrawPolyLine(2,line3);
11379 gVirtualX->DrawPolyLine(2,line4);
11380 gVirtualX->DrawPolyLine(5,endface1);
11381 gVirtualX->DrawPolyLine(5,endface2);
11382 }
11383 xx[0] = xaxis->GetBinCenter(binx);
11384 xx[1] = yaxis->GetBinCenter(biny);
11385 xx[2] = zaxis->GetXmin();
11386 view->WCtoNDC(xx,u);
11387 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11388 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11389 xx[2] = zaxis->GetXmax();
11390 view->WCtoNDC(xx,u);
11391 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11392 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11393 gVirtualX->DrawPolyLine(2,line1);
11394 if (nbins>1) {
11395 xx[2] = zaxis->GetXmin();
11396 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11397 xx[0] = xaxis->GetBinCenter(binx);
11398 view->WCtoNDC(xx,u);
11399 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11400 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11401 xx[2] = zaxis->GetXmax();
11402 view->WCtoNDC(xx,u);
11403 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11404 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11405
11406 xx[2] = zaxis->GetXmin();
11407 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11408 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11409 view->WCtoNDC(xx,u);
11410 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11411 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11412 xx[2] = zaxis->GetXmax();
11413 view->WCtoNDC(xx,u);
11414 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11415 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11416
11417 xx[2] = zaxis->GetXmin();
11418 xx[1] = yaxis->GetBinCenter(biny);
11419 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11420 view->WCtoNDC(xx,u);
11421 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11422 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11423 xx[2] = zaxis->GetXmax();
11424 view->WCtoNDC(xx,u);
11425 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11426 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11427
11428 endface1[0].SetX(line1[0].GetX());
11429 endface1[0].SetY(line1[0].GetY());
11430 endface1[1].SetX(line2[0].GetX());
11431 endface1[1].SetY(line2[0].GetY());
11432 endface1[2].SetX(line3[0].GetX());
11433 endface1[2].SetY(line3[0].GetY());
11434 endface1[3].SetX(line4[0].GetX());
11435 endface1[3].SetY(line4[0].GetY());
11436 endface1[4].SetX(line1[0].GetX());
11437 endface1[4].SetY(line1[0].GetY());
11438
11439 endface2[0].SetX(line1[1].GetX());
11440 endface2[0].SetY(line1[1].GetY());
11441 endface2[1].SetX(line2[1].GetX());
11442 endface2[1].SetY(line2[1].GetY());
11443 endface2[2].SetX(line3[1].GetX());
11444 endface2[2].SetY(line3[1].GetY());
11445 endface2[3].SetX(line4[1].GetX());
11446 endface2[3].SetY(line4[1].GetY());
11447 endface2[4].SetX(line1[1].GetX());
11448 endface2[4].SetY(line1[1].GetY());
11449
11450 gVirtualX->DrawPolyLine(2,line2);
11451 gVirtualX->DrawPolyLine(2,line3);
11452 gVirtualX->DrawPolyLine(2,line4);
11453 gVirtualX->DrawPolyLine(5,endface1);
11454 gVirtualX->DrawPolyLine(5,endface2);
11455 }
11456 c->Clear();
11457 c->cd();
11458 TH1 *hp = h3->Project3D("z");
11459 xaxis->SetRange(firstX,lastX);
11460 yaxis->SetRange(firstY,lastY);
11461 if (hp) {
11462 hp->SetFillColor(38);
11463 if (nbins == 1)
11464 hp->SetTitle(TString::Format("ProjectionZ of binx=%d [x=%.1f..%.1f] biny=%d [y=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
11465 biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny)));
11466 else
11467 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),
11468 biny, biny2, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny2) ) );
11469 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11470 hp->SetYTitle("Number of Entries");
11471 hp->Draw(fShowOption.Data());
11472 }
11473 }
11474 break;
11475
11476 case 4:
11477 // "xy"
11478 {
11479 Int_t first = zaxis->GetFirst();
11480 Int_t last = zaxis->GetLast();
11481 Int_t binz = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11482 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11483 zaxis->SetRange(binz,binz2);
11484 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11485 if (nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11486 xx[0] = xaxis->GetXmin();
11487 xx[1] = yaxis->GetXmax();
11488 xx[2] = zaxis->GetBinCenter(binz);
11489 view->WCtoNDC(xx,u);
11490 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11491 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11492 rect1[4].SetX(rect1[0].GetX());
11493 rect1[4].SetY(rect1[0].GetY());
11494 xx[0] = xaxis->GetXmax();
11495 view->WCtoNDC(xx,u);
11496 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11497 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11498 xx[1] = yaxis->GetXmin();
11499 view->WCtoNDC(xx,u);
11500 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11501 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11502 xx[0] = xaxis->GetXmin();
11503 view->WCtoNDC(xx,u);
11504 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11505 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11506 gVirtualX->DrawPolyLine(5,rect1);
11507 if (nbins>1) {
11508 xx[0] = xaxis->GetXmin();
11509 xx[1] = yaxis->GetXmax();
11510 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11511 view->WCtoNDC(xx,u);
11512 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11513 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11514 rect2[4].SetX(rect2[0].GetX());
11515 rect2[4].SetY(rect2[0].GetY());
11516 xx[0] = xaxis->GetXmax();
11517 view->WCtoNDC(xx,u);
11518 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11519 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11520 xx[1] = yaxis->GetXmin();
11521 view->WCtoNDC(xx,u);
11522 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11523 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11524 xx[0] = xaxis->GetXmin();
11525 view->WCtoNDC(xx,u);
11526 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11527 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11528 gVirtualX->DrawPolyLine(5,rect2);
11529 }
11530
11531 c->Clear();
11532 c->cd();
11533 TH2 *hp = (TH2*)h3->Project3D("xy");
11534 zaxis->SetRange(first,last);
11535 if (hp) {
11536 hp->SetFillColor(38);
11537 if (nbins==1)hp->SetTitle(TString::Format("ProjectionXY of binz=%d [z=%.1f..%.f]", binz,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz)));
11538 else hp->SetTitle(TString::Format("ProjectionXY, binz=[%d,%d] [z=%.1f..%.1f]", binz,binz2,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz2)));
11539 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11540 hp->SetYTitle(fH->GetXaxis()->GetTitle());
11541 hp->SetZTitle("Number of Entries");
11542 hp->Draw(fShowOption.Data());
11543 }
11544 }
11545 break;
11546
11547 case 5:
11548 // "yx"
11549 {
11550 Int_t first = zaxis->GetFirst();
11551 Int_t last = zaxis->GetLast();
11552 Int_t binz = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11553 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11554 zaxis->SetRange(binz,binz2);
11555 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11556 if (nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11557 xx[0] = xaxis->GetXmin();
11558 xx[1] = yaxis->GetXmax();
11559 xx[2] = zaxis->GetBinCenter(binz);
11560 view->WCtoNDC(xx,u);
11561 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11562 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11563 rect1[4].SetX(rect1[0].GetX());
11564 rect1[4].SetY(rect1[0].GetY());
11565 xx[0] = xaxis->GetXmax();
11566 view->WCtoNDC(xx,u);
11567 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11568 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11569 xx[1] = yaxis->GetXmin();
11570 view->WCtoNDC(xx,u);
11571 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11572 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11573 xx[0] = xaxis->GetXmin();
11574 view->WCtoNDC(xx,u);
11575 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11576 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11577 gVirtualX->DrawPolyLine(5,rect1);
11578 if (nbins>1) {
11579 xx[0] = xaxis->GetXmin();
11580 xx[1] = yaxis->GetXmax();
11581 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11582 view->WCtoNDC(xx,u);
11583 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11584 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11585 rect2[4].SetX(rect2[0].GetX());
11586 rect2[4].SetY(rect2[0].GetY());
11587 xx[0] = xaxis->GetXmax();
11588 view->WCtoNDC(xx,u);
11589 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11590 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11591 xx[1] = yaxis->GetXmin();
11592 view->WCtoNDC(xx,u);
11593 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11594 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11595 xx[0] = xaxis->GetXmin();
11596 view->WCtoNDC(xx,u);
11597 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11598 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11599 gVirtualX->DrawPolyLine(5,rect2);
11600 }
11601 c->Clear();
11602 c->cd();
11603 TH2 *hp = (TH2*)h3->Project3D("yx");
11604 zaxis->SetRange(first,last);
11605 if (hp) {
11606 hp->SetFillColor(38);
11607 if (nbins==1)hp->SetTitle(TString::Format("ProjectionYX of binz=%d [z=%.1f..%.f]", binz,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz)));
11608 else hp->SetTitle(TString::Format("ProjectionYX, binz=[%d,%d] [z=%.1f..%.1f]", binz,binz2,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz2)));
11609 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11610 hp->SetYTitle(fH->GetYaxis()->GetTitle());
11611 hp->SetZTitle("Number of Entries");
11612 hp->Draw(fShowOption.Data());
11613 }
11614 }
11615 break;
11616
11617 case 6:
11618 // "xz"
11619 {
11620 Int_t first = yaxis->GetFirst();
11621 Int_t last = yaxis->GetLast();
11622 Int_t biny = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11623 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11624 yaxis->SetRange(biny,biny2);
11625 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11626 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11627 xx[0] = xaxis->GetXmin();
11628 xx[2] = zaxis->GetXmax();
11629 xx[1] = yaxis->GetBinCenter(biny);
11630 view->WCtoNDC(xx,u);
11631 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11632 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11633 rect1[4].SetX(rect1[0].GetX());
11634 rect1[4].SetY(rect1[0].GetY());
11635 xx[0] = xaxis->GetXmax();
11636 view->WCtoNDC(xx,u);
11637 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11638 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11639 xx[2] = zaxis->GetXmin();
11640 view->WCtoNDC(xx,u);
11641 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11642 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11643 xx[0] = xaxis->GetXmin();
11644 view->WCtoNDC(xx,u);
11645 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11646 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11647 gVirtualX->DrawPolyLine(5,rect1);
11648 if (nbins>1) {
11649 xx[0] = xaxis->GetXmin();
11650 xx[2] = zaxis->GetXmax();
11651 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11652 view->WCtoNDC(xx,u);
11653 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11654 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11655 rect2[4].SetX(rect2[0].GetX());
11656 rect2[4].SetY(rect2[0].GetY());
11657 xx[0] = xaxis->GetXmax();
11658 view->WCtoNDC(xx,u);
11659 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11660 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11661 xx[2] = zaxis->GetXmin();
11662 view->WCtoNDC(xx,u);
11663 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11664 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11665 xx[0] = xaxis->GetXmin();
11666 view->WCtoNDC(xx,u);
11667 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11668 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11669 gVirtualX->DrawPolyLine(5,rect2);
11670 }
11671 c->Clear();
11672 c->cd();
11673 TH2 *hp = (TH2*)h3->Project3D("xz");
11674 yaxis->SetRange(first,last);
11675 if (hp) {
11676 hp->SetFillColor(38);
11677 if (nbins==1)hp->SetTitle(TString::Format("ProjectionXZ of biny=%d [y=%.1f..%.f]", biny,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny)));
11678 else hp->SetTitle(TString::Format("ProjectionXZ, biny=[%d,%d] [y=%.1f..%.1f]", biny,biny2,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny2)));
11679 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11680 hp->SetYTitle(fH->GetXaxis()->GetTitle());
11681 hp->SetZTitle("Number of Entries");
11682 hp->Draw(fShowOption.Data());
11683 }
11684 }
11685 break;
11686
11687 case 7:
11688 // "zx"
11689 {
11690 Int_t first = yaxis->GetFirst();
11691 Int_t last = yaxis->GetLast();
11692 Int_t biny = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11693 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11694 yaxis->SetRange(biny,biny2);
11695 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11696 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11697 xx[0] = xaxis->GetXmin();
11698 xx[2] = zaxis->GetXmax();
11699 xx[1] = yaxis->GetBinCenter(biny);
11700 view->WCtoNDC(xx,u);
11701 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11702 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11703 rect1[4].SetX(rect1[0].GetX());
11704 rect1[4].SetY(rect1[0].GetY());
11705 xx[0] = xaxis->GetXmax();
11706 view->WCtoNDC(xx,u);
11707 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11708 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11709 xx[2] = zaxis->GetXmin();
11710 view->WCtoNDC(xx,u);
11711 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11712 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11713 xx[0] = xaxis->GetXmin();
11714 view->WCtoNDC(xx,u);
11715 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11716 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11717 gVirtualX->DrawPolyLine(5,rect1);
11718 if (nbins>1) {
11719 xx[0] = xaxis->GetXmin();
11720 xx[2] = zaxis->GetXmax();
11721 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11722 view->WCtoNDC(xx,u);
11723 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11724 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11725 rect2[4].SetX(rect2[0].GetX());
11726 rect2[4].SetY(rect2[0].GetY());
11727 xx[0] = xaxis->GetXmax();
11728 view->WCtoNDC(xx,u);
11729 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11730 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11731 xx[2] = zaxis->GetXmin();
11732 view->WCtoNDC(xx,u);
11733 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11734 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11735 xx[0] = xaxis->GetXmin();
11736 view->WCtoNDC(xx,u);
11737 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11738 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11739 gVirtualX->DrawPolyLine(5,rect2);
11740 }
11741 c->Clear();
11742 c->cd();
11743 TH2 *hp = (TH2*)h3->Project3D("zx");
11744 yaxis->SetRange(first,last);
11745 if (hp) {
11746 hp->SetFillColor(38);
11747 if (nbins==1)hp->SetTitle(TString::Format("ProjectionZX of biny=%d [y=%.1f..%.f]", biny,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny)));
11748 else hp->SetTitle(TString::Format("ProjectionZX, biny=[%d,%d] [y=%.1f..%.1f]", biny,biny2,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny2)));
11749 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11750 hp->SetYTitle(fH->GetZaxis()->GetTitle());
11751 hp->SetZTitle("Number of Entries");
11752 hp->Draw(fShowOption.Data());
11753 }
11754 }
11755 break;
11756
11757 case 8:
11758 // "yz"
11759 {
11760 Int_t first = xaxis->GetFirst();
11761 Int_t last = xaxis->GetLast();
11762 Int_t binx = first + Int_t((last-first)*(px-pxmin)/(pxmax-pxmin));
11763 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11764 xaxis->SetRange(binx,binx2);
11765 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11766 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11767 xx[2] = zaxis->GetXmin();
11768 xx[1] = yaxis->GetXmax();
11769 xx[0] = xaxis->GetBinCenter(binx);
11770 view->WCtoNDC(xx,u);
11771 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11772 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11773 rect1[4].SetX(rect1[0].GetX());
11774 rect1[4].SetY(rect1[0].GetY());
11775 xx[2] = zaxis->GetXmax();
11776 view->WCtoNDC(xx,u);
11777 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11778 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11779 xx[1] = yaxis->GetXmin();
11780 view->WCtoNDC(xx,u);
11781 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11782 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11783 xx[2] = zaxis->GetXmin();
11784 view->WCtoNDC(xx,u);
11785 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11786 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11787 gVirtualX->DrawPolyLine(5,rect1);
11788 if (nbins>1) {
11789 xx[2] = zaxis->GetXmin();
11790 xx[1] = yaxis->GetXmax();
11791 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11792 view->WCtoNDC(xx,u);
11793 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11794 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11795 rect2[4].SetX(rect2[0].GetX());
11796 rect2[4].SetY(rect2[0].GetY());
11797 xx[2] = zaxis->GetXmax();
11798 view->WCtoNDC(xx,u);
11799 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11800 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11801 xx[1] = yaxis->GetXmin();
11802 view->WCtoNDC(xx,u);
11803 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11804 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11805 xx[2] = zaxis->GetXmin();
11806 view->WCtoNDC(xx,u);
11807 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11808 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11809 gVirtualX->DrawPolyLine(5,rect2);
11810 }
11811 c->Clear();
11812 c->cd();
11813 TH2 *hp = (TH2*)h3->Project3D("yz");
11814 xaxis->SetRange(first,last);
11815 if (hp) {
11816 hp->SetFillColor(38);
11817 if (nbins==1)hp->SetTitle(TString::Format("ProjectionYZ of binx=%d [x=%.1f..%.f]", binx,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx)));
11818 else hp->SetTitle(TString::Format("ProjectionYZ, binx=[%d,%d] [x=%.1f..%.1f]", binx,binx2,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx2)));
11819 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11820 hp->SetYTitle(fH->GetYaxis()->GetTitle());
11821 hp->SetZTitle("Number of Entries");
11822 hp->Draw(fShowOption.Data());
11823 }
11824 }
11825 break;
11826
11827 case 9:
11828 // "zy"
11829 {
11830 Int_t first = xaxis->GetFirst();
11831 Int_t last = xaxis->GetLast();
11832 Int_t binx = first + Int_t((last-first)*(px-pxmin)/(pxmax-pxmin));
11833 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11834 xaxis->SetRange(binx,binx2);
11835 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11836 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11837 xx[2] = zaxis->GetXmin();
11838 xx[1] = yaxis->GetXmax();
11839 xx[0] = xaxis->GetBinCenter(binx);
11840 view->WCtoNDC(xx,u);
11841 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11842 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11843 rect1[4].SetX(rect1[0].GetX());
11844 rect1[4].SetY(rect1[0].GetY());
11845 xx[2] = zaxis->GetXmax();
11846 view->WCtoNDC(xx,u);
11847 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11848 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11849 xx[1] = yaxis->GetXmin();
11850 view->WCtoNDC(xx,u);
11851 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11852 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11853 xx[2] = zaxis->GetXmin();
11854 view->WCtoNDC(xx,u);
11855 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11856 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11857 gVirtualX->DrawPolyLine(5,rect1);
11858 if (nbins>1) {
11859 xx[2] = zaxis->GetXmin();
11860 xx[1] = yaxis->GetXmax();
11861 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11862 view->WCtoNDC(xx,u);
11863 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11864 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11865 rect2[4].SetX(rect2[0].GetX());
11866 rect2[4].SetY(rect2[0].GetY());
11867 xx[2] = zaxis->GetXmax();
11868 view->WCtoNDC(xx,u);
11869 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11870 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11871 xx[1] = yaxis->GetXmin();
11872 view->WCtoNDC(xx,u);
11873 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11874 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11875 xx[2] = zaxis->GetXmin();
11876 view->WCtoNDC(xx,u);
11877 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11878 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11879 gVirtualX->DrawPolyLine(5,rect2);
11880 }
11881 c->Clear();
11882 c->cd();
11883 TH2 *hp = (TH2*)h3->Project3D("zy");
11884 xaxis->SetRange(first,last);
11885 if (hp) {
11886 hp->SetFillColor(38);
11887 if (nbins==1)hp->SetTitle(TString::Format("ProjectionZY of binx=%d [x=%.1f..%.f]", binx,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx)));
11888 else hp->SetTitle(TString::Format("ProjectionZY, binx=[%d,%d] [x=%.1f..%.1f]", binx,binx2,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx2)));
11889 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11890 hp->SetYTitle(fH->GetZaxis()->GetTitle());
11891 hp->SetZTitle("Number of Entries");
11892 hp->Draw(fShowOption.Data());
11893 }
11894 }
11895 break;
11896 }
11897 c->Update();
11898}
@ 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
@ 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:32
const Int_t kPOLAR
Definition TView3D.cxx:33
#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 void SetTextAlign(Short_t align=11)
Set the text alignment.
Definition TAttText.h:44
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
virtual void SetTextColor(Color_t tcolor=1)
Set the text color.
Definition TAttText.h:46
virtual void SetTextFont(Font_t tfont=62)
Set the text font.
Definition TAttText.h:48
virtual void SetTextSize(Float_t tsize=1)
Set the text size.
Definition TAttText.h:49
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:481
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:443
virtual Int_t FindBin(Double_t x)
Find bin number corresponding to abscissa x.
Definition TAxis.cxx:292
virtual Double_t GetBinLowEdge(Int_t bin) const
Return low edge of bin.
Definition TAxis.cxx:521
virtual Int_t FindFixBin(Double_t x) const
Find bin number corresponding to abscissa x
Definition TAxis.cxx:421
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:126
Int_t GetLast() const
Return last bin on the axis i.e.
Definition TAxis.cxx:472
virtual const char * GetTimeFormatOnly() const
Return only the time format from the string fTimeFormat.
Definition TAxis.cxx:603
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:1074
virtual const char * GetTimeFormat() const
Definition TAxis.h:134
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width.
Definition TAxis.cxx:545
virtual Double_t GetBinUpEdge(Int_t bin) const
Return up edge of bin.
Definition TAxis.cxx:531
Int_t GetFirst() const
Return first bin on the axis i.e.
Definition TAxis.cxx:461
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:2473
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:2973
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
The color creation and management class.
Definition TColor.h:22
static void RGBtoHLS(Float_t r, Float_t g, Float_t b, Float_t &h, Float_t &l, Float_t &s)
Definition TColor.h:83
static Int_t GetColor(const char *hexcolor)
Static method returning color number for color specified by hex color string of form: "#rrggbb",...
Definition TColor.cxx:1926
static Int_t GetColorBright(Int_t color)
Static function: Returns the bright color number corresponding to n If the TColor object does not exi...
Definition TColor.cxx:2095
static Int_t GetColorDark(Int_t color)
Static function: Returns the dark color number corresponding to n If the TColor object does not exist...
Definition TColor.cxx:2138
static void HLStoRGB(Float_t h, Float_t l, Float_t s, Float_t &r, Float_t &g, Float_t &b)
Definition TColor.h:78
To draw a Crown.
Definition TCrown.h:19
Graphical cut class.
Definition TCutG.h:20
static TClass * Class()
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition TEnv.cxx:505
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:1916
virtual void GetParLimits(Int_t ipar, Double_t &parmin, Double_t &parmax) const
Return limits for parameter ipar.
Definition TF1.cxx:1967
virtual Double_t GetParError(Int_t ipar) const
Return value of parameter number ipar.
Definition TF1.cxx:1957
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:3425
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:1927
@ 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:3438
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:1446
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:751
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:2945
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:1007
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:2918
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:954
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:2910
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:2005
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:2014
1-D histogram with a double per channel (see TH1 documentation)
Definition TH1.h:926
1-D histogram with a float per channel (see TH1 documentation)
Definition TH1.h:878
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:109
TAxis * GetZaxis()
Definition TH1.h:573
virtual EBinErrorOpt GetBinErrorOption() const
Definition TH1.h:517
virtual Float_t GetBarWidth() const
Definition TH1.h:501
virtual Double_t GetMinimumStored() const
Definition TH1.h:537
virtual Float_t GetBarOffset() const
Definition TH1.h:500
static TClass * Class()
virtual Double_t GetStdDev(Int_t axis=1) const
Returns the Standard Deviation (Sigma).
Definition TH1.cxx:7648
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:9106
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:7576
virtual Double_t GetSkewness(Int_t axis=1) const
Definition TH1.cxx:7712
virtual Double_t GetContourLevelPad(Int_t level) const
Return the value of contour number "level" in Pad coordinates.
Definition TH1.cxx:8486
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:1263
@ 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:4979
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:8591
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:9122
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:7987
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:9265
virtual Double_t GetBinLowEdge(Int_t bin) const
Return bin lower edge for 1D histogram.
Definition TH1.cxx:9195
virtual Double_t GetEntries() const
Return the current number of entries.
Definition TH1.cxx:4416
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:7616
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:8777
@ kNormal
Errors with Normal (Wald) approximation: errorUp=errorLow= sqrt(N)
Definition TH1.h:115
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition TH1.cxx:5081
virtual Int_t GetContour(Double_t *levels=nullptr)
Return contour values into array levels if pointer levels is non zero.
Definition TH1.cxx:8457
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:9206
virtual void SetContour(Int_t nlevels, const Double_t *levels=nullptr)
Set the number and values of contour levels.
Definition TH1.cxx:8529
virtual Double_t GetBinErrorUp(Int_t bin) const
Return upper error associated to bin number bin.
Definition TH1.cxx:9153
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:7696
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:8681
static Bool_t AddDirectoryStatus()
Static function: cannot be inlined on Windows/NT.
Definition TH1.cxx:741
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:5265
virtual Int_t BufferEmpty(Int_t action=0)
Fill histogram with all entries in the buffer.
Definition TH1.cxx:1383
virtual Double_t GetKurtosis(Int_t axis=1) const
Definition TH1.cxx:7785
2-D histogram with a double per channel (see TH1 documentation)
Definition TH2.h:400
2-D histogram with a float per channel (see TH1 documentation)
Definition TH2.h:345
Helper class to represent a bin in the TH2Poly histogram.
Definition TH2Poly.h:25
2D Histogram with Polygonal Bins
Definition TH2Poly.h:66
static TClass * Class()
Service class for 2-D histogram classes.
Definition TH2.h:30
static TClass * Class()
The 3-D histogram classes derived from the 1-D histogram classes.
Definition TH3.h:45
static TClass * Class()
The Histogram stack class.
Definition THStack.h:40
static TClass * Class()
The histogram painter class.
static Int_t ProjectSinusoidal2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function code for sinusoidal projection from Ernst-Jan Buis Source https://en....
void Paint(Option_t *option="") override
Control routine to paint any kind of histograms
TAxis * fYaxis
Pointer to Y axis.
std::unique_ptr< TPainter3dAlgorithms > fLego
Pointer to a TPainter3dAlgorithms object.
std::vector< Double_t > fXbuf
X buffer coordinates.
Int_t fXHighlightBin
X highlight bin.
TF3 * fCurrentF3
Current TF3 function.
virtual void PaintErrors(Option_t *option)
Draw 1D histograms error bars.
~THistPainter() override
destructor.
Int_t fShowProjection2
True if a second projection must be drawn (when calling SetShowProjectionXY on a TH2)
virtual void PaintTF3()
Control function to draw a 3D implicit functions.
virtual Int_t TableInit()
Initialize various options to draw 2D histograms.
virtual void PaintTH2PolyScatterPlot(Option_t *option)
Control function to draw a TH2Poly as a scatter plot.
static Int_t ProjectMollweide2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
static Int_t ProjectAitoff2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
virtual void PaintText(Option_t *option)
Control function to draw a 1D/2D histograms with the bin values.
Int_t DistancetoPrimitive(Int_t px, Int_t py) override
Compute the distance from the point px,py to a line.
virtual void PaintAxis(Bool_t drawGridOnly=kFALSE)
Draw axis (2D case) of an histogram.
virtual void PaintColorLevelsFast(Option_t *option)
[Rendering scheme for the COL2 and COLZ2 options] (HP14)
virtual Int_t PaintInit()
Compute histogram parameters used by the drawing routines.
virtual void Paint2DErrors(Option_t *option)
Draw 2D histograms errors.
Int_t fYHighlightBin
Y highlight bin.
virtual void PaintCandlePlot(Option_t *option)
Control function to draw a 2D histogram as a candle (box) plot or violin plot
virtual void PaintScatterPlot(Option_t *option)
Control function to draw a 2D histogram as a scatter plot.
void SetShowProjectionXY(const char *option, Int_t nbinsY, Int_t nbinsX) override
virtual void PaintLego(Option_t *option)
Control function to draw a 2D histogram as a lego plot.
virtual void PaintH3(Option_t *option="")
Control function to draw a 3D histograms.
Int_t fNcuts
Number of graphical cuts.
TString fShowOption
Option to draw the projection.
virtual void PaintHighlightBin(Option_t *option="")
Paint highlight bin as TBox object.
virtual void PaintTH2PolyBins(Option_t *option)
Control function to draw a TH2Poly bins' contours.
virtual Int_t PaintContourLine(Double_t elev1, Int_t icont1, Double_t x1, Double_t y1, Double_t elev2, Int_t icont2, Double_t x2, Double_t y2, Double_t *xarr, Double_t *yarr, Int_t *itarr, Double_t *levels)
Fill the matrix xarr and yarr for Contour Plot.
Int_t fShowProjection
True if a projection must be drawn.
virtual void PaintLegoAxis(TGaxis *axis, Double_t ang)
Draw the axis for legos and surface plots.
virtual void PaintTriangles(Option_t *option)
Control function to draw a table using Delaunay triangles.
virtual void HighlightBin(Int_t px, Int_t py)
Check on highlight bin.
virtual void PaintH3Box(Int_t iopt)
Control function to draw a 3D histogram with boxes.
Int_t MakeCuts(char *cutsopt) override
Decode string choptin and fill Graphical cuts structure.
TList * fFunctions
Pointer to histogram list of functions.
void DrawPanel() override
Display a panel with all histogram drawing options.
std::unique_ptr< TPie > fPie
Pointer to a TPie in case of option PIE.
static void PaintSpecialObjects(const TObject *obj, Option_t *option)
Static function to paint special objects like vectors and matrices.
virtual void PaintTitle()
new TGaxis/////////////////// Draw the histogram title
virtual void PaintTH2PolyColorLevels(Option_t *option)
Control function to draw a TH2Poly as a color plot.
virtual std::vector< THistRenderingRegion > ComputeRenderingRegions(TAxis *pAxis, Int_t nPixels, bool isLog)
Returns the rendering regions for an axis to use in the COL2 option.
virtual void ShowProjectionX(Int_t px, Int_t py)
Show projection onto X.
virtual void PaintPalette()
Paint the color palette on the right side of the pad.
TAxis * fXaxis
Pointer to X axis.
virtual void PaintStat2(Int_t dostat, TF1 *fit)
Draw the statistics box for 2D histograms.
virtual void PaintArrows(Option_t *option)
Control function to draw a table as an arrow plot
virtual void RecalculateRange()
Recompute the histogram range following graphics operations.
void PaintStat(Int_t dostat, TF1 *fit) override
Draw the statistics box for 1D and profile histograms.
static Int_t ProjectParabolic2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function code for parabolic projection from Ernst-Jan Buis.
std::unique_ptr< TGraph2DPainter > fGraph2DPainter
Pointer to a TGraph2DPainter object.
virtual void PaintBarH(Option_t *option)
Draw a bar char in a rotated pad (X vertical, Y horizontal)
virtual void PaintStat3(Int_t dostat, TF1 *fit)
Draw the statistics box for 3D histograms.
virtual void PaintSurface(Option_t *option)
Control function to draw a 2D histogram as a surface plot.
TList * fStack
Pointer to stack of histograms (if any)
THistPainter()
Default constructor.
TH1 * fH
Pointer to histogram to paint.
virtual void PaintTH2PolyText(Option_t *option)
Control function to draw a TH2Poly as a text plot.
virtual void ShowProjection3(Int_t px, Int_t py)
Show projection (specified by fShowProjection) of a TH3.
TAxis * fZaxis
Pointer to Z axis.
void SetHistogram(TH1 *h) override
Set current histogram to h
virtual void PaintFunction(Option_t *option)
[Paint functions associated to an histogram.](HP28")
virtual void PaintBar(Option_t *option)
Draw a bar-chart in a normal pad.
static Int_t ProjectMercator2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
virtual void PaintBoxes(Option_t *option)
Control function to draw a 2D histogram as a box plot
virtual Int_t MakeChopt(Option_t *option)
Decode string choptin and fill Hoption structure.
char * GetObjectInfo(Int_t px, Int_t py) const override
Display the histogram info (bin number, contents, integral up to bin corresponding to cursor position...
TList * GetContourList(Double_t contour) const override
Get a contour (as a list of TGraphs) using the Delaunay triangulation.
void ProcessMessage(const char *mess, const TObject *obj) override
Process message mess.
void SetShowProjection(const char *option, Int_t nbins) override
Set projection.
virtual void ShowProjectionY(Int_t px, Int_t py)
Show projection onto Y.
static const char * GetBestFormat(Double_t v, Double_t e, const char *f)
This function returns the best format to print the error value (e) knowing the parameter value (v) an...
virtual void PaintContour(Option_t *option)
Control function to draw a 2D histogram as a contour plot.
TCutG * fCuts[kMaxCuts]
Pointers to graphical cuts.
virtual void PaintTable(Option_t *option)
Control function to draw 2D/3D histograms (tables).
void ExecuteEvent(Int_t event, Int_t px, Int_t py) override
Execute the actions corresponding to event.
virtual Int_t PaintInitH()
Compute histogram parameters used by the drawing routines for a rotated pad.
virtual void PaintFrame()
Calculate range and clear pad (canvas).
Int_t fCutsOpt[kMaxCuts]
Sign of each cut.
virtual void PaintH3Iso()
Control function to draw a 3D histogram with Iso Surfaces.
std::vector< Double_t > fYbuf
Y buffer coordinates.
virtual void PaintH3BoxRaster()
Control function to draw a 3D histogram with boxes.
virtual void PaintHist(Option_t *option)
Control routine to draw 1D histograms
void SetHighlight() override
Set highlight (enable/disable) mode for fH.
virtual void DefineColorLevels(Int_t ndivz)
Define the color levels used to paint legos, surfaces etc..
TString fObjectInfo
virtual void PaintColorLevels(Option_t *option)
Control function to draw a 2D histogram as a color plot.
Bool_t IsInside(Int_t x, Int_t y) override
Return kTRUE if the cell ix, iy is inside one of the graphical cuts.
A class to define a conversion from pixel values to pixel color.
Definition TAttImage.h:33
static TImagePalette * CreateCOLPalette(Int_t nContours)
Factory method to creates an image palette for histogram plotting.
An abstract interface to image processing library.
Definition TImage.h:29
static TImage * Create()
Create an image.
Definition TImage.cxx:34
void Reset()
To draw Mathematical Formula.
Definition TLatex.h:20
A doubly linked list.
Definition TList.h:38
TObject * FindObject(const char *name) const override
Find an object in this list using its name.
Definition TList.cxx:575
void Add(TObject *obj) override
Definition TList.h:81
TObject * Remove(TObject *obj) override
Remove object from the list.
Definition TList.cxx:819
TObject * First() const override
Return the first object in the list. Returns 0 when list is empty.
Definition TList.cxx:656
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:354
void AddFirst(TObject *obj) override
Add object at the beginning of the list.
Definition TList.cxx:97
TMatrixTBase.
static TClass * Class()
A TMultiGraph is a collection of TGraph (or derived) objects.
Definition TMultiGraph.h:34
TList * GetListOfGraphs() const
Definition TMultiGraph.h: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
Int_t GetOptStat() const
Return the stat option.
virtual void SetStatFormat(const char *format="6.4g")
Change (i.e. set) the format for printing statistics.
void SetOptStat(Int_t stat=1)
Set the stat option.
virtual const char * GetFitFormat() const
Definition TPaveStats.h:35
virtual void SetFitFormat(const char *format="5.4g")
Change (i.e. set) the format for printing fit parameters in statistics box.
Int_t GetOptFit() const
Return the fit option.
void SetParent(TObject *obj) override
Definition TPaveStats.h:53
void SetOptFit(Int_t fit=1)
Set the fit option.
virtual const char * GetStatFormat() const
Definition TPaveStats.h:36
void Paint(Option_t *option="") override
Paint the pave stat.
static TClass * Class()
A Pave (see TPave) with text, lines or/and boxes inside.
Definition TPaveText.h:21
virtual TText * AddText(Double_t x1, Double_t y1, const char *label)
Add a new Text line to this pavetext at given coordinates.
static TClass * Class()
void Clear(Option_t *option="") override
Clear all lines in this pavetext.
virtual TText * GetLine(Int_t number) const
Get Pointer to line number in this pavetext.
const char * GetName() const override
Returns name of object.
Definition TPave.h:58
virtual void SetName(const char *name="")
Definition TPave.h:81
virtual void SetBorderSize(Int_t bordersize=4)
Sets the border size of the TPave box and shadow.
Definition TPave.h:79
Option_t * GetOption() const override
Definition TPave.h:59
Double_t GetX1NDC() const
Definition TPave.h:61
virtual void SetX2NDC(Double_t x2)
Definition TPave.h:85
void SetX(SCoord_t x)
Definition TPoint.h:48
void SetY(SCoord_t y)
Definition TPoint.h:49
Profile2D histograms are used to display the mean value of Z and its error for each cell in X,...
Definition TProfile2D.h:27
static TClass * Class()
Profile Histogram.
Definition TProfile.h:32
static TClass * Class()
Random number generator class based on the maximally quidistributed combined Tausworthe generator by ...
Definition TRandom2.h:27
Sequenceable collection abstract base class.
Basic string class.
Definition TString.h:138
void ToLower()
Change string to lower-case.
Definition TString.cxx:1189
const char * Data() const
Definition TString.h:384
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:2384
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2362
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:641
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:660
Int_t GetOptStat() const
Definition TStyle.h:247
Color_t GetStatTextColor() const
Definition TStyle.h:260
Float_t GetTitleX() const
Definition TStyle.h:282
Int_t GetOptTitle() const
Definition TStyle.h:248
Float_t GetStatFontSize() const
Definition TStyle.h:263
Float_t GetBarOffset() const
Definition TStyle.h:184
Float_t GetStatX() const
Definition TStyle.h:266
Float_t GetTitleSize(Option_t *axis="X") const
Return title size.
Definition TStyle.cxx:1241
Float_t GetTitleY() const
Definition TStyle.h:283
Style_t GetTitleFont(Option_t *axis="X") const
Return title font.
Definition TStyle.cxx:1217
Bool_t GetHistMinimumZero() const
Definition TStyle.h:239
Float_t GetStatY() const
Definition TStyle.h:267
Color_t GetTitleFillColor() const
Definition TStyle.h:273
Style_t GetTitleStyle() const
Definition TStyle.h:275
Color_t GetStatColor() const
Definition TStyle.h:259
Float_t GetBarWidth() const
Definition TStyle.h:185
void SetDrawBorder(Int_t drawborder=1)
Definition TStyle.h:346
Float_t GetStatH() const
Definition TStyle.h:269
Width_t GetTitleBorderSize() const
Definition TStyle.h:277
Int_t GetColorPalette(Int_t i) const
Return color number i in current palette.
Definition TStyle.cxx:1102
Float_t GetErrorX() const
Definition TStyle.h:188
Double_t GetHistTopMargin() const
Definition TStyle.h:240
void SetBarOffset(Float_t baroff=0.5)
Definition TStyle.h:339
Float_t GetEndErrorSize() const
Definition TStyle.h:187
Int_t GetDrawBorder() const
Definition TStyle.h:186
Width_t GetStatBorderSize() const
Definition TStyle.h:261
Color_t GetTitleTextColor() const
Definition TStyle.h:274
void SetBarWidth(Float_t barwidth=0.5)
Definition TStyle.h:340
Float_t GetTitleH() const
Definition TStyle.h:285
Style_t GetStatStyle() const
Definition TStyle.h:264
Float_t GetStatW() const
Definition TStyle.h:268
const char * GetFitFormat() const
Definition TStyle.h:201
const char * GetStatFormat() const
Definition TStyle.h:265
Int_t GetNumberOfColors() const
Return number of colors in the color palette.
Definition TStyle.cxx:1176
Int_t GetOptFit() const
Definition TStyle.h:246
Int_t GetNumberContours() const
Definition TStyle.h:243
const char * GetPaintTextFormat() const
Definition TStyle.h:252
Style_t GetStatFont() const
Definition TStyle.h:262
Float_t GetTitleFontSize() const
Definition TStyle.h:276
Int_t GetTitleAlign() const
Definition TStyle.h:272
Float_t GetTitleW() const
Definition TStyle.h:284
virtual int Load(const char *module, const char *entry="", Bool_t system=kFALSE)
Load a shared library.
Definition TSystem.cxx:1868
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:704
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:651
constexpr Double_t PiOver2()
Definition TMath.h:54
Double_t Log(Double_t x)
Returns the natural logarithm of x.
Definition TMath.h:767
constexpr Double_t DegToRad()
Conversion from degree to radian: .
Definition TMath.h:82
Double_t Sqrt(Double_t x)
Returns the square root of x.
Definition TMath.h:673
LongDouble_t Power(LongDouble_t x, LongDouble_t y)
Returns x raised to the power y.
Definition TMath.h:732
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:605
constexpr Double_t Pi()
Definition TMath.h:40
Bool_t AreEqualRel(Double_t af, Double_t bf, Double_t relPrec)
Comparing floating points.
Definition TMath.h:429
Double_t Sin(Double_t)
Returns the sine of an angle of x radians.
Definition TMath.h:599
Double_t Tan(Double_t)
Returns the tangent of an angle of x radians.
Definition TMath.h:611
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:75
Double_t Log10(Double_t x)
Returns the common (base-10) logarithm of x.
Definition TMath.h:773
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