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) {
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 continue;
6172 }
6173
6174 ipoly = itarr[ix-1];
6175 if (ipoly >=0 && ipoly <ncontour) {
6176 polys[ipoly]->SetPoint(np[ipoly] ,xarr[ix-1],yarr[ix-1]);
6177 polys[ipoly]->SetPoint(np[ipoly]+1,xarr[ix], yarr[ix]);
6178 np[ipoly] += 2;
6179 if (npmax < np[ipoly]) npmax = np[ipoly];
6180 }
6181 }
6182 } // end of if (ir[0]
6183 } //end of for (i
6184 } //end of for (j
6185
6187 std::vector<Double_t> xp, yp;
6189 Int_t istart;
6190 Int_t first = ncontour;
6191 std::vector<Int_t> polysort;
6193 if (Hoption.Contour != 1) goto theEND;
6194
6195 //The 2 points line generated above are now sorted/merged to generate
6196 //a list of consecutive points.
6197 // If the option "List" has been specified, the list of points is saved
6198 // in the form of TGraph objects in the ROOT list of special objects.
6199 xmin = gPad->GetUxmin();
6200 ymin = gPad->GetUymin();
6201 xp.resize(2*npmax);
6202 yp.resize(2*npmax);
6203 polysort.resize(ncontour);
6204 //find first positive contour
6205 for (ipoly=0;ipoly<ncontour;ipoly++) {
6206 if (levels[ipoly] >= 0) {first = ipoly; break;}
6207 }
6208 //store negative contours from 0 to minimum, then all positive contours
6209 k = 0;
6210 for (ipoly=first-1;ipoly>=0;ipoly--) {polysort[k] = ipoly; k++;}
6211 for (ipoly=first;ipoly<ncontour;ipoly++) {polysort[k] = ipoly; k++;}
6212 // we can now draw sorted contours
6213 contListNb = 0;
6214 fH->SetFillStyle(1001);
6215 for (k=0;k<ncontour;k++) {
6216 ipoly = polysort[k];
6217 if (np[ipoly] == 0) continue;
6218 if (Hoption.List) list = (TList*)contours->At(contListNb);
6219 contListNb++;
6220 Double_t *xx = polys[ipoly]->GetX();
6221 Double_t *yy = polys[ipoly]->GetY();
6222 istart = 0;
6223 while (true) {
6224 iminus = npmax;
6225 iplus = iminus+1;
6226 xp[iminus]= xx[istart]; yp[iminus] = yy[istart];
6227 xp[iplus] = xx[istart+1]; yp[iplus] = yy[istart+1];
6228 xx[istart] = xmin; yy[istart] = ymin;
6229 xx[istart+1] = xmin; yy[istart+1] = ymin;
6230 while (true) {
6231 nadd = 0;
6232 for (i=2;i<np[ipoly];i+=2) {
6233 if ((iplus < 2*npmax-1) && (xx[i] == xp[iplus]) && (yy[i] == yp[iplus])) {
6234 iplus++;
6235 xp[iplus] = xx[i+1]; yp[iplus] = yy[i+1];
6236 xx[i] = xmin; yy[i] = ymin;
6237 xx[i+1] = xmin; yy[i+1] = ymin;
6238 nadd++;
6239 }
6240 if ((iminus > 0) && (xx[i+1] == xp[iminus]) && (yy[i+1] == yp[iminus])) {
6241 iminus--;
6242 xp[iminus] = xx[i]; yp[iminus] = yy[i];
6243 xx[i] = xmin; yy[i] = ymin;
6244 xx[i+1] = xmin; yy[i+1] = ymin;
6245 nadd++;
6246 }
6247 }
6248 if (nadd == 0) break;
6249 }
6250 theColor = Int_t((ipoly+0.99)*Float_t(ncolors)/Float_t(ndivz));
6252 if (ndivz > 1) fH->SetFillColor(icol);
6253 fH->TAttFill::Modify();
6254 gPad->PaintFillArea(iplus-iminus+1,xp.data()+iminus,yp.data()+iminus);
6255 if (Hoption.List) {
6256 graph = new TGraph(iplus-iminus+1,xp.data()+iminus,yp.data()+iminus);
6257 graph->SetFillColor(icol);
6258 graph->SetLineWidth(fH->GetLineWidth());
6259 list->Add(graph);
6260 }
6261 //check if more points are left
6262 istart = 0;
6263 for (i=2;i<np[ipoly];i+=2) {
6264 if (xx[i] != xmin && yy[i] != ymin) {
6265 istart = i;
6266 break;
6267 }
6268 }
6269 if (istart == 0) break;
6270 }
6271 }
6272
6273theEND:
6274 gPad->ResetBit(TGraph::kClipFrame);
6279}
6280
6281////////////////////////////////////////////////////////////////////////////////
6282/// Fill the matrix `xarr` and `yarr` for Contour Plot.
6283
6287{
6288
6289 Bool_t vert;
6291 Int_t n, i, icount;
6292
6293 if (x1 == x2) {
6294 vert = kTRUE;
6295 tlen = y2 - y1;
6296 } else {
6297 vert = kFALSE;
6298 tlen = x2 - x1;
6299 }
6300
6301 n = icont1 +1;
6302 tdif = elev2 - elev1;
6303 i = 0;
6304 icount = 0;
6305 while (n <= icont2 && i <= kMAXCONTOUR/2 -3) {
6306 //elev = fH->GetContourLevel(n);
6307 elev = levels[n];
6308 diff = elev - elev1;
6309 pdif = diff/tdif;
6310 xlen = tlen*pdif;
6311 if (vert) {
6312 if (Hoption.Logx)
6313 xarr[i] = TMath::Log10(x1);
6314 else
6315 xarr[i] = x1;
6316 if (Hoption.Logy)
6317 yarr[i] = TMath::Log10(y1 + xlen);
6318 else
6319 yarr[i] = y1 + xlen;
6320 } else {
6321 if (Hoption.Logx)
6322 xarr[i] = TMath::Log10(x1 + xlen);
6323 else
6324 xarr[i] = x1 + xlen;
6325 if (Hoption.Logy)
6326 yarr[i] = TMath::Log10(y1);
6327 else
6328 yarr[i] = y1;
6329 }
6330 itarr[i] = n;
6331 icount++;
6332 i +=2;
6333 n++;
6334 }
6335 return icount;
6336}
6337
6338////////////////////////////////////////////////////////////////////////////////
6339/// [Draw 1D histograms error bars.](\ref HP09)
6340
6342{
6343
6344 // On iOS, we do not highlight histogram, if it's not picked at the moment
6345 // (but part of histogram (axis or pavestat) was picked, that's why this code
6346 // is called at all. This conditional statement never executes on non-iOS platform.
6347 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH) return;
6348
6349 const Int_t kBASEMARKER=8;
6350 Double_t xp, yp, ex1, ex2, ey1, ey2;
6351 Double_t delta;
6353 Double_t xi1, xi2, xi3, xi4, yi1, yi2, yi3, yi4;
6355 Double_t logxmin = 0;
6356 Double_t logymin = 0;
6357 Double_t offset = 0.;
6358 Double_t width = 0.;
6359 Int_t i, k, npoints, first, last, fixbin;
6360 Int_t if1 = 0;
6361 Int_t if2 = 0;
6364 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};
6365 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};
6366
6367 std::vector<Double_t> xline, yline;
6369 if (Hoption.Error >= 40) {Hoption.Error -=40; option0 = 1;}
6370 if (Int_t(Hoption.Error/10) == 2) {optionEX0 = 1; Hoption.Error -= 10;}
6371 if (Hoption.Error == 31) {optionEX0 = 1; Hoption.Error = 1;}
6372 if (Hoption.Error == 11) option1 = 1;
6373 if (Hoption.Error == 12) option2 = 1;
6374 if (Hoption.Error == 13) option3 = 1;
6375 if (Hoption.Error == 14) {option4 = 1; option3 = 1;}
6376 if (Hoption.Error == 15) {optionI0 = 1; option3 = 1;}
6377 if (Hoption.Error == 16) {optionI0 = 1; option4 = 1; option3 = 1;}
6378 if (option2+option3 == 0) optionE = 1;
6379 if (Hoption.Error == 0) optionE = 0;
6380 if (fXaxis->GetXbins()->fN) fixbin = 0;
6381 else fixbin = 1;
6382
6383 offset = fH->GetBarOffset();
6384 width = fH->GetBarWidth();
6385
6387 if (optionEX0) {
6388 xerror = 0;
6389 } else {
6390 xerror = gStyle->GetErrorX();
6391 }
6393 if (errormarker == 1) symbolsize = 0.01;
6395 if (errormarker >= 20 && errormarker <= 49) {
6396 sbasex *= cxx[errormarker-20];
6397 sbasey *= cyy[errormarker-20];
6398 }
6399 // set the graphics attributes
6400
6401 fH->TAttLine::Modify();
6402 fH->TAttFill::Modify();
6403 fH->TAttMarker::Modify();
6404
6405 // set the first and last bin
6406
6407 Double_t factor = Hparam.factor;
6408 first = Hparam.xfirst;
6409 last = Hparam.xlast;
6410 npoints = last - first +1;
6411 xmin = gPad->GetUxmin();
6412 xmax = gPad->GetUxmax();
6413 ymin = gPad->GetUymin();
6414 ymax = gPad->GetUymax();
6415
6416
6417 if (option3) {
6418 xline.resize(2*npoints);
6419 yline.resize(2*npoints);
6420 if ((npoints > 0) && (xline.empty() || yline.empty())) {
6421 Error("PaintErrors", "too many points, out of memory");
6422 return;
6423 }
6424 if1 = 1;
6425 if2 = 2*npoints;
6426 }
6427
6428 // compute the offset of the error bars due to the symbol size
6429 s2x = gPad->PixeltoX(Int_t(0.5*sbasex)) - gPad->PixeltoX(0);
6430 s2y =-gPad->PixeltoY(Int_t(0.5*sbasey)) + gPad->PixeltoY(0);
6431
6432 // compute size of the lines at the end of the error bars
6434 bxsize = gPad->PixeltoX(dxend) - gPad->PixeltoX(0);
6435 bysize =-gPad->PixeltoY(dxend) + gPad->PixeltoY(0);
6436
6437
6438 if (fixbin) {
6440 else xp = Hparam.xmin + 0.5*Hparam.xbinsize;
6441 } else {
6442 delta = fH->GetBinWidth(first);
6443 xp = fH->GetBinLowEdge(first) + 0.5*delta;
6444 }
6445
6446 // if errormarker = 0 or symbolsize = 0. no symbol is drawn
6449
6450 // ---------------------- Loop over the points---------------------
6451 for (k=first; k<=last; k++) {
6452
6453 // get the data
6454 // xp = X position of the current point
6455 // yp = Y position of the current point
6456 // ex1 = Low X error
6457 // ex2 = Up X error
6458 // ey1 = Low Y error
6459 // ey2 = Up Y error
6460 // (xi,yi) = Error bars coordinates
6461
6462 // apply offset on errors for bar histograms
6463 Double_t xminTmp = gPad->XtoPad(fXaxis->GetBinLowEdge(k));
6464 Double_t xmaxTmp = gPad->XtoPad(fXaxis->GetBinUpEdge(k));
6465 if (Hoption.Logx) {
6468 }
6471 xmaxTmp = xminTmp + w;
6472 xp = (xminTmp+xmaxTmp)/2.;
6473
6474 if (Hoption.Logx) {
6475 if (xp <= 0) goto L30;
6476 if (xp < logxmin) goto L30;
6477 if (xp > TMath::Power(10,xmax)) break;
6478 } else {
6479 if (xp < xmin) goto L30;
6480 if (xp > xmax) break;
6481 }
6482 yp = factor*fH->GetBinContent(k);
6483 if (optionI0 && yp==0) goto L30;
6484 if (fixbin) {
6486 } else {
6487 delta = fH->GetBinWidth(k);
6488 ex1 = xerror*delta;
6489 }
6490 if (fH->GetBinErrorOption() == TH1::kNormal) {
6491 ey1 = factor*fH->GetBinError(k);
6492 ey2 = ey1;
6493 } else {
6494 ey1 = factor*fH->GetBinErrorLow(k);
6495 ey2 = factor*fH->GetBinErrorUp(k);
6496 }
6497 ex2 = ex1;
6498
6499 xi4 = xp;
6500 xi3 = xp;
6501 xi2 = xp + ex2;
6502 xi1 = xp - ex1;
6503
6504 yi1 = yp;
6505 yi2 = yp;
6506 yi3 = yp - ey1;
6507 yi4 = yp + ey2;
6508
6509 // take the LOG if necessary
6510 if (Hoption.Logx) {
6515 }
6516 if (Hoption.Logy) {
6521 }
6522
6523 // test if error bars are not outside the limits
6524 // otherwise they are truncated
6525
6530
6531 // test if the marker is on the frame limits. If "Yes", the
6532 // marker will not be drawn and the error bars will be readjusted.
6533
6534 drawmarker = kTRUE;
6535 if (!option0 && !option3) {
6536 if (Hoption.Logy && yp < logymin) goto L30;
6537 if (yi1 < ymin || yi1 > ymax) goto L30;
6538 if (Hoption.Error != 0 && yp == 0 && ey1 <= 0) drawmarker = kFALSE;
6539 }
6541
6542 // draw the error rectangles
6543 if (option2) {
6544 if (yi3 >= ymax) goto L30;
6545 if (yi4 <= ymin) goto L30;
6546 gPad->PaintBox(xi1,yi3,xi2,yi4);
6547 }
6548
6549 // keep points for fill area drawing
6550 if (option3) {
6551 xline[if1-1] = xi3;
6552 xline[if2-1] = xi3;
6553 yline[if1-1] = yi4;
6554 yline[if2-1] = yi3;
6555 if1++;
6556 if2--;
6557 }
6558
6559 // draw the error bars
6560 if (Hoption.Logy && yp < logymin) drawmarker = kFALSE;
6561 if (optionE && drawmarker) {
6562 if ((yi3 < yi1 - s2y) && (yi3 < ymax)) gPad->PaintLine(xi3,yi3,xi4,TMath::Min(yi1 - s2y,ymax));
6563 if ((yi1 + s2y < yi4) && (yi4 > ymin)) gPad->PaintLine(xi3,TMath::Max(yi1 + s2y, ymin),xi4,yi4);
6564 // don't duplicate the horizontal line
6565 if (Hoption.Hist != 2) {
6567 if (xi1 < xi3 - s2x) gPad->PaintLine(xi1,yi1,xi3 - s2x,yi2);
6568 if (xi3 + s2x < xi2) gPad->PaintLine(xi3 + s2x,yi1,xi2,yi2);
6569 }
6570 }
6571 }
6572 if (optionE && !drawmarker && (ey1 != 0 || ey2 !=0)) {
6573 if ((yi3 < yi1) && (yi3 < ymax)) gPad->PaintLine(xi3,yi3,xi4,TMath::Min(yi1,ymax));
6574 if ((yi1 < yi4) && (yi4 > ymin)) gPad->PaintLine(xi3,TMath::Max(yi1,ymin),xi4,yi4);
6575 // don't duplicate the horizontal line
6576 if (Hoption.Hist != 2) {
6578 if (xi1 < xi3) gPad->PaintLine(xi1,yi1,xi3,yi2);
6579 if (xi3 < xi2) gPad->PaintLine(xi3,yi1,xi2,yi2);
6580 }
6581 }
6582 }
6583
6584 // draw line at the end of the error bars
6585
6586 if (option1 && drawmarker) {
6587
6588 if (yi3 < yi1-s2y && yi3 < ymax && yi3 > ymin) gPad->PaintLine(xi3 - bxsize, yi3 , xi3 + bxsize, yi3);
6589 if (yi4 > yi1+s2y && yi4 < ymax && yi4 > ymin) gPad->PaintLine(xi3 - bxsize, yi4 , xi3 + bxsize, yi4);
6591 if (xi1 < xi3-s2x) gPad->PaintLine(xi1 , yi1 - bysize, xi1 , yi1 + bysize);
6592 if (xi2 > xi3+s2x) gPad->PaintLine(xi2 , yi1 - bysize, xi2 , yi1 + bysize);
6593 }
6594 }
6595
6596 // draw the marker
6597
6598 if (drawmarker) gPad->PaintPolyMarker(1, &xi3, &yi1);
6599
6600L30:
6601 if (fixbin) xp += Hparam.xbinsize;
6602 else {
6603 if (k < last) {
6604 delta = fH->GetBinWidth(k+1);
6605 xp = fH->GetBinLowEdge(k+1) + 0.5*delta;
6606 }
6607 }
6608 } //end of for loop
6609
6610 // draw the filled area
6611
6612 if (option3) {
6613 TGraph graph;
6614 graph.SetLineStyle(fH->GetLineStyle());
6615 graph.SetLineColor(fH->GetLineColor());
6616 graph.SetLineWidth(fH->GetLineWidth());
6617 graph.SetFillStyle(fH->GetFillStyle());
6618 graph.SetFillColor(fH->GetFillColor());
6619 Int_t logx = gPad->GetLogx();
6620 Int_t logy = gPad->GetLogy();
6621 gPad->SetLogx(0);
6622 gPad->SetLogy(0);
6623
6624 // In some cases the number of points in the fill area is smaller than
6625 // 2*npoints. In such cases the array xline and yline must be arranged
6626 // before being plotted. The next loop does that.
6627 if (if2 > npoints) {
6628 for (i=1; i<if1; i++) {
6629 xline[if1-2+i] = xline[if2-1+i];
6630 yline[if1-2+i] = yline[if2-1+i];
6631 }
6632 npoints = if1-1;
6633 }
6634 if (option4) graph.PaintGraph(2*npoints,xline.data(),yline.data(),"FC");
6635 else graph.PaintGraph(2*npoints,xline.data(),yline.data(),"F");
6636 gPad->SetLogx(logx);
6637 gPad->SetLogy(logy);
6638 }
6639}
6640
6641////////////////////////////////////////////////////////////////////////////////
6642/// Draw 2D histograms errors.
6643
6645{
6646
6647 fH->TAttMarker::Modify();
6648 fH->TAttLine::Modify();
6649
6650 // Define the 3D view
6651 fXbuf[0] = Hparam.xmin;
6652 fYbuf[0] = Hparam.xmax;
6653 fXbuf[1] = Hparam.ymin;
6654 fYbuf[1] = Hparam.ymax;
6655 fXbuf[2] = Hparam.zmin;
6656 fYbuf[2] = Hparam.zmax*(1. + gStyle->GetHistTopMargin());
6657 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
6658 TView *view = gPad ? gPad->GetView() : nullptr;
6659 if (!view) {
6660 Error("Paint2DErrors", "no TView in current pad");
6661 return;
6662 }
6663 Double_t thedeg = 90 - gPad->GetTheta();
6664 Double_t phideg = -90 - gPad->GetPhi();
6665 Double_t psideg = view->GetPsi();
6666 Int_t irep;
6667 view->SetView(phideg, thedeg, psideg, irep);
6668
6669 // Set color/style for back box
6670 fLego->SetFillStyle(gPad->GetFrameFillStyle());
6671 fLego->SetFillColor(gPad->GetFrameFillColor());
6672 fLego->TAttFill::Modify();
6673 Int_t backcolor = gPad->GetFrameFillColor();
6674 if (Hoption.System != kCARTESIAN) backcolor = 0;
6675 view->PadRange(backcolor);
6676 fLego->SetFillStyle(fH->GetFillStyle());
6677 fLego->SetFillColor(fH->GetFillColor());
6678 fLego->TAttFill::Modify();
6679
6680 // Paint the Back Box if needed
6681 if (Hoption.BackBox && !Hoption.Same && !Hoption.Lego && !Hoption.Surf) {
6682 fLego->InitMoveScreen(-1.1,1.1);
6683 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
6685 fLego->BackBox(90);
6686 }
6687
6688 // Paint the Errors
6689 Double_t x, ex, x1, x2;
6690 Double_t y, ey, y1, y2;
6691 Double_t z, ez1, ez2, z1, z2;
6692 Double_t temp1[3],temp2[3];
6694 if (Hoption.Error == 110) {
6695 xyerror = 0;
6696 } else {
6698 }
6699
6701 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
6702 y = fYaxis->GetBinCenter(j);
6704 y1 = y-ey;
6705 y2 = y+ey;
6706 if (Hoption.Logy) {
6707 if (y > 0) y = TMath::Log10(y);
6708 else continue;
6709 if (y1 > 0) y1 = TMath::Log10(y1);
6710 else y1 = Hparam.ymin;
6711 if (y2 > 0) y2 = TMath::Log10(y2);
6712 else y2 = Hparam.ymin;
6713 }
6716 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
6717 xk = fXaxis->GetBinLowEdge(i);
6718 xstep = fXaxis->GetBinWidth(i);
6719 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
6720 Int_t bin = fH->GetBin(i,j);
6721 x = fXaxis->GetBinCenter(i);
6723 x1 = x-ex;
6724 x2 = x+ex;
6725 if (Hoption.Logx) {
6726 if (x > 0) x = TMath::Log10(x);
6727 else continue;
6728 if (x1 > 0) x1 = TMath::Log10(x1);
6729 else x1 = Hparam.xmin;
6730 if (x2 > 0) x2 = TMath::Log10(x2);
6731 else x2 = Hparam.xmin;
6732 }
6733 z = fH->GetBinContent(bin);
6734 if (fH->GetBinErrorOption() == TH1::kNormal) {
6735 ez1 = fH->GetBinError(bin);
6736 ez2 = ez1;
6737 }
6738 else {
6739 ez1 = fH->GetBinErrorLow(bin);
6740 ez2 = fH->GetBinErrorUp(bin);
6741 }
6742 z1 = z - ez1;
6743 z2 = z + ez2;
6744 if (Hoption.Logz) {
6745 if (z > 0) z = TMath::Log10(z);
6746 else z = Hparam.zmin;
6747 if (z1 > 0) z1 = TMath::Log10(z1);
6748 else z1 = Hparam.zmin;
6749 if (z2 > 0) z2 = TMath::Log10(z2);
6750 else z2 = Hparam.zmin;
6751
6752 }
6753 if (z <= Hparam.zmin) continue;
6754 if (z > Hparam.zmax) z = Hparam.zmax;
6755
6756 temp1[0] = x1;
6757 temp1[1] = y;
6758 temp1[2] = z;
6759 temp2[0] = x2;
6760 temp2[1] = y;
6761 temp2[2] = z;
6762 gPad->PaintLine3D(temp1, temp2);
6763 temp1[0] = x;
6764 temp1[1] = y1;
6765 temp1[2] = z;
6766 temp2[0] = x;
6767 temp2[1] = y2;
6768 temp2[2] = z;
6769 gPad->PaintLine3D(temp1, temp2);
6770 temp1[0] = x;
6771 temp1[1] = y;
6772 temp1[2] = z1;
6773 temp2[0] = x;
6774 temp2[1] = y;
6775 temp2[2] = z2;
6776 gPad->PaintLine3D(temp1, temp2);
6777 temp1[0] = x;
6778 temp1[1] = y;
6779 temp1[2] = z;
6780 view->WCtoNDC(temp1, &temp2[0]);
6781 gPad->PaintPolyMarker(1, &temp2[0], &temp2[1]);
6782 }
6783 }
6784
6785 // Paint the Front Box if needed
6786 if (Hoption.FrontBox) {
6787 fLego->InitMoveScreen(-1.1,1.1);
6789 fLego->FrontBox(90);
6790 }
6791
6792 // Paint the Axis if needed
6793 if (!Hoption.Axis && !Hoption.Same && !Hoption.Lego && !Hoption.Surf) {
6794 TGaxis axis;
6795 PaintLegoAxis(&axis, 90);
6796 }
6797
6798 fLego.reset();
6799}
6800
6801////////////////////////////////////////////////////////////////////////////////
6802/// Calculate range and clear pad (canvas).
6803
6805{
6806
6807 if (Hoption.Same) return;
6808
6810
6811 if (Hoption.Lego || Hoption.Surf || Hoption.Tri ||
6812 Hoption.Contour == 14 || Hoption.Error >= 100) {
6813 TObject *frame = gPad->FindObject("TFrame");
6814 if (frame) gPad->Remove(frame);
6815 return;
6816 }
6817
6818 //The next statement is always executed on non-iOS platform,
6819 //on iOS depends on pad mode.
6820 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode())
6821 gPad->PaintPadFrame(Hparam.xmin,Hparam.ymin,Hparam.xmax,Hparam.ymax);
6822}
6823
6824////////////////////////////////////////////////////////////////////////////////
6825/// [Paint functions associated to an histogram.](\ref HP28")
6826
6828{
6829 auto lnk = fFunctions->FirstLink();
6830
6831 while (lnk) {
6832 auto obj = lnk->GetObject();
6834 if (obj->InheritsFrom(TF2::Class())) {
6835 if (!obj->TestBit(TF2::kNotDraw)) {
6836 if (Hoption.Lego || Hoption.Surf || Hoption.Error >= 100) {
6837 TF2 *f2 = (TF2*)obj;
6838 f2->SetMinimum(fH->GetMinimum());
6839 f2->SetMaximum(fH->GetMaximum());
6840 f2->SetRange(fH->GetXaxis()->GetXmin(), fH->GetYaxis()->GetXmin(), fH->GetXaxis()->GetXmax(), fH->GetYaxis()->GetXmax() );
6841 f2->Paint("surf same");
6842 } else {
6843 obj->Paint("cont3 same");
6844 }
6845 }
6846 } else if (obj->InheritsFrom(TF1::Class())) {
6847 if (!obj->TestBit(TF1::kNotDraw)) obj->Paint("lsame");
6848 } else {
6849 //Let's make this 'function' selectable on iOS device (for example, it can be TPaveStat).
6850 gPad->PushSelectableObject(obj);
6851
6852 //The next statement is ALWAYS executed on non-iOS platform, on iOS it depends on pad's mode
6853 //and picked object.
6854 if (!gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && obj == gPad->GetSelected()))
6855 obj->Paint(lnk->GetOption());
6856 }
6857 lnk = lnk->Next();
6858 }
6859}
6860
6861////////////////////////////////////////////////////////////////////////////////
6862/// [Control routine to draw 1D histograms](\ref HP01b)
6863
6865{
6866
6867 //On iOS: do not highlight hist, if part of it was selected.
6868 //Never executes on non-iOS platform.
6869 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
6870 return;
6871
6872 static char chopth[17];
6873
6875 Int_t i, j, first, last, nbins, fixbin;
6876 Double_t c1, yb;
6877 yb = 0;
6878
6879 strlcpy(chopth, " ",17);
6880
6883 Double_t baroffset = fH->GetBarOffset();
6884 Double_t barwidth = fH->GetBarWidth();
6887 gStyle->SetBarOffset(baroffset);
6888 gStyle->SetBarWidth(barwidth);
6889
6890 // Create "LIFE" structure to keep current histogram status
6891
6892 first = Hparam.xfirst;
6893 last = Hparam.xlast;
6894 nbins = last - first + 1;
6895
6896 std::vector<Double_t> keepx, keepy;
6897 if (fXaxis->GetXbins()->fN) fixbin = 0;
6898 else fixbin = 1;
6899 if (fixbin) keepx.resize(2);
6900 else keepx.resize(nbins+1);
6901 keepy.resize(nbins);
6902 Double_t logymin = 0;
6904
6905 // Loop on histogram bins
6906
6907 for (j=first; j<=last;j++) {
6909 if (TMath::Abs(ymax-ymin) > 0) {
6911 else yb = c1;
6912 }
6913 if (!Hoption.Line) {
6914 yb = TMath::Max(yb, ymin);
6915 yb = TMath::Min(yb, ymax);
6916 }
6917 keepy[j-first] = yb;
6918 }
6919
6920 // Draw histogram according to value of FillStyle and FillColor
6921
6922 if (fixbin) { keepx[0] = Hparam.xmin; keepx[1] = Hparam.xmax; }
6923 else {
6924 for (i=0; i<nbins; i++) keepx[i] = fXaxis->GetBinLowEdge(i+first);
6925 keepx[nbins] = fXaxis->GetBinUpEdge(nbins-1+first);
6926 }
6927
6928 // Prepare Fill area (systematic with option "Bar").
6929
6931 htype = oldhtype;
6932 if (Hoption.Bar) {
6933 if (htype == 0 || htype == 1000) htype = 1001;
6934 }
6935
6937
6938 // Code option for GrapHist
6939
6940 if (Hoption.Line) chopth[0] = 'L';
6941 if (Hoption.Star) chopth[1] = '*';
6942 if (Hoption.Mark) chopth[2] = 'P';
6943 if (Hoption.Mark == 10) chopth[3] = '0';
6945 if (Hoption.Curve) chopth[3] = 'C';
6946 if (Hoption.Hist > 0) chopth[4] = 'H';
6947 else if (Hoption.Bar) chopth[5] = 'B';
6948 if (Hoption.Logy) chopth[6] = '1';
6949 if (fH->GetFillColor() && htype) {
6950 if (Hoption.Hist > 0 || Hoption.Curve || Hoption.Line) {
6951 chopth[7] = 'F';
6952 }
6953 }
6954 }
6955 if (!fixbin && strlen(chopth)) {
6956 chopth[8] = 'N';
6957 }
6958
6959 if (Hoption.Fill == 2) chopth[13] = '2';
6960
6961 // Option LOGX
6962
6963 if (Hoption.Logx) {
6964 chopth[9] = 'G';
6965 chopth[10] = 'X';
6966 if (fixbin) {
6967 keepx[0] = TMath::Power(10,keepx[0]);
6968 keepx[1] = TMath::Power(10,keepx[1]);
6969 }
6970 }
6971
6972 if (Hoption.Off) {
6973 chopth[11] = ']';
6974 chopth[12] = '[';
6975 }
6976
6977 // Draw the histogram
6978
6979 TGraph graph;
6980 graph.SetLineWidth(lw);
6981 graph.SetLineStyle(fH->GetLineStyle());
6982 graph.SetLineColor(fH->GetLineColor());
6983 graph.SetFillStyle(htype);
6984 graph.SetFillColor(fH->GetFillColor());
6986 graph.SetMarkerSize(fH->GetMarkerSize());
6989
6990 graph.PaintGrapHist(nbins, keepx.data(), keepy.data() ,chopth);
6991
6994
6996}
6997
6998////////////////////////////////////////////////////////////////////////////////
6999/// [Control function to draw a 3D histograms.](\ref HP01d)
7000
7002{
7003
7004 TString cmd;
7005 TString opt = option;
7006 opt.ToLower();
7007 Int_t irep;
7008 Float_t NEntries = fH->GetEntries();
7009
7010 if (fCurrentF3 || strstr(opt,"tf3")) {
7011 PaintTF3();
7012 return;
7013 }
7014
7015 if (NEntries > 0) {
7016 if (Hoption.Box || Hoption.Lego || Hoption.Color) {
7017 if (Hoption.Box == 11 || Hoption.Lego == 11) {
7018 PaintH3Box(1);
7019 } else if (Hoption.Box == 12 || Hoption.Lego == 12 || Hoption.Color == 1) {
7020 PaintH3Box(2);
7021 } else if (Hoption.Box == 13 || Hoption.Lego == 13) {
7022 PaintH3Box(3);
7023 } else {
7025 }
7026 return;
7027 }
7028
7029 if (strstr(opt,"iso")) {
7030 PaintH3Iso();
7031 return;
7032 }
7033 }
7034
7035 TView *view = gPad ? gPad->GetView() : nullptr;
7036 if (!view) return;
7037
7038 if (strstr(opt,"fb")) Hoption.FrontBox = 0;
7039 if (strstr(opt,"bb")) Hoption.BackBox = 0;
7040
7041 Double_t thedeg = 90 - gPad->GetTheta();
7042 Double_t phideg = -90 - gPad->GetPhi();
7043 Double_t psideg = view->GetPsi();
7044 view->SetView(phideg, thedeg, psideg, irep);
7045
7046 if(NEntries > 0) { // Paint as 3D scatter plot
7047 cmd.Form("TPolyMarker3D::PaintH3((TH1 *)0x%zx,\"%s\");",(size_t)fH,option);
7048 gROOT->ProcessLine(cmd.Data());
7049 } else {
7050 TAxis* xAxis = fH->GetXaxis();
7051 TAxis* yAxis = fH->GetYaxis();
7052 TAxis* zAxis = fH->GetZaxis();
7053 Double_t xmin = xAxis->GetXmin();
7054 Double_t xmax = xAxis->GetXmax();
7055 Double_t ymin = yAxis->GetXmin();
7056 Double_t ymax = yAxis->GetXmax();
7057 Double_t zmin = zAxis->GetXmin();
7058 Double_t zmax = zAxis->GetXmax();
7059 view->SetRange(xmin, ymin, zmin, xmax, ymax, zmax); // Set the axis limits (Xmin, Ymin, Zmin, Xmax, Ymax, Zmax)
7060 }
7061
7062 if (Hoption.Same) return;
7063
7064 // Draw axis
7065 view->SetOutlineToCube();
7066 TSeqCollection *ol = view->GetOutline();
7067 if (ol && Hoption.BackBox && Hoption.FrontBox) ol->Paint(option);
7069
7070 if (!Hoption.Axis && !Hoption.Same) {
7071 TGaxis axis;
7072 PaintLegoAxis(&axis, 90);
7073 }
7074
7075 // Draw palette. In case of 4D plot with TTree::Draw() the palette should
7076 // be painted with the option colz.
7077 if (fH->GetDrawOption() && strstr(opt,"colz")) {
7078 Int_t ndiv = fH->GetContour();
7079 if (ndiv == 0 ) {
7080 ndiv = gStyle->GetNumberContours();
7081 fH->SetContour(ndiv);
7082 }
7083 PaintPalette();
7084 }
7085
7086 // Draw title
7087 PaintTitle();
7088
7089 //Draw stats and fit results
7090 TF1 *fit = nullptr;
7091 TIter next(fFunctions);
7092 while (auto obj = next()) {
7093 if (obj->InheritsFrom(TF1::Class())) {
7094 fit = (TF1*)obj;
7095 break;
7096 }
7097 }
7098 if ((Hoption.Same%10) != 1) {
7099 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7101 }
7102 }
7103
7104}
7105
7106////////////////////////////////////////////////////////////////////////////////
7107/// Compute histogram parameters used by the drawing routines.
7108
7110{
7111
7112 if (fH->GetDimension() > 1 || Hoption.Lego || Hoption.Surf) return 1;
7113
7114 Int_t i;
7115 static const char *where = "PaintInit";
7117 Int_t maximum = 0;
7118 Int_t minimum = 0;
7119 if (fH->GetMaximumStored() != -1111) maximum = 1;
7120 if (fH->GetMinimumStored() != -1111) minimum = 1;
7121
7122 // Compute X axis parameters
7123
7124 Int_t last = fXaxis->GetLast();
7125 Int_t first = fXaxis->GetFirst();
7128 Hparam.xlast = last;
7129 Hparam.xfirst = first;
7132
7133 // if log scale in X, replace xmin,max by the log
7134 if (Hoption.Logx) {
7135 if (Hparam.xmax<=0) {
7136 Error(where, "cannot set X axis to log scale");
7137 return 0;
7138 }
7139 if (Hparam.xlowedge <=0 ) {
7140 if (Hoption.Same) {
7141 TH1* h1 = nullptr;
7142 TObject *obj;
7143 TIter next(gPad->GetListOfPrimitives());
7144 while ((obj = (TObject *)next())) {
7145 if (obj->InheritsFrom(TH1::Class())) { h1 = (TH1*)(obj) ; break; }
7146 if (obj->InheritsFrom(THStack::Class())) { h1 = ((THStack*)(obj))->GetHistogram() ; break; }
7147 if (obj->InheritsFrom(TGraph::Class())) { h1 = ((TGraph*)(obj))->GetHistogram() ; break; }
7148 if (obj->InheritsFrom(TMultiGraph::Class())) { h1 = ((TMultiGraph*)(obj))->GetHistogram(); break; }
7149 if (obj->InheritsFrom(TGraph2D::Class())) { h1 = ((TGraph2D*)(obj))->GetHistogram(); break; }
7150 if (obj->InheritsFrom(TF1::Class())) { h1 = ((TF1*)(obj))->GetHistogram(); break; }
7151 }
7152 if (h1) {
7154 } else {
7155 Error(where, "undefined user's coordinates. Cannot use option SAME");
7156 return 0;
7157 }
7158 } else {
7159 for (i=first; i<=last; i++) {
7160 Double_t binLow = fXaxis->GetBinLowEdge(i);
7161 if (binLow>0) {
7162 Hparam.xlowedge = binLow;
7163 break;
7164 }
7165 if (binLow == 0 && fH->GetBinContent(i) !=0) {
7166 Hparam.xlowedge = fXaxis->GetBinUpEdge(i)*0.001;
7167 break;
7168 }
7169 }
7170 if (Hparam.xlowedge<=0) {
7171 Error(where, "cannot set X axis to log scale");
7172 return 0;
7173 }
7174 }
7176 }
7181 if (Hparam.xlast > last) Hparam.xlast = last;
7182 if (Hparam.xfirst < first) Hparam.xfirst = first;
7183 }
7184
7185 // Compute Y axis parameters
7186 Double_t bigp = TMath::Power(10,32);
7187 Double_t ymax = -bigp;
7188 Double_t ymin = bigp;
7189 Double_t c1, e1;
7190 Double_t xv[1];
7191 Double_t fval;
7192 TObject *f;
7193 TF1 *f1;
7194 Double_t allchan = 0;
7195 Int_t nonNullErrors = 0;
7196 TIter next(fFunctions);
7197 for (i=first; i<=last;i++) {
7198 c1 = fH->GetBinContent(i);
7200 if (Hoption.Logy) {
7201 if (c1 > 0) ymin = TMath::Min(ymin,c1);
7202 } else {
7204 }
7205 if (Hoption.Error) {
7207 e1 = fH->GetBinError(i);
7208 else
7209 e1 = fH->GetBinErrorUp(i);
7210 if (e1 > 0) nonNullErrors++;
7213 e1 = fH->GetBinErrorLow(i);
7214
7215 if (Hoption.Logy) {
7216 if (c1-e1>0.01*TMath::Abs(c1)) ymin = TMath::Min(ymin,c1-e1);
7217 } else {
7219 }
7220 }
7221 if (Hoption.Func) {
7222 xv[0] = fXaxis->GetBinCenter(i);
7223 while ((f = (TObject*) next())) {
7224 if (f->IsA() == TF1::Class()) {
7225 f1 = (TF1*)f;
7226 if (xv[0] < f1->GetXmin() || xv[0] > f1->GetXmax()) continue;
7227 fval = f1->Eval(xv[0],0,0);
7228 if (f1->GetMaximumStored() != -1111) fval = TMath::Min(f1->GetMaximumStored(), fval);
7230 if (Hoption.Logy) {
7231 if (c1 > 0 && fval > 0.3*c1) ymin = TMath::Min(ymin,fval);
7232 }
7233 }
7234 }
7235 next.Reset();
7236 }
7237 allchan += c1;
7238 }
7239 if (!nonNullErrors) {
7240 if (Hoption.Error) {
7241 if (!Hoption.Mark && !Hoption.Line && !Hoption.Star && !Hoption.Curve) Hoption.Hist = 2;
7242 Hoption.Error=0;
7243 }
7244 }
7245
7246
7247 // Take into account maximum , minimum
7248
7249 if (Hoption.Logy && ymin <= 0) {
7250 if (ymax >= 1) ymin = TMath::Max(.005,ymax*1e-10);
7251 else ymin = 0.001*ymax;
7252 }
7253
7254 Double_t xm = ymin;
7255 if (maximum) ymax = fH->GetMaximumStored();
7256 if (minimum) xm = fH->GetMinimumStored();
7257 if (Hoption.Logy && xm < 0) {
7258 Error(where, "log scale requested with a negative argument (%f)", xm);
7259 return 0;
7260 } else if (Hoption.Logy && xm>=0 && ymax==0) { // empty histogram in log scale
7261 ymin = 0.01;
7262 ymax = 10.;
7263 } else {
7264 ymin = xm;
7265 }
7266
7267 if (ymin >= ymax) {
7268 if (Hoption.Logy) {
7269 if (ymax > 0) ymin = 0.001*ymax;
7270 else {
7271 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", ymax);
7272 return 0;
7273 }
7274 }
7275 else {
7276 if (ymin > 0) {
7277 ymin = 0;
7278 ymax *= 2;
7279 } else if (ymin < 0) {
7280 ymax = 0;
7281 ymin *= 2;
7282 } else {
7283 ymin = 0;
7284 ymax = 1;
7285 }
7286 }
7287 }
7288
7289 // In some cases, mainly because of precision issues, ymin and ymax could almost equal.
7290 if (TMath::AreEqualRel(ymin,ymax,1E-15)) {
7291 ymin = ymin*(1-1E-14);
7292 ymax = ymax*(1+1E-14);
7293 }
7294
7295 // take into account normalization factor
7296 Hparam.allchan = allchan;
7297 Double_t factor = allchan;
7298 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
7299 if (allchan) factor /= allchan;
7300 if (factor == 0) factor = 1;
7301 Hparam.factor = factor;
7302 ymax = factor*ymax;
7303 ymin = factor*ymin;
7304 //just in case the norm factor is negative
7305 // this may happen with a positive norm factor and a negative integral !
7306 if (ymax < ymin) {
7307 Double_t temp = ymax;
7308 ymax = ymin;
7309 ymin = temp;
7310 }
7311
7312 // For log scales, histogram coordinates are LOG10(ymin) and
7313 // LOG10(ymax). Final adjustment (if not option "Same"
7314 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
7315 // Maximum and Minimum are not defined.
7316 if (Hoption.Logy) {
7317 if (ymin <=0 || ymax <=0) {
7318 Error(where, "Cannot set Y axis to log scale");
7319 return 0;
7320 }
7322 if (!minimum) ymin += TMath::Log10(0.5);
7324 if (!maximum) ymax += TMath::Log10(2*(0.9/0.95));
7325 if (!Hoption.Same) {
7326 Hparam.ymin = ymin;
7327 Hparam.ymax = ymax;
7328 }
7329 return 1;
7330 }
7331
7332 // final adjustment of ymin for linear scale.
7333 // if minimum is not set , then ymin is set to zero if >0
7334 // or to ymin - margin if <0.
7335 if (!minimum) {
7336 if (Hoption.MinimumZero) {
7337 if (ymin >= 0) ymin = 0;
7338 else ymin -= yMARGIN*(ymax-ymin);
7339 } else {
7341 if (ymin >= 0 && (ymin-dymin <= 0)) ymin = 0;
7342 else ymin -= dymin;
7343 }
7344 }
7345
7346 // final adjustment of YMAXI for linear scale (if not option "Same"):
7347 // decrease histogram height to MAX% of allowed height if HMAXIM
7348 // has not been called.
7349 if (!maximum) {
7350 ymax += yMARGIN*(ymax-ymin);
7351 }
7352
7353 Hparam.ymin = ymin;
7354 Hparam.ymax = ymax;
7355 return 1;
7356}
7357
7358////////////////////////////////////////////////////////////////////////////////
7359/// Compute histogram parameters used by the drawing routines for a rotated pad.
7360
7362{
7363
7364 static const char *where = "PaintInitH";
7366 Int_t maximum = 0;
7367 Int_t minimum = 0;
7368 if (fH->GetMaximumStored() != -1111) maximum = 1;
7369 if (fH->GetMinimumStored() != -1111) minimum = 1;
7370
7371 // Compute X axis parameters
7372
7373 Int_t last = fXaxis->GetLast();
7374 Int_t first = fXaxis->GetFirst();
7377 Hparam.xlast = last;
7378 Hparam.xfirst = first;
7381
7382 // if log scale in Y, replace ymin,max by the log
7383 if (Hoption.Logy) {
7384 if (Hparam.xlowedge <=0 ) {
7387 }
7388 if (Hparam.ymin <=0 || Hparam.ymax <=0) {
7389 Error(where, "cannot set Y axis to log scale");
7390 return 0;
7391 }
7396 if (Hparam.xlast > last) Hparam.xlast = last;
7397 }
7398
7399 // Compute Y axis parameters
7400 Double_t bigp = TMath::Power(10,32);
7401 Double_t xmax = -bigp;
7402 Double_t xmin = bigp;
7403 Double_t c1, e1;
7404 Double_t xv[1];
7405 Double_t fval;
7406 Int_t i;
7407 TObject *f;
7408 TF1 *f1;
7409 Double_t allchan = 0;
7410 TIter next(fFunctions);
7411 for (i=first; i<=last;i++) {
7412 c1 = fH->GetBinContent(i);
7415 if (Hoption.Error) {
7416 e1 = fH->GetBinError(i);
7419 }
7420 if (Hoption.Func) {
7421 xv[0] = fXaxis->GetBinCenter(i);
7422 while ((f = (TObject*) next())) {
7423 if (f->IsA() == TF1::Class()) {
7424 f1 = (TF1*)f;
7425 if (xv[0] < f1->GetXmin() || xv[0] > f1->GetXmax()) continue;
7426 fval = f1->Eval(xv[0],0,0);
7428 if (Hoption.Logy) {
7429 if (fval > 0.3*c1) xmin = TMath::Min(xmin,fval);
7430 }
7431 }
7432 }
7433 next.Reset();
7434 }
7435 allchan += c1;
7436 }
7437
7438 // Take into account maximum , minimum
7439
7440 if (Hoption.Logx && xmin <= 0) {
7441 if (xmax >= 1) xmin = TMath::Max(.5,xmax*1e-10);
7442 else xmin = 0.001*xmax;
7443 }
7444 Double_t xm = xmin;
7445 if (maximum) xmax = fH->GetMaximumStored();
7446 if (minimum) xm = fH->GetMinimumStored();
7447 if (Hoption.Logx && xm <= 0) {
7448 Error(where, "log scale requested with zero or negative argument (%f)", xm);
7449 return 0;
7450 }
7451 else xmin = xm;
7452 if (xmin >= xmax) {
7453 if (Hoption.Logx) {
7454 if (xmax > 0) xmin = 0.001*xmax;
7455 else {
7456 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", xmax);
7457 return 0;
7458 }
7459 }
7460 else {
7461 if (xmin > 0) {
7462 xmin = 0;
7463 xmax *= 2;
7464 } else if (xmin < 0) {
7465 xmax = 0;
7466 xmin *= 2;
7467 } else {
7468 xmin = 0;
7469 xmax = 1;
7470 }
7471 }
7472 }
7473
7474 // take into account normalization factor
7475 Hparam.allchan = allchan;
7476 Double_t factor = allchan;
7477 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
7478 if (allchan) factor /= allchan;
7479 if (factor == 0) factor = 1;
7480 Hparam.factor = factor;
7481 xmax = factor*xmax;
7482 xmin = factor*xmin;
7483
7484 // For log scales, histogram coordinates are LOG10(ymin) and
7485 // LOG10(ymax). Final adjustment (if not option "Same"
7486 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
7487 // Maximum and Minimum are not defined.
7488 if (Hoption.Logx) {
7489 if (xmin <=0 || xmax <=0) {
7490 Error(where, "Cannot set Y axis to log scale");
7491 return 0;
7492 }
7494 if (!minimum) xmin += TMath::Log10(0.5);
7496 if (!maximum) xmax += TMath::Log10(2*(0.9/0.95));
7497 if (!Hoption.Same) {
7498 Hparam.xmin = xmin;
7499 Hparam.xmax = xmax;
7500 }
7501 return 1;
7502 }
7503
7504 // final adjustment of ymin for linear scale.
7505 // if minimum is not set , then ymin is set to zero if >0
7506 // or to ymin - margin if <0.
7507 if (!minimum) {
7508 if (xmin >= 0) xmin = 0;
7509 else xmin -= yMARGIN*(xmax-xmin);
7510 }
7511
7512 // final adjustment of YMAXI for linear scale (if not option "Same"):
7513 // decrease histogram height to MAX% of allowed height if HMAXIM
7514 // has not been called.
7515 if (!maximum) {
7516 xmax += yMARGIN*(xmax-xmin);
7517 }
7518 Hparam.xmin = xmin;
7519 Hparam.xmax = xmax;
7520 return 1;
7521}
7522
7523////////////////////////////////////////////////////////////////////////////////
7524/// [Control function to draw a 3D histogram with boxes.](\ref HP25)
7525
7527{
7528 // Predefined box structure
7529 Double_t wxyz[8][3] = { {-1,-1,-1}, {1,-1,-1}, {1,1,-1}, {-1,1,-1},
7530 {-1,-1, 1}, {1,-1, 1}, {1,1, 1}, {-1,1, 1} };
7531 Int_t iface[6][4] = { {0,3,2,1}, {4,5,6,7},
7532 {0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7} };
7533
7534 // Define dimensions of world space
7535 TAxis *xaxis = fH->GetXaxis();
7536 TAxis *yaxis = fH->GetYaxis();
7537 TAxis *zaxis = fH->GetZaxis();
7538
7539 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7540 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7541 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7542 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7543 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7544 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7545
7546 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7547
7548 // Set view
7549 TView *view = gPad ? gPad->GetView() : nullptr;
7550 if (!view) {
7551 Error("PaintH3", "no TView in current pad");
7552 return;
7553 }
7554 Double_t thedeg = 90 - gPad->GetTheta();
7555 Double_t phideg = -90 - gPad->GetPhi();
7556 Double_t psideg = view->GetPsi();
7557 Int_t irep;
7558 view->SetView(phideg, thedeg, psideg, irep);
7559
7560 Int_t backcolor = gPad->GetFrameFillColor();
7561 view->PadRange(backcolor);
7562
7563 // Draw back surfaces of frame box
7564 fLego->InitMoveScreen(-1.1,1.1);
7565 if (Hoption.BackBox) {
7566 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
7568 fLego->BackBox(90);
7569 }
7570
7572
7573 // Define order of drawing
7574 Double_t *tnorm = view->GetTnorm();
7575 if (!tnorm) return;
7576 Int_t incrx = (tnorm[ 8] < 0.) ? -1 : +1;
7577 Int_t incry = (tnorm[ 9] < 0.) ? -1 : +1;
7578 Int_t incrz = (tnorm[10] < 0.) ? -1 : +1;
7579 Int_t ix1 = (incrx == +1) ? xaxis->GetFirst() : xaxis->GetLast();
7580 Int_t iy1 = (incry == +1) ? yaxis->GetFirst() : yaxis->GetLast();
7581 Int_t iz1 = (incrz == +1) ? zaxis->GetFirst() : zaxis->GetLast();
7582 Int_t ix2 = (incrx == +1) ? xaxis->GetLast() : xaxis->GetFirst();
7583 Int_t iy2 = (incry == +1) ? yaxis->GetLast() : yaxis->GetFirst();
7584 Int_t iz2 = (incrz == +1) ? zaxis->GetLast() : zaxis->GetFirst();
7585
7586 // Set graphic attributes (colour, style, etc.)
7591
7592 fH->SetFillStyle(1001);
7593 fH->TAttFill::Modify();
7594 fH->TAttLine::Modify();
7595 Int_t ncolors = gStyle->GetNumberOfColors();
7597
7598 // Create bin boxes and draw
7602
7603 Double_t pmin[3], pmax[3], sxyz[8][3];
7604 for (Int_t ix = ix1; ix !=ix2+incrx; ix += incrx) {
7605 pmin[0] = xaxis->GetBinLowEdge(ix);
7606 pmax[0] = xaxis->GetBinUpEdge(ix);
7607 for (Int_t iy = iy1; iy != iy2+incry; iy += incry) {
7608 pmin[1] = yaxis->GetBinLowEdge(iy);
7609 pmax[1] = yaxis->GetBinUpEdge(iy);
7610 for (Int_t iz = iz1; iz != iz2+incrz; iz += incrz) {
7611 pmin[2] = zaxis->GetBinLowEdge(iz);
7612 pmax[2] = zaxis->GetBinUpEdge(iz);
7613 Double_t w = fH->GetBinContent(fH->GetBin(ix,iy,iz));
7614 Bool_t neg = kFALSE;
7615 Int_t n = 5;
7616 if (w<0) {
7617 w = -w;
7618 neg = kTRUE;
7619 }
7620 if (w < wmin) continue;
7621 if (w > wmax) w = wmax;
7622 Double_t scale = (TMath::Power((w-wmin)/(wmax-wmin),1./3.))/2.;
7623 if (scale == 0) continue;
7624 for (Int_t i=0; i<3; ++i) {
7625 Double_t c = (pmax[i] + pmin[i])*0.5;
7626 Double_t d = (pmax[i] - pmin[i])*scale;
7627 for (Int_t k=0; k<8; ++k) { // set bin box vertices
7628 sxyz[k][i] = wxyz[k][i]*d + c;
7629 }
7630 }
7631 for (Int_t k=0; k<8; ++k) { // transform to normalized space
7632 view->WCtoNDC(&sxyz[k][0],&sxyz[k][0]);
7633 }
7634 Double_t x[8], y[8]; // draw bin box faces
7635 for (Int_t k=0; k<6; ++k) {
7636 for (Int_t i=0; i<4; ++i) {
7637 Int_t iv = iface[k][i];
7638 x[i] = sxyz[iv][0];
7639 y[i] = sxyz[iv][1];
7640 }
7641 x[4] = x[0] ; y[4] = y[0];
7642 if (neg) {
7643 x[5] = x[2] ; y[5] = y[2];
7644 x[6] = x[3] ; y[6] = y[3];
7645 x[7] = x[1] ; y[7] = y[1];
7646 n = 8;
7647 } else {
7648 n = 5;
7649 }
7650 Double_t z = (x[2]-x[0])*(y[3]-y[1]) - (y[2]-y[0])*(x[3]-x[1]);
7651 if (z <= 0.) continue;
7652 if (iopt == 2) {
7653 theColor = ncolors*((w-wmin)/(wmax-wmin)) -1;
7655 } else {
7656 if (k == 3 || k == 5) {
7658 } else if (k == 0 || k == 1) {
7660 } else {
7662 }
7663 }
7664 fH->TAttFill::Modify();
7665 gPad->PaintFillArea(4, x, y);
7666 if (iopt != 3)gPad->PaintPolyLine(n, x, y);
7667 }
7668 }
7669 }
7670 }
7671
7672 // Draw front surfaces of frame box
7673 if (Hoption.FrontBox) fLego->FrontBox(90);
7674
7675 // Draw axis and title
7676 if (!Hoption.Axis && !Hoption.Same) {
7677 TGaxis axis;
7678 PaintLegoAxis(&axis, 90);
7679 }
7680 PaintTitle();
7681
7682 // Draw palette. if needed.
7683 if (Hoption.Zscale) {
7684 Int_t ndiv = fH->GetContour();
7685 if (ndiv == 0 ) {
7686 ndiv = gStyle->GetNumberContours();
7687 fH->SetContour(ndiv);
7688 }
7689 PaintPalette();
7690 }
7691
7692 //Draw stats and fit results
7693 TF1 *fit = nullptr;
7694 TIter next(fFunctions);
7695 while (auto obj = next()) {
7696 if (obj->InheritsFrom(TF1::Class())) {
7697 fit = (TF1*)obj;
7698 break;
7699 }
7700 }
7701 if ((Hoption.Same%10) != 1) {
7702 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7704 }
7705 }
7706
7707 fLego.reset();
7708
7711 fH->TAttFill::Modify();
7712}
7713
7714////////////////////////////////////////////////////////////////////////////////
7715/// [Control function to draw a 3D histogram with boxes.](\ref HP25)
7716
7718{
7719 // Predefined box structure
7720 Double_t wxyz[8][3] = {
7721 {-1,-1,-1}, {1,-1,-1}, {1,1,-1}, {-1,1,-1}, // bottom vertices
7722 {-1,-1, 1}, {1,-1, 1}, {1,1, 1}, {-1,1, 1} // top vertices
7723 };
7724 Int_t iface[6][4] = {
7725 {0,3,2,1}, {4,5,6,7}, // bottom and top faces
7726 {0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7} // side faces
7727 };
7728 Double_t normal[6][3] = {
7729 {0,0,-1}, {0,0,1}, // Z-, Z+
7730 {0,-1,0}, {1,0,0}, {0,1,0}, {-1,0,0} // Y-, X+, Y+, X-
7731 };
7732
7733 // Define dimensions of world space
7734 TAxis *xaxis = fH->GetXaxis();
7735 TAxis *yaxis = fH->GetYaxis();
7736 TAxis *zaxis = fH->GetZaxis();
7737
7738 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7739 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7740 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7741 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7742 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7743 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7744
7745 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7746
7747 // Set view
7748 TView *view = gPad ? gPad->GetView() : nullptr;
7749 if (!view) {
7750 Error("PaintH3", "no TView in current pad");
7751 return;
7752 }
7753 Double_t thedeg = 90 - gPad->GetTheta();
7754 Double_t phideg = -90 - gPad->GetPhi();
7755 Double_t psideg = view->GetPsi();
7756 Int_t irep;
7757 view->SetView(phideg, thedeg, psideg, irep);
7758
7759 Int_t backcolor = gPad->GetFrameFillColor();
7760 view->PadRange(backcolor);
7761
7762 // Draw front surfaces of frame box
7763 if (Hoption.FrontBox) {
7764 fLego->InitMoveScreen(-1.1,1.1);
7766 }
7767
7768 // Initialize hidden line removal algorithm "raster screen"
7769 fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
7770
7771 // Define order of drawing
7772 Double_t *tnorm = view->GetTnorm();
7773 if (!tnorm) return;
7774 Int_t incrx = (tnorm[ 8] < 0.) ? +1 : -1;
7775 Int_t incry = (tnorm[ 9] < 0.) ? +1 : -1;
7776 Int_t incrz = (tnorm[10] < 0.) ? +1 : -1;
7777 Int_t ix1 = (incrx == +1) ? xaxis->GetFirst() : xaxis->GetLast();
7778 Int_t iy1 = (incry == +1) ? yaxis->GetFirst() : yaxis->GetLast();
7779 Int_t iz1 = (incrz == +1) ? zaxis->GetFirst() : zaxis->GetLast();
7780 Int_t ix2 = (incrx == +1) ? xaxis->GetLast() : xaxis->GetFirst();
7781 Int_t iy2 = (incry == +1) ? yaxis->GetLast() : yaxis->GetFirst();
7782 Int_t iz2 = (incrz == +1) ? zaxis->GetLast() : zaxis->GetFirst();
7783
7784 // Set line attributes (colour, style, etc.)
7785 fH->TAttLine::Modify();
7786
7787 // Create bin boxes and draw
7788 const Int_t NTMAX = 100;
7789 Double_t tt[NTMAX][2];
7793 Double_t pmin[3], pmax[3], sxyz[8][3], pp[4][2];
7794 for (Int_t ix = ix1; ix !=ix2+incrx; ix += incrx) {
7795 pmin[0] = xaxis->GetBinLowEdge(ix);
7796 pmax[0] = xaxis->GetBinUpEdge(ix);
7797 for (Int_t iy = iy1; iy != iy2+incry; iy += incry) {
7798 pmin[1] = yaxis->GetBinLowEdge(iy);
7799 pmax[1] = yaxis->GetBinUpEdge(iy);
7800 for (Int_t iz = iz1; iz != iz2+incrz; iz += incrz) {
7801 pmin[2] = zaxis->GetBinLowEdge(iz);
7802 pmax[2] = zaxis->GetBinUpEdge(iz);
7803 Double_t w = fH->GetBinContent(fH->GetBin(ix,iy,iz));
7804 Bool_t neg = kFALSE;
7805 if (w<0) {
7806 w = -w;
7807 neg = kTRUE;
7808 }
7809 if (w < wmin) continue;
7810 if (w > wmax) w = wmax;
7811 Double_t scale = (TMath::Power((w-wmin)/(wmax-wmin),1./3.))/2.;
7812 if (scale == 0) continue;
7813 for (Int_t i=0; i<3; ++i) {
7814 Double_t c = (pmax[i] + pmin[i])*0.5;
7815 Double_t d = (pmax[i] - pmin[i])*scale;
7816 for (Int_t k=0; k<8; ++k) { // set bin box vertices
7817 sxyz[k][i] = wxyz[k][i]*d + c;
7818 }
7819 }
7820 for (Int_t k=0; k<8; ++k) { // transform to normalized space
7821 view->WCtoNDC(&sxyz[k][0],&sxyz[k][0]);
7822 }
7823 for (Int_t k=0; k<6; ++k) { // draw box faces
7824 Double_t zn;
7825 view->FindNormal(normal[k][0], normal[k][1], normal[k][2], zn);
7826 if (zn <= 0) continue;
7827 for (Int_t i=0; i<4; ++i) {
7828 Int_t ip = iface[k][i];
7829 pp[i][0] = sxyz[ip][0];
7830 pp[i][1] = sxyz[ip][1];
7831 }
7832 for (Int_t i=0; i<4; ++i) {
7833 Int_t i1 = i;
7834 Int_t i2 = (i == 3) ? 0 : i + 1;
7835 Int_t nt;
7836 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7837 Double_t xdel = pp[i2][0] - pp[i1][0];
7838 Double_t ydel = pp[i2][1] - pp[i1][1];
7839 Double_t x[2], y[2];
7840 for (Int_t it = 0; it < nt; ++it) {
7841 x[0] = pp[i1][0] + xdel*tt[it][0];
7842 y[0] = pp[i1][1] + ydel*tt[it][0];
7843 x[1] = pp[i1][0] + xdel*tt[it][1];
7844 y[1] = pp[i1][1] + ydel*tt[it][1];
7845 gPad->PaintPolyLine(2, x, y);
7846 }
7847 }
7848 if (neg) {
7849 Int_t i1 = 0;
7850 Int_t i2 = 2;
7851 Int_t nt;
7852 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7853 Double_t xdel = pp[i2][0] - pp[i1][0];
7854 Double_t ydel = pp[i2][1] - pp[i1][1];
7855 Double_t x[2], y[2];
7856 for (Int_t it = 0; it < nt; ++it) {
7857 x[0] = pp[i1][0] + xdel*tt[it][0];
7858 y[0] = pp[i1][1] + ydel*tt[it][0];
7859 x[1] = pp[i1][0] + xdel*tt[it][1];
7860 y[1] = pp[i1][1] + ydel*tt[it][1];
7861 gPad->PaintPolyLine(2, x, y);
7862 }
7863 i1 = 1;
7864 i2 = 3;
7865 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7866 xdel = pp[i2][0] - pp[i1][0];
7867 ydel = pp[i2][1] - pp[i1][1];
7868 for (Int_t it = 0; it < nt; ++it) {
7869 x[0] = pp[i1][0] + xdel*tt[it][0];
7870 y[0] = pp[i1][1] + ydel*tt[it][0];
7871 x[1] = pp[i1][0] + xdel*tt[it][1];
7872 y[1] = pp[i1][1] + ydel*tt[it][1];
7873 gPad->PaintPolyLine(2, x, y);
7874 }
7875 }
7876 fLego->FillPolygonBorder(4, &pp[0][0]); // update raster screen
7877 }
7878 }
7879 }
7880 }
7881
7882 // Draw frame box
7883 if (Hoption.BackBox) {
7884 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
7886 fLego->BackBox(90);
7887 }
7888
7889 if (Hoption.FrontBox) fLego->FrontBox(90);
7890
7891 // Draw axis and title
7892 if (!Hoption.Axis && !Hoption.Same) {
7893 TGaxis axis;
7894 PaintLegoAxis(&axis, 90);
7895 }
7896 PaintTitle();
7897
7898 //Draw stats and fit results
7899 TF1 *fit = nullptr;
7900 TIter next(fFunctions);
7901 while (auto obj = next()) {
7902 if (obj->InheritsFrom(TF1::Class())) {
7903 fit = (TF1*)obj;
7904 break;
7905 }
7906 }
7907 if ((Hoption.Same%10) != 1) {
7908 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7910 }
7911 }
7912
7913 fLego.reset();
7914}
7915
7916////////////////////////////////////////////////////////////////////////////////
7917/// [Control function to draw a 3D histogram with Iso Surfaces.](\ref HP25)
7918
7920{
7921
7922 const Double_t ydiff = 1;
7923 const Double_t yligh1 = 10;
7924 const Double_t qa = 0.15;
7925 const Double_t qd = 0.15;
7926 const Double_t qs = 0.8;
7928 Int_t i, irep;
7929 Int_t nbcol = 28;
7930 Int_t icol1 = 201;
7931 Int_t ic1 = icol1;
7932 Int_t ic2 = ic1+nbcol;
7933 Int_t ic3 = ic2+nbcol;
7934
7935 TAxis *xaxis = fH->GetXaxis();
7936 TAxis *yaxis = fH->GetYaxis();
7937 TAxis *zaxis = fH->GetZaxis();
7938
7939 Int_t nx = fH->GetNbinsX();
7940 Int_t ny = fH->GetNbinsY();
7941 Int_t nz = fH->GetNbinsZ();
7942
7943 std::vector<Double_t> x(nx);
7944 std::vector<Double_t> y(ny);
7945 std::vector<Double_t> z(nz);
7946
7947 for (i=0; i<nx; i++) x[i] = xaxis->GetBinCenter(i+1);
7948 for (i=0; i<ny; i++) y[i] = yaxis->GetBinCenter(i+1);
7949 for (i=0; i<nz; i++) z[i] = zaxis->GetBinCenter(i+1);
7950
7951 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7952 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7953 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7954 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7955 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7956 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7957
7958 Double_t s[3];
7959 s[0] = fH->GetSumOfWeights()/(fH->GetNbinsX()*fH->GetNbinsY()*fH->GetNbinsZ());
7960 s[1] = 0.5*s[0];
7961 s[2] = 1.5*s[0];
7962
7963 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7964
7965 TView *view = gPad ? gPad->GetView() : nullptr;
7966 if (!view) {
7967 Error("PaintH3Iso", "no TView in current pad");
7968 return;
7969 }
7970 Double_t thedeg = 90 - gPad->GetTheta();
7971 Double_t phideg = -90 - gPad->GetPhi();
7972 Double_t psideg = view->GetPsi();
7973 view->SetView(phideg, thedeg, psideg, irep);
7974
7975 Int_t backcolor = gPad->GetFrameFillColor();
7976 if (Hoption.System != kCARTESIAN) backcolor = 0;
7977 view->PadRange(backcolor);
7978
7979 Double_t dcol = 0.5/Double_t(nbcol);
7980 TColor *colref = gROOT->GetColor(fH->GetFillColor());
7981 if (!colref) {
7982 return;
7983 }
7984 Float_t r, g, b, hue, light, satur;
7985 colref->GetRGB(r,g,b);
7987 TColor *acol;
7988 for (Int_t col=0;col<nbcol;col++) {
7989 acol = gROOT->GetColor(col+icol1);
7990 TColor::HLStoRGB(hue, .4+col*dcol, satur, r, g, b);
7991 if (acol) acol->SetRGB(r, g, b);
7992 }
7993
7994 fLego->InitMoveScreen(-1.1,1.1);
7995
7996 if (Hoption.BackBox) {
7997 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
7999 fLego->BackBox(90);
8000 }
8001
8002 fLego->LightSource(0, ydiff, 0, 0, 0, irep);
8003 fLego->LightSource(1, yligh1, 1, 1, 1, irep);
8004 fLego->SurfaceProperty(qa, qd, qs, 1, irep);
8005 fmin = ydiff*qa;
8006 fmax = ydiff*qa + (yligh1+0.1)*(qd+qs);
8007 fLego->SetIsoSurfaceParameters(fmin, fmax, nbcol, ic1, ic2, ic3);
8008
8009 fLego->IsoSurface(1, s, nx, ny, nz, x.data(), y.data(), z.data(), "BF");
8010
8011 if (Hoption.FrontBox) {
8012 fLego->InitMoveScreen(-1.1,1.1);
8014 fLego->FrontBox(90);
8015 }
8016 if (!Hoption.Axis && !Hoption.Same) {
8017 TGaxis axis;
8018 PaintLegoAxis(&axis, 90);
8019 }
8020
8021 PaintTitle();
8022
8023 //Draw stats and fit results
8024 TF1 *fit = nullptr;
8025 TIter next(fFunctions);
8026 while (auto obj = next()) {
8027 if (obj->InheritsFrom(TF1::Class())) {
8028 fit = (TF1*)obj;
8029 break;
8030 }
8031 }
8032 if ((Hoption.Same%10) != 1) {
8033 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
8035 }
8036 }
8037
8038 fLego.reset();
8039}
8040
8041////////////////////////////////////////////////////////////////////////////////
8042/// [Control function to draw a 2D histogram as a lego plot.](\ref HP17)
8043
8045{
8046
8047 Int_t raster = 1;
8048 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
8049 Int_t nx = Hparam.xlast - Hparam.xfirst + 1;
8050 Int_t ny = Hparam.ylast - Hparam.yfirst + 1;
8051 Double_t zmin = Hparam.zmin;
8052 Double_t zmax = Hparam.zmax;
8057 Double_t dangle = 10*3.141592/180; //Delta angle for Rapidity option
8058 Double_t deltaz = TMath::Abs(zmin);
8059 if (deltaz == 0) deltaz = 1;
8060 if (zmin >= zmax) {
8061 zmin -= 0.5*deltaz;
8062 zmax += 0.5*deltaz;
8063 }
8064 Double_t z1c = zmin;
8065 Double_t z2c = zmin + (zmax-zmin)*(1+gStyle->GetHistTopMargin());
8066
8067 // Compute the lego limits and instantiate a lego object
8068 fXbuf[0] = -1;
8069 fYbuf[0] = 1;
8070 fXbuf[1] = -1;
8071 fYbuf[1] = 1;
8072 if (Hoption.System == kPOLAR) {
8073 fXbuf[2] = z1c;
8074 fYbuf[2] = z2c;
8075 } else if (Hoption.System == kCYLINDRICAL) {
8076 if (Hoption.Logy) {
8077 if (ylab1 > 0) fXbuf[2] = TMath::Log10(ylab1);
8078 else fXbuf[2] = 0;
8079 if (ylab2 > 0) fYbuf[2] = TMath::Log10(ylab2);
8080 else fYbuf[2] = 0;
8081 } else {
8082 fXbuf[2] = ylab1;
8083 fYbuf[2] = ylab2;
8084 }
8085 z1c = 0; z2c = 1;
8086 } else if (Hoption.System == kSPHERICAL) {
8087 fXbuf[2] = -1;
8088 fYbuf[2] = 1;
8089 z1c = 0; z2c = 1;
8090 } else if (Hoption.System == kRAPIDITY) {
8091 fXbuf[2] = -1/TMath::Tan(dangle);
8092 fYbuf[2] = 1/TMath::Tan(dangle);
8093 } else {
8094 fXbuf[0] = xlab1;
8095 fYbuf[0] = xlab2;
8096 fXbuf[1] = ylab1;
8097 fYbuf[1] = ylab2;
8098 fXbuf[2] = z1c;
8099 fYbuf[2] = z2c;
8100 raster = 0;
8101 }
8102
8103 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data(), Hoption.System);
8104
8105 Int_t nids = -1;
8106 TH1 * hid = nullptr;
8107 Color_t colormain = -1, colordark = -1;
8109
8110 // LEGO3 is like LEGO1 except that the black lines around each lego are not drawn.
8111 if (Hoption.Lego == 13) {
8112 Hoption.Lego = 11;
8113 fLego->SetMesh(0);
8114 }
8115 // LEGO4 is like LEGO1 except no shadows are drawn.
8116 if (Hoption.Lego == 14) {
8117 Hoption.Lego = 11;
8119 }
8120
8121 // Initialize the levels on the Z axis
8122 Int_t ndiv = fH->GetContour();
8123 if (ndiv == 0 ) {
8124 ndiv = gStyle->GetNumberContours();
8125 fH->SetContour(ndiv);
8126 }
8127 Int_t ndivz = TMath::Abs(ndiv);
8128 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
8129
8130 // Initialize colors
8131 if (!fStack) {
8132 fLego->SetEdgeAtt(fH->GetLineColor(),fH->GetLineStyle(),fH->GetLineWidth(),0);
8133 } else {
8134 for (Int_t id=0;id<=fStack->GetSize();id++) {
8135 hid = (TH1*)fStack->At((id==0)?id:id-1);
8136 fLego->SetEdgeAtt(hid->GetLineColor(),hid->GetLineStyle(),hid->GetLineWidth(),id);
8137 }
8138 }
8139
8140 if (Hoption.Lego == 11) {
8141 nids = 1;
8142 if (fStack) nids = fStack->GetSize();
8143 hid = fH;
8144 for (Int_t id=0;id<=nids;id++) {
8145 if (id > 0 && fStack) hid = (TH1*)fStack->At(id-1);
8146 colormain = hid->GetFillColor();
8147 if (colormain == 1) colormain = 17; //avoid drawing with black
8149 else colordark = colormain;
8150 fLego->SetColorMain(colormain,id);
8151 fLego->SetColorDark(colordark,id);
8152 if (id <= 1) fLego->SetColorMain(colormain,-1); // Set Bottom color
8153 if (id == nids) fLego->SetColorMain(colormain,99); // Set Top color
8154 }
8155 }
8156
8157 // Now ready to draw the lego plot
8158 Int_t irep = 0;
8159
8160 TView *view = gPad ? gPad->GetView() : nullptr;
8161 if (!view) {
8162 Error("PaintLego", "no TView in current pad");
8163 return;
8164 }
8165
8166 Double_t thedeg = 90 - gPad->GetTheta();
8167 Double_t phideg = -90 - gPad->GetPhi();
8168 Double_t psideg = view->GetPsi();
8169 view->SetView(phideg, thedeg, psideg, irep);
8170
8171 fLego->SetLineColor(kBlack); // zgrid color for lego1 & lego2
8172 fLego->SetFillStyle(fH->GetFillStyle());
8173
8174 // Set color/style for back box
8175 fLego->SetFillStyle(gPad->GetFrameFillStyle());
8176 fLego->SetFillColor(gPad->GetFrameFillColor());
8177 fLego->TAttFill::Modify();
8178
8179 Int_t backcolor = gPad->GetFrameFillColor();
8180 if (Hoption.System != kCARTESIAN) backcolor = 0;
8181 view->PadRange(backcolor);
8182
8183 fLego->SetFillStyle(fH->GetFillStyle());
8184 fLego->SetFillColor(fH->GetFillColor());
8185 fLego->TAttFill::Modify();
8186
8187 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
8188
8189 if (raster) fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
8190 else fLego->InitMoveScreen(-1.1,1.1);
8191
8192 if (Hoption.Lego == 19) {
8194 if (Hoption.BackBox) fLego->BackBox(90);
8195 if (Hoption.FrontBox) fLego->FrontBox(90);
8196 if (!Hoption.Axis) { TGaxis axis; PaintLegoAxis(&axis, 90); }
8197 return;
8198 }
8199
8200 if (Hoption.Lego == 11 || Hoption.Lego == 12) {
8203 fLego->BackBox(90);
8204 }
8205 }
8206
8207 if (Hoption.Lego == 12) DefineColorLevels(ndivz);
8208
8209 fLego->SetLegoFunction(&TPainter3dAlgorithms::LegoFunction);
8211 if (Hoption.Lego == 11) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode3);
8212 if (Hoption.Lego == 12) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode2);
8213 if (Hoption.System == kPOLAR) {
8214 if (Hoption.Lego == 1) fLego->LegoPolar(1,nx,ny,"FB");
8215 if (Hoption.Lego == 11) fLego->LegoPolar(1,nx,ny,"BF");
8216 if (Hoption.Lego == 12) fLego->LegoPolar(1,nx,ny,"BF");
8217 } else if (Hoption.System == kCYLINDRICAL) {
8218 if (Hoption.Lego == 1) fLego->LegoCylindrical(1,nx,ny,"FB");
8219 if (Hoption.Lego == 11) fLego->LegoCylindrical(1,nx,ny,"BF");
8220 if (Hoption.Lego == 12) fLego->LegoCylindrical(1,nx,ny,"BF");
8221 } else if (Hoption.System == kSPHERICAL) {
8222 if (Hoption.Lego == 1) fLego->LegoSpherical(0,1,nx,ny,"FB");
8223 if (Hoption.Lego == 11) fLego->LegoSpherical(0,1,nx,ny,"BF");
8224 if (Hoption.Lego == 12) fLego->LegoSpherical(0,1,nx,ny,"BF");
8225 } else if (Hoption.System == kRAPIDITY) {
8226 if (Hoption.Lego == 1) fLego->LegoSpherical(1,1,nx,ny,"FB");
8227 if (Hoption.Lego == 11) fLego->LegoSpherical(1,1,nx,ny,"BF");
8228 if (Hoption.Lego == 12) fLego->LegoSpherical(1,1,nx,ny,"BF");
8229 } else {
8230 if (Hoption.Lego == 1) {
8232 fLego->LegoCartesian(90,nx,ny,"FB");}
8233 if (Hoption.Lego == 11) fLego->LegoCartesian(90,nx,ny,"BF");
8234 if (Hoption.Lego == 12) fLego->LegoCartesian(90,nx,ny,"BF");
8235 }
8236
8237 if (Hoption.Lego == 1 || Hoption.Lego == 11) {
8240 fLego->BackBox(90);
8241 }
8242 }
8243 if (Hoption.System == kCARTESIAN) {
8244 fLego->InitMoveScreen(-1.1,1.1);
8246 if (Hoption.FrontBox) fLego->FrontBox(90);
8247 }
8248 if (!Hoption.Axis && !Hoption.Same) {
8249 TGaxis axis;
8250 PaintLegoAxis(&axis, 90);
8251 }
8253 fLego.reset();
8254}
8255
8256////////////////////////////////////////////////////////////////////////////////
8257/// Draw the axis for legos and surface plots.
8258
8260{
8261
8262 static Double_t epsil = 0.001;
8263
8266 Double_t r[24] /* was [3][8] */;
8267 Int_t ndivx, ndivy, ndivz, i;
8268 Double_t x1[3], x2[3], y1[3], y2[3], z1[3], z2[3], av[24] /* was [3][8] */;
8269 static char chopax[8], chopay[8], chopaz[8];
8270 Int_t ix1, ix2, iy1, iy2, iz1, iz2;
8271 Double_t rad;
8272
8273 TView *view = gPad ? gPad->GetView() : nullptr;
8274 if (!view) {
8275 Error("PaintLegoAxis", "no TView in current pad");
8276 return;
8277 }
8278
8279 // In polar coordinates, draw a short line going from the external circle
8280 // corresponding to r = 1 up to r = 1.1
8281 if (Hoption.System == kPOLAR) {
8282 r[0] = 1;
8283 r[1] = 0;
8284 r[2] = 0;
8285 view->WCtoNDC(r, x1);
8286 r[0] = 1.1;
8287 r[1] = 0;
8288 r[2] = 0;
8289 view->WCtoNDC(r, x2);
8290 gPad->PaintLine(x1[0],x1[1],x2[0],x2[1]);
8291 return;
8292 }
8293
8294 if (Hoption.System != kCARTESIAN) return;
8295
8296 rad = TMath::ATan(1.) * 4. /180.;
8297 cosa = TMath::Cos(ang*rad);
8298 sina = TMath::Sin(ang*rad);
8299
8300 view->AxisVertex(ang, av, ix1, ix2, iy1, iy2, iz1, iz2);
8301 for (i = 1; i <= 8; ++i) {
8302 r[i*3 - 3] = av[i*3 - 3] + av[i*3 - 2]*cosa;
8303 r[i*3 - 2] = av[i*3 - 2]*sina;
8304 r[i*3 - 1] = av[i*3 - 1];
8305 }
8306
8307 view->WCtoNDC(&r[ix1*3 - 3], x1);
8308 view->WCtoNDC(&r[ix2*3 - 3], x2);
8309 view->WCtoNDC(&r[iy1*3 - 3], y1);
8310 view->WCtoNDC(&r[iy2*3 - 3], y2);
8311 view->WCtoNDC(&r[iz1*3 - 3], z1);
8312 view->WCtoNDC(&r[iz2*3 - 3], z2);
8313
8314 view->SetAxisNDC(x1, x2, y1, y2, z1, z2);
8315
8316 Double_t *rmin = view->GetRmin();
8317 Double_t *rmax = view->GetRmax();
8318 if (!rmin || !rmax) return;
8319
8320 // Initialize the axis options
8321 if (x1[0] > x2[0]) strlcpy(chopax, "SDH=+",8);
8322 else strlcpy(chopax, "SDH=-",8);
8323 if (y1[0] > y2[0]) strlcpy(chopay, "SDH=+",8);
8324 else strlcpy(chopay, "SDH=-",8);
8325 if (z2[1] > z1[1]) strlcpy(chopaz, "SDH=+",8);
8326 else strlcpy(chopaz, "SDH=-",8);
8327
8328 // Option LOG is required ?
8329 if (Hoption.Logx) strlcat(chopax,"G",8);
8330 if (Hoption.Logy) strlcat(chopay,"G",8);
8331 if (Hoption.Logz) strlcat(chopaz,"G",8);
8332
8333 // Initialize the number of divisions. If the
8334 // number of divisions is negative, option 'N' is required.
8338 if (ndivx < 0) {
8340 strlcat(chopax, "N",8);
8341 }
8342 if (ndivy < 0) {
8344 strlcat(chopay, "N",8);
8345 }
8346 if (ndivz < 0) {
8348 strlcat(chopaz, "N",8);
8349 }
8350
8351 // Set Axis attributes.
8352 // The variable SCALE rescales the VSIZ
8353 // in order to have the same label size for all angles.
8354
8355 axis->SetLineWidth(1);
8356
8357 // X axis drawing
8358 if (TMath::Abs(x1[0] - x2[0]) >= epsil || TMath::Abs(x1[1] - x2[1]) > epsil) {
8361 if (Hoption.Logx && !fH->InheritsFrom(TH3::Class())) {
8362 bmin = TMath::Power(10, rmin[0]);
8363 bmax = TMath::Power(10, rmax[0]);
8364 } else {
8365 bmin = rmin[0];
8366 bmax = rmax[0];
8367 }
8368 // Option time display is required ?
8369 if (fXaxis->GetTimeDisplay()) {
8370 strlcat(chopax,"t",8);
8371 if (strlen(fXaxis->GetTimeFormatOnly()) == 0) {
8373 } else {
8375 }
8376 }
8377 axis->SetOption(chopax);
8378 axis->PaintAxis(x1[0], x1[1], x2[0], x2[1], bmin, bmax, ndivx, chopax);
8379 }
8380
8381 // Y axis drawing
8382 if (TMath::Abs(y1[0] - y2[0]) >= epsil || TMath::Abs(y1[1] - y2[1]) > epsil) {
8385 if (fYaxis->GetTitleOffset() == 0) axis->SetTitleOffset(1.5);
8386
8387 if (fH->GetDimension() < 2) {
8388 strlcpy(chopay, "V=+UN",8);
8389 ndivy = 0;
8390 }
8391 if (TMath::Abs(y1[0] - y2[0]) < epsil) {
8392 y2[0] = y1[0];
8393 }
8394 if (Hoption.Logy && !fH->InheritsFrom(TH3::Class())) {
8395 bmin = TMath::Power(10, rmin[1]);
8396 bmax = TMath::Power(10, rmax[1]);
8397 } else {
8398 bmin = rmin[1];
8399 bmax = rmax[1];
8400 }
8401 // Option time display is required ?
8402 if (fYaxis->GetTimeDisplay()) {
8403 strlcat(chopay,"t",8);
8404 if (strlen(fYaxis->GetTimeFormatOnly()) == 0) {
8406 } else {
8408 }
8409 }
8410 axis->SetOption(chopay);
8411 axis->PaintAxis(y1[0], y1[1], y2[0], y2[1], bmin, bmax, ndivy, chopay);
8412 }
8413
8414 // Z axis drawing
8415 if (TMath::Abs(z1[0] - z2[0]) >= 100*epsil || TMath::Abs(z1[1] - z2[1]) > 100*epsil) {
8417 if (Hoption.Logz && !fH->InheritsFrom(TH3::Class())) {
8418 bmin = TMath::Power(10, rmin[2]);
8419 bmax = TMath::Power(10, rmax[2]);
8420 } else {
8421 bmin = rmin[2];
8422 bmax = rmax[2];
8423 }
8424 // Option time display is required ?
8425 if (fZaxis->GetTimeDisplay()) {
8426 strlcat(chopaz,"t",8);
8427 if (strlen(fZaxis->GetTimeFormatOnly()) == 0) {
8429 } else {
8431 }
8432 }
8433 axis->SetOption(chopaz);
8435 if (ztit.Index(";")>0) {
8436 ztit.Remove(ztit.Index(";"),ztit.Length());
8437 axis->SetTitle(ztit.Data());
8438 }
8439 axis->PaintAxis(z1[0], z1[1], z2[0], z2[1], bmin, bmax, ndivz, chopaz);
8440 }
8441
8442 //fH->SetLineStyle(1); /// otherwise fEdgeStyle[i] gets overwritten!
8443}
8444
8445////////////////////////////////////////////////////////////////////////////////
8446/// [Paint the color palette on the right side of the pad.](\ref HP22)
8447
8449{
8451 TView *view = gPad ? gPad->GetView() : nullptr;
8452 if (palette) {
8453 if (view) {
8454 if (!palette->TestBit(TPaletteAxis::kHasView)) {
8456 delete palette; palette = nullptr;
8457 }
8458 } else {
8459 if (palette->TestBit(TPaletteAxis::kHasView)) {
8461 delete palette; palette = nullptr;
8462 }
8463 }
8464 // make sure the histogram member of the palette is setup correctly. It may not be after a Clone()
8465 if (palette && !palette->GetHistogram()) palette->SetHistogram(fH);
8466 }
8467
8468 if (!palette) {
8469 Double_t xup = gPad->GetUxmax();
8470 Double_t x2 = gPad->PadtoX(gPad->GetX2());
8471 Double_t ymin = gPad->PadtoY(gPad->GetUymin());
8472 Double_t ymax = gPad->PadtoY(gPad->GetUymax());
8473 Double_t xr = 0.05*(gPad->GetX2() - gPad->GetX1());
8474 Double_t xmin = gPad->PadtoX(xup +0.1*xr);
8475 Double_t xmax = gPad->PadtoX(xup + xr);
8476 if (xmax > x2) xmax = gPad->PadtoX(gPad->GetX2()-0.01*xr);
8479 palette->Paint();
8480 }
8481}
8482
8483////////////////////////////////////////////////////////////////////////////////
8484/// [Control function to draw a 2D histogram as a scatter plot.](\ref HP11)
8485
8487{
8488
8489 fH->TAttMarker::Modify();
8490
8491 Int_t k, marker;
8492 Double_t dz, z, xk,xstep, yk, ystep;
8493 Double_t scale = 1;
8495 Double_t zmax = fH->GetMaximum();
8496 Double_t zmin = fH->GetMinimum();
8497 if (zmin == 0 && zmax == 0) return;
8498 if (zmin == zmax) {
8499 zmax += 0.1*TMath::Abs(zmax);
8500 zmin -= 0.1*TMath::Abs(zmin);
8501 }
8503 if (Hoption.Logz) {
8504 if (zmin > 0) zmin = TMath::Log10(zmin);
8505 else zmin = 0;
8506 if (zmax > 0) zmax = TMath::Log10(zmax);
8507 else zmax = 0;
8508 if (zmin == 0 && zmax == 0) return;
8509 dz = zmax - zmin;
8510 scale = 100/dz;
8511 if (ncells > 10000) scale /= 5;
8512 ltest = kTRUE;
8513 } else {
8514 dz = zmax - zmin;
8515 if (dz >= kNMAX || zmax < 1) {
8516 scale = (kNMAX-1)/dz;
8517 if (ncells > 10000) scale /= 5;
8518 ltest = kTRUE;
8519 }
8520 }
8521 if (fH->GetMinimumStored() == -1111) {
8523 if (Hoption.MinimumZero) {
8524 if (zmin >= 0) zmin = 0;
8525 else zmin -= yMARGIN*(zmax-zmin);
8526 } else {
8527 Double_t dzmin = yMARGIN*(zmax-zmin);
8528 if (zmin >= 0 && (zmin-dzmin <= 0)) zmin = 0;
8529 else zmin -= dzmin;
8530 }
8531 }
8532
8533 TString opt = option;
8534 opt.ToLower();
8535 if (opt.Contains("scat=")) {
8536 char optscat[100];
8537 strlcpy(optscat,opt.Data(),100);
8538 char *oscat = strstr(optscat,"scat=");
8539 char *blank = strstr(oscat," "); if (blank) *blank = 0;
8540 sscanf(oscat+5,"%lg",&scale);
8541 }
8542 // use an independent instance of a random generator
8543 // instead of gRandom to avoid conflicts and
8544 // to get same random numbers when drawing the same histogram
8546 marker=0;
8547 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
8550 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
8551 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
8552 xk = fXaxis->GetBinLowEdge(i);
8553 xstep = fXaxis->GetBinWidth(i);
8554 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
8555 z = fH->GetBinContent(bin);
8556 if (z < zmin) z = zmin;
8557 if (z > zmax) z = zmax;
8558 if (Hoption.Logz) {
8559 if (z > 0) z = TMath::Log10(z) - zmin;
8560 } else {
8561 z -= zmin;
8562 }
8563 if (z <= 0) continue;
8564 k = Int_t(z*scale);
8565 if (ltest) k++;
8566 if (k > 0) {
8567 for (Int_t loop=0; loop<k; loop++) {
8568 if (k+marker >= kNMAX) {
8569 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
8570 marker=0;
8571 }
8572 fXbuf[marker] = (random.Rndm()*xstep) + xk;
8573 fYbuf[marker] = (random.Rndm()*ystep) + yk;
8574 if (Hoption.Logx) {
8575 if (fXbuf[marker] > 0) fXbuf[marker] = TMath::Log10(fXbuf[marker]);
8576 else break;
8577 }
8578 if (Hoption.Logy) {
8579 if (fYbuf[marker] > 0) fYbuf[marker] = TMath::Log10(fYbuf[marker]);
8580 else break;
8581 }
8582 if (fXbuf[marker] < gPad->GetUxmin()) break;
8583 if (fYbuf[marker] < gPad->GetUymin()) break;
8584 if (fXbuf[marker] > gPad->GetUxmax()) break;
8585 if (fYbuf[marker] > gPad->GetUymax()) break;
8586 marker++;
8587 }
8588 }
8589 }
8590 }
8591 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
8592
8594}
8595
8596////////////////////////////////////////////////////////////////////////////////
8597/// Static function to paint special objects like vectors and matrices.
8598/// This function is called via `gROOT->ProcessLine` to paint these objects
8599/// without having a direct dependency of the graphics or histogramming
8600/// system.
8601
8603{
8604
8605 if (!obj) return;
8608
8609 if (obj->InheritsFrom(TMatrixFBase::Class())) {
8610 // case TMatrixF
8611 TH2F *R__TMatrixFBase = new TH2F((TMatrixFBase &)*obj);
8612 R__TMatrixFBase->SetBit(kCanDelete);
8613 R__TMatrixFBase->Draw(option);
8614
8615 } else if (obj->InheritsFrom(TMatrixDBase::Class())) {
8616 // case TMatrixD
8617 TH2D *R__TMatrixDBase = new TH2D((TMatrixDBase &)*obj);
8618 R__TMatrixDBase->SetBit(kCanDelete);
8619 R__TMatrixDBase->Draw(option);
8620
8621 } else if (obj->InheritsFrom(TVectorF::Class())) {
8622 //case TVectorF
8623 TH1F *R__TVectorF = new TH1F((TVectorF &)*obj);
8624 R__TVectorF->SetBit(kCanDelete);
8625 R__TVectorF->Draw(option);
8626
8627 } else if (obj->InheritsFrom(TVectorD::Class())) {
8628 //case TVectorD
8629 TH1D *R__TVectorD = new TH1D((TVectorD &)*obj);
8630 R__TVectorD->SetBit(kCanDelete);
8631 R__TVectorD->Draw(option);
8632 }
8633
8634 TH1::AddDirectory(status);
8635}
8636
8637////////////////////////////////////////////////////////////////////////////////
8638/// [Draw the statistics box for 1D and profile histograms.](\ref HP07)
8639
8641{
8642 TString tt, tf;
8643 Int_t dofit;
8644 TPaveStats *stats = nullptr;
8645 TIter next(fFunctions);
8646 while (auto obj = next()) {
8647 if (obj->InheritsFrom(TPaveStats::Class())) {
8648 stats = (TPaveStats*)obj;
8649 break;
8650 }
8651 }
8652
8653 if (stats && dostat) {
8654 dofit = stats->GetOptFit();
8655 dostat = stats->GetOptStat();
8656 } else {
8657 dofit = gStyle->GetOptFit();
8658 }
8659 if (!dofit) fit = nullptr;
8660 if (dofit == 1) dofit = 111;
8661 if (dostat == 1) dostat = 1111;
8662 Int_t print_name = dostat%10;
8663 Int_t print_entries = (dostat/10)%10;
8664 Int_t print_mean = (dostat/100)%10;
8665 Int_t print_stddev = (dostat/1000)%10;
8666 Int_t print_under = (dostat/10000)%10;
8667 Int_t print_over = (dostat/100000)%10;
8668 Int_t print_integral= (dostat/1000000)%10;
8669 Int_t print_skew = (dostat/10000000)%10;
8670 Int_t print_kurt = (dostat/100000000)%10;
8674 Int_t print_fval = dofit%10;
8675 Int_t print_ferrors = (dofit/10)%10;
8676 Int_t print_fchi2 = (dofit/100)%10;
8677 Int_t print_fprob = (dofit/1000)%10;
8679 if (fit) {
8680 if (print_fval < 2) nlinesf += fit->GetNumberFreeParameters();
8681 else nlinesf += fit->GetNpar();
8682 }
8684
8685 // Pavetext with statistics
8686 Bool_t done = kFALSE;
8687 if (!dostat && !fit) {
8688 if (stats) { fFunctions->Remove(stats); delete stats;}
8689 return;
8690 }
8692 if (fit) statw = 1.8*gStyle->GetStatW();
8694 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
8695 stath = 0.25*(nlines+nlinesf)*gStyle->GetStatH();
8696 }
8697 if (stats) {
8698 stats->Clear();
8699 done = kTRUE;
8700 } else {
8701 stats = new TPaveStats(
8704 gStyle->GetStatX(),
8705 gStyle->GetStatY(),"brNDC");
8706
8707 stats->SetParent(fH);
8708 stats->SetOptFit(dofit);
8709 stats->SetOptStat(dostat);
8710 stats->SetFillColor(gStyle->GetStatColor());
8711 stats->SetFillStyle(gStyle->GetStatStyle());
8712 stats->SetBorderSize(gStyle->GetStatBorderSize());
8713 stats->SetTextFont(gStyle->GetStatFont());
8714 if (gStyle->GetStatFont()%10 > 2)
8715 stats->SetTextSize(gStyle->GetStatFontSize());
8716 stats->SetFitFormat(gStyle->GetFitFormat());
8717 stats->SetStatFormat(gStyle->GetStatFormat());
8718 stats->SetName("stats");
8719
8720 stats->SetTextColor(gStyle->GetStatTextColor());
8721 stats->SetTextAlign(12);
8722 stats->SetBit(kCanDelete);
8723 stats->SetBit(kMustCleanup);
8724 }
8725 if (print_name) stats->AddText(fH->GetName());
8726 if (print_entries) {
8727 if (fH->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(fH->GetEntries()+0.5));
8728 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(fH->GetEntries()));
8729 stats->AddText(tt.Data());
8730 }
8731 if (print_mean) {
8732 if (print_mean == 1) {
8733 tf.Form("%s = %s%s",gStringMean.Data(),"%",stats->GetStatFormat());
8734 tt.Form(tf.Data(),fH->GetMean(1));
8735 } else {
8736 tf.Form("%s = %s%s #pm %s%s",gStringMean.Data(),"%",stats->GetStatFormat()
8737 ,"%",stats->GetStatFormat());
8738 tt.Form(tf.Data(),fH->GetMean(1),fH->GetMeanError(1));
8739 }
8740 stats->AddText(tt.Data());
8742 if (print_mean == 1) {
8743 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
8744 tt.Form(tf.Data(),fH->GetMean(2));
8745 } else {
8746 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
8747 ,"%",stats->GetStatFormat());
8748 tt.Form(tf.Data(),fH->GetMean(2),fH->GetMeanError(2));
8749 }
8750 stats->AddText(tt.Data());
8751 }
8752 }
8753 if (print_stddev) {
8754 if (print_stddev == 1) {
8755 tf.Form("%s = %s%s",gStringStdDev.Data(),"%",stats->GetStatFormat());
8756 tt.Form(tf.Data(),fH->GetStdDev(1));
8757 } else {
8758 tf.Form("%s = %s%s #pm %s%s",gStringStdDev.Data(),"%",stats->GetStatFormat()
8759 ,"%",stats->GetStatFormat());
8760 tt.Form(tf.Data(),fH->GetStdDev(1),fH->GetStdDevError(1));
8761 }
8762 stats->AddText(tt.Data());
8764 if (print_stddev == 1) {
8765 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
8766 tt.Form(tf.Data(),fH->GetStdDev(2));
8767 } else {
8768 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
8769 ,"%",stats->GetStatFormat());
8770 tt.Form(tf.Data(),fH->GetStdDev(2),fH->GetStdDevError(2));
8771 }
8772 stats->AddText(tt.Data());
8773 }
8774 }
8775 if (print_under) {
8776 tf.Form("%s = %s%s",gStringUnderflow.Data(),"%",stats->GetStatFormat());
8777 tt.Form(tf.Data(),fH->GetBinContent(0));
8778 stats->AddText(tt.Data());
8779 }
8780 if (print_over) {
8781 tf.Form("%s = %s%s",gStringOverflow.Data(),"%",stats->GetStatFormat());
8782 tt.Form(tf.Data(),fH->GetBinContent(fXaxis->GetNbins()+1));
8783 stats->AddText(tt.Data());
8784 }
8785 if (print_integral) {
8786 if (print_integral == 1) {
8787 tf.Form("%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
8788 tt.Form(tf.Data(),fH->Integral());
8789 } else {
8790 tf.Form("%s = %s%s",gStringIntegralBinWidth.Data(),"%",stats->GetStatFormat());
8791 tt.Form(tf.Data(),fH->Integral("width"));
8792 }
8793 stats->AddText(tt.Data());
8794 }
8795 if (print_skew) {
8796 if (print_skew == 1) {
8797 tf.Form("%s = %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat());
8798 tt.Form(tf.Data(),fH->GetSkewness(1));
8799 } else {
8800 tf.Form("%s = %s%s #pm %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat()
8801 ,"%",stats->GetStatFormat());
8802 tt.Form(tf.Data(),fH->GetSkewness(1),fH->GetSkewness(11));
8803 }
8804 stats->AddText(tt.Data());
8805 }
8806 if (print_kurt) {
8807 if (print_kurt == 1) {
8808 tf.Form("%s = %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat());
8809 tt.Form(tf.Data(),fH->GetKurtosis(1));
8810 } else {
8811 tf.Form("%s = %s%s #pm %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat()
8812 ,"%",stats->GetStatFormat());
8813 tt.Form(tf.Data(),fH->GetKurtosis(1),fH->GetKurtosis(11));
8814 }
8815 stats->AddText(tt.Data());
8816 }
8817
8818 // Draw Fit parameters
8819 if (fit) {
8820 Int_t ndf = fit->GetNDF();
8821 tf.Form("#chi^{2} / ndf = %s%s / %d","%",stats->GetFitFormat(),ndf);
8822 tt.Form(tf.Data(),fit->GetChisquare());
8823 if (print_fchi2) stats->AddText(tt.Data());
8824 if (print_fprob) {
8825 tf.Form("Prob = %s%s","%",stats->GetFitFormat());
8826 tt.Form(tf.Data(),TMath::Prob(fit->GetChisquare(),ndf));
8827 stats->AddText(tt.Data());
8828 }
8829 if (print_fval || print_ferrors) {
8831 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
8832 fit->GetParLimits(ipar,parmin,parmax);
8834 if (print_ferrors) {
8835 tf.Form("%-8s = %s%s #pm %s ", fit->GetParName(ipar), "%",stats->GetFitFormat(),
8836 GetBestFormat(fit->GetParameter(ipar), fit->GetParError(ipar), stats->GetFitFormat()));
8837 tt.Form(tf.Data(),fit->GetParameter(ipar)
8838 ,fit->GetParError(ipar));
8839 } else {
8840 tf.Form("%-8s = %s%s ",fit->GetParName(ipar), "%",stats->GetFitFormat());
8841 tt.Form(tf.Data(),fit->GetParameter(ipar));
8842 }
8843 stats->AddText(tt.Data());
8844 }
8845 }
8846 }
8847
8848 if (!done) fFunctions->Add(stats);
8849 stats->Paint(stats->GetOption());
8850}
8851
8852////////////////////////////////////////////////////////////////////////////////
8853/// [Draw the statistics box for 2D histograms.](\ref HP07)
8854
8856{
8857
8858 if (fH->GetDimension() != 2) return;
8859 TH2 *h2 = (TH2*)fH;
8860
8861 TString tt, tf;
8862 Int_t dofit;
8863 TPaveStats *stats = nullptr;
8864 TIter next(fFunctions);
8865 while (auto obj = next()) {
8866 if (obj->InheritsFrom(TPaveStats::Class())) {
8867 stats = (TPaveStats*)obj;
8868 break;
8869 }
8870 }
8871 if (stats && dostat) {
8872 dofit = stats->GetOptFit();
8873 dostat = stats->GetOptStat();
8874 } else {
8875 dofit = gStyle->GetOptFit();
8876 }
8877 if (dostat == 1) dostat = 1111;
8878 Int_t print_name = dostat%10;
8879 Int_t print_entries = (dostat/10)%10;
8880 Int_t print_mean = (dostat/100)%10;
8881 Int_t print_stddev = (dostat/1000)%10;
8882 Int_t print_under = (dostat/10000)%10;
8883 Int_t print_over = (dostat/100000)%10;
8884 Int_t print_integral= (dostat/1000000)%10;
8885 Int_t print_skew = (dostat/10000000)%10;
8886 Int_t print_kurt = (dostat/100000000)%10;
8888 if (print_under || print_over) nlines += 3;
8889
8890 // Pavetext with statistics
8891 if (!gStyle->GetOptFit()) fit = nullptr;
8892 Bool_t done = kFALSE;
8893 if (!dostat && !fit) {
8894 if (stats) { fFunctions->Remove(stats); delete stats;}
8895 return;
8896 }
8898 if (fit) statw = 1.8*gStyle->GetStatW();
8900 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
8901 stath = 0.25*nlines*gStyle->GetStatH();
8902 }
8903 if (fit) stath += gStyle->GetStatH();
8904 if (stats) {
8905 stats->Clear();
8906 done = kTRUE;
8907 } else {
8908 stats = new TPaveStats(
8911 gStyle->GetStatX(),
8912 gStyle->GetStatY(),"brNDC");
8913
8914 stats->SetParent(fH);
8915 stats->SetOptFit(dofit);
8916 stats->SetOptStat(dostat);
8917 stats->SetFillColor(gStyle->GetStatColor());
8918 stats->SetFillStyle(gStyle->GetStatStyle());
8919 stats->SetBorderSize(gStyle->GetStatBorderSize());
8920 stats->SetName("stats");
8921
8922 stats->SetTextColor(gStyle->GetStatTextColor());
8923 stats->SetTextAlign(12);
8924 stats->SetTextFont(gStyle->GetStatFont());
8925 if (gStyle->GetStatFont()%10 > 2)
8926 stats->SetTextSize(gStyle->GetStatFontSize());
8927 stats->SetFitFormat(gStyle->GetFitFormat());
8928 stats->SetStatFormat(gStyle->GetStatFormat());
8929 stats->SetBit(kCanDelete);
8930 stats->SetBit(kMustCleanup);
8931 }
8932 if (print_name) stats->AddText(h2->GetName());
8933 if (print_entries) {
8934 if (h2->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(h2->GetEntries()+0.5));
8935 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(h2->GetEntries()));
8936 stats->AddText(tt.Data());
8937 }
8938 if (print_mean) {
8939 if (print_mean == 1) {
8940 tf.Form("%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
8941 tt.Form(tf.Data(),h2->GetMean(1));
8942 stats->AddText(tt.Data());
8943 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
8944 tt.Form(tf.Data(),h2->GetMean(2));
8945 stats->AddText(tt.Data());
8946 } else {
8947 tf.Form("%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
8948 ,"%",stats->GetStatFormat());
8949 tt.Form(tf.Data(),h2->GetMean(1),h2->GetMeanError(1));
8950 stats->AddText(tt.Data());
8951 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
8952 ,"%",stats->GetStatFormat());
8953 tt.Form(tf.Data(),h2->GetMean(2),h2->GetMeanError(2));
8954 stats->AddText(tt.Data());
8955 }
8956 }
8957 if (print_stddev) {
8958 if (print_stddev == 1) {
8959 tf.Form("%s = %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat());
8960 tt.Form(tf.Data(),h2->GetStdDev(1));
8961 stats->AddText(tt.Data());
8962 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
8963 tt.Form(tf.Data(),h2->GetStdDev(2));
8964 stats->AddText(tt.Data());
8965 } else {
8966 tf.Form("%s = %s%s #pm %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat()
8967 ,"%",stats->GetStatFormat());
8968 tt.Form(tf.Data(),h2->GetStdDev(1),h2->GetStdDevError(1));
8969 stats->AddText(tt.Data());
8970 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
8971 ,"%",stats->GetStatFormat());
8972 tt.Form(tf.Data(),h2->GetStdDev(2),h2->GetStdDevError(2));
8973 stats->AddText(tt.Data());
8974 }
8975 }
8976 if (print_integral) {
8977 tf.Form("%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
8978 tt.Form(tf.Data(),fH->Integral());
8979 stats->AddText(tt.Data());
8980 }
8981 if (print_skew) {
8982 if (print_skew == 1) {
8983 tf.Form("%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
8984 tt.Form(tf.Data(),h2->GetSkewness(1));
8985 stats->AddText(tt.Data());
8986 tf.Form("%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
8987 tt.Form(tf.Data(),h2->GetSkewness(2));
8988 stats->AddText(tt.Data());
8989 } else {
8990 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
8991 ,"%",stats->GetStatFormat());
8992 tt.Form(tf.Data(),h2->GetSkewness(1),h2->GetSkewness(11));
8993 stats->AddText(tt.Data());
8994 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
8995 ,"%",stats->GetStatFormat());
8996 tt.Form(tf.Data(),h2->GetSkewness(2),h2->GetSkewness(12));
8997 stats->AddText(tt.Data());
8998 }
8999 }
9000 if (print_kurt) {
9001 if (print_kurt == 1) {
9002 tf.Form("%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
9003 tt.Form(tf.Data(),h2->GetKurtosis(1));
9004 stats->AddText(tt.Data());
9005 tf.Form("%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
9006 tt.Form(tf.Data(),h2->GetKurtosis(2));
9007 stats->AddText(tt.Data());
9008 } else {
9009 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
9010 ,"%",stats->GetStatFormat());
9011 tt.Form(tf.Data(),h2->GetKurtosis(1),h2->GetKurtosis(11));
9012 stats->AddText(tt.Data());
9013 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
9014 ,"%",stats->GetStatFormat());
9015 tt.Form(tf.Data(),h2->GetKurtosis(2),h2->GetKurtosis(12));
9016 stats->AddText(tt.Data());
9017 }
9018 }
9019 if (print_under || print_over) {
9020 //get 3*3 under/overflows for 2d hist
9021 Double_t unov[9];
9022
9023 Int_t cellsX = h2->GetXaxis()->GetNbins() + 1;
9024 Int_t cellsY = h2->GetYaxis()->GetNbins() + 1;
9025 Int_t firstX = std::max(1, h2->GetXaxis()->GetFirst());
9026 Int_t firstY = std::max(1, h2->GetYaxis()->GetFirst());
9027 Int_t lastX = std::min(h2->GetXaxis()->GetLast(), h2->GetXaxis()->GetNbins());
9028 Int_t lastY = std::min(h2->GetYaxis()->GetLast(), h2->GetYaxis()->GetNbins());
9029
9030 unov[0] = h2->Integral( 0, firstX-1, lastY+1, cellsY );
9031 unov[1] = h2->Integral(firstX , lastX , lastY+1, cellsY );
9032 unov[2] = h2->Integral(lastX+1, cellsX , lastY+1, cellsY );
9033 unov[3] = h2->Integral( 0, firstX-1, firstY , lastY );
9034 unov[4] = h2->Integral(firstX , lastX , firstY , lastY );
9035 unov[5] = h2->Integral(lastX+1, cellsX , firstY , lastY );
9036 unov[6] = h2->Integral( 0, firstX-1, 0, firstY-1);
9037 unov[7] = h2->Integral(firstX, lastX, 0, firstY-1);
9038 unov[8] = h2->Integral(lastX+1, cellsX , 0, firstY-1);
9039
9040 tt.Form("%g|%g|%g\n", unov[0], unov[1], unov[2]);
9041 stats->AddText(tt.Data());
9042 tt.Form("%g|%g|%g\n", unov[3], unov[4], unov[5]);
9043 stats->AddText(tt.Data());
9044 tt.Form("%g|%g|%g\n", unov[6], unov[7], unov[8]);
9045 stats->AddText(tt.Data());
9046 }
9047
9048 // Draw Fit parameters
9049 if (fit) {
9050 Int_t ndf = fit->GetNDF();
9051 tt.Form("#chi^{2} / ndf = %6.4g / %d",fit->GetChisquare(),ndf);
9052 stats->AddText(tt.Data());
9053 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
9054 tt.Form("%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
9055 ,fit->GetParameter(ipar)
9056 ,fit->GetParError(ipar));
9057 stats->AddText(tt.Data());
9058 }
9059 }
9060
9061 if (!done) fFunctions->Add(stats);
9062 stats->Paint(stats->GetOption());
9063}
9064
9065////////////////////////////////////////////////////////////////////////////////
9066/// [Draw the statistics box for 3D histograms.](\ref HP07)
9067
9069{
9070
9071 if (fH->GetDimension() != 3) return;
9072 TH3 *h3 = (TH3*)fH;
9073
9074 TString tt, tf;
9075 Int_t dofit;
9076 TPaveStats *stats = nullptr;
9077 TIter next(fFunctions);
9078 while (auto obj = next()) {
9079 if (obj->InheritsFrom(TPaveStats::Class())) {
9080 stats = (TPaveStats*)obj;
9081 break;
9082 }
9083 }
9084 if (stats && dostat) {
9085 dofit = stats->GetOptFit();
9086 dostat = stats->GetOptStat();
9087 } else {
9088 dofit = gStyle->GetOptFit();
9089 }
9090 if (dostat == 1) dostat = 1111;
9091 Int_t print_name = dostat%10;
9092 Int_t print_entries = (dostat/10)%10;
9093 Int_t print_mean = (dostat/100)%10;
9094 Int_t print_stddev = (dostat/1000)%10;
9095 Int_t print_under = (dostat/10000)%10;
9096 Int_t print_over = (dostat/100000)%10;
9097 Int_t print_integral= (dostat/1000000)%10;
9098 Int_t print_skew = (dostat/10000000)%10;
9099 Int_t print_kurt = (dostat/100000000)%10;
9101 if (print_under || print_over) nlines += 3;
9102
9103 // Pavetext with statistics
9104 if (!gStyle->GetOptFit()) fit = nullptr;
9105 Bool_t done = kFALSE;
9106 if (!dostat && !fit) {
9107 if (stats) { fFunctions->Remove(stats); delete stats;}
9108 return;
9109 }
9111 if (fit) statw = 1.8*gStyle->GetStatW();
9113 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
9114 stath = 0.25*nlines*gStyle->GetStatH();
9115 }
9116 if (fit) stath += gStyle->GetStatH();
9117 if (stats) {
9118 stats->Clear();
9119 done = kTRUE;
9120 } else {
9121 stats = new TPaveStats(
9124 gStyle->GetStatX(),
9125 gStyle->GetStatY(),"brNDC");
9126
9127 stats->SetParent(fH);
9128 stats->SetOptFit(dofit);
9129 stats->SetOptStat(dostat);
9130 stats->SetFillColor(gStyle->GetStatColor());
9131 stats->SetFillStyle(gStyle->GetStatStyle());
9132 stats->SetBorderSize(gStyle->GetStatBorderSize());
9133 stats->SetName("stats");
9134
9135 stats->SetTextColor(gStyle->GetStatTextColor());
9136 stats->SetTextAlign(12);
9137 stats->SetTextFont(gStyle->GetStatFont());
9138 stats->SetFitFormat(gStyle->GetFitFormat());
9139 stats->SetStatFormat(gStyle->GetStatFormat());
9140 stats->SetBit(kCanDelete);
9141 stats->SetBit(kMustCleanup);
9142 }
9143 if (print_name) stats->AddText(h3->GetName());
9144 if (print_entries) {
9145 if (h3->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(h3->GetEntries()+0.5));
9146 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(h3->GetEntries()+0.5));
9147 stats->AddText(tt.Data());
9148 }
9149 if (print_mean) {
9150 if (print_mean == 1) {
9151 tf.Form("%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
9152 tt.Form(tf.Data(),h3->GetMean(1));
9153 stats->AddText(tt.Data());
9154 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
9155 tt.Form(tf.Data(),h3->GetMean(2));
9156 stats->AddText(tt.Data());
9157 tf.Form("%s = %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat());
9158 tt.Form(tf.Data(),h3->GetMean(3));
9159 stats->AddText(tt.Data());
9160 } else {
9161 tf.Form("%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
9162 ,"%",stats->GetStatFormat());
9163 tt.Form(tf.Data(),h3->GetMean(1),h3->GetMeanError(1));
9164 stats->AddText(tt.Data());
9165 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
9166 ,"%",stats->GetStatFormat());
9167 tt.Form(tf.Data(),h3->GetMean(2),h3->GetMeanError(2));
9168 stats->AddText(tt.Data());
9169 tf.Form("%s = %s%s #pm %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat()
9170 ,"%",stats->GetStatFormat());
9171 tt.Form(tf.Data(),h3->GetMean(3),h3->GetMeanError(3));
9172 stats->AddText(tt.Data());
9173 }
9174 }
9175 if (print_stddev) {
9176 if (print_stddev == 1) {
9177 tf.Form("%s = %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat());
9178 tt.Form(tf.Data(),h3->GetStdDev(1));
9179 stats->AddText(tt.Data());
9180 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
9181 tt.Form(tf.Data(),h3->GetStdDev(2));
9182 stats->AddText(tt.Data());
9183 tf.Form("%s = %s%s",gStringStdDevZ.Data(),"%",stats->GetStatFormat());
9184 tt.Form(tf.Data(),h3->GetStdDev(3));
9185 stats->AddText(tt.Data());
9186 } else {
9187 tf.Form("%s = %s%s #pm %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat()
9188 ,"%",stats->GetStatFormat());
9189 tt.Form(tf.Data(),h3->GetStdDev(1),h3->GetStdDevError(1));
9190 stats->AddText(tt.Data());
9191 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
9192 ,"%",stats->GetStatFormat());
9193 tt.Form(tf.Data(),h3->GetStdDev(2),h3->GetStdDevError(2));
9194 stats->AddText(tt.Data());
9195 tf.Form("%s = %s%s #pm %s%s",gStringStdDevZ.Data(),"%",stats->GetStatFormat()
9196 ,"%",stats->GetStatFormat());
9197 tt.Form(tf.Data(),h3->GetStdDev(3),h3->GetStdDevError(3));
9198 stats->AddText(tt.Data());
9199 }
9200 }
9201 if (print_integral) {
9202 tt.Form("%s = %6.4g",gStringIntegral.Data(),h3->Integral());
9203 stats->AddText(tt.Data());
9204 }
9205 if (print_skew) {
9206 if (print_skew == 1) {
9207 tf.Form("%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
9208 tt.Form(tf.Data(),h3->GetSkewness(1));
9209 stats->AddText(tt.Data());
9210 tf.Form("%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
9211 tt.Form(tf.Data(),h3->GetSkewness(2));
9212 stats->AddText(tt.Data());
9213 tf.Form("%s = %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat());
9214 tt.Form(tf.Data(),h3->GetSkewness(3));
9215 stats->AddText(tt.Data());
9216 } else {
9217 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
9218 ,"%",stats->GetStatFormat());
9219 tt.Form(tf.Data(),h3->GetSkewness(1),h3->GetSkewness(11));
9220 stats->AddText(tt.Data());
9221 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
9222 ,"%",stats->GetStatFormat());
9223 tt.Form(tf.Data(),h3->GetSkewness(2),h3->GetSkewness(12));
9224 stats->AddText(tt.Data());
9225 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat()
9226 ,"%",stats->GetStatFormat());
9227 tt.Form(tf.Data(),h3->GetSkewness(3),h3->GetSkewness(13));
9228 stats->AddText(tt.Data());
9229 }
9230 }
9231 if (print_kurt) {
9232 if (print_kurt == 1) {
9233 tf.Form("%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
9234 tt.Form(tf.Data(),h3->GetKurtosis(1));
9235 stats->AddText(tt.Data());
9236 tf.Form("%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
9237 tt.Form(tf.Data(),h3->GetKurtosis(2));
9238 stats->AddText(tt.Data());
9239 tf.Form("%s = %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat());
9240 tt.Form(tf.Data(),h3->GetKurtosis(3));
9241 stats->AddText(tt.Data());
9242 } else {
9243 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
9244 ,"%",stats->GetStatFormat());
9245 tt.Form(tf.Data(),h3->GetKurtosis(1),h3->GetKurtosis(11));
9246 stats->AddText(tt.Data());
9247 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
9248 ,"%",stats->GetStatFormat());
9249 tt.Form(tf.Data(),h3->GetKurtosis(2),h3->GetKurtosis(12));
9250 stats->AddText(tt.Data());
9251 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat()
9252 ,"%",stats->GetStatFormat());
9253 tt.Form(tf.Data(),h3->GetKurtosis(3),h3->GetKurtosis(13));
9254 stats->AddText(tt.Data());
9255 }
9256 }
9257 if (print_under || print_over) {
9258 // no underflow - overflow printing for a 3D histogram
9259 // one would need a 3D table
9260 }
9261
9262 // Draw Fit parameters
9263 if (fit) {
9264 Int_t ndf = fit->GetNDF();
9265 tt.Form("#chi^{2} / ndf = %6.4g / %d",fit->GetChisquare(),ndf);
9266 stats->AddText(tt.Data());
9267 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
9268 tt.Form("%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
9269 ,fit->GetParameter(ipar)
9270 ,fit->GetParError(ipar));
9271 stats->AddText(tt.Data());
9272 }
9273 }
9274
9275 if (!done) fFunctions->Add(stats);
9276 stats->Paint(stats->GetOption());
9277}
9278
9279////////////////////////////////////////////////////////////////////////////////
9280/// [Control function to draw a 2D histogram as a surface plot.](\ref HP18)
9281
9283{
9284
9285 const Double_t ydiff = 1;
9286 const Double_t yligh1 = 10;
9287 const Double_t qa = 0.15;
9288 const Double_t qd = 0.15;
9289 const Double_t qs = 0.8;
9291 Int_t raster = 0;
9292 Int_t irep = 0;
9293
9294 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
9297 Double_t zmin = Hparam.zmin;
9298 Double_t zmax = Hparam.zmax;
9303 Double_t dangle = 10*3.141592/180; //Delta angle for Rapidity option
9304 Double_t deltaz = TMath::Abs(zmin);
9305 if (deltaz == 0) deltaz = 1;
9306 if (zmin >= zmax) {
9307 zmin -= 0.5*deltaz;
9308 zmax += 0.5*deltaz;
9309 }
9310 Double_t z1c = zmin;
9311 Double_t z2c = zmin + (zmax-zmin)*(1+gStyle->GetHistTopMargin());
9312 // Compute the lego limits and instantiate a lego object
9313 fXbuf[0] = -1;
9314 fYbuf[0] = 1;
9315 fXbuf[1] = -1;
9316 fYbuf[1] = 1;
9317 if (Hoption.System >= kPOLAR && (Hoption.Surf == 1 || Hoption.Surf == 13)) raster = 1;
9318 if (Hoption.System == kPOLAR) {
9319 fXbuf[2] = z1c;
9320 fYbuf[2] = z2c;
9321 } else if (Hoption.System == kCYLINDRICAL) {
9322 if (Hoption.Logy) {
9323 if (ylab1 > 0) fXbuf[2] = TMath::Log10(ylab1);
9324 else fXbuf[2] = 0;
9325 if (ylab2 > 0) fYbuf[2] = TMath::Log10(ylab2);
9326 else fYbuf[2] = 0;
9327 } else {
9328 fXbuf[2] = ylab1;
9329 fYbuf[2] = ylab2;
9330 }
9331 z1c = 0; z2c = 1;
9332 } else if (Hoption.System == kSPHERICAL) {
9333 fXbuf[2] = -1;
9334 fYbuf[2] = 1;
9335 z1c = 0; z2c = 1;
9336 } else if (Hoption.System == kRAPIDITY) {
9337 fXbuf[2] = -1/TMath::Tan(dangle);
9338 fYbuf[2] = 1/TMath::Tan(dangle);
9339 } else {
9340 fXbuf[0] = xlab1;
9341 fYbuf[0] = xlab2;
9342 fXbuf[1] = ylab1;
9343 fYbuf[1] = ylab2;
9344 fXbuf[2] = z1c;
9345 fYbuf[2] = z2c;
9346 }
9347
9348 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data(), Hoption.System);
9349 fLego->SetEdgeAtt(fH->GetLineColor(),fH->GetLineStyle(),fH->GetLineWidth(),0);
9350 fLego->SetFillColor(fH->GetFillColor());
9351
9352 // Initialize the levels on the Z axis
9353 Int_t ndiv = fH->GetContour();
9354 if (ndiv == 0 ) {
9355 ndiv = gStyle->GetNumberContours();
9356 fH->SetContour(ndiv);
9357 }
9358 Int_t ndivz = TMath::Abs(ndiv);
9359 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
9360
9361 if (Hoption.Surf == 13 || Hoption.Surf == 15) fLego->SetMesh(3);
9362 if (Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) fLego->SetMesh(0);
9363
9364 // Close the surface in case of non cartesian coordinates.
9365
9366 if (Hoption.System != kCARTESIAN) {nx++; ny++;}
9367
9368 // Now ready to draw the surface plot
9369
9370 TView *view = gPad ? gPad->GetView() : nullptr;
9371 if (!view) {
9372 Error("PaintSurface", "no TView in current pad");
9373 return;
9374 }
9375
9376 Double_t thedeg = 90 - gPad->GetTheta();
9377 Double_t phideg = -90 - gPad->GetPhi();
9378 Double_t psideg = view->GetPsi();
9379 view->SetView(phideg, thedeg, psideg, irep);
9380
9381 // Set color/style for back box
9382 if (Hoption.Same) {
9383 fLego->SetFillStyle(0);
9384 fLego->SetFillColor(1);
9385 } else {
9386 fLego->SetFillStyle(gPad->GetFrameFillStyle());
9387 fLego->SetFillColor(gPad->GetFrameFillColor());
9388 }
9389 fLego->TAttFill::Modify();
9390
9391 Int_t backcolor = gPad->GetFrameFillColor();
9392 if (Hoption.System != kCARTESIAN) backcolor = 0;
9393 view->PadRange(backcolor);
9394
9395 fLego->SetFillStyle(fH->GetFillStyle());
9396 fLego->SetFillColor(fH->GetFillColor());
9397 fLego->TAttFill::Modify();
9398
9399 // Draw the filled contour on top
9401
9403 if (Hoption.Surf == 13 || Hoption.Surf == 15) {
9405 Hoption.Surf = 23;
9406 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9408 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"BF");
9409 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9410 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9411 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9412 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"BF");
9414 fLego->SetMesh(1);
9415 }
9416
9417 if (raster) fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
9418 else fLego->InitMoveScreen(-1.1,1.1);
9419
9420 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) {
9421 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9424 fLego->BackBox(90);
9425 }
9426 }
9427
9428 // Gouraud Shading surface
9429 if (Hoption.Surf == 14) {
9430 // Set light sources
9431 fLego->LightSource(0, ydiff, 0,0,0,irep);
9432 fLego->LightSource(1, yligh1 ,1,1,1,irep);
9433 fLego->SurfaceProperty(qa, qd, qs, 1, irep);
9434 fmin = ydiff*qa;
9435 fmax = fmin + (yligh1+0.1)*(qd+qs);
9436 Int_t nbcol = 28;
9437 icol1 = 201;
9438 Double_t dcol = 0.5/Double_t(nbcol);
9439 TColor *colref = gROOT->GetColor(fH->GetFillColor());
9440 if (!colref) return;
9442 colref->GetRGB(r,g,b);
9444 TColor *acol;
9445 for (Int_t col=0;col<nbcol;col++) {
9446 acol = gROOT->GetColor(col+icol1);
9447 TColor::HLStoRGB(hue,.4+col*dcol,satur,r,g,b);
9448 if (acol) acol->SetRGB(r,g,b);
9449 }
9450 fLego->Spectrum(nbcol, fmin, fmax, icol1, 1, irep);
9451 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::GouraudFunction);
9453 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"BF");
9454 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9455 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9456 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9457 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"BF");
9458 } else if (Hoption.Surf == 15) {
9459 // The surface is not drawn in this case.
9460 } else {
9461 // Draw the surface
9462 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 16 || Hoption.Surf == 17) {
9464 } else {
9465 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9466 }
9467 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9468 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceRaster1);
9469 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode2);
9470 if (Hoption.System == kPOLAR) {
9471 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfacePolar(1,nx,ny,"FB");
9472 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfacePolar(1,nx,ny,"BF");
9473 } else if (Hoption.System == kCYLINDRICAL) {
9474 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceCylindrical(1,nx,ny,"FB");
9475 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9476 } else if (Hoption.System == kSPHERICAL) {
9477 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceSpherical(0,1,nx,ny,"FB");
9478 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9479 } else if (Hoption.System == kRAPIDITY) {
9480 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceSpherical(1,1,nx,ny,"FB");
9481 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9482 } else {
9483 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove1);
9484 if (Hoption.Surf == 16) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove3);
9485 if (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16) fLego->SurfaceCartesian(90,nx,ny,"FB");
9486 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCartesian(90,nx,ny,"BF");
9487 }
9488 }
9489
9490 // Paint the line contour on top for option SURF7
9491 if (Hoption.Surf == 17) {
9492 fLego->InitMoveScreen(-1.1,1.1);
9493 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9494 Hoption.Surf = 23;
9495 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9497 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"FB");
9498 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"FB");
9499 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"FB");
9500 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"FB");
9501 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"FB");
9502 }
9503
9504 if ((!Hoption.Same) &&
9505 (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16)) {
9508 fLego->BackBox(90);
9509 }
9510 }
9511 if (Hoption.System == kCARTESIAN) {
9512 fLego->InitMoveScreen(-1.1,1.1);
9514 if (Hoption.FrontBox) fLego->FrontBox(90);
9515 }
9516 if (!Hoption.Axis && !Hoption.Same) {
9517 TGaxis axis;
9518 PaintLegoAxis(&axis, 90);
9519 }
9520
9522
9523 fLego.reset();
9524}
9525
9526////////////////////////////////////////////////////////////////////////////////
9527/// Control function to draw a table using Delaunay triangles.
9528
9530{
9531
9532 TGraphDelaunay2D *dt = nullptr;
9533 TGraphDelaunay *dtOld = nullptr;
9534
9535 // Check if fH contains a TGraphDelaunay2D
9537 dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
9538 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
9539 if (!dt && !dtOld) return;
9540
9541 // If needed, create a TGraph2DPainter
9542 if (!fGraph2DPainter)
9543 fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
9544
9545 // Define the 3D view
9546 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
9547 if (Hoption.Same) {
9548 TView *viewsame = gPad ? gPad->GetView() : nullptr;
9549 if (!viewsame) {
9550 Error("PaintTriangles", "no TView in current pad, do not use option SAME");
9551 return;
9552 }
9553 Double_t *rmin = viewsame->GetRmin();
9554 Double_t *rmax = viewsame->GetRmax();
9555 if (!rmin || !rmax) return;
9556 fXbuf[0] = rmin[0];
9557 fYbuf[0] = rmax[0];
9558 fXbuf[1] = rmin[1];
9559 fYbuf[1] = rmax[1];
9560 fXbuf[2] = rmin[2];
9561 fYbuf[2] = rmax[2];
9562 fH->SetMaximum(rmax[2]);
9563 fH->SetMinimum(rmin[2]);
9564 fH->GetXaxis()->SetRangeUser(rmin[0],rmax[0]);
9565 fH->GetYaxis()->SetRangeUser(rmin[1],rmax[1]);
9566 } else {
9567 fXbuf[0] = Hparam.xmin;
9568 fYbuf[0] = Hparam.xmax;
9569 fXbuf[1] = Hparam.ymin;
9570 fYbuf[1] = Hparam.ymax;
9571 fXbuf[2] = Hparam.zmin;
9572 fYbuf[2] = Hparam.zmax;
9573 }
9574
9575 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
9576 TView *view = gPad ? gPad->GetView() : nullptr;
9577 if (!view) {
9578 Error("PaintTriangles", "no TView in current pad");
9579 return;
9580 }
9581 Double_t thedeg = 90 - gPad->GetTheta();
9582 Double_t phideg = -90 - gPad->GetPhi();
9583 Double_t psideg = view->GetPsi();
9584 Int_t irep;
9585 view->SetView(phideg, thedeg, psideg, irep);
9586
9587 // Set color/style for back box
9588 fLego->SetFillStyle(gPad->GetFrameFillStyle());
9589 fLego->SetFillColor(gPad->GetFrameFillColor());
9590 fLego->TAttFill::Modify();
9591 Int_t backcolor = gPad->GetFrameFillColor();
9592 if (Hoption.System != kCARTESIAN) backcolor = 0;
9593 view->PadRange(backcolor);
9594 fLego->SetFillStyle(fH->GetFillStyle());
9595 fLego->SetFillColor(fH->GetFillColor());
9596 fLego->TAttFill::Modify();
9597
9598 // Paint the Back Box if needed
9599 if (Hoption.BackBox && !Hoption.Same) {
9600 fLego->InitMoveScreen(-1.1,1.1);
9601 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9603 fLego->BackBox(90);
9604 }
9605
9606 // Paint the triangles
9607 fGraph2DPainter->Paint(option);
9608
9609 // Paint the Front Box if needed
9610 if (Hoption.FrontBox) {
9611 fLego->InitMoveScreen(-1.1,1.1);
9613 fLego->FrontBox(90);
9614 }
9615
9616 // Paint the Axis if needed
9617 if (!Hoption.Axis && !Hoption.Same) {
9618 TGaxis axis;
9619 PaintLegoAxis(&axis, 90);
9620 }
9621
9623
9624 fLego.reset();
9625}
9626
9627////////////////////////////////////////////////////////////////////////////////
9628/// Define the color levels used to paint legos, surfaces etc..
9629
9631{
9632
9633 Int_t i, irep;
9634
9635 // Initialize the color levels
9636 if (ndivz >= 100) {
9637 Warning("PaintSurface", "too many color levels, %d >= 100, reset to 99", ndivz);
9638 ndivz = 99;
9639 }
9640 std::vector<Double_t> funlevel(ndivz+1);
9641 std::vector<Int_t> colorlevel(ndivz+1);
9643 Int_t ncolors = gStyle->GetNumberOfColors();
9644 for (i = 0; i < ndivz; ++i) {
9646 theColor = Int_t((i+0.99)*Float_t(ncolors)/Float_t(ndivz));
9648 }
9649 colorlevel[ndivz] = gStyle->GetColorPalette(ncolors-1);
9650 fLego->ColorFunction(ndivz, funlevel.data(), colorlevel.data(), irep);
9651}
9652
9653////////////////////////////////////////////////////////////////////////////////
9654/// [Control function to draw 2D/3D histograms (tables).](\ref HP01c)
9655
9657{
9658
9659 // Fill Hparam structure with histo parameters
9660 if (!TableInit()) return;
9661
9662 // Draw histogram frame
9663 PaintFrame();
9664
9665 // If palette option not specified, delete a possible existing palette
9666 if (!Hoption.Zscale) {
9667 TObject *palette = fFunctions->FindObject("palette");
9668 if (palette) { fFunctions->Remove(palette); delete palette;}
9669 }
9670
9671 // Do not draw the histogram. Only the attached functions will be drawn.
9672 if (Hoption.Func == 2) {
9673 if (Hoption.Zscale) {
9674 Int_t ndiv = fH->GetContour();
9675 if (ndiv == 0 ) {
9676 ndiv = gStyle->GetNumberContours();
9677 fH->SetContour(ndiv);
9678 }
9679 PaintPalette();
9680 }
9681
9682 // Draw the histogram according to the option
9683 } else {
9684 if (fH->InheritsFrom(TH2Poly::Class()) && Hoption.Axis<=0) {
9685 if (Hoption.Fill) PaintTH2PolyBins("f");
9689 if (Hoption.Line) PaintTH2PolyBins("l");
9690 if (Hoption.Mark) PaintTH2PolyBins("P");
9691 } else if (Hoption.Axis<=0) {
9695 if (Hoption.Color) {
9698 }
9701 if (Hoption.Error >= 100) Paint2DErrors(option);
9703 }
9707 }
9708
9709 // Draw histogram title
9710 PaintTitle();
9711
9712 // Draw the axes
9713 if (!Hoption.Lego && !Hoption.Surf &&
9714 !Hoption.Tri && !(Hoption.Error >= 100)) PaintAxis(kFALSE);
9715
9716 TF1 *fit = nullptr;
9717 TIter next(fFunctions);
9718 while (auto obj = next()) {
9719 if (obj->InheritsFrom(TF1::Class())) {
9720 fit = (TF1*)obj;
9721 break;
9722 }
9723 }
9724 if ((Hoption.Same%10) != 1) {
9725 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
9726 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
9727 //ALWAYS executed on non-iOS platform.
9728 //On iOS, depends on mode.
9730 }
9731 }
9732 }
9733}
9734
9735////////////////////////////////////////////////////////////////////////////////
9736/// Control function to draw a TH2Poly bins' contours.
9737///
9738/// - option = "F" draw the bins as filled areas.
9739/// - option = "L" draw the bins as line.
9740/// - option = "P" draw the bins as markers.
9741
9743{
9744
9745 //Do not highlight the histogram, if its part was picked.
9746 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH) return;
9747
9748 TString opt = option;
9749 opt.ToLower();
9750 Bool_t line = kFALSE;
9751 Bool_t fill = kFALSE;
9752 Bool_t mark = kFALSE;
9753 if (opt.Contains("l")) line = kTRUE;
9754 if (opt.Contains("f")) fill = kTRUE;
9755 if (opt.Contains("p")) mark = kTRUE;
9756
9757 TH2PolyBin *b;
9758 Double_t z;
9759
9760 TIter next(((TH2Poly*)fH)->GetBins());
9761 TObject *obj, *poly;
9762
9763 while ((obj=next())) {
9764 b = (TH2PolyBin*)obj;
9765 z = b->GetContent();
9766 if (z==0 && Hoption.Zero) continue; // Do not draw empty bins in case of option "COL0 L"
9767 poly = b->GetPolygon();
9768
9769 // Paint the TGraph bins.
9770 if (poly->IsA() == TGraph::Class()) {
9771 TGraph *g = (TGraph*)poly;
9772 g->TAttLine::Modify();
9773 g->TAttMarker::Modify();
9774 g->TAttFill::Modify();
9775 if (line) {
9776 Int_t fs = g->GetFillStyle();
9778 g->SetFillStyle(0);
9780 g->Paint("F");
9782 g->SetFillStyle(fs);
9783 }
9784 if (fill) g->Paint("F");
9785 if (mark) g->Paint("P");
9786 }
9787
9788 // Paint the TMultiGraph bins.
9789 if (poly->IsA() == TMultiGraph::Class()) {
9791 TList *gl = mg->GetListOfGraphs();
9792 if (!gl) return;
9793 TGraph *g;
9794 TIter nextg(gl);
9795 while ((g = (TGraph*) nextg())) {
9796 g->TAttLine::Modify();
9797 g->TAttMarker::Modify();
9798 g->TAttFill::Modify();
9799 if (line) {
9800 Int_t fs = g->GetFillStyle();
9802 g->SetFillStyle(0);
9804 g->Paint("F");
9806 g->SetFillStyle(fs);
9807 }
9808 if (fill) g->Paint("F");
9809 if (mark) g->Paint("P");
9810 }
9811 }
9812 }
9813}
9814
9815////////////////////////////////////////////////////////////////////////////////
9816/// [Control function to draw a TH2Poly as a color plot.](\ref HP20a)
9817
9819{
9820
9821 //Do not highlight the histogram, if its part was picked.
9822 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
9823 return;
9824
9825 Int_t ncolors, color, theColor;
9826 Double_t z, zc;
9827 Double_t zmin = fH->GetMinimum();
9828 Double_t zmax = fH->GetMaximum();
9829 if (Hoption.Logz) {
9830 if (zmax > 0) {
9831 if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
9832 zmin = TMath::Log10(zmin);
9833 zmax = TMath::Log10(zmax);
9834 } else {
9835 return;
9836 }
9837 }
9838 Double_t dz = zmax - zmin;
9839
9840 // Initialize the levels on the Z axis
9841 ncolors = gStyle->GetNumberOfColors();
9842 Int_t ndiv = fH->GetContour();
9843 if (ndiv == 0 ) {
9844 ndiv = gStyle->GetNumberContours();
9845 fH->SetContour(ndiv);
9846 }
9847 Int_t ndivz = TMath::Abs(ndiv);
9848 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
9850
9851 TIter next(((TH2Poly*)fH)->GetBins());
9852
9853 while (auto obj = next()) {
9854 TH2PolyBin *b = (TH2PolyBin*)obj;
9855 TObject *poly = b->GetPolygon();
9856
9857 z = b->GetContent();
9858 if (z==0 && Hoption.Zero) continue;
9859 if (Hoption.Logz) {
9860 if (z > 0) z = TMath::Log10(z);
9861 else z = zmin;
9862 }
9863 if (z < zmin) continue;
9864
9865 // Define the bin color.
9867 zc = fH->GetContourLevelPad(0);
9868 if (z < zc) continue;
9869 color = -1;
9870 for (Int_t k=0; k<ndiv; k++) {
9871 zc = fH->GetContourLevelPad(k);
9872 if (z < zc) {
9873 continue;
9874 } else {
9875 color++;
9876 }
9877 }
9878 } else {
9879 color = Int_t(0.01+(z-zmin)*scale);
9880 }
9881 theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
9882 if (theColor > ncolors-1) theColor = ncolors-1;
9883
9884 // Paint the TGraph bins.
9885 if (poly->IsA() == TGraph::Class()) {
9886 TGraph *g = (TGraph*)poly;
9887 g->SetFillColor(gStyle->GetColorPalette(theColor));
9888 g->TAttFill::Modify();
9889 g->Paint("F");
9890 }
9891
9892 // Paint the TMultiGraph bins.
9893 if (poly->IsA() == TMultiGraph::Class()) {
9895 TList *gl = mg->GetListOfGraphs();
9896 if (!gl) return;
9897 TGraph *g;
9898 TIter nextg(gl);
9899 while ((g = (TGraph*) nextg())) {
9900 g->SetFillColor(gStyle->GetColorPalette(theColor));
9901 g->TAttFill::Modify();
9902 g->Paint("F");
9903 }
9904 }
9905 }
9907}
9908
9909////////////////////////////////////////////////////////////////////////////////
9910/// [Control function to draw a TH2Poly as a scatter plot.](\ref HP20a)
9911
9913{
9914
9915 //Do not highlight the histogram, if its part was selected.
9916 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
9917 return;
9918
9919 Int_t k, loop, marker=0;
9920 Double_t z, xk,xstep, yk, ystep, xp, yp;
9921 Double_t scale = 1;
9922 Double_t zmin = fH->GetMinimum();
9923 Double_t zmax = fH->GetMaximum();
9924 if (Hoption.Logz) {
9925 if (zmax > 0) {
9926 if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
9927 zmin = TMath::Log10(zmin);
9928 zmax = TMath::Log10(zmax);
9929 } else {
9930 return;
9931 }
9932 }
9933 Double_t dz = zmax - zmin;
9934 scale = (kNMAX-1)/dz;
9935
9936
9937 // use an independent instance of a random generator
9938 // instead of gRandom to avoid conflicts and
9939 // to get same random numbers when drawing the same histogram
9941
9942 TH2PolyBin *b;
9943
9944 TIter next(((TH2Poly*)fH)->GetBins());
9945 TObject *obj, *poly;
9946
9947 Double_t maxarea = 0, a;
9948 while ((obj=next())) {
9949 b = (TH2PolyBin*)obj;
9950 a = b->GetArea();
9951 if (a>maxarea) maxarea = a;
9952 }
9953
9954 next.Reset();
9955
9956 while ((obj=next())) {
9957 b = (TH2PolyBin*)obj;
9958 poly = b->GetPolygon();
9959 z = b->GetContent();
9960 if (z < zmin) z = zmin;
9961 if (z > zmax) z = zmax;
9962 if (Hoption.Logz) {
9963 if (z > 0) z = TMath::Log10(z) - zmin;
9964 } else {
9965 z -= zmin;
9966 }
9967 k = Int_t((z*scale)*(b->GetArea()/maxarea));
9968 xk = b->GetXMin();
9969 yk = b->GetYMin();
9970 xstep = b->GetXMax()-xk;
9971 ystep = b->GetYMax()-yk;
9972
9973 // Paint the TGraph bins.
9974 if (poly->IsA() == TGraph::Class()) {
9975 TGraph *g = (TGraph*)poly;
9976 if (k <= 0 || z <= 0) continue;
9977 loop = 0;
9978 while (loop<k) {
9979 if (k+marker >= kNMAX) {
9980 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
9981 marker=0;
9982 }
9983 xp = (random.Rndm()*xstep) + xk;
9984 yp = (random.Rndm()*ystep) + yk;
9985 if (g->IsInside(xp,yp)) {
9986 fXbuf[marker] = xp;
9987 fYbuf[marker] = yp;
9988 marker++;
9989 loop++;
9990 }
9991 }
9992 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
9993 }
9994
9995 // Paint the TMultiGraph bins.
9996 if (poly->IsA() == TMultiGraph::Class()) {
9998 TList *gl = mg->GetListOfGraphs();
9999 if (!gl) return;
10000 if (k <= 0 || z <= 0) continue;
10001 loop = 0;
10002 while (loop<k) {
10003 if (k+marker >= kNMAX) {
10004 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10005 marker=0;
10006 }
10007 xp = (random.Rndm()*xstep) + xk;
10008 yp = (random.Rndm()*ystep) + yk;
10009 if (mg->IsInside(xp,yp)) {
10010 fXbuf[marker] = xp;
10011 fYbuf[marker] = yp;
10012 marker++;
10013 loop++;
10014 }
10015 }
10016 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10017 }
10018 }
10019 PaintTH2PolyBins("l");
10020}
10021
10022////////////////////////////////////////////////////////////////////////////////
10023/// [Control function to draw a TH2Poly as a text plot.](\ref HP20a)
10024
10026{
10027
10028 TLatex text;
10029 text.SetTextFont(gStyle->GetTextFont());
10030 text.SetTextColor(fH->GetMarkerColor());
10031 text.SetTextSize(0.02*fH->GetMarkerSize());
10032
10033 Double_t x, y, z, e, angle = 0;
10034 TString tt, tf;
10035 tf.Form("%s%s","%",gStyle->GetPaintTextFormat());
10036 if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
10037 Int_t opt = (Int_t)Hoption.Text/1000;
10038
10039 text.SetTextAlign(22);
10040 if (Hoption.Text == 1) angle = 0;
10041 text.SetTextAngle(angle);
10042 text.TAttText::Modify();
10043
10044 TH2PolyBin *b;
10045
10046 TIter next(((TH2Poly*)fH)->GetBins());
10047 TObject *obj, *p;
10048
10049 while ((obj=next())) {
10050 b = (TH2PolyBin*)obj;
10051 p = b->GetPolygon();
10052 x = (b->GetXMin()+b->GetXMax())/2;
10053 if (Hoption.Logx) {
10054 if (x > 0) x = TMath::Log10(x);
10055 else continue;
10056 }
10057 y = (b->GetYMin()+b->GetYMax())/2;
10058 if (Hoption.Logy) {
10059 if (y > 0) y = TMath::Log10(y);
10060 else continue;
10061 }
10062 z = b->GetContent();
10063 if (z < fH->GetMinimum() || (z == 0 && !Hoption.MinimumZero)) continue;
10064 if (opt==2) {
10065 e = fH->GetBinError(b->GetBinNumber());
10066 tf.Form("#splitline{%s%s}{#pm %s%s}",
10068 "%",gStyle->GetPaintTextFormat());
10069 tt.Form(tf.Data(),z,e);
10070 } else {
10071 tt.Form(tf.Data(),z);
10072 }
10073 if (opt==3) text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),p->GetName());
10074 else text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),tt.Data());
10075 }
10076
10077 PaintTH2PolyBins("l");
10078}
10079
10080////////////////////////////////////////////////////////////////////////////////
10081/// [Control function to draw a 1D/2D histograms with the bin values.](\ref HP15)
10082
10084{
10085
10086 TLatex text;
10087 text.SetTextFont(((int)gStyle->GetTextFont()/10)*10+2); // font precision must be 2
10088 text.SetTextColor(fH->GetMarkerColor());
10089 text.SetTextSize(0.02*fH->GetMarkerSize());
10090
10091 Double_t x, y, z, e, angle = 0;
10092 TString tt, tf;
10093 tf.Form("%s%s","%",gStyle->GetPaintTextFormat());
10094 if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
10095
10096 // 1D histograms
10097 if (fH->GetDimension() == 1) {
10099 Double_t yt;
10100 TProfile *hp = (TProfile*)fH;
10101 if (Hoption.Text>2000 && fH->InheritsFrom(TProfile::Class())) {
10102 Hoption.Text = Hoption.Text-2000;
10103 getentries = kTRUE;
10104 }
10105 if (Hoption.Text == 1) angle = 90;
10106 text.SetTextAlign(11);
10107 if (angle == 90) text.SetTextAlign(12);
10108 if (angle == 0) text.SetTextAlign(21);
10109 text.TAttText::Modify();
10110 Double_t dt = 0.02*(gPad->GetY2()-gPad->GetY1());
10111 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10112 if (Hoption.Bar) {
10113 x = fH->GetXaxis()->GetBinLowEdge(i)+
10114 fH->GetXaxis()->GetBinWidth(i)*
10115 (fH->GetBarOffset()+0.5*fH->GetBarWidth());
10116 } else {
10117 x = fH->GetXaxis()->GetBinCenter(i);
10118 }
10119 y = fH->GetBinContent(i);
10120 yt = y;
10121 if (Hoption.MinimumZero && y<0) y = 0;
10122 if (getentries) yt = hp->GetBinEntries(i);
10123 if (yt == 0.) continue;
10124 tt.Form(tf.Data(),yt);
10125 if (Hoption.Logx) {
10126 if (x > 0) x = TMath::Log10(x);
10127 else continue;
10128 }
10129 if (Hoption.Logy) {
10130 if (y > 0) y = TMath::Log10(y);
10131 else continue;
10132 }
10133 if (y >= gPad->GetY2()) continue;
10134 if (y <= gPad->GetY1()) continue;
10135 text.PaintLatex(x,y+0.2*dt,angle,0.02*fH->GetMarkerSize(),tt.Data());
10136 }
10137
10138 // 2D histograms
10139 } else {
10140 Double_t zmin = Hparam.zmin;
10141 if (Hoption.Logz) zmin = TMath::Power(10,Hparam.zmin);
10142
10143 text.SetTextAlign(22);
10144 if (Hoption.Text == 1) angle = 0;
10145 text.SetTextAngle(angle);
10146 text.TAttText::Modify();
10147 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
10148 y = fYaxis->GetBinCenter(j);
10149 if (Hoption.Logy) {
10150 if (y > 0) y = TMath::Log10(y);
10151 else continue;
10152 }
10153 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10154 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
10155 x = fXaxis->GetBinCenter(i);
10156 if (Hoption.Logx) {
10157 if (x > 0) x = TMath::Log10(x);
10158 else continue;
10159 }
10160 if (!IsInside(x,y)) continue;
10161 z = fH->GetBinContent(bin);
10162 if (z < zmin || (z == 0 && !Hoption.MinimumZero)) continue;
10163 if (Hoption.Text>2000) {
10164 e = fH->GetBinError(bin);
10165 tf.Form("#splitline{%s%s}{#pm %s%s}",
10167 "%",gStyle->GetPaintTextFormat());
10168 tt.Form(tf.Data(),z,e);
10169 } else {
10170 tt.Form(tf.Data(),z);
10171 }
10172 text.PaintLatex(x,y+fH->GetBarOffset()*fYaxis->GetBinWidth(j),
10173 angle,0.02*fH->GetMarkerSize(),tt.Data());
10174 }
10175 }
10176 }
10177}
10178
10179////////////////////////////////////////////////////////////////////////////////
10180/// [Control function to draw a 3D implicit functions.](\ref HP27)
10181
10183{
10184
10185 Int_t irep;
10186
10187 TAxis *xaxis = fH->GetXaxis();
10188 TAxis *yaxis = fH->GetYaxis();
10189 TAxis *zaxis = fH->GetZaxis();
10190
10191 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
10192 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
10193 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
10194 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
10195 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
10196 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
10197
10198 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
10199
10200 TView *view = gPad ? gPad->GetView() : nullptr;
10201 if (!view) {
10202 Error("PaintTF3", "no TView in current pad");
10203 return;
10204 }
10205 Double_t thedeg = 90 - gPad->GetTheta();
10206 Double_t phideg = -90 - gPad->GetPhi();
10207 Double_t psideg = view->GetPsi();
10208 view->SetView(phideg, thedeg, psideg, irep);
10209
10210 fLego->InitMoveScreen(-1.1,1.1);
10211
10212 if (Hoption.BackBox) {
10213 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
10215 fLego->BackBox(90);
10216 }
10217
10219
10220 fLego->ImplicitFunction(fCurrentF3, fXbuf.data(), fYbuf.data(), fH->GetNbinsX(),
10221 fH->GetNbinsY(),
10222 fH->GetNbinsZ(), "BF");
10223
10224 if (Hoption.FrontBox) {
10225 fLego->InitMoveScreen(-1.1,1.1);
10227 fLego->FrontBox(90);
10228 }
10229 if (!Hoption.Axis && !Hoption.Same) {
10230 TGaxis axis;
10231 PaintLegoAxis(&axis, 90);
10232 }
10233
10234 PaintTitle();
10235
10236 fLego.reset();
10237}
10238
10239/////////////////////////////////////////////////////////////new TGaxis///////////////////
10240/// Draw the histogram title
10241///
10242/// The title is drawn according to the title alignment returned by
10243/// `GetTitleAlign()`. It is a 2 digits integer): hv
10244///
10245/// where `h` is the horizontal alignment and `v` is the
10246/// vertical alignment.
10247///
10248/// - `h` can get the values 1 2 3 for left, center, and right
10249/// - `v` can get the values 1 2 3 for bottom, middle and top
10250///
10251/// for instance the default alignment is: 13 (left top)
10252
10254{
10255 // probably best place for calls PaintHighlightBin
10256 // calls after paint histo (1D or 2D) and before paint title and stats
10257 if (!gPad->GetView()) PaintHighlightBin();
10258
10259 if (Hoption.Same) return;
10260 if (fH->TestBit(TH1::kNoTitle)) return;
10261 Int_t nt = strlen(fH->GetTitle());
10262 TPaveText *title = nullptr;
10263 TObject *obj;
10264 TIter next(gPad->GetListOfPrimitives());
10265 while ((obj = next())) {
10266 if (!obj->InheritsFrom(TPaveText::Class())) continue;
10267 title = (TPaveText*)obj;
10268 if (strcmp(title->GetName(),"title")) {title = nullptr; continue;}
10269 break;
10270 }
10271 if (nt == 0 || gStyle->GetOptTitle() <= 0) {
10272 if (title) delete title;
10273 return;
10274 }
10277
10278 if (ht <= 0) {
10279 if (gStyle->GetTitleFont("")%10 == 3) {
10280 Double_t hw = TMath::Max((Double_t)gPad->XtoPixel(gPad->GetX2()),
10281 (Double_t)gPad->YtoPixel(gPad->GetY1()));
10282 ht = 1.1*(gStyle->GetTitleSize("")/hw);
10283 } else {
10284 ht = 1.1*gStyle->GetTitleFontSize();
10285 }
10286 }
10287 if (ht <= 0) ht = 0.05;
10288 if (wt <= 0) {
10289 TLatex l;
10290 l.SetTextSize(ht);
10291 l.SetTitle(fH->GetTitle());
10292 // adjustment in case the title has several lines (#splitline)
10293 ht = TMath::Max(ht, 1.2*l.GetYsize()/(gPad->GetY2() - gPad->GetY1()));
10294 Double_t wndc = l.GetXsize()/(gPad->GetX2() - gPad->GetX1());
10295 wt = TMath::Min(0.7, 0.02+wndc);
10296 }
10297 if (title) {
10298 TText *t0 = (TText*)title->GetLine(0);
10299 if (t0) {
10300 if (!strcmp(t0->GetTitle(),fH->GetTitle())) return;
10301 t0->SetTitle(fH->GetTitle());
10302 if (wt > 0) title->SetX2NDC(title->GetX1NDC()+wt);
10303 }
10304 return;
10305 }
10306
10308 if (talh < 1) talh = 1; else if (talh > 3) talh = 3;
10310 if (talv < 1) talv = 1; else if (talv > 3) talv = 3;
10312 xpos = gStyle->GetTitleX();
10313 ypos = gStyle->GetTitleY();
10314 if (talh == 2) xpos = xpos-wt/2.;
10315 if (talh == 3) xpos = xpos-wt;
10316 if (talv == 2) ypos = ypos+ht/2.;
10317 if (talv == 1) ypos = ypos+ht;
10318
10319 TPaveText *ptitle = new TPaveText(xpos, ypos-ht, xpos+wt, ypos,"blNDC");
10320
10321 // box with the histogram title
10322 ptitle->SetFillColor(gStyle->GetTitleFillColor());
10323 ptitle->SetFillStyle(gStyle->GetTitleStyle());
10324 ptitle->SetName("title");
10325 ptitle->SetBorderSize(gStyle->GetTitleBorderSize());
10326 ptitle->SetTextColor(gStyle->GetTitleTextColor());
10327 ptitle->SetTextFont(gStyle->GetTitleFont(""));
10328 if (gStyle->GetTitleFont("")%10 > 2)
10329 ptitle->SetTextSize(gStyle->GetTitleFontSize());
10330 ptitle->AddText(fH->GetTitle());
10331 ptitle->SetBit(kCanDelete);
10332 ptitle->Draw();
10333 ptitle->Paint("blNDC");
10334
10335 if(!gPad->IsEditable()) delete ptitle;
10336}
10337
10338////////////////////////////////////////////////////////////////////////////////
10339/// Process message `mess`.
10340
10341void THistPainter::ProcessMessage(const char *mess, const TObject *obj)
10342{
10343 if (!strcmp(mess,"SetF3")) {
10344 fCurrentF3 = (TF3 *)obj;
10345 }
10346}
10347
10348////////////////////////////////////////////////////////////////////////////////
10349/// Static function.
10350///
10351/// Convert Right Ascension, Declination to X,Y using an AITOFF projection.
10352/// This procedure can be used to create an all-sky map in Galactic
10353/// coordinates with an equal-area Aitoff projection. Output map
10354/// coordinates are zero longitude centered.
10355/// Also called Hammer-Aitoff projection (first presented by Ernst von Hammer in 1892)
10356///
10357/// source: GMT
10358///
10359/// code from Ernst-Jan Buis
10360
10362{
10363
10364 Double_t x, y;
10365
10367 Double_t delta = b*TMath::DegToRad();
10368 Double_t r2 = TMath::Sqrt(2.);
10369 Double_t f = 2*r2/TMath::Pi();
10370 Double_t cdec = TMath::Cos(delta);
10373 y = TMath::Sin(delta)*r2/denom;
10374 x *= TMath::RadToDeg()/f;
10375 y *= TMath::RadToDeg()/f;
10376 // x *= -1.; // for a skymap swap left<->right
10377 Al = x;
10378 Ab = y;
10379
10380 return 0;
10381}
10382
10383////////////////////////////////////////////////////////////////////////////////
10384/// Static function
10385///
10386/// Probably the most famous of the various map projections, the Mercator projection
10387/// takes its name from Mercator who presented it in 1569. It is a cylindrical, conformal projection
10388/// with no distortion along the equator.
10389/// The Mercator projection has been used extensively for world maps in which the distortion towards
10390/// the polar regions grows rather large, thus incorrectly giving the impression that, for example,
10391/// Greenland is larger than South America. In reality, the latter is about eight times the size of
10392/// Greenland. Also, the Former Soviet Union looks much bigger than Africa or South America. One may wonder
10393/// whether this illusion has had any influence on U.S. foreign policy.' (Source: GMT)
10394/// code from Ernst-Jan Buis
10395
10397{
10398
10399 Al = l;
10401 Ab = TMath::Log(aid);
10402 return 0;
10403}
10404
10405////////////////////////////////////////////////////////////////////////////////
10406/// Static function code for sinusoidal projection
10407/// from Ernst-Jan Buis
10408/// Source https://en.wikipedia.org/wiki/Sinusoidal_projection
10409
10411{
10412
10413 Al = l*cos(b*TMath::DegToRad());
10414 Ab = b;
10415 return 0;
10416}
10417
10418////////////////////////////////////////////////////////////////////////////////
10419/// Static function code for parabolic projection
10420/// from Ernst-Jan Buis
10421
10423{
10424
10425 Al = l*(2.*TMath::Cos(2*b*TMath::DegToRad()/3) - 1);
10426 Ab = 180*TMath::Sin(b*TMath::DegToRad()/3);
10427 return 0;
10428}
10429
10430////////////////////////////////////////////////////////////////////////////////
10431/// Static function.
10432///
10433/// Convert Right Ascension, Declination to X,Y using an MOLLWEIDE projection.
10434/// This procedure can be used to create an all-sky map in Galactic
10435/// coordinates with an equal-area Mollweide projection. Output map
10436/// coordinates are zero longitude centered.
10437/// It is also known as the Babinet projection, homalographic projection, homolographic projection, and elliptical projection.
10438/// Source: https://en.wikipedia.org/wiki/Mollweide_projection
10439///
10440/// code from Marco Meyer-Conde
10441
10443{
10444
10445 Double_t theta0 = b * TMath::DegToRad(), theta = theta0;
10446
10447 for (int i = 0; i < 100; i++) {
10448 Double_t num = 2 * theta + TMath::Sin(2 * theta) - TMath::Pi() * TMath::Sin(theta0);
10449 Double_t den = 4 * TMath::Power(TMath::Cos(theta), 2);
10450
10451 if (den < 1e-20) {
10452 theta = theta0;
10453 break;
10454 }
10455
10456 theta -= num / den;
10457
10458 if (TMath::Abs(num / den) < 1e-4) break;
10459 }
10460
10461 Al = l * TMath::Cos(theta);
10462 Ab = 90 * TMath::Sin(theta);
10463
10464 return 0;
10465}
10466
10467////////////////////////////////////////////////////////////////////////////////
10468/// Recompute the histogram range following graphics operations.
10469
10471{
10472
10473 if (Hoption.Same) return;
10474
10475 // Compute x,y range
10477 xmax = Hparam.xmax,
10478 ymin = Hparam.ymin,
10479 ymax = Hparam.ymax,
10480 xscale = 1;
10481
10482 std::function<Int_t(Double_t,Double_t,Double_t&,Double_t&)> func;
10483
10484 if (Hoption.Proj == 1) {
10485 func = ProjectAitoff2xy;
10486 xscale = 0.9999;
10487 } else if (Hoption.Proj == 2) {
10488 if (Hparam.ymin <= -90 || Hparam.ymax >= 90) {
10489 Warning("Mercator Projection", "Latitude out of range %f or %f", Hparam.ymin, Hparam.ymax);
10490 Hoption.Proj = 0;
10491 } else {
10494 }
10495 } else if (Hoption.Proj == 3) {
10496 func = ProjectSinusoidal2xy;
10497 } else if (Hoption.Proj == 4) {
10498 func = ProjectParabolic2xy;
10499 } else if (Hoption.Proj == 5) {
10500 func = ProjectMollweide2xy;
10501 }
10502
10503 if (func) {
10505
10509 func(Hparam.xmax, Hparam.ymin, xmax, ymin);
10510
10511 if (xmin > xmin_aid) xmin = xmin_aid;
10512 if (ymin > ymin_aid) ymin = ymin_aid;
10513 if (xmax < xmax_aid) xmax = xmax_aid;
10514 if (ymax < ymax_aid) ymax = ymax_aid;
10515 if (Hparam.ymin < 0 && Hparam.ymax > 0) {
10516 // there is an 'equator', check its range in the plot..
10517 func(Hparam.xmin*xscale, 0, xmin_aid, ymin_aid);
10518 func(Hparam.xmax*xscale, 0, xmax_aid, ymin_aid);
10519 if (xmin > xmin_aid) xmin = xmin_aid;
10520 if (xmax < xmax_aid) xmax = xmax_aid;
10521 }
10522 if (Hparam.xmin < 0 && Hparam.xmax > 0) {
10523 func(0, Hparam.ymin, xmin_aid, ymin_aid);
10524 func(0, Hparam.ymax, xmax_aid, ymax_aid);
10525 if (ymin > ymin_aid) ymin = ymin_aid;
10526 if (ymax < ymax_aid) ymax = ymax_aid;
10527 }
10528 }
10529
10530 Hparam.xmin = xmin;
10531 Hparam.xmax = xmax;
10532 Hparam.ymin = ymin;
10533 Hparam.ymax = ymax;
10534
10535 Double_t dx = xmax-xmin;
10536 Double_t dy = ymax-ymin;
10537 Double_t dxr = dx/(1 - gPad->GetLeftMargin() - gPad->GetRightMargin());
10538 Double_t dyr = dy/(1 - gPad->GetBottomMargin() - gPad->GetTopMargin());
10539
10540 // Range() could change the size of the pad pixmap and therefore should
10541 // be called before the other paint routines
10542 gPad->Range(xmin - dxr*gPad->GetLeftMargin(),
10543 ymin - dyr*gPad->GetBottomMargin(),
10544 xmax + dxr*gPad->GetRightMargin(),
10545 ymax + dyr*gPad->GetTopMargin());
10546 gPad->RangeAxis(xmin, ymin, xmax, ymax);
10547}
10548
10549////////////////////////////////////////////////////////////////////////////////
10550/// Set current histogram to `h`
10551
10553{
10554
10555 if (h == nullptr) return;
10556 fH = h;
10557 fXaxis = h->GetXaxis();
10558 fYaxis = h->GetYaxis();
10559 fZaxis = h->GetZaxis();
10561}
10562
10563////////////////////////////////////////////////////////////////////////////////
10564/// Initialize various options to draw 2D histograms.
10565
10567{
10568
10569 static const char *where = "TableInit";
10570
10571 Int_t first, last;
10573 Double_t zmin, zmax;
10574 Int_t maximum = 0;
10575 Int_t minimum = 0;
10576 if (fH->GetMaximumStored() != -1111) maximum = 1;
10577 if (fH->GetMinimumStored() != -1111) minimum = 1;
10578
10579 // ----------------- Compute X axis parameters
10580 first = fXaxis->GetFirst();
10581 last = fXaxis->GetLast();
10582 Hparam.xlast = last;
10583 Hparam.xfirst = first;
10588
10589 // if log scale in X, replace xmin,max by the log
10590 if (Hoption.Logx) {
10591 // find the first edge of a bin that is > 0
10592 if (Hparam.xlowedge <=0 ) {
10595 }
10596 if (Hparam.xmin <=0 || Hparam.xmax <=0) {
10597 Error(where, "cannot set X axis to log scale");
10598 return 0;
10599 }
10601 if (Hparam.xfirst < first) Hparam.xfirst = first;
10603 if (Hparam.xlast > last) Hparam.xlast = last;
10606 }
10607
10608 // ----------------- Compute Y axis parameters
10609 first = fYaxis->GetFirst();
10610 last = fYaxis->GetLast();
10611 Hparam.ylast = last;
10612 Hparam.yfirst = first;
10615 if (!Hparam.ybinsize) Hparam.ybinsize = 1;
10618
10619 // if log scale in Y, replace ymin,max by the log
10620 if (Hoption.Logy) {
10621 if (Hparam.ylowedge <=0 ) {
10624 }
10625 if (Hparam.ymin <=0 || Hparam.ymax <=0) {
10626 Error(where, "cannot set Y axis to log scale");
10627 return 0;
10628 }
10630 if (Hparam.yfirst < first) Hparam.yfirst = first;
10632 if (Hparam.ylast > last) Hparam.ylast = last;
10635 }
10636
10637
10638 // ----------------- Compute Z axis parameters
10639 Double_t bigp = TMath::Power(10,32);
10640 zmax = -bigp;
10641 zmin = bigp;
10642 Double_t c1, e1;
10643 Double_t allchan = 0;
10644 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
10645 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10646 c1 = fH->GetBinContent(i,j);
10647 zmax = TMath::Max(zmax,c1);
10648 if (Hoption.Error) {
10649 e1 = fH->GetBinError(i,j);
10650 zmax = TMath::Max(zmax,c1+e1);
10651 }
10652 zmin = TMath::Min(zmin,c1);
10653 allchan += c1;
10654 }
10655 }
10656
10657 // Take into account maximum , minimum
10658
10659 if (maximum) zmax = fH->GetMaximumStored();
10660 if (minimum) zmin = fH->GetMinimumStored();
10661 if (Hoption.Logz && zmax < 0) {
10662 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10663 return 0;
10664 } else if (Hoption.Logz && zmin>=0 && zmax==0) { // empty histogram in log scale
10665 zmin = 0.01;
10666 zmax = 10.;
10667 }
10668 if (zmin >= zmax) {
10669 if (Hoption.Logz) {
10670 if (zmax > 0) zmin = 0.001*zmax;
10671 else {
10672 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10673 return 0;
10674 }
10675 }
10676 }
10677
10678 // take into account normalization factor
10679 Hparam.allchan = allchan;
10680 Double_t factor = allchan;
10681 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
10682 if (allchan) factor /= allchan;
10683 if (factor == 0) factor = 1;
10684 Hparam.factor = factor;
10685 zmax = factor*zmax;
10686 zmin = factor*zmin;
10687 c1 = zmax;
10688 if (TMath::Abs(zmin) > TMath::Abs(c1)) c1 = zmin;
10689
10690 // For log scales, histogram coordinates are log10(ymin) and
10691 // log10(ymax). Final adjustment (if not option "Same")
10692 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
10693 // Maximum and Minimum are not defined.
10694 if (Hoption.Logz) {
10695 if (zmin <= 0) {
10696 zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
10697 fH->SetMinimum(zmin);
10698 }
10699 zmin = TMath::Log10(zmin);
10700 if (!minimum) zmin += TMath::Log10(0.5);
10701 zmax = TMath::Log10(zmax);
10702 if (!maximum) zmax += TMath::Log10(2*(0.9/0.95));
10703 goto LZMIN;
10704 }
10705
10706 // final adjustment of YMAXI for linear scale (if not option "Same"):
10707 // decrease histogram height to MAX% of allowed height if HMAXIM
10708 // has not been called.
10709 // MAX% is the value in percent which has been set in HPLSET
10710 // (default is 90%).
10711 if (!maximum) {
10712 zmax += yMARGIN*(zmax-zmin);
10713 }
10714
10715 // final adjustment of ymin for linear scale.
10716 // if minimum is not set , then ymin is set to zero if >0
10717 // or to ymin - yMARGIN if <0.
10718 if (!minimum) {
10719 if (Hoption.MinimumZero) {
10720 if (zmin >= 0) zmin = 0;
10721 else zmin -= yMARGIN*(zmax-zmin);
10722 } else {
10723 Double_t dzmin = yMARGIN*(zmax-zmin);
10724 if (zmin >= 0 && (zmin-dzmin <= 0)) zmin = 0;
10725 else zmin -= dzmin;
10726 }
10727 }
10728
10729LZMIN:
10730 Hparam.zmin = zmin;
10731 Hparam.zmax = zmax;
10732
10733 // Set bar offset and width
10736
10737 return 1;
10738}
10739
10740////////////////////////////////////////////////////////////////////////////////
10741/// This function returns the best format to print the error value (e)
10742/// knowing the parameter value (v) and the format (f) used to print it.
10743
10745{
10746
10747 static TString ef;
10748 TString tf, tv;
10749
10750 // print v with the format f in tv.
10751 tf.Form("%s%s","%",f);
10752 tv.Form(tf.Data(),v);
10753
10754 // Analyse tv.
10755 int ie = tv.Index("e");
10756 int iE = tv.Index("E");
10757 int id = tv.Index(".");
10758
10759 // v has been printed with the exponent notation.
10760 // There is 2 cases, the exponent is positive or negative
10761 if (ie >= 0 || iE >= 0) {
10762 if (tv.Index("+") >= 0) {
10763 if (e < 1) {
10764 ef.Form("%s.1f","%");
10765 } else {
10766 if (ie >= 0) {
10767 ef.Form("%s.%de","%",ie-id-1);
10768 } else {
10769 ef.Form("%s.%dE","%",iE-id-1);
10770 }
10771 }
10772 } else {
10773 if (ie >= 0) {
10774 ef.Form("%s.%de","%",ie-id-1);
10775 } else {
10776 ef.Form("%s.%dE","%",iE-id-1);
10777 }
10778 }
10779
10780 // There is not '.' in tv. e will be printed with one decimal digit.
10781 } else if (id < 0) {
10782 ef.Form("%s.1f","%");
10783
10784 // There is a '.' in tv and no exponent notation. e's decimal part will
10785 // have the same number of digits as v's one.
10786 } else {
10787 ef.Form("%s.%df","%",tv.Length()-id-1);
10788 }
10789
10790 return ef.Data();
10791}
10792
10793////////////////////////////////////////////////////////////////////////////////
10794/// Set projection.
10795
10797{
10798 if (fShowProjection2) {
10799 auto name2 = TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2);
10800 auto c2 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name2.Data()));
10801 if (c2) c2->Close();
10802 fShowProjection2 = 0;
10803 }
10804 if (fShowProjection) {
10805 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10806 auto c1 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name1.Data()));
10807 if (c1) c1->Close();
10808 fShowProjection = 0;
10809 }
10810
10811 if (nbins <= 0) return;
10812
10813 TString opt = option;
10814 opt.ToLower();
10815 Int_t projection = 0;
10816 if (opt.Contains("x")) projection = 1;
10817 if (opt.Contains("y")) projection = 2;
10818 if (opt.Contains("z")) projection = 3;
10819 if (opt.Contains("xy")) projection = 4;
10820 if (opt.Contains("yx")) projection = 5;
10821 if (opt.Contains("xz")) projection = 6;
10822 if (opt.Contains("zx")) projection = 7;
10823 if (opt.Contains("yz")) projection = 8;
10824 if (opt.Contains("zy")) projection = 9;
10825 if (projection < 4) fShowOption = option+1;
10826 else fShowOption = option+2;
10827 fShowProjection = projection+100*nbins;
10828 fShowProjection2 = 0;
10829 gROOT->MakeDefCanvas();
10830 gPad->SetName(TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection).Data());
10831 gPad->SetGrid();
10832}
10833
10835{
10836 if (fShowProjection2) {
10837 auto name2 = TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2);
10838 auto c2 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name2.Data()));
10839 if (c2) c2->Close();
10840 fShowProjection2 = 0;
10841 }
10842 if (fShowProjection) {
10843 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10844 auto c1 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name1.Data()));
10845 if (c1) c1->Close();
10846 fShowProjection = 0;
10847 }
10848
10849 if ((nbinsX <= 0) || (nbinsY <= 0)) return;
10850
10851
10852 TString opt = option;
10853 opt.ToLower();
10854 Int_t projection = 0;
10855 if (opt.Contains("x")) projection = 1;
10856 if (opt.Contains("y")) projection = 2;
10857 if (opt.Contains("z")) projection = 3;
10858 if (opt.Contains("xy")) projection = 4;
10859 if (opt.Contains("yx")) projection = 5;
10860 if (opt.Contains("xz")) projection = 6;
10861 if (opt.Contains("zx")) projection = 7;
10862 if (opt.Contains("yz")) projection = 8;
10863 if (opt.Contains("zy")) projection = 9;
10864 if (projection < 4) fShowOption = option+1;
10865 else fShowOption = option+2;
10868 gROOT->MakeDefCanvas();
10869 gPad->SetName(TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection).Data());
10870 gPad->SetGrid();
10871 gROOT->MakeDefCanvas();
10872 gPad->SetName(TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2).Data());
10873 gPad->SetGrid();
10874}
10875
10876
10877////////////////////////////////////////////////////////////////////////////////
10878/// Show projection onto X.
10879
10881{
10882
10883 Int_t nbins = (Int_t)fShowProjection/100;
10884 gPad->SetDoubleBuffer(0); // turn off double buffer mode
10885 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
10886
10887 // Erase old position and draw a line at current position
10888 static int pyold1 = 0;
10889 static int pyold2 = 0;
10890 float uxmin = gPad->GetUxmin();
10891 float uxmax = gPad->GetUxmax();
10892 int pxmin = gPad->XtoAbsPixel(uxmin);
10893 int pxmax = gPad->XtoAbsPixel(uxmax);
10894 Float_t upy = gPad->AbsPixeltoY(py);
10895 Float_t y = gPad->PadtoY(upy);
10896 Int_t biny1 = fH->GetYaxis()->FindBin(y);
10897 Int_t biny2 = TMath::Min(biny1+nbins-1, fH->GetYaxis()->GetNbins());
10898 Int_t py1 = gPad->YtoAbsPixel(gPad->GetLogy() ? TMath::Log10(fH->GetYaxis()->GetBinLowEdge(biny1)) : fH->GetYaxis()->GetBinLowEdge(biny1));
10899 Int_t py2 = gPad->YtoAbsPixel(gPad->GetLogy() ? TMath::Log10(fH->GetYaxis()->GetBinUpEdge(biny2)) : fH->GetYaxis()->GetBinUpEdge(biny2));
10900
10902 gVirtualX->DrawBox(pxmin,py1,pxmax,py2,TVirtualX::kFilled);
10903 pyold1 = py1;
10904 pyold2 = py2;
10905
10906 // Create or set the new canvas proj x
10908 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10909 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(name1.Data());
10910 if (c) {
10911 c->Clear();
10912 } else {
10913 fShowProjection = 0;
10914 fShowProjection2 = 0;
10915 pyold1 = 0;
10916 pyold2 = 0;
10917 return;
10918 }
10919 c->cd();
10920 c->SetLogy(ctxt.GetSaved()->GetLogz());
10921 c->SetLogx(ctxt.GetSaved()->GetLogx());
10922
10923 // Draw slice corresponding to mouse position
10924 TString prjName = TString::Format("slice_px_of_%s",fH->GetName());
10925 TH1D *hp = ((TH2*)fH)->ProjectionX(prjName, biny1, biny2);
10926 if (hp) {
10927 hp->SetFillColor(38);
10928 // apply a patch from Oliver Freyermuth to set the title in the projection
10929 // using the range of the projected Y values
10930 if (biny1 == biny2) {
10933 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
10935 if (fH->GetYaxis()->GetLabels() != nullptr) {
10936 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf] %s", biny1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetYaxis()->GetBinLabel(biny1)));
10937 } else {
10938 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf]", biny1, valuePrecision, valueFrom, valuePrecision, valueTo));
10939 }
10940 } else {
10943 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
10944 // biny1 is used here to get equal precision no matter how large the binrange is,
10945 // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
10947 if (fH->GetYaxis()->GetLabels() != nullptr) {
10948 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)));
10949 } else {
10950 hp->SetTitle(TString::Format("ProjectionX of biny=[%d,%d] [y=%.*lf..%.*lf]", biny1, biny2, valuePrecision, valueFrom, valuePrecision, valueTo));
10951 }
10952 }
10953 hp->SetXTitle(fH->GetXaxis()->GetTitle());
10954 hp->SetYTitle(((TH2*)fH)->GetZaxis()->GetTitle() ? ((TH2*)fH)->GetZaxis()->GetTitle() : "Number of Entries");
10955 hp->Draw();
10956 c->Update();
10957 }
10958}
10959
10960////////////////////////////////////////////////////////////////////////////////
10961/// Show projection onto Y.
10962
10964{
10965
10966 Int_t nbins = (Int_t)fShowProjection/100;
10967 if (fShowProjection2)
10968 nbins = (Int_t)fShowProjection2/100;
10969 gPad->SetDoubleBuffer(0); // turn off double buffer mode
10970 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
10971
10972 // Erase old position and draw a line at current position
10973 static int pxold1 = 0;
10974 static int pxold2 = 0;
10975 float uymin = gPad->GetUymin();
10976 float uymax = gPad->GetUymax();
10977 int pymin = gPad->YtoAbsPixel(uymin);
10978 int pymax = gPad->YtoAbsPixel(uymax);
10979 Float_t upx = gPad->AbsPixeltoX(px);
10980 Float_t x = gPad->PadtoX(upx);
10981 Int_t binx1 = fH->GetXaxis()->FindBin(x);
10982 Int_t binx2 = TMath::Min(binx1+nbins-1, fH->GetXaxis()->GetNbins());
10983 Int_t px1 = gPad->XtoAbsPixel(gPad->GetLogx() ? TMath::Log10(fH->GetXaxis()->GetBinLowEdge(binx1)) : fH->GetXaxis()->GetBinLowEdge(binx1));
10984 Int_t px2 = gPad->XtoAbsPixel(gPad->GetLogx() ? TMath::Log10(fH->GetXaxis()->GetBinUpEdge(binx2)) : fH->GetXaxis()->GetBinUpEdge(binx2));
10985
10987 gVirtualX->DrawBox(px1,pymin,px2,pymax,TVirtualX::kFilled);
10988 pxold1 = px1;
10989 pxold2 = px2;
10990
10991 // Create or set the new canvas proj y
10993
10994 TString name2 = fShowProjection2 ? TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2)
10995 : TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10996
10997 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(name2.Data());
10998 if (c) {
10999 c->Clear();
11000 } else {
11001 fShowProjection = 0;
11002 fShowProjection2 = 0;
11003 pxold1 = 0;
11004 pxold2 = 0;
11005 return;
11006 }
11007 c->cd();
11008 c->SetLogy(ctxt.GetSaved()->GetLogz());
11009 c->SetLogx(ctxt.GetSaved()->GetLogy());
11010
11011 // Draw slice corresponding to mouse position
11012 TString prjName = TString::Format("slice_py_of_%s",fH->GetName());
11013 TH1D *hp = ((TH2*)fH)->ProjectionY(prjName, binx1, binx2);
11014 if (hp) {
11015 hp->SetFillColor(38);
11016 // apply a patch from Oliver Freyermuth to set the title in the projection
11017 // using the range of the projected X values
11018 if (binx1 == binx2) {
11021 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11023 if (fH->GetXaxis()->GetLabels() != nullptr) {
11024 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf] [%s]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetXaxis()->GetBinLabel(binx1)));
11025 } else {
11026 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo));
11027 }
11028 } else {
11031 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11032 // binx1 is used here to get equal precision no matter how large the binrange is,
11033 // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
11035 if (fH->GetXaxis()->GetLabels() != nullptr) {
11036 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)));
11037 } else {
11038 hp->SetTitle(TString::Format("ProjectionY of binx=[%d,%d] [x=%.*lf..%.*lf]", binx1, binx2, valuePrecision, valueFrom, valuePrecision, valueTo));
11039 }
11040 }
11041 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11042 hp->SetYTitle(((TH2*)fH)->GetZaxis()->GetTitle() ? ((TH2*)fH)->GetZaxis()->GetTitle() : "Number of Entries");
11043 hp->Draw(fShowProjection2 ? "hbar" : "");
11044 c->Update();
11045 }
11046}
11047
11048////////////////////////////////////////////////////////////////////////////////
11049/// Show projection (specified by `fShowProjection`) of a `TH3`.
11050/// The drawing option for the projection is in `fShowOption`.
11051///
11052/// First implementation; R.Brun
11053///
11054/// Full implementation: Tim Tran (timtran@jlab.org) April 2006
11055
11057{
11058
11059 Int_t nbins=(Int_t)fShowProjection/100; //decode nbins
11060 if (fH->GetDimension() < 3) {
11061 if (fShowProjection2 % 100 == 1) {
11062 ShowProjectionY(px, py);
11063 }
11064 if (fShowProjection % 100 == 1) {
11065 ShowProjectionX(px, py);
11066 return;
11067 }
11068 if (fShowProjection % 100 == 2) {
11069 ShowProjectionY(px, py);
11070 return;
11071 }
11072 }
11073
11074 gPad->SetDoubleBuffer(0); // turn off double buffer mode
11075 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
11076
11077 // Erase old position and draw a line at current position
11078 TView *view = gPad->GetView();
11079 if (!view) return;
11080 TH3 *h3 = (TH3*)fH;
11081 TAxis *xaxis = h3->GetXaxis();
11082 TAxis *yaxis = h3->GetYaxis();
11083 TAxis *zaxis = h3->GetZaxis();
11084 Double_t u[3],xx[3];
11085
11086 static TPoint line1[2];//store end points of a line, initialised 0 by default
11087 static TPoint line2[2];// second line when slice thickness > 1 bin thickness
11088 static TPoint line3[2];
11089 static TPoint line4[2];
11090 static TPoint endface1[5];
11091 static TPoint endface2[5];
11092 static TPoint rect1[5];//store vertices of the polyline (rectangle), initialsed 0 by default
11093 static TPoint rect2[5];// second rectangle when slice thickness > 1 bin thickness
11094
11095 Double_t uxmin = gPad->GetUxmin();
11096 Double_t uxmax = gPad->GetUxmax();
11097 Double_t uymin = gPad->GetUymin();
11098 Double_t uymax = gPad->GetUymax();
11099
11100 int pxmin = gPad->XtoAbsPixel(uxmin);
11101 int pxmax = gPad->XtoAbsPixel(uxmax);
11102 if (pxmin==pxmax) return;
11103 int pymin = gPad->YtoAbsPixel(uymin);
11104 int pymax = gPad->YtoAbsPixel(uymax);
11105 if (pymin==pymax) return;
11108 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(TString::Format("c_%zx_projection_%d",
11109 (size_t)fH, fShowProjection).Data());
11110 if (!c) {
11111 fShowProjection = 0;
11112 return;
11113 }
11114
11116
11117 switch ((Int_t)fShowProjection%100) {
11118 case 1:
11119 // "x"
11120 {
11121 Int_t firstY = yaxis->GetFirst();
11122 Int_t lastY = yaxis->GetLast();
11124 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11125 yaxis->SetRange(biny,biny2);
11126 Int_t firstZ = zaxis->GetFirst();
11127 Int_t lastZ = zaxis->GetLast();
11129 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11130 zaxis->SetRange(binz,binz2);
11131 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11132 if (nbins>1 && line1[0].GetX()) {
11133 gVirtualX->DrawPolyLine(2,line2);
11134 gVirtualX->DrawPolyLine(2,line3);
11135 gVirtualX->DrawPolyLine(2,line4);
11136 gVirtualX->DrawPolyLine(5,endface1);
11137 gVirtualX->DrawPolyLine(5,endface2);
11138 }
11139 xx[0] = xaxis->GetXmin();
11140 xx[2] = zaxis->GetBinCenter(binz);
11141 xx[1] = yaxis->GetBinCenter(biny);
11142 view->WCtoNDC(xx,u);
11143 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11144 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11145 xx[0] = xaxis->GetXmax();
11146 view->WCtoNDC(xx,u);
11147 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11148 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11149 gVirtualX->DrawPolyLine(2,line1);
11150 if (nbins>1) {
11151 xx[0] = xaxis->GetXmin();
11152 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11153 xx[1] = yaxis->GetBinCenter(biny);
11154 view->WCtoNDC(xx,u);
11155 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11156 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11157 xx[0] = xaxis->GetXmax();
11158 view->WCtoNDC(xx,u);
11159 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11160 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11161
11162 xx[0] = xaxis->GetXmin();
11163 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11164 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11165 view->WCtoNDC(xx,u);
11166 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11167 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11168 xx[0] = xaxis->GetXmax();
11169 view->WCtoNDC(xx,u);
11170 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11171 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11172
11173 xx[0] = xaxis->GetXmin();
11174 xx[2] = zaxis->GetBinCenter(binz);
11175 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11176 view->WCtoNDC(xx,u);
11177 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11178 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11179 xx[0] = xaxis->GetXmax();
11180 view->WCtoNDC(xx,u);
11181 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11182 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11183
11184 endface1[0].SetX(line1[0].GetX());
11185 endface1[0].SetY(line1[0].GetY());
11186 endface1[1].SetX(line2[0].GetX());
11187 endface1[1].SetY(line2[0].GetY());
11188 endface1[2].SetX(line3[0].GetX());
11189 endface1[2].SetY(line3[0].GetY());
11190 endface1[3].SetX(line4[0].GetX());
11191 endface1[3].SetY(line4[0].GetY());
11192 endface1[4].SetX(line1[0].GetX());
11193 endface1[4].SetY(line1[0].GetY());
11194
11195 endface2[0].SetX(line1[1].GetX());
11196 endface2[0].SetY(line1[1].GetY());
11197 endface2[1].SetX(line2[1].GetX());
11198 endface2[1].SetY(line2[1].GetY());
11199 endface2[2].SetX(line3[1].GetX());
11200 endface2[2].SetY(line3[1].GetY());
11201 endface2[3].SetX(line4[1].GetX());
11202 endface2[3].SetY(line4[1].GetY());
11203 endface2[4].SetX(line1[1].GetX());
11204 endface2[4].SetY(line1[1].GetY());
11205
11206 gVirtualX->DrawPolyLine(2,line2);
11207 gVirtualX->DrawPolyLine(2,line3);
11208 gVirtualX->DrawPolyLine(2,line4);
11209 gVirtualX->DrawPolyLine(5,endface1);
11210 gVirtualX->DrawPolyLine(5,endface2);
11211 }
11212 c->Clear();
11213 c->cd();
11214 TH1 *hp = h3->Project3D("x");
11215 yaxis->SetRange(firstY,lastY);
11216 zaxis->SetRange(firstZ,lastZ);
11217 if (hp) {
11218 hp->SetFillColor(38);
11219 if (nbins == 1)
11220 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny),
11221 binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
11222 else {
11223 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),
11224 binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
11225 }
11226 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11227 hp->SetYTitle("Number of Entries");
11228 hp->Draw(fShowOption.Data());
11229 }
11230 }
11231 break;
11232
11233 case 2:
11234 // "y"
11235 {
11236 Int_t firstX = xaxis->GetFirst();
11237 Int_t lastX = xaxis->GetLast();
11239 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11240 xaxis->SetRange(binx,binx2);
11241 Int_t firstZ = zaxis->GetFirst();
11242 Int_t lastZ = zaxis->GetLast();
11244 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11245 zaxis->SetRange(binz,binz2);
11246 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11247 if (nbins>1 && line1[0].GetX()) {
11248 gVirtualX->DrawPolyLine(2,line2);
11249 gVirtualX->DrawPolyLine(2,line3);
11250 gVirtualX->DrawPolyLine(2,line4);
11251 gVirtualX->DrawPolyLine(5,endface1);
11252 gVirtualX->DrawPolyLine(5,endface2);
11253 }
11254 xx[0]=xaxis->GetBinCenter(binx);
11255 xx[2] = zaxis->GetBinCenter(binz);
11256 xx[1] = yaxis->GetXmin();
11257 view->WCtoNDC(xx,u);
11258 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11259 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11260 xx[1] = yaxis->GetXmax();
11261 view->WCtoNDC(xx,u);
11262 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11263 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11264 gVirtualX->DrawPolyLine(2,line1);
11265 if (nbins>1) {
11266 xx[1] = yaxis->GetXmin();
11267 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11268 xx[0] = xaxis->GetBinCenter(binx);
11269 view->WCtoNDC(xx,u);
11270 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11271 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11272 xx[1] = yaxis->GetXmax();
11273 view->WCtoNDC(xx,u);
11274 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11275 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11276
11277 xx[1] = yaxis->GetXmin();
11278 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11279 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11280 view->WCtoNDC(xx,u);
11281 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11282 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11283 xx[1] = yaxis->GetXmax();
11284 view->WCtoNDC(xx,u);
11285 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11286 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11287
11288 xx[1] = yaxis->GetXmin();
11289 xx[2] = zaxis->GetBinCenter(binz);
11290 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11291 view->WCtoNDC(xx,u);
11292 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11293 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11294 xx[1] = yaxis->GetXmax();
11295 view->WCtoNDC(xx,u);
11296 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11297 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11298
11299 endface1[0].SetX(line1[0].GetX());
11300 endface1[0].SetY(line1[0].GetY());
11301 endface1[1].SetX(line2[0].GetX());
11302 endface1[1].SetY(line2[0].GetY());
11303 endface1[2].SetX(line3[0].GetX());
11304 endface1[2].SetY(line3[0].GetY());
11305 endface1[3].SetX(line4[0].GetX());
11306 endface1[3].SetY(line4[0].GetY());
11307 endface1[4].SetX(line1[0].GetX());
11308 endface1[4].SetY(line1[0].GetY());
11309
11310 endface2[0].SetX(line1[1].GetX());
11311 endface2[0].SetY(line1[1].GetY());
11312 endface2[1].SetX(line2[1].GetX());
11313 endface2[1].SetY(line2[1].GetY());
11314 endface2[2].SetX(line3[1].GetX());
11315 endface2[2].SetY(line3[1].GetY());
11316 endface2[3].SetX(line4[1].GetX());
11317 endface2[3].SetY(line4[1].GetY());
11318 endface2[4].SetX(line1[1].GetX());
11319 endface2[4].SetY(line1[1].GetY());
11320
11321 gVirtualX->DrawPolyLine(2,line2);
11322 gVirtualX->DrawPolyLine(2,line3);
11323 gVirtualX->DrawPolyLine(2,line4);
11324 gVirtualX->DrawPolyLine(5,endface1);
11325 gVirtualX->DrawPolyLine(5,endface2);
11326 }
11327 c->Clear();
11328 c->cd();
11329 TH1 *hp = h3->Project3D("y");
11330 xaxis->SetRange(firstX,lastX);
11331 zaxis->SetRange(firstZ,lastZ);
11332 if (hp) {
11333 hp->SetFillColor(38);
11334 if (nbins == 1)
11335 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
11336 binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
11337 else
11338 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),
11339 binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
11340 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11341 hp->SetYTitle("Number of Entries");
11342 hp->Draw(fShowOption.Data());
11343 }
11344 }
11345 break;
11346
11347 case 3:
11348 // "z"
11349 {
11350 Int_t firstX = xaxis->GetFirst();
11351 Int_t lastX = xaxis->GetLast();
11353 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11354 xaxis->SetRange(binx,binx2);
11355 Int_t firstY = yaxis->GetFirst();
11356 Int_t lastY = yaxis->GetLast();
11358 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11359 yaxis->SetRange(biny,biny2);
11360 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11361 if (nbins>1 && line1[0].GetX()) {
11362 gVirtualX->DrawPolyLine(2,line2);
11363 gVirtualX->DrawPolyLine(2,line3);
11364 gVirtualX->DrawPolyLine(2,line4);
11365 gVirtualX->DrawPolyLine(5,endface1);
11366 gVirtualX->DrawPolyLine(5,endface2);
11367 }
11368 xx[0] = xaxis->GetBinCenter(binx);
11369 xx[1] = yaxis->GetBinCenter(biny);
11370 xx[2] = zaxis->GetXmin();
11371 view->WCtoNDC(xx,u);
11372 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11373 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11374 xx[2] = zaxis->GetXmax();
11375 view->WCtoNDC(xx,u);
11376 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11377 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11378 gVirtualX->DrawPolyLine(2,line1);
11379 if (nbins>1) {
11380 xx[2] = zaxis->GetXmin();
11381 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11382 xx[0] = xaxis->GetBinCenter(binx);
11383 view->WCtoNDC(xx,u);
11384 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11385 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11386 xx[2] = zaxis->GetXmax();
11387 view->WCtoNDC(xx,u);
11388 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11389 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11390
11391 xx[2] = zaxis->GetXmin();
11392 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11393 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11394 view->WCtoNDC(xx,u);
11395 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11396 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11397 xx[2] = zaxis->GetXmax();
11398 view->WCtoNDC(xx,u);
11399 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11400 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11401
11402 xx[2] = zaxis->GetXmin();
11403 xx[1] = yaxis->GetBinCenter(biny);
11404 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11405 view->WCtoNDC(xx,u);
11406 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11407 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11408 xx[2] = zaxis->GetXmax();
11409 view->WCtoNDC(xx,u);
11410 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11411 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11412
11413 endface1[0].SetX(line1[0].GetX());
11414 endface1[0].SetY(line1[0].GetY());
11415 endface1[1].SetX(line2[0].GetX());
11416 endface1[1].SetY(line2[0].GetY());
11417 endface1[2].SetX(line3[0].GetX());
11418 endface1[2].SetY(line3[0].GetY());
11419 endface1[3].SetX(line4[0].GetX());
11420 endface1[3].SetY(line4[0].GetY());
11421 endface1[4].SetX(line1[0].GetX());
11422 endface1[4].SetY(line1[0].GetY());
11423
11424 endface2[0].SetX(line1[1].GetX());
11425 endface2[0].SetY(line1[1].GetY());
11426 endface2[1].SetX(line2[1].GetX());
11427 endface2[1].SetY(line2[1].GetY());
11428 endface2[2].SetX(line3[1].GetX());
11429 endface2[2].SetY(line3[1].GetY());
11430 endface2[3].SetX(line4[1].GetX());
11431 endface2[3].SetY(line4[1].GetY());
11432 endface2[4].SetX(line1[1].GetX());
11433 endface2[4].SetY(line1[1].GetY());
11434
11435 gVirtualX->DrawPolyLine(2,line2);
11436 gVirtualX->DrawPolyLine(2,line3);
11437 gVirtualX->DrawPolyLine(2,line4);
11438 gVirtualX->DrawPolyLine(5,endface1);
11439 gVirtualX->DrawPolyLine(5,endface2);
11440 }
11441 c->Clear();
11442 c->cd();
11443 TH1 *hp = h3->Project3D("z");
11444 xaxis->SetRange(firstX,lastX);
11445 yaxis->SetRange(firstY,lastY);
11446 if (hp) {
11447 hp->SetFillColor(38);
11448 if (nbins == 1)
11449 hp->SetTitle(TString::Format("ProjectionZ of binx=%d [x=%.1f..%.1f] biny=%d [y=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
11450 biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny)));
11451 else
11452 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),
11453 biny, biny2, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny2) ) );
11454 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11455 hp->SetYTitle("Number of Entries");
11456 hp->Draw(fShowOption.Data());
11457 }
11458 }
11459 break;
11460
11461 case 4:
11462 // "xy"
11463 {
11464 Int_t first = zaxis->GetFirst();
11465 Int_t last = zaxis->GetLast();
11466 Int_t binz = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11467 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11468 zaxis->SetRange(binz,binz2);
11469 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11470 if (nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11471 xx[0] = xaxis->GetXmin();
11472 xx[1] = yaxis->GetXmax();
11473 xx[2] = zaxis->GetBinCenter(binz);
11474 view->WCtoNDC(xx,u);
11475 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11476 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11477 rect1[4].SetX(rect1[0].GetX());
11478 rect1[4].SetY(rect1[0].GetY());
11479 xx[0] = xaxis->GetXmax();
11480 view->WCtoNDC(xx,u);
11481 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11482 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11483 xx[1] = yaxis->GetXmin();
11484 view->WCtoNDC(xx,u);
11485 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11486 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11487 xx[0] = xaxis->GetXmin();
11488 view->WCtoNDC(xx,u);
11489 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11490 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11491 gVirtualX->DrawPolyLine(5,rect1);
11492 if (nbins>1) {
11493 xx[0] = xaxis->GetXmin();
11494 xx[1] = yaxis->GetXmax();
11495 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11496 view->WCtoNDC(xx,u);
11497 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11498 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11499 rect2[4].SetX(rect2[0].GetX());
11500 rect2[4].SetY(rect2[0].GetY());
11501 xx[0] = xaxis->GetXmax();
11502 view->WCtoNDC(xx,u);
11503 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11504 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11505 xx[1] = yaxis->GetXmin();
11506 view->WCtoNDC(xx,u);
11507 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11508 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11509 xx[0] = xaxis->GetXmin();
11510 view->WCtoNDC(xx,u);
11511 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11512 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11513 gVirtualX->DrawPolyLine(5,rect2);
11514 }
11515
11516 c->Clear();
11517 c->cd();
11518 TH2 *hp = (TH2*)h3->Project3D("xy");
11519 zaxis->SetRange(first,last);
11520 if (hp) {
11521 hp->SetFillColor(38);
11522 if (nbins==1)hp->SetTitle(TString::Format("ProjectionXY of binz=%d [z=%.1f..%.f]", binz,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz)));
11523 else hp->SetTitle(TString::Format("ProjectionXY, binz=[%d,%d] [z=%.1f..%.1f]", binz,binz2,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz2)));
11524 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11525 hp->SetYTitle(fH->GetXaxis()->GetTitle());
11526 hp->SetZTitle("Number of Entries");
11527 hp->Draw(fShowOption.Data());
11528 }
11529 }
11530 break;
11531
11532 case 5:
11533 // "yx"
11534 {
11535 Int_t first = zaxis->GetFirst();
11536 Int_t last = zaxis->GetLast();
11537 Int_t binz = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11538 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11539 zaxis->SetRange(binz,binz2);
11540 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11541 if (nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11542 xx[0] = xaxis->GetXmin();
11543 xx[1] = yaxis->GetXmax();
11544 xx[2] = zaxis->GetBinCenter(binz);
11545 view->WCtoNDC(xx,u);
11546 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11547 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11548 rect1[4].SetX(rect1[0].GetX());
11549 rect1[4].SetY(rect1[0].GetY());
11550 xx[0] = xaxis->GetXmax();
11551 view->WCtoNDC(xx,u);
11552 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11553 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11554 xx[1] = yaxis->GetXmin();
11555 view->WCtoNDC(xx,u);
11556 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11557 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11558 xx[0] = xaxis->GetXmin();
11559 view->WCtoNDC(xx,u);
11560 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11561 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11562 gVirtualX->DrawPolyLine(5,rect1);
11563 if (nbins>1) {
11564 xx[0] = xaxis->GetXmin();
11565 xx[1] = yaxis->GetXmax();
11566 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11567 view->WCtoNDC(xx,u);
11568 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11569 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11570 rect2[4].SetX(rect2[0].GetX());
11571 rect2[4].SetY(rect2[0].GetY());
11572 xx[0] = xaxis->GetXmax();
11573 view->WCtoNDC(xx,u);
11574 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11575 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11576 xx[1] = yaxis->GetXmin();
11577 view->WCtoNDC(xx,u);
11578 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11579 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11580 xx[0] = xaxis->GetXmin();
11581 view->WCtoNDC(xx,u);
11582 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11583 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11584 gVirtualX->DrawPolyLine(5,rect2);
11585 }
11586 c->Clear();
11587 c->cd();
11588 TH2 *hp = (TH2*)h3->Project3D("yx");
11589 zaxis->SetRange(first,last);
11590 if (hp) {
11591 hp->SetFillColor(38);
11592 if (nbins==1)hp->SetTitle(TString::Format("ProjectionYX of binz=%d [z=%.1f..%.f]", binz,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz)));
11593 else hp->SetTitle(TString::Format("ProjectionYX, binz=[%d,%d] [z=%.1f..%.1f]", binz,binz2,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz2)));
11594 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11595 hp->SetYTitle(fH->GetYaxis()->GetTitle());
11596 hp->SetZTitle("Number of Entries");
11597 hp->Draw(fShowOption.Data());
11598 }
11599 }
11600 break;
11601
11602 case 6:
11603 // "xz"
11604 {
11605 Int_t first = yaxis->GetFirst();
11606 Int_t last = yaxis->GetLast();
11607 Int_t biny = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11608 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11609 yaxis->SetRange(biny,biny2);
11610 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11611 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11612 xx[0] = xaxis->GetXmin();
11613 xx[2] = zaxis->GetXmax();
11614 xx[1] = yaxis->GetBinCenter(biny);
11615 view->WCtoNDC(xx,u);
11616 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11617 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11618 rect1[4].SetX(rect1[0].GetX());
11619 rect1[4].SetY(rect1[0].GetY());
11620 xx[0] = xaxis->GetXmax();
11621 view->WCtoNDC(xx,u);
11622 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11623 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11624 xx[2] = zaxis->GetXmin();
11625 view->WCtoNDC(xx,u);
11626 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11627 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11628 xx[0] = xaxis->GetXmin();
11629 view->WCtoNDC(xx,u);
11630 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11631 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11632 gVirtualX->DrawPolyLine(5,rect1);
11633 if (nbins>1) {
11634 xx[0] = xaxis->GetXmin();
11635 xx[2] = zaxis->GetXmax();
11636 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11637 view->WCtoNDC(xx,u);
11638 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11639 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11640 rect2[4].SetX(rect2[0].GetX());
11641 rect2[4].SetY(rect2[0].GetY());
11642 xx[0] = xaxis->GetXmax();
11643 view->WCtoNDC(xx,u);
11644 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11645 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11646 xx[2] = zaxis->GetXmin();
11647 view->WCtoNDC(xx,u);
11648 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11649 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11650 xx[0] = xaxis->GetXmin();
11651 view->WCtoNDC(xx,u);
11652 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11653 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11654 gVirtualX->DrawPolyLine(5,rect2);
11655 }
11656 c->Clear();
11657 c->cd();
11658 TH2 *hp = (TH2*)h3->Project3D("xz");
11659 yaxis->SetRange(first,last);
11660 if (hp) {
11661 hp->SetFillColor(38);
11662 if (nbins==1)hp->SetTitle(TString::Format("ProjectionXZ of biny=%d [y=%.1f..%.f]", biny,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny)));
11663 else hp->SetTitle(TString::Format("ProjectionXZ, biny=[%d,%d] [y=%.1f..%.1f]", biny,biny2,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny2)));
11664 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11665 hp->SetYTitle(fH->GetXaxis()->GetTitle());
11666 hp->SetZTitle("Number of Entries");
11667 hp->Draw(fShowOption.Data());
11668 }
11669 }
11670 break;
11671
11672 case 7:
11673 // "zx"
11674 {
11675 Int_t first = yaxis->GetFirst();
11676 Int_t last = yaxis->GetLast();
11677 Int_t biny = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11678 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11679 yaxis->SetRange(biny,biny2);
11680 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11681 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11682 xx[0] = xaxis->GetXmin();
11683 xx[2] = zaxis->GetXmax();
11684 xx[1] = yaxis->GetBinCenter(biny);
11685 view->WCtoNDC(xx,u);
11686 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11687 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11688 rect1[4].SetX(rect1[0].GetX());
11689 rect1[4].SetY(rect1[0].GetY());
11690 xx[0] = xaxis->GetXmax();
11691 view->WCtoNDC(xx,u);
11692 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11693 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11694 xx[2] = zaxis->GetXmin();
11695 view->WCtoNDC(xx,u);
11696 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11697 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11698 xx[0] = xaxis->GetXmin();
11699 view->WCtoNDC(xx,u);
11700 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11701 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11702 gVirtualX->DrawPolyLine(5,rect1);
11703 if (nbins>1) {
11704 xx[0] = xaxis->GetXmin();
11705 xx[2] = zaxis->GetXmax();
11706 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11707 view->WCtoNDC(xx,u);
11708 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11709 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11710 rect2[4].SetX(rect2[0].GetX());
11711 rect2[4].SetY(rect2[0].GetY());
11712 xx[0] = xaxis->GetXmax();
11713 view->WCtoNDC(xx,u);
11714 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11715 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11716 xx[2] = zaxis->GetXmin();
11717 view->WCtoNDC(xx,u);
11718 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11719 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11720 xx[0] = xaxis->GetXmin();
11721 view->WCtoNDC(xx,u);
11722 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11723 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11724 gVirtualX->DrawPolyLine(5,rect2);
11725 }
11726 c->Clear();
11727 c->cd();
11728 TH2 *hp = (TH2*)h3->Project3D("zx");
11729 yaxis->SetRange(first,last);
11730 if (hp) {
11731 hp->SetFillColor(38);
11732 if (nbins==1)hp->SetTitle(TString::Format("ProjectionZX of biny=%d [y=%.1f..%.f]", biny,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny)));
11733 else hp->SetTitle(TString::Format("ProjectionZX, biny=[%d,%d] [y=%.1f..%.1f]", biny,biny2,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny2)));
11734 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11735 hp->SetYTitle(fH->GetZaxis()->GetTitle());
11736 hp->SetZTitle("Number of Entries");
11737 hp->Draw(fShowOption.Data());
11738 }
11739 }
11740 break;
11741
11742 case 8:
11743 // "yz"
11744 {
11745 Int_t first = xaxis->GetFirst();
11746 Int_t last = xaxis->GetLast();
11747 Int_t binx = first + Int_t((last-first)*(px-pxmin)/(pxmax-pxmin));
11748 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11749 xaxis->SetRange(binx,binx2);
11750 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11751 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11752 xx[2] = zaxis->GetXmin();
11753 xx[1] = yaxis->GetXmax();
11754 xx[0] = xaxis->GetBinCenter(binx);
11755 view->WCtoNDC(xx,u);
11756 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11757 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11758 rect1[4].SetX(rect1[0].GetX());
11759 rect1[4].SetY(rect1[0].GetY());
11760 xx[2] = zaxis->GetXmax();
11761 view->WCtoNDC(xx,u);
11762 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11763 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11764 xx[1] = yaxis->GetXmin();
11765 view->WCtoNDC(xx,u);
11766 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11767 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11768 xx[2] = zaxis->GetXmin();
11769 view->WCtoNDC(xx,u);
11770 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11771 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11772 gVirtualX->DrawPolyLine(5,rect1);
11773 if (nbins>1) {
11774 xx[2] = zaxis->GetXmin();
11775 xx[1] = yaxis->GetXmax();
11776 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11777 view->WCtoNDC(xx,u);
11778 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11779 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11780 rect2[4].SetX(rect2[0].GetX());
11781 rect2[4].SetY(rect2[0].GetY());
11782 xx[2] = zaxis->GetXmax();
11783 view->WCtoNDC(xx,u);
11784 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11785 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11786 xx[1] = yaxis->GetXmin();
11787 view->WCtoNDC(xx,u);
11788 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11789 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11790 xx[2] = zaxis->GetXmin();
11791 view->WCtoNDC(xx,u);
11792 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11793 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11794 gVirtualX->DrawPolyLine(5,rect2);
11795 }
11796 c->Clear();
11797 c->cd();
11798 TH2 *hp = (TH2*)h3->Project3D("yz");
11799 xaxis->SetRange(first,last);
11800 if (hp) {
11801 hp->SetFillColor(38);
11802 if (nbins==1)hp->SetTitle(TString::Format("ProjectionYZ of binx=%d [x=%.1f..%.f]", binx,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx)));
11803 else hp->SetTitle(TString::Format("ProjectionYZ, binx=[%d,%d] [x=%.1f..%.1f]", binx,binx2,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx2)));
11804 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11805 hp->SetYTitle(fH->GetYaxis()->GetTitle());
11806 hp->SetZTitle("Number of Entries");
11807 hp->Draw(fShowOption.Data());
11808 }
11809 }
11810 break;
11811
11812 case 9:
11813 // "zy"
11814 {
11815 Int_t first = xaxis->GetFirst();
11816 Int_t last = xaxis->GetLast();
11817 Int_t binx = first + Int_t((last-first)*(px-pxmin)/(pxmax-pxmin));
11818 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11819 xaxis->SetRange(binx,binx2);
11820 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11821 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11822 xx[2] = zaxis->GetXmin();
11823 xx[1] = yaxis->GetXmax();
11824 xx[0] = xaxis->GetBinCenter(binx);
11825 view->WCtoNDC(xx,u);
11826 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11827 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11828 rect1[4].SetX(rect1[0].GetX());
11829 rect1[4].SetY(rect1[0].GetY());
11830 xx[2] = zaxis->GetXmax();
11831 view->WCtoNDC(xx,u);
11832 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11833 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11834 xx[1] = yaxis->GetXmin();
11835 view->WCtoNDC(xx,u);
11836 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11837 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11838 xx[2] = zaxis->GetXmin();
11839 view->WCtoNDC(xx,u);
11840 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11841 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11842 gVirtualX->DrawPolyLine(5,rect1);
11843 if (nbins>1) {
11844 xx[2] = zaxis->GetXmin();
11845 xx[1] = yaxis->GetXmax();
11846 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11847 view->WCtoNDC(xx,u);
11848 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11849 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11850 rect2[4].SetX(rect2[0].GetX());
11851 rect2[4].SetY(rect2[0].GetY());
11852 xx[2] = zaxis->GetXmax();
11853 view->WCtoNDC(xx,u);
11854 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11855 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11856 xx[1] = yaxis->GetXmin();
11857 view->WCtoNDC(xx,u);
11858 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11859 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11860 xx[2] = zaxis->GetXmin();
11861 view->WCtoNDC(xx,u);
11862 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11863 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11864 gVirtualX->DrawPolyLine(5,rect2);
11865 }
11866 c->Clear();
11867 c->cd();
11868 TH2 *hp = (TH2*)h3->Project3D("zy");
11869 xaxis->SetRange(first,last);
11870 if (hp) {
11871 hp->SetFillColor(38);
11872 if (nbins==1)hp->SetTitle(TString::Format("ProjectionZY of binx=%d [x=%.1f..%.f]", binx,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx)));
11873 else hp->SetTitle(TString::Format("ProjectionZY, binx=[%d,%d] [x=%.1f..%.1f]", binx,binx2,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx2)));
11874 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11875 hp->SetYTitle(fH->GetZaxis()->GetTitle());
11876 hp->SetZTitle("Number of Entries");
11877 hp->Draw(fShowOption.Data());
11878 }
11879 }
11880 break;
11881 }
11882 c->Update();
11883}
@ 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 Font_t GetTextFont() const
Return the text font.
Definition TAttText.h:37
virtual void SetTextAngle(Float_t tangle=0)
Set the text angle.
Definition TAttText.h:45
Class to manage histogram axis.
Definition TAxis.h:32
virtual Bool_t GetTimeDisplay() const
Definition TAxis.h:133
Bool_t IsAlphanumeric() const
Definition TAxis.h:90
const char * GetTitle() const override
Returns title of object.
Definition TAxis.h:137
virtual Double_t GetBinCenter(Int_t bin) const
Return center of bin.
Definition TAxis.cxx: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:490
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:2943
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:2916
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:2908
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:1986
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:1995
1-D histogram with a double per channel (see TH1 documentation)
Definition TH1.h:927
1-D histogram with a float per channel (see TH1 documentation)
Definition TH1.h:879
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:109
TAxis * GetZaxis()
Definition TH1.h:574
virtual EBinErrorOpt GetBinErrorOption() const
Definition TH1.h:518
virtual Float_t GetBarWidth() const
Definition TH1.h:502
virtual Double_t GetMinimumStored() const
Definition TH1.h:538
virtual Float_t GetBarOffset() const
Definition TH1.h:501
static TClass * Class()
virtual Double_t GetStdDev(Int_t axis=1) const
Returns the Standard Deviation (Sigma).
Definition TH1.cxx:7630
virtual Int_t GetNbinsY() const
Definition TH1.h:543
virtual Double_t GetBinError(Int_t bin) const
Return value of error associated to bin number bin.
Definition TH1.cxx:9088
virtual Int_t GetNbinsZ() const
Definition TH1.h:544
virtual Double_t GetNormFactor() const
Definition TH1.h:546
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:7558
virtual Double_t GetSkewness(Int_t axis=1) const
Definition TH1.cxx:7694
virtual Double_t GetContourLevelPad(Int_t level) const
Return the value of contour number "level" in Pad coordinates.
Definition TH1.cxx:8468
virtual Int_t GetDimension() const
Definition TH1.h:528
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:409
@ kUserContour
User specified contour levels.
Definition TH1.h:405
@ kNoStats
Don't draw stats box.
Definition TH1.h:404
TAxis * GetXaxis()
Definition TH1.h:572
virtual Double_t GetSumOfWeights() const
Return the sum of weights across all bins excluding under/overflows.
Definition TH1.h:560
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:4963
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:8573
virtual Int_t GetNbinsX() const
Definition TH1.h:542
virtual void SetMaximum(Double_t maximum=-1111)
Definition TH1.h:653
TAxis * GetYaxis()
Definition TH1.h:573
virtual Double_t GetBinErrorLow(Int_t bin) const
Return lower error associated to bin number bin.
Definition TH1.cxx:9104
virtual void SetMinimum(Double_t minimum=-1111)
Definition TH1.h:654
virtual Double_t Integral(Option_t *option="") const
Return integral of bin contents.
Definition TH1.cxx:7969
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:9247
virtual Double_t GetBinLowEdge(Int_t bin) const
Return bin lower edge for 1D histogram.
Definition TH1.cxx:9177
virtual Double_t GetEntries() const
Return the current number of entries.
Definition TH1.cxx:4400
TList * GetListOfFunctions() const
Definition TH1.h:489
virtual Double_t GetMeanError(Int_t axis=1) const
Return standard error of mean of this histogram along the X axis.
Definition TH1.cxx:7598
virtual Double_t GetMaximumStored() const
Definition TH1.h:534
virtual void GetMinimumAndMaximum(Double_t &min, Double_t &max) const
Retrieve the minimum and maximum values in the histogram.
Definition TH1.cxx:8759
@ 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:5063
virtual Int_t GetContour(Double_t *levels=nullptr)
Return contour values into array levels if pointer levels is non zero.
Definition TH1.cxx:8439
const Double_t * GetBuffer() const
Definition TH1.h:484
virtual Bool_t IsHighlight() const
Definition TH1.h:586
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width for 1D histogram.
Definition TH1.cxx:9188
virtual void SetContour(Int_t nlevels, const Double_t *levels=nullptr)
Set the number and values of contour levels.
Definition TH1.cxx:8511
virtual Double_t GetBinErrorUp(Int_t bin) const
Return upper error associated to bin number bin.
Definition TH1.cxx:9135
virtual Int_t GetSumw2N() const
Definition TH1.h:563
virtual Double_t GetStdDevError(Int_t axis=1) const
Return error of standard deviation estimation for Normal distribution.
Definition TH1.cxx:7678
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:8663
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:5247
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:7767
2-D histogram with a double per channel (see TH1 documentation)
Definition TH2.h:356
2-D histogram with a float per channel (see TH1 documentation)
Definition TH2.h:307
Helper class to represent a bin in the TH2Poly histogram.
Definition TH2Poly.h:25
2D Histogram with Polygonal Bins
Definition TH2Poly.h:66
static TClass * Class()
Service class for 2-D histogram classes.
Definition TH2.h:30
static TClass * Class()
The 3-D histogram classes derived from the 1-D histogram classes.
Definition TH3.h:40
static TClass * Class()
The Histogram stack class.
Definition THStack.h:40
static TClass * Class()
The histogram painter class.
static Int_t ProjectSinusoidal2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function code for sinusoidal projection from Ernst-Jan Buis Source https://en....
void Paint(Option_t *option="") override
Control routine to paint any kind of histograms
TAxis * fYaxis
Pointer to Y axis.
std::unique_ptr< TPainter3dAlgorithms > fLego
Pointer to a TPainter3dAlgorithms object.
std::vector< Double_t > fXbuf
X buffer coordinates.
Int_t fXHighlightBin
X highlight bin.
TF3 * fCurrentF3
Current TF3 function.
virtual void PaintErrors(Option_t *option)
Draw 1D histograms error bars.
~THistPainter() override
destructor.
Int_t fShowProjection2
True if a second projection must be drawn (when calling SetShowProjectionXY on a TH2)
virtual void PaintTF3()
Control function to draw a 3D implicit functions.
virtual Int_t TableInit()
Initialize various options to draw 2D histograms.
virtual void PaintTH2PolyScatterPlot(Option_t *option)
Control function to draw a TH2Poly as a scatter plot.
static Int_t ProjectMollweide2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
static Int_t ProjectAitoff2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
virtual void PaintText(Option_t *option)
Control function to draw a 1D/2D histograms with the bin values.
Int_t DistancetoPrimitive(Int_t px, Int_t py) override
Compute the distance from the point px,py to a line.
virtual void PaintAxis(Bool_t drawGridOnly=kFALSE)
Draw axis (2D case) of an histogram.
virtual void PaintColorLevelsFast(Option_t *option)
[Rendering scheme for the COL2 and COLZ2 options] (HP14)
virtual Int_t PaintInit()
Compute histogram parameters used by the drawing routines.
virtual void Paint2DErrors(Option_t *option)
Draw 2D histograms errors.
Int_t fYHighlightBin
Y highlight bin.
virtual void PaintCandlePlot(Option_t *option)
Control function to draw a 2D histogram as a candle (box) plot or violin plot
virtual void PaintScatterPlot(Option_t *option)
Control function to draw a 2D histogram as a scatter plot.
void SetShowProjectionXY(const char *option, Int_t nbinsY, Int_t nbinsX) override
virtual void PaintLego(Option_t *option)
Control function to draw a 2D histogram as a lego plot.
virtual void PaintH3(Option_t *option="")
Control function to draw a 3D histograms.
Int_t fNcuts
Number of graphical cuts.
TString fShowOption
Option to draw the projection.
virtual void PaintHighlightBin(Option_t *option="")
Paint highlight bin as TBox object.
virtual void PaintTH2PolyBins(Option_t *option)
Control function to draw a TH2Poly bins' contours.
virtual Int_t PaintContourLine(Double_t elev1, Int_t icont1, Double_t x1, Double_t y1, Double_t elev2, Int_t icont2, Double_t x2, Double_t y2, Double_t *xarr, Double_t *yarr, Int_t *itarr, Double_t *levels)
Fill the matrix xarr and yarr for Contour Plot.
Int_t fShowProjection
True if a projection must be drawn.
virtual void PaintLegoAxis(TGaxis *axis, Double_t ang)
Draw the axis for legos and surface plots.
virtual void PaintTriangles(Option_t *option)
Control function to draw a table using Delaunay triangles.
virtual void HighlightBin(Int_t px, Int_t py)
Check on highlight bin.
virtual void PaintH3Box(Int_t iopt)
Control function to draw a 3D histogram with boxes.
Int_t MakeCuts(char *cutsopt) override
Decode string choptin and fill Graphical cuts structure.
TList * fFunctions
Pointer to histogram list of functions.
void DrawPanel() override
Display a panel with all histogram drawing options.
std::unique_ptr< TPie > fPie
Pointer to a TPie in case of option PIE.
static void PaintSpecialObjects(const TObject *obj, Option_t *option)
Static function to paint special objects like vectors and matrices.
virtual void PaintTitle()
new TGaxis/////////////////// Draw the histogram title
virtual void PaintTH2PolyColorLevels(Option_t *option)
Control function to draw a TH2Poly as a color plot.
virtual std::vector< THistRenderingRegion > ComputeRenderingRegions(TAxis *pAxis, Int_t nPixels, bool isLog)
Returns the rendering regions for an axis to use in the COL2 option.
virtual void ShowProjectionX(Int_t px, Int_t py)
Show projection onto X.
virtual void PaintPalette()
Paint the color palette on the right side of the pad.
TAxis * fXaxis
Pointer to X axis.
virtual void PaintStat2(Int_t dostat, TF1 *fit)
Draw the statistics box for 2D histograms.
virtual void PaintArrows(Option_t *option)
Control function to draw a table as an arrow plot
virtual void RecalculateRange()
Recompute the histogram range following graphics operations.
void PaintStat(Int_t dostat, TF1 *fit) override
Draw the statistics box for 1D and profile histograms.
static Int_t ProjectParabolic2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function code for parabolic projection from Ernst-Jan Buis.
std::unique_ptr< TGraph2DPainter > fGraph2DPainter
Pointer to a TGraph2DPainter object.
virtual void PaintBarH(Option_t *option)
Draw a bar char in a rotated pad (X vertical, Y horizontal)
virtual void PaintStat3(Int_t dostat, TF1 *fit)
Draw the statistics box for 3D histograms.
virtual void PaintSurface(Option_t *option)
Control function to draw a 2D histogram as a surface plot.
TList * fStack
Pointer to stack of histograms (if any)
THistPainter()
Default constructor.
TH1 * fH
Pointer to histogram to paint.
virtual void PaintTH2PolyText(Option_t *option)
Control function to draw a TH2Poly as a text plot.
virtual void ShowProjection3(Int_t px, Int_t py)
Show projection (specified by fShowProjection) of a TH3.
TAxis * fZaxis
Pointer to Z axis.
void SetHistogram(TH1 *h) override
Set current histogram to h
virtual void PaintFunction(Option_t *option)
[Paint functions associated to an histogram.](HP28")
virtual void PaintBar(Option_t *option)
Draw a bar-chart in a normal pad.
static Int_t ProjectMercator2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
virtual void PaintBoxes(Option_t *option)
Control function to draw a 2D histogram as a box plot
virtual Int_t MakeChopt(Option_t *option)
Decode string choptin and fill Hoption structure.
char * GetObjectInfo(Int_t px, Int_t py) const override
Display the histogram info (bin number, contents, integral up to bin corresponding to cursor position...
TList * GetContourList(Double_t contour) const override
Get a contour (as a list of TGraphs) using the Delaunay triangulation.
void ProcessMessage(const char *mess, const TObject *obj) override
Process message mess.
void SetShowProjection(const char *option, Int_t nbins) override
Set projection.
virtual void ShowProjectionY(Int_t px, Int_t py)
Show projection onto Y.
static const char * GetBestFormat(Double_t v, Double_t e, const char *f)
This function returns the best format to print the error value (e) knowing the parameter value (v) an...
virtual void PaintContour(Option_t *option)
Control function to draw a 2D histogram as a contour plot.
TCutG * fCuts[kMaxCuts]
Pointers to graphical cuts.
virtual void PaintTable(Option_t *option)
Control function to draw 2D/3D histograms (tables).
void ExecuteEvent(Int_t event, Int_t px, Int_t py) override
Execute the actions corresponding to event.
virtual Int_t PaintInitH()
Compute histogram parameters used by the drawing routines for a rotated pad.
virtual void PaintFrame()
Calculate range and clear pad (canvas).
Int_t fCutsOpt[kMaxCuts]
Sign of each cut.
virtual void PaintH3Iso()
Control function to draw a 3D histogram with Iso Surfaces.
std::vector< Double_t > fYbuf
Y buffer coordinates.
virtual void PaintH3BoxRaster()
Control function to draw a 3D histogram with boxes.
virtual void PaintHist(Option_t *option)
Control routine to draw 1D histograms
void SetHighlight() override
Set highlight (enable/disable) mode for fH.
virtual void DefineColorLevels(Int_t ndivz)
Define the color levels used to paint legos, surfaces etc..
TString fObjectInfo
virtual void PaintColorLevels(Option_t *option)
Control function to draw a 2D histogram as a color plot.
Bool_t IsInside(Int_t x, Int_t y) override
Return kTRUE if the cell ix, iy is inside one of the graphical cuts.
A class to define a conversion from pixel values to pixel color.
Definition TAttImage.h:33
static TImagePalette * CreateCOLPalette(Int_t nContours)
Factory method to creates an image palette for histogram plotting.
An abstract interface to image processing library.
Definition TImage.h:29
static TImage * Create()
Create an image.
Definition TImage.cxx:34
void Reset()
To draw Mathematical Formula.
Definition TLatex.h:18
A doubly linked list.
Definition TList.h:38
TObject * FindObject(const char *name) const override
Find an object in this list using its name.
Definition TList.cxx: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
static TClass * Class()
A Pave (see TPave) with text, lines or/and boxes inside.
Definition TPaveText.h:21
static TClass * Class()
virtual TText * GetLine(Int_t number) const
Get Pointer to line number in this pavetext.
const char * GetName() const override
Returns name of object.
Definition TPave.h:58
Double_t GetX1NDC() const
Definition TPave.h:61
virtual void SetX2NDC(Double_t x2)
Definition TPave.h:85
void SetX(SCoord_t x)
Definition TPoint.h:48
void SetY(SCoord_t y)
Definition TPoint.h:49
Profile2D histograms are used to display the mean value of Z and its error for each cell in X,...
Definition TProfile2D.h:27
static TClass * Class()
Profile Histogram.
Definition TProfile.h:32
static TClass * Class()
Random number generator class based on the maximally quidistributed combined Tausworthe generator by ...
Definition TRandom2.h:27
Sequenceable collection abstract base class.
Basic string class.
Definition TString.h: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:640
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:659
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:699
Short_t Max(Short_t a, Short_t b)
Returns the largest of a and b.
Definition TMathBase.h:251
Double_t Prob(Double_t chi2, Int_t ndf)
Computation of the probability for a certain Chi-squared (chi2) and number of degrees of freedom (ndf...
Definition TMath.cxx:637
Double_t ATan(Double_t)
Returns the principal value of the arc tangent of x, expressed in radians.
Definition TMath.h:646
constexpr Double_t PiOver2()
Definition TMath.h:52
Double_t Log(Double_t x)
Returns the natural logarithm of x.
Definition TMath.h:762
constexpr Double_t DegToRad()
Conversion from degree to radian: .
Definition TMath.h:80
Double_t Sqrt(Double_t x)
Returns the square root of x.
Definition TMath.h:668
LongDouble_t Power(LongDouble_t x, LongDouble_t y)
Returns x raised to the power y.
Definition TMath.h:727
Short_t Min(Short_t a, Short_t b)
Returns the smallest of a and b.
Definition TMathBase.h:199
Double_t Cos(Double_t)
Returns the cosine of an angle of x radians.
Definition TMath.h:600
constexpr Double_t Pi()
Definition TMath.h:38
Bool_t AreEqualRel(Double_t af, Double_t bf, Double_t relPrec)
Comparing floating points.
Definition TMath.h:427
Double_t Sin(Double_t)
Returns the sine of an angle of x radians.
Definition TMath.h:594
Double_t Tan(Double_t)
Returns the tangent of an angle of x radians.
Definition TMath.h:606
Long64_t BinarySearch(Long64_t n, const T *array, T value)
Binary search in an array of n values to locate value.
Definition TMathBase.h:348
constexpr Double_t RadToDeg()
Conversion from radian to degree: .
Definition TMath.h:73
Double_t Log10(Double_t x)
Returns the common (base-10) logarithm of x.
Definition TMath.h:768
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:124
Histograms' drawing options structure.
Definition Hoption.h:24
int Curve
"C" A smooth Curve is drawn.
Definition Hoption.h:32
int Proj
"AITOFF", "MERCATOR", "SINUSOIDAL" and "PARABOLIC" projections for 2d plots.
Definition Hoption.h:59
int Axis
"A" Axis are not drawn around the graph.
Definition Hoption.h:30
int Box
"BOX" Draw 2D plot with proportional Boxes.
Definition Hoption.h:41
int Scat
"SCAT" Draw 2D plot a Scatter plot.
Definition Hoption.h:48
int Text
"TEXT" Draw 2D plot with the content of each cell.
Definition Hoption.h:50
int Color
"COL" Draw 2D plot with Colored boxes.
Definition Hoption.h:43
int AxisPos
"X+" and "Y+" Axis position
Definition Hoption.h:60
int List
"LIST" Generate the TObjArray "contours". To be used with option "CONT"
Definition Hoption.h:58
int Logx
log scale in X. Also set by histogram option
Definition Hoption.h:70
int Zscale
"Z" Display the color palette.
Definition Hoption.h:55
int MinimumZero
"MIN0" or gStyle->GetHistMinimumZero()
Definition Hoption.h:63
int Contour
"CONTn" Draw 2D plot as a Contour plot (0 <= n <= 5).
Definition Hoption.h:44
int Off
"][" The first and last vertical lines are not drawn.
Definition Hoption.h:35
int Func
"FUNC" Draw only the function (for example in case of fit).
Definition Hoption.h:45
long Candle
"CANDLE" and "VIOLIN" Draw a 2D histogram as candle/box plot or violin plot.
Definition Hoption.h:53
int Spec
"SPEC" TSpectrum graphics
Definition Hoption.h:61
int FrontBox
"FB" Suppress the front box for the 3D plots.
Definition Hoption.h:56
int Pie
"PIE" Draw 1D plot as a pie chart.
Definition Hoption.h:52
int Star
"*" With option "P", a * is plotted at each point.
Definition Hoption.h:39
int Zero
"0" if selected with any LEGO option the empty bins are not drawn.
Definition Hoption.h:62
int Logz
log scale in Z. Also set by histogram option
Definition Hoption.h:72
int Tri
"TRI" Draw TGraph2D with Delaunay triangles.
Definition Hoption.h:51
int BackBox
"BB" Suppress the back box for the 3D plots.
Definition Hoption.h:57
int Mark
"P" The current Marker is drawn at each point.
Definition Hoption.h:37
int Arrow
"ARR" Draw 2D plot with Arrows.
Definition Hoption.h:40
int Line
"L" A simple polyline through every point is drawn.
Definition Hoption.h:36
int Same
"SAME" Histogram is plotted in the current pad.
Definition Hoption.h:38
int Lego
"LEGO" and "LEGOn" Draw as a Lego plot(1 <= n <= 4).
Definition Hoption.h:47
int Bar
"B", "BAR" and "HBAR" A Bar chart is drawn at each point.
Definition Hoption.h:31
int Fill
"F" A fill area is drawn ("CF" draw a smooth fill area).
Definition Hoption.h:34
int Hist
"HIST" Draw only the histogram.
Definition Hoption.h:46
int Surf
"SURF" and "SURFn" Draw as a Surface ((1 <= n <= 4).
Definition Hoption.h:49
int Logy
log scale in Y. Also set by histogram option
Definition Hoption.h:71
int System
"POL", "CYL", "SPH" and "PSR" Type of coordinate system for 3D plots.
Definition Hoption.h:54
int Error
"En" Draw Errors with current marker type and size (0 <= n <=6).
Definition Hoption.h:33
Histogram parameters structure.
Definition Hparam.h:27
Double_t baroffset
Offset of bin for bars or legos [0,1].
Definition Hparam.h:42
Double_t ylowedge
Low edge of axis.
Definition Hparam.h:33
Double_t xmin
Minimum value along X.
Definition Hparam.h:30
Int_t ylast
Last bin number along Y.
Definition Hparam.h:47
Int_t xfirst
First bin number along X.
Definition Hparam.h:44
Double_t zmin
Minimum value along Z.
Definition Hparam.h:38
Double_t xbinsize
Bin size in case of equidistant bins.
Definition Hparam.h:28
Double_t ymin
Minimum value along y.
Definition Hparam.h:34
Double_t allchan
Integrated sum of contents.
Definition Hparam.h:41
Double_t xlowedge
Low edge of axis.
Definition Hparam.h:29
Double_t ymax
Maximum value along y.
Definition Hparam.h:35
Double_t factor
Multiplication factor (normalization)
Definition Hparam.h:40
Int_t xlast
Last bin number along X.
Definition Hparam.h:45
Double_t ybinsize
Bin size in case of equidistant bins.
Definition Hparam.h:32
Double_t barwidth
Width of bin for bars and legos [0,1].
Definition Hparam.h:43
Double_t zmax
Maximum value along Z.
Definition Hparam.h:39
Double_t xmax
Maximum value along X.
Definition Hparam.h:31
Int_t yfirst
First bin number along Y.
Definition Hparam.h:46
auto * th2
Definition textalign.C:18
TMarker m
Definition textangle.C:8
TLine l
Definition textangle.C:4
auto * tt
Definition textangle.C:16