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 `$ROOTSYS/tutorials/visualisation/gl/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
2978`$ROOTSYS/tutorials/visualisation/gl/glparametric.C` shows how to create parametric
2979equations and visualize the surface.
2980
2981\anchor HP29f
2982#### Interaction with the plots
2983
2984All the interactions are implemented via standard methods
2985`DistancetoPrimitive()` and `ExecuteEvent()`. That's why all the
2986interactions with the OpenGL plots are possible only when the mouse cursor is
2987in the plot's area (the plot's area is the part of a the pad occupied by
2988gl-produced picture). If the mouse cursor is not above gl-picture, the standard
2989pad interaction is performed.
2990
2991\anchor HP29g
2992#### Selectable parts
2993
2994Different parts of the plot can be selected:
2995
2996- xoz, yoz, xoy back planes: When such a plane selected, it's highlighted in green
2997 if the dynamic slicing by this plane is supported, and it's highlighted in red,
2998 if the dynamic slicing is not supported.
2999- The plot itself:
3000 On surfaces, the selected surface is outlined in red. (TF3 and
3001 ISO are not outlined). On lego plots, the selected bin is
3002 highlighted. The bin number and content are displayed in pad's
3003 status bar. In box plots, the box or sphere is highlighted and
3004 the bin info is displayed in pad's status bar.
3005
3006
3007\anchor HP29h
3008#### Rotation and zooming
3009
3010
3011- Rotation:
3012 When the plot is selected, it can be rotated by pressing and
3013 holding the left mouse button and move the cursor.
3014- Zoom/Unzoom:
3015 Mouse wheel or 'j', 'J', 'k', 'K' keys.
3016
3017
3018\anchor HP29i
3019#### Panning
3020
3021The selected plot can be moved in a pad's area by pressing and
3022holding the left mouse button and the shift key.
3023
3024\anchor HP29j
3025#### Box cut
3026
3027Surface, iso, box, TF3 and parametric painters support box cut by
3028pressing the 'c' or 'C' key when the mouse cursor is in a plot's
3029area. That will display a transparent box, cutting away part of the
3030surface (or boxes) in order to show internal part of plot. This box
3031can be moved inside the plot's area (the full size of the box is
3032equal to the plot's surrounding box) by selecting one of the box
3033cut axes and pressing the left mouse button to move it.
3034
3035\anchor HP29k
3036#### Plot specific interactions (dynamic slicing etc.)
3037
3038Currently, all gl-plots support some form of slicing. When back plane
3039is selected (and if it's highlighted in green) you can press and hold
3040left mouse button and shift key and move this back plane inside
3041plot's area, creating the slice. During this "slicing" plot becomes
3042semi-transparent. To remove all slices (and projected curves for
3043surfaces) double click with left mouse button in a plot's area.
3044
3045\anchor HP29l
3046#### Surface with option "GLSURF"
3047
3048The surface profile is displayed on the slicing plane.
3049The profile projection is drawn on the back plane
3050by pressing `'p'` or `'P'` key.
3051
3052\anchor HP29m
3053#### TF3
3054
3055The contour plot is drawn on the slicing plane. For TF3 the color
3056scheme can be changed by pressing 's' or 'S'.
3057
3058\anchor HP29n
3059#### Box
3060
3061The contour plot corresponding to slice plane position is drawn in real time.
3062
3063\anchor HP29o
3064#### Iso
3065
3066Slicing is similar to "GLBOX" option.
3067
3068\anchor HP29p
3069#### Parametric plot
3070
3071No slicing. Additional keys: 's' or 'S' to change color scheme -
3072about 20 color schemes supported ('s' for "scheme"); 'l' or 'L' to
3073increase number of polygons ('l' for "level" of details), 'w' or 'W'
3074to show outlines ('w' for "wireframe").
3075
3076\anchor HP30
3077#### Highlight mode for histogram
3078
3079\since **ROOT version 6.15/01**
3080
3081\image html hlHisto3_top.gif "Highlight mode"
3082
3083Highlight mode is implemented for `TH1` (and for `TGraph`) class. When
3084highlight mode is on, mouse movement over the bin will be represented
3085graphically. Bin will be highlighted as "bin box" (presented by box
3086object). Moreover, any highlight (change of bin) emits signal
3087`TCanvas::Highlighted()` which allows the user to react and call their own
3088function. For a better understanding see also the tutorial `hist043` to `hist046`
3089lacated in `$ROOTSYS/tutorials/hist/`.
3090
3091Highlight mode is switched on/off by `TH1::SetHighlight()` function
3092or interactively from `TH1` context menu. `TH1::IsHighlight()` to verify
3093whether the highlight mode enabled or disabled, default it is disabled.
3094
3095~~~ {.cpp}
3096 root [0] .x $ROOTSYS/tutorials/hsimple.C
3097 root [1] hpx->SetHighlight(kTRUE) // or interactively from TH1 context menu
3098 root [2] hpx->IsHighlight()
3099 (bool) true
3100~~~
3101
3102\image html hlsimple_nofun.gif "Highlight mode for histogram"
3103
3104\anchor HP30a
3105#### Highlight mode and user function
3106
3107The user can use (connect) `TCanvas::Highlighted()` signal, which is always
3108emitted if there is a highlight bin and call user function via signal
3109and slot communication mechanism. `TCanvas::Highlighted()` is similar
3110`TCanvas::Picked()`
3111
3112- when selected object (histogram as a whole) is different from previous
3113then emit `Picked()` signal
3114- when selected (highlighted) bin from histogram is different from previous
3115then emit `Highlighted()` signal
3116
3117Any user function (or functions) has to be defined
3118`UserFunction(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)`.
3119In example (see below) has name `PrintInfo()`. All parameters of user
3120function are taken from
3121
3122 void TCanvas::Highlighted(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)
3123
3124- `pad` is pointer to pad with highlighted histogram
3125- `obj` is pointer to highlighted histogram
3126- `x` is highlighted x bin for 1D histogram
3127- `y` is highlighted y bin for 2D histogram (for 1D histogram not in use)
3128
3129Example how to create a connection from any `TCanvas` object to a user
3130`UserFunction()` slot (see also `TQObject::Connect()` for additional info)
3131
3132 TQObject::Connect("TCanvas", "Highlighted(TVirtualPad*,TObject*,Int_t,Int_t)",
3133 0, 0, "UserFunction(TVirtualPad*,TObject*,Int_t,Int_t)");
3134
3135or use non-static "simplified" function
3136`TCanvas::HighlightConnect(const char *slot)`
3137
3138 c1->HighlightConnect("UserFunction(TVirtualPad*,TObject*,Int_t,Int_t)");
3139
3140NOTE the signal and slot string must have a form
3141"(TVirtualPad*,TObject*,Int_t,Int_t)"
3142
3143 root [0] .x $ROOTSYS/tutorials/hsimple.C
3144 root [1] hpx->SetHighlight(kTRUE)
3145 root [2] .x hlprint.C
3146
3147file `hlprint.C`
3148~~~ {.cpp}
3149void PrintInfo(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)
3150{
3151 auto h = (TH1F *)obj;
3152 if (!h->IsHighlight()) // after highlight disabled
3153 h->SetTitle("highlight disable");
3154 else
3155 h->SetTitle(TString::Format("bin[%03d] (%5.2f) content %g", x,
3156 h->GetBinCenter(x), h->GetBinContent(x)));
3157 pad->Update();
3158}
3159
3160void hlprint()
3161{
3162 if (!gPad) return;
3163 gPad->GetCanvas()->HighlightConnect("PrintInfo(TVirtualPad*,TObject*,Int_t,Int_t)");
3164}
3165~~~
3166
3167\image html hlsimple.gif "Highlight mode and simple user function"
3168
3169For more complex demo please see for example `$ROOTSYS/tutorials/io/tree/tree200_temperature.C` file.
3170
3171*/
3172
3174
3177
3178const Int_t kNMAX = 2000;
3179
3180const Int_t kMAXCONTOUR = 104;
3182
3183static std::unique_ptr<TBox> gXHighlightBox, gYHighlightBox; // highlight X and Y box
3184
3206
3208
3209////////////////////////////////////////////////////////////////////////////////
3210/// Default constructor.
3211
3213{
3214 fH = nullptr;
3215 fXaxis = nullptr;
3216 fYaxis = nullptr;
3217 fZaxis = nullptr;
3218 fFunctions = nullptr;
3219 fNcuts = 0;
3220 fStack = nullptr;
3221 fShowProjection = 0;
3222 fShowProjection2 = 0;
3223 fShowOption = "";
3224 for (int i=0; i<kMaxCuts; i++) {
3225 fCuts[i] = nullptr;
3226 fCutsOpt[i] = 0;
3227 }
3228 fXHighlightBin = -1;
3229 fYHighlightBin = -1;
3230 fCurrentF3 = nullptr;
3231
3232 gStringEntries = gEnv->GetValue("Hist.Stats.Entries", "Entries");
3233 gStringMean = gEnv->GetValue("Hist.Stats.Mean", "Mean");
3234 gStringMeanX = gEnv->GetValue("Hist.Stats.MeanX", "Mean x");
3235 gStringMeanY = gEnv->GetValue("Hist.Stats.MeanY", "Mean y");
3236 gStringMeanZ = gEnv->GetValue("Hist.Stats.MeanZ", "Mean z");
3237 gStringStdDev = gEnv->GetValue("Hist.Stats.StdDev", "Std Dev");
3238 gStringStdDevX = gEnv->GetValue("Hist.Stats.StdDevX", "Std Dev x");
3239 gStringStdDevY = gEnv->GetValue("Hist.Stats.StdDevY", "Std Dev y");
3240 gStringStdDevZ = gEnv->GetValue("Hist.Stats.StdDevZ", "Std Dev z");
3241 gStringUnderflow = gEnv->GetValue("Hist.Stats.Underflow", "Underflow");
3242 gStringOverflow = gEnv->GetValue("Hist.Stats.Overflow", "Overflow");
3243 gStringIntegral = gEnv->GetValue("Hist.Stats.Integral", "Integral");
3244 gStringIntegralBinWidth = gEnv->GetValue("Hist.Stats.IntegralBinWidth", "Integral(w)");
3245 gStringSkewness = gEnv->GetValue("Hist.Stats.Skewness", "Skewness");
3246 gStringSkewnessX = gEnv->GetValue("Hist.Stats.SkewnessX", "Skewness x");
3247 gStringSkewnessY = gEnv->GetValue("Hist.Stats.SkewnessY", "Skewness y");
3248 gStringSkewnessZ = gEnv->GetValue("Hist.Stats.SkewnessZ", "Skewness z");
3249 gStringKurtosis = gEnv->GetValue("Hist.Stats.Kurtosis", "Kurtosis");
3250 gStringKurtosisX = gEnv->GetValue("Hist.Stats.KurtosisX", "Kurtosis x");
3251 gStringKurtosisY = gEnv->GetValue("Hist.Stats.KurtosisY", "Kurtosis y");
3252 gStringKurtosisZ = gEnv->GetValue("Hist.Stats.KurtosisZ", "Kurtosis z");
3253}
3254
3255////////////////////////////////////////////////////////////////////////////////
3256/// destructor.
3257
3261
3262////////////////////////////////////////////////////////////////////////////////
3263/// Compute the distance from the point px,py to a line.
3264///
3265/// Compute the closest distance of approach from point px,py to elements of
3266/// an histogram. The distance is computed in pixels units.
3267///
3268/// Algorithm: Currently, this simple model computes the distance from the mouse
3269/// to the histogram contour only.
3270
3272{
3273
3274 Double_t defaultLabelSize = 0.04; // See TAttAxis.h for source of this value
3275
3276 const Int_t big = 9999;
3277 const Int_t kMaxDiff = 7;
3278
3279 if (fPie)
3280 return fPie->DistancetoPrimitive(px, py);
3281
3282 Double_t x = gPad->AbsPixeltoX(px);
3283 Double_t x1 = gPad->AbsPixeltoX(px+1);
3284
3285 Int_t puxmin = gPad->XtoAbsPixel(gPad->GetUxmin());
3286 Int_t puymin = gPad->YtoAbsPixel(gPad->GetUymin());
3287 Int_t puxmax = gPad->XtoAbsPixel(gPad->GetUxmax());
3288 Int_t puymax = gPad->YtoAbsPixel(gPad->GetUymax());
3289 Int_t curdist = big;
3291 Bool_t dsame;
3292 TObject *PadPointer = gPad->GetPadPointer();
3293 if (!PadPointer) return 0;
3294 TString doption = PadPointer->GetDrawOption();
3295 Double_t factor = 1;
3296 if (fH->GetNormFactor() != 0) {
3297 factor = fH->GetNormFactor()/fH->GetSumOfWeights();
3298 }
3299 // return if point is not in the histogram area
3300
3301 // If a 3D view exists, check distance to axis
3302 TView *view = gPad->GetView();
3303 Int_t d1,d2,d3;
3304 if (view && Hoption.Contour != 14) {
3305 Double_t ratio;
3306 d3 = view->GetDistancetoAxis(3, px, py, ratio);
3307 if (d3 <= kMaxDiff) {gPad->SetSelected(fZaxis); return 0;}
3308 d1 = view->GetDistancetoAxis(1, px, py, ratio);
3309 if (d1 <= kMaxDiff) {gPad->SetSelected(fXaxis); return 0;}
3310 d2 = view->GetDistancetoAxis(2, px, py, ratio);
3311 if (d2 <= kMaxDiff) {gPad->SetSelected(fYaxis); return 0;}
3312 if ( px > puxmin && px < puxmax && py > puymax && py < puymin) curdist = 1;
3313 goto FUNCTIONS;
3314 }
3315 // check if point is close to an axis
3316 doption.ToLower();
3317 dsame = kFALSE;
3318 if (doption.Contains("same")) dsame = kTRUE;
3319
3321 if (doption.Contains("y+")) {
3323 if (px <= xyaxis+dyaxis && px >= xyaxis && py >puymax && py < puymin) {
3324 if (!dsame) {
3325 if (gPad->IsVertical()) gPad->SetSelected(fYaxis);
3326 else gPad->SetSelected(fXaxis);
3327 return 0;
3328 }
3329 }
3330 } else {
3332 if (px >= xyaxis-dyaxis && px <= xyaxis && py >puymax && py < puymin) {
3333 if (!dsame) {
3334 if (gPad->IsVertical()) gPad->SetSelected(fYaxis);
3335 else gPad->SetSelected(fXaxis);
3336 return 0;
3337 }
3338 }
3339 }
3340
3342 if (doption.Contains("x+")) {
3344 if (py >= yxaxis-dxaxis && py <= yxaxis && px <puxmax && px > puxmin) {
3345 if (!dsame) {
3346 if (gPad->IsVertical()) gPad->SetSelected(fXaxis);
3347 else gPad->SetSelected(fYaxis);
3348 return 0;
3349 }
3350 }
3351 } else {
3353 if (yxaxis < puymin) yxaxis = puymin;
3355 if (!dsame) {
3356 if (gPad->IsVertical()) gPad->SetSelected(fXaxis);
3357 else gPad->SetSelected(fYaxis);
3358 return 0;
3359 }
3360 }
3361 }
3362
3363 if (fH->IsHighlight()) { // only if highlight is enable
3364 if ((px > puxmin) && (py < puymin) && (px < puxmax) && (py > puymax))
3365 HighlightBin(px, py);
3366 }
3367
3368 // if object is 2D or 3D return this object
3369 if (fH->GetDimension() == 2) {
3370 if (fH->InheritsFrom(TH2Poly::Class())) {
3371 TH2Poly *th2 = (TH2Poly*)fH;
3373 gPad->GetRangeAxis(xmin, ymin, xmax, ymax);
3374 Double_t pxu = gPad->AbsPixeltoX(px);
3375 Double_t pyu = gPad->AbsPixeltoY(py);
3376 if ((pxu>xmax) || (pxu < xmin) || (pyu>ymax) || (pyu < ymin)) {
3377 curdist = big;
3378 goto FUNCTIONS;
3379 } else {
3380 Int_t bin = th2->FindBin(pxu, pyu);
3381 if (bin>0) curdist = 1;
3382 else curdist = big;
3383 goto FUNCTIONS;
3384 }
3385 }
3386 Int_t delta2 = 5; //Give a margin of delta2 pixels to be in the 2-d area
3387 if ( px > puxmin + delta2
3388 && px < puxmax - delta2
3389 && py > puymax + delta2
3390 && py < puymin - delta2) {curdist =1; goto FUNCTIONS;}
3391 }
3392
3393 // point is inside histogram area. Find channel number
3394 if (gPad->IsVertical()) {
3395 Int_t bin = fXaxis->FindFixBin(gPad->PadtoX(x));
3396 Int_t binsup = fXaxis->FindFixBin(gPad->PadtoX(x1));
3397 Double_t binval = factor*fH->GetBinContent(bin);
3398 Int_t pybin = gPad->YtoAbsPixel(gPad->YtoPad(binval));
3399 if (binval == 0 && pybin < puymin) pybin = 10000;
3400 // special case if more than one bin for the pixel
3401 if (binsup-bin>1) {
3405 for (Int_t ibin=bin+1; ibin<binsup; ibin++) {
3409 }
3410 Int_t pybinmin = gPad->YtoAbsPixel(gPad->YtoPad(binvalmax));
3411 Int_t pybinmax = gPad->YtoAbsPixel(gPad->YtoPad(binvalmin));
3413 }
3414 if (bin != binsup) { // Mouse on bin border
3416 Int_t pybinsub = gPad->YtoAbsPixel(gPad->YtoPad(binsupval));
3417 if (py <= TMath::Max(pybinsub,pybin) && py >= TMath::Min(pybinsub,pybin) && pybin != 10000) return 0;
3418 }
3419 if (TMath::Abs(py - pybin) <= kMaxDiff) return TMath::Abs(py - pybin);
3420 } else {
3421 Double_t y = gPad->AbsPixeltoY(py);
3422 Double_t y1 = gPad->AbsPixeltoY(py+1);
3423 Int_t bin = fXaxis->FindFixBin(gPad->PadtoY(y));
3424 Int_t binsup = fXaxis->FindFixBin(gPad->PadtoY(y1));
3425 Double_t binval = factor*fH->GetBinContent(bin);
3426 Int_t pxbin = gPad->XtoAbsPixel(gPad->XtoPad(binval));
3427 if (binval == 0 && pxbin > puxmin) pxbin = 10000;
3428 // special case if more than one bin for the pixel
3429 if (binsup-bin>1) {
3433 for (Int_t ibin=bin+1; ibin<binsup; ibin++) {
3437 }
3438 Int_t pxbinmin = gPad->XtoAbsPixel(gPad->XtoPad(binvalmax));
3439 Int_t pxbinmax = gPad->XtoAbsPixel(gPad->XtoPad(binvalmin));
3441 }
3442 if (TMath::Abs(px - pxbin) <= kMaxDiff) return TMath::Abs(px - pxbin);
3443 }
3444 // Loop on the list of associated functions and user objects
3445FUNCTIONS:
3446 TObject *f;
3447 TIter next(fFunctions);
3448 while ((f = (TObject*) next())) {
3449 Int_t dist;
3450 if (f->InheritsFrom(TF1::Class())) dist = f->DistancetoPrimitive(-px,py);
3451 else dist = f->DistancetoPrimitive(px,py);
3452 if (dist < kMaxDiff) {gPad->SetSelected(f); return dist;}
3453 }
3454 return curdist;
3455}
3456
3457////////////////////////////////////////////////////////////////////////////////
3458/// Display a panel with all histogram drawing options.
3459
3461{
3462
3463 gCurrentHist = fH;
3464 if (!gPad) {
3465 Error("DrawPanel", "need to draw histogram first");
3466 return;
3467 }
3469 editor->Show();
3470 gROOT->ProcessLine(TString::Format("((TCanvas*)0x%zx)->Selected((TVirtualPad*)0x%zx,(TObject*)0x%zx,1)",
3471 (size_t)gPad->GetCanvas(), (size_t)gPad, (size_t)fH).Data());
3472}
3473
3474////////////////////////////////////////////////////////////////////////////////
3475/// Execute the actions corresponding to `event`.
3476///
3477/// This function is called when a histogram is clicked with the locator at
3478/// the pixel position px,py.
3479
3481{
3482
3483 if (!gPad) return;
3484
3485 static Int_t bin, px1, py1, px2, py2, pyold;
3486 static std::unique_ptr<TBox> zoombox;
3488
3489 Int_t bin1, bin2;
3490 Double_t xlow, xup, ylow, binval, x, baroffset, barwidth, binwidth;
3491 Bool_t opaque = gPad->OpaqueMoving();
3492
3493 if (!gPad->IsEditable()) return;
3494
3495 if (fPie) {
3496 fPie->ExecuteEvent(event, px, py);
3497 return;
3498 }
3499 // come here if we have a lego/surface in the pad
3500 TView *view = gPad->GetView();
3501
3502 if (!fShowProjection && view && !view->TestBit(kCannotRotate)) {
3503 view->ExecuteRotateView(event, px, py);
3504 return;
3505 }
3506
3507 TAxis *xaxis = fH->GetXaxis();
3508 TAxis *yaxis = fH->GetYaxis();
3509 Int_t dimension = fH->GetDimension();
3510
3511 // In case of option SAME the axis must be the ones of the first drawn histogram
3512 TString IsSame = fH->GetDrawOption();
3513 IsSame.ToLower();
3514 if (IsSame.Index("same")>=0) {
3515 TH1 *h1;
3516 TIter next(gPad->GetListOfPrimitives());
3517 while ((h1 = (TH1 *)next())) {
3518 if (!h1->InheritsFrom(TH1::Class())) continue;
3519 xaxis = h1->GetXaxis();
3520 yaxis = h1->GetYaxis();
3521 break;
3522 }
3523 }
3524
3525 Double_t factor = 1;
3526 if (fH->GetNormFactor() != 0) {
3527 factor = fH->GetNormFactor()/fH->GetSumOfWeights();
3528 }
3529
3530 switch (event) {
3531
3532 case kButton1Down:
3533
3534 if (!opaque) gVirtualX->SetLineColor(-1);
3535 fH->TAttLine::Modify();
3536
3537 if (opaque && dimension ==2) {
3538 zbx1 = gPad->AbsPixeltoX(px);
3539 zbx2 = gPad->AbsPixeltoX(px);
3540 zby1 = gPad->AbsPixeltoY(py);
3541 zby2 = gPad->AbsPixeltoY(py);
3542 px1 = px;
3543 py1 = py;
3544 if (gPad->GetLogx()) {
3545 zbx1 = TMath::Power(10,zbx1);
3546 zbx2 = TMath::Power(10,zbx2);
3547 }
3548 if (gPad->GetLogy()) {
3549 zby1 = TMath::Power(10,zby1);
3550 zby2 = TMath::Power(10,zby2);
3551 }
3552 if (zoombox) Error("ExecuteEvent", "Last zoom box was not deleted");
3553 zoombox = std::make_unique<TBox>(zbx1, zby1, zbx2, zby2);
3554 Int_t ci = TColor::GetColor("#7d7dff");
3555 TColor *zoomcolor = gROOT->GetColor(ci);
3556 if (!TCanvas::SupportAlpha() || !zoomcolor) zoombox->SetFillStyle(3002);
3557 else zoomcolor->SetAlpha(0.5);
3558 zoombox->SetFillColor(ci);
3559 zoombox->Draw();
3560 gPad->Modified();
3561 gPad->Update();
3562 }
3563 // No break !!!
3564
3565 case kMouseMotion:
3566
3567 if (fShowProjection) {ShowProjection3(px,py); break;}
3568
3569 gPad->SetCursor(kPointer);
3570 if (dimension ==1) {
3571 if (Hoption.Bar) {
3572 baroffset = fH->GetBarOffset();
3573 barwidth = fH->GetBarWidth();
3574 } else {
3575 baroffset = 0;
3576 barwidth = 1;
3577 }
3578 x = gPad->AbsPixeltoX(px);
3579 bin = fXaxis->FindFixBin(gPad->PadtoX(x));
3580 binwidth = fXaxis->GetBinWidth(bin);
3581 xlow = gPad->XtoPad(fXaxis->GetBinLowEdge(bin) + baroffset*binwidth);
3582 xup = gPad->XtoPad(xlow + barwidth*binwidth);
3583 ylow = gPad->GetUymin();
3584 px1 = gPad->XtoAbsPixel(xlow);
3585 px2 = gPad->XtoAbsPixel(xup);
3586 py1 = gPad->YtoAbsPixel(ylow);
3587 py2 = py;
3588 pyold = py;
3589 if (gROOT->GetEditHistograms()) gPad->SetCursor(kArrowVer);
3590 }
3591
3592 break;
3593
3594 case kButton1Motion:
3595
3596 if (dimension ==1) {
3597 if (gROOT->GetEditHistograms()) {
3598 if (!opaque) {
3599 gVirtualX->DrawBox(px1, py1, px2, py2,TVirtualX::kHollow); // Draw the old box
3600 py2 += py - pyold;
3601 gVirtualX->DrawBox(px1, py1, px2, py2,TVirtualX::kHollow); // Draw the new box
3602 pyold = py;
3603 } else {
3604 py2 += py - pyold;
3605 pyold = py;
3606 binval = gPad->PadtoY(gPad->AbsPixeltoY(py2))/factor;
3607 fH->SetBinContent(bin,binval);
3608 gPad->Modified(kTRUE);
3609 }
3610 }
3611 }
3612
3613 if (opaque && dimension ==2) {
3614 if (TMath::Abs(px1-px)>5 && TMath::Abs(py1-py)>5) {
3615 zbx2 = gPad->AbsPixeltoX(px);
3616 zby2 = gPad->AbsPixeltoY(py);
3617 if (gPad->GetLogx()) zbx2 = TMath::Power(10,zbx2);
3618 if (gPad->GetLogy()) zby2 = TMath::Power(10,zby2);
3619 if (zoombox) {
3620 zoombox->SetX2(zbx2);
3621 zoombox->SetY2(zby2);
3622 }
3623 gPad->Modified();
3624 gPad->Update();
3625 }
3626 }
3627
3628 break;
3629
3630 case kWheelUp:
3631
3632 if (dimension ==2) {
3633 bin1 = xaxis->GetFirst()+1;
3634 bin2 = xaxis->GetLast()-1;
3635 bin1 = TMath::Max(bin1, 1);
3636 bin2 = TMath::Min(bin2, xaxis->GetNbins());
3637 if (bin2>bin1) xaxis->SetRange(bin1,bin2);
3638 bin1 = yaxis->GetFirst()+1;
3639 bin2 = yaxis->GetLast()-1;
3640 bin1 = TMath::Max(bin1, 1);
3641 bin2 = TMath::Min(bin2, yaxis->GetNbins());
3642 if (bin2>bin1) yaxis->SetRange(bin1,bin2);
3643 }
3644 gPad->Modified();
3645 gPad->Update();
3646
3647 break;
3648
3649 case kWheelDown:
3650
3651 if (dimension == 2) {
3652 bin1 = xaxis->GetFirst()-1;
3653 bin2 = xaxis->GetLast()+1;
3654 bin1 = TMath::Max(bin1, 1);
3655 bin2 = TMath::Min(bin2, xaxis->GetNbins());
3656 const bool resetXaxisRange = bin1 == 1 && xaxis->GetFirst() == 1 && bin2 == xaxis->GetNbins() && xaxis->GetLast() == xaxis->GetNbins();
3657 if (bin2>bin1) xaxis->SetRange(bin1,bin2);
3658 if (resetXaxisRange) xaxis->ResetBit(TAxis::kAxisRange);
3659 bin1 = yaxis->GetFirst()-1;
3660 bin2 = yaxis->GetLast()+1;
3661 bin1 = TMath::Max(bin1, 1);
3662 bin2 = TMath::Min(bin2, yaxis->GetNbins());
3663 const bool resetYaxisRange = bin1 == 1 && yaxis->GetFirst() == 1 && bin2 == yaxis->GetNbins() && yaxis->GetLast() == yaxis->GetNbins();
3664 if (bin2>bin1) yaxis->SetRange(bin1,bin2);
3665 if (resetYaxisRange) yaxis->ResetBit(TAxis::kAxisRange);
3666 }
3667 gPad->Modified();
3668 gPad->Update();
3669
3670 break;
3671
3672 case kButton1Up:
3673 if (dimension ==1) {
3674 if (gROOT->GetEditHistograms()) {
3675 binval = gPad->PadtoY(gPad->AbsPixeltoY(py2))/factor;
3676 fH->SetBinContent(bin,binval);
3677 PaintInit(); // recalculate Hparam structure and recalculate range
3678 }
3679
3680 // might resize pad pixmap so should be called before any paint routine
3682 }
3683 if (opaque && dimension ==2) {
3684 if (zoombox) {
3685 Double_t x1 = TMath::Min(zoombox->GetX1(), zoombox->GetX2());
3686 Double_t x2 = TMath::Max(zoombox->GetX1(), zoombox->GetX2());
3687 Double_t y1 = TMath::Min(zoombox->GetY1(), zoombox->GetY2());
3688 Double_t y2 = TMath::Max(zoombox->GetY1(), zoombox->GetY2());
3689 x1 = TMath::Max(x1,xaxis->GetXmin());
3690 x2 = TMath::Min(x2,xaxis->GetXmax());
3691 y1 = TMath::Max(y1,yaxis->GetXmin());
3692 y2 = TMath::Min(y2,yaxis->GetXmax());
3693 if (x1<x2 && y1<y2) {
3694 xaxis->SetRangeUser(x1, x2);
3695 yaxis->SetRangeUser(y1, y2);
3696 }
3697 zoombox.reset();
3698 }
3699 }
3700 gPad->Modified(kTRUE);
3701 if (opaque) gVirtualX->SetLineColor(-1);
3702
3703 break;
3704
3705 case kButton1Locate:
3706
3707 ExecuteEvent(kButton1Down, px, py);
3708
3709 while (true) {
3710 px = py = 0;
3711 event = gVirtualX->RequestLocator(1, 1, px, py);
3712
3714
3715 if (event != -1) { // button is released
3716 ExecuteEvent(kButton1Up, px, py);
3717 return;
3718 }
3719 }
3720 }
3721}
3722
3723////////////////////////////////////////////////////////////////////////////////
3724/// Get a contour (as a list of TGraphs) using the Delaunay triangulation.
3725
3727{
3728 // Check if fH contains a TGraphDelaunay2D
3730 TGraphDelaunay2D *dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
3731 // try with the old painter
3732 TGraphDelaunay *dtOld = nullptr;
3733 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
3734
3735 if (!dt && !dtOld) return nullptr;
3736
3737 gCurrentHist = fH;
3738
3739 if (!fGraph2DPainter)
3740 ((THistPainter*)this)->fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
3741
3742 return fGraph2DPainter->GetContourList(contour);
3743}
3744
3745////////////////////////////////////////////////////////////////////////////////
3746/// Display the histogram info (bin number, contents, integral up to bin
3747/// corresponding to cursor position px,py.
3748
3750{
3751
3752 if (!gPad) return (char*)"";
3753
3754 Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
3755 Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
3756 Double_t x1 = gPad->PadtoX(gPad->AbsPixeltoX(px+1));
3758 drawOption.ToLower();
3761 if (fH->GetDimension() == 2) {
3762 if (gPad->GetView() || drawOption.Index("cont") >= 0) {
3763 uxmin=gPad->GetUxmin();
3764 uxmax=gPad->GetUxmax();
3767 x = xmin +(xmax-xmin)*(x-uxmin)/(uxmax-uxmin);
3768 uymin=gPad->GetUymin();
3769 uymax=gPad->GetUymax();
3772 y = ymin +(ymax-ymin)*(y-uymin)/(uymax-uymin);
3773 }
3774 }
3776 if (gPad->IsVertical()) {
3777 binx = fXaxis->FindFixBin(x);
3778 if (drawOption.Index("same") >= 0) {
3779 TH1 *h1;
3780 TIter next(gPad->GetListOfPrimitives());
3781 while ((h1 = (TH1 *)next())) {
3782 if (!h1->InheritsFrom(TH1::Class())) continue;
3783 binmin = h1->GetXaxis()->GetFirst();
3784 break;
3785 }
3786 } else {
3787 binmin = fXaxis->GetFirst();
3788 }
3790 // special case if more than 1 bin in x per pixel
3791 if (binx1-binx>1 && fH->GetDimension() == 1) {
3794 for (Int_t ibin=binx+1; ibin<binx1; ibin++) {
3798 binnear=ibin;
3799 }
3800 }
3801 binx = binnear;
3802 }
3803 } else {
3804 x1 = gPad->PadtoY(gPad->AbsPixeltoY(py+1));
3805 binx = fXaxis->FindFixBin(y);
3806 if (drawOption.Index("same") >= 0) {
3807 TH1 *h1;
3808 TIter next(gPad->GetListOfPrimitives());
3809 while ((h1 = (TH1 *)next())) {
3810 if (!h1->InheritsFrom(TH1::Class())) continue;
3811 binmin = h1->GetXaxis()->GetFirst();
3812 break;
3813 }
3814 } else {
3815 binmin = fXaxis->GetFirst();
3816 }
3818 // special case if more than 1 bin in x per pixel
3819 if (binx1-binx>1 && fH->GetDimension() == 1) {
3822 for (Int_t ibin=binx+1; ibin<binx1; ibin++) {
3826 binnear=ibin;
3827 }
3828 }
3829 binx = binnear;
3830 }
3831 }
3832 if (fH->GetDimension() == 1) {
3834 TProfile *tp = (TProfile*)fH;
3835 fObjectInfo.Form("(x=%g, y=%g, binx=%d, binc=%g, bine=%g, binn=%d)",
3837 (Int_t) tp->GetBinEntries(binx));
3838 }
3839 else {
3840 Double_t integ = 0;
3841 for (Int_t bin=binmin;bin<=binx;bin++) {integ += fH->GetBinContent(bin);}
3842 fObjectInfo.Form("(x=%g, y=%g, binx=%d, binc=%g, Sum=%g)",
3844 }
3845 } else if (fH->GetDimension() == 2) {
3846 if (fH->InheritsFrom(TH2Poly::Class())) {
3847 TH2Poly *th2 = (TH2Poly*)fH;
3848 biny = th2->FindBin(x,y);
3849 fObjectInfo.Form("%s (x=%g, y=%g, bin=%d, binc=%g)",
3850 th2->GetBinTitle(biny),x,y,biny,th2->GetBinContent(biny));
3851 }
3852 else if (fH->InheritsFrom(TProfile2D::Class())) {
3854 biny = fYaxis->FindFixBin(y);
3855 Int_t bin = fH->GetBin(binx,biny);
3856 fObjectInfo.Form("(x=%g, y=%g, binx=%d, biny=%d, binc=%g, bine=%g, binn=%d)",
3857 x, y, binx, biny, fH->GetBinContent(bin),
3858 fH->GetBinError(bin), (Int_t) tp->GetBinEntries(bin));
3859 } else {
3860 biny = fYaxis->FindFixBin(y);
3861 fObjectInfo.Form("(x=%g, y=%g, binx=%d, biny=%d, binc=%g bine=%g)",
3864 }
3865 } else {
3866 // 3d case: retrieving the x,y,z bin is not yet implemented
3867 // print just the x,y info
3868 fObjectInfo.Form("(x=%g, y=%g)",x,y);
3869 }
3870
3871 return (char *)fObjectInfo.Data();
3872}
3873
3874////////////////////////////////////////////////////////////////////////////////
3875/// Set highlight (enable/disable) mode for fH
3876
3878{
3879 if (fH->IsHighlight()) return;
3880
3881 fXHighlightBin = -1;
3882 fYHighlightBin = -1;
3883 // delete previous highlight box
3884 if (gXHighlightBox) gXHighlightBox.reset();
3885 if (gYHighlightBox) gYHighlightBox.reset();
3886 // emit Highlighted() signal (user can check on disabled)
3887 if (gPad->GetCanvas()) gPad->GetCanvas()->Highlighted(gPad, fH, fXHighlightBin, fYHighlightBin);
3888}
3889
3890////////////////////////////////////////////////////////////////////////////////
3891/// Check on highlight bin
3892
3894{
3895 // call from DistancetoPrimitive (only if highlight is enable)
3896
3897 Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
3898 Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
3901 if (!gPad->IsVertical()) binx = fXaxis->FindFixBin(y);
3902
3904 if (binx != fXHighlightBin) {
3906 changedBin = kTRUE;
3907 } else if (fH->GetDimension() == 1) return;
3908 if (biny != fYHighlightBin) {
3910 changedBin = kTRUE;
3911 }
3912 if (!changedBin) return;
3913
3914 // Info("HighlightBin", "histo: %p '%s'\txbin: %d, ybin: %d",
3915 // (void *)fH, fH->GetName(), fXHighlightBin, fYHighlightBin);
3916
3917 // paint highlight bin as box (recursive calls PaintHighlightBin)
3918 gPad->Modified(kTRUE);
3919 gPad->Update();
3920
3921 // emit Highlighted() signal
3922 if (gPad->GetCanvas()) gPad->GetCanvas()->Highlighted(gPad, fH, fXHighlightBin, fYHighlightBin);
3923}
3924
3925////////////////////////////////////////////////////////////////////////////////
3926/// Paint highlight bin as TBox object
3927
3929{
3930 // call from PaintTitle
3931
3932 if (!fH->IsHighlight()) return;
3933
3934 Double_t uxmin = gPad->GetUxmin();
3935 Double_t uxmax = gPad->GetUxmax();
3936 Double_t uymin = gPad->GetUymin();
3937 Double_t uymax = gPad->GetUymax();
3938 if (gPad->GetLogx()) {
3939 uxmin = TMath::Power(10.0, uxmin);
3940 uxmax = TMath::Power(10.0, uxmax);
3941 }
3942 if (gPad->GetLogy()) {
3943 uymin = TMath::Power(10.0, uymin);
3944 uymax = TMath::Power(10.0, uymax);
3945 }
3946
3947 // testing specific possibility (after zoom, draw with "same", log, etc.)
3949 if (gPad->IsVertical()) {
3951 if ((hcenter < uxmin) || (hcenter > uxmax)) return;
3952 } else {
3954 if ((hcenter < uymin) || (hcenter > uymax)) return;
3955 }
3956 if (fH->GetDimension() == 2) {
3958 if ((hcenter < uymin) || (hcenter > uymax)) return;
3959 }
3960
3961 // paint X highlight bin (for 1D or 2D)
3963 if (gPad->IsVertical()) {
3966 hby1 = uymin;
3967 hby2 = uymax;
3968 } else {
3969 hbx1 = uxmin;
3970 hbx2 = uxmax;
3973 }
3974
3975 if (!gXHighlightBox) {
3976 gXHighlightBox = std::make_unique<TBox>(hbx1, hby1, hbx2, hby2);
3977 gXHighlightBox->SetBit(kCannotPick);
3978 gXHighlightBox->SetFillColor(TColor::GetColor("#9797ff"));
3979 if (!TCanvas::SupportAlpha()) gXHighlightBox->SetFillStyle(3001);
3980 else gROOT->GetColor(gXHighlightBox->GetFillColor())->SetAlpha(0.5);
3981 }
3982 gXHighlightBox->SetX1(hbx1);
3983 gXHighlightBox->SetX2(hbx2);
3984 gXHighlightBox->SetY1(hby1);
3985 gXHighlightBox->SetY2(hby2);
3986 gXHighlightBox->Paint();
3987
3988 // Info("PaintHighlightBin", "histo: %p '%s'\txbin: %d, ybin: %d",
3989 // (void *)fH, fH->GetName(), fXHighlightBin, fYHighlightBin);
3990
3991 // paint Y highlight bin (only for 2D)
3992 if (fH->GetDimension() != 2) return;
3993 hbx1 = uxmin;
3994 hbx2 = uxmax;
3997
3998 if (!gYHighlightBox) {
3999 gYHighlightBox = std::make_unique<TBox>(hbx1, hby1, hbx2, hby2);
4000 gYHighlightBox->SetBit(kCannotPick);
4001 gYHighlightBox->SetFillColor(gXHighlightBox->GetFillColor());
4002 gYHighlightBox->SetFillStyle(gXHighlightBox->GetFillStyle());
4003 }
4004 gYHighlightBox->SetX1(hbx1);
4005 gYHighlightBox->SetX2(hbx2);
4006 gYHighlightBox->SetY1(hby1);
4007 gYHighlightBox->SetY2(hby2);
4008 gYHighlightBox->Paint();
4009}
4010
4011////////////////////////////////////////////////////////////////////////////////
4012/// Return `kTRUE` if the cell `ix`, `iy` is inside one of the graphical cuts.
4013
4015{
4016
4017 for (Int_t i=0;i<fNcuts;i++) {
4020 if (fCutsOpt[i] > 0) {
4021 if (!fCuts[i]->IsInside(x,y)) return kFALSE;
4022 } else {
4023 if (fCuts[i]->IsInside(x,y)) return kFALSE;
4024 }
4025 }
4026 return kTRUE;
4027}
4028
4029////////////////////////////////////////////////////////////////////////////////
4030/// Return `kTRUE` if the point `x`, `y` is inside one of the graphical cuts.
4031
4033{
4034
4035 for (Int_t i=0;i<fNcuts;i++) {
4036 if (fCutsOpt[i] > 0) {
4037 if (!fCuts[i]->IsInside(x,y)) return kFALSE;
4038 } else {
4039 if (fCuts[i]->IsInside(x,y)) return kFALSE;
4040 }
4041 }
4042 return kTRUE;
4043}
4044
4045////////////////////////////////////////////////////////////////////////////////
4046/// Decode string `choptin` and fill Hoption structure.
4047
4049{
4050
4051 char *l;
4052 char chopt[128];
4054 strlcpy(chopt,choptin,128);
4057
4065 Hoption.Candle = 0;
4066
4067 // special 2D options
4068 Hoption.List = 0;
4069 Hoption.Zscale = 0;
4070 Hoption.FrontBox = 1;
4071 Hoption.BackBox = 1;
4073
4074 Hoption.Zero = 0;
4075
4077
4078 //check for graphical cuts
4079 MakeCuts(chopt);
4080
4081 for (Int_t i=0;i<nch;i++) chopt[i] = toupper(chopt[i]);
4082 if (hdim > 1) Hoption.Color = 1; // Default drawing option for 2D and 3D histograms
4083 if (!nch) Hoption.Hist = 1;
4084 if (fFunctions->First()) Hoption.Func = 1;
4085 if (fH->GetSumw2N() && hdim == 1) Hoption.Error = 2;
4086
4087 char *l1 = strstr(chopt,"PFC"); // Automatic Fill Color
4088 char *l2 = strstr(chopt,"PLC"); // Automatic Line Color
4089 char *l3 = strstr(chopt,"PMC"); // Automatic Marker Color
4090 if (l1 || l2 || l3) {
4091 Int_t i = gPad->NextPaletteColor();
4092 if (l1) {memcpy(l1," ",3); fH->SetFillColor(i);}
4093 if (l2) {memcpy(l2," ",3); fH->SetLineColor(i);}
4094 if (l3) {memcpy(l3," ",3); fH->SetMarkerColor(i);}
4095 Hoption.Hist = 1; // Make sure something is drawn in case there is no drawing option specified.
4096 }
4097
4098 l = strstr(chopt,"MIN0");
4099 if (l) {
4100 Hoption.MinimumZero = 1;
4101 memcpy(l," ",4);
4102 }
4103
4104 l = strstr(chopt,"SPEC");
4105 if (l) {
4106 Hoption.Color = 0;
4107 memcpy(l," ",4);
4108 Int_t bs=0;
4109 l = strstr(chopt,"BF(");
4110 if (l) {
4111 if (sscanf(&l[3],"%d",&bs) > 0) {
4112 Int_t i=0;
4113 while (l[i]!=')') {
4114 l[i] = ' ';
4115 i++;
4116 }
4117 l[i] = ' ';
4118 }
4119 }
4120 Hoption.Spec = TMath::Max(1600,bs);
4121 return 1;
4122 }
4123
4124 l = strstr(chopt,"GL");
4125 if (l) {
4126 memcpy(l," ",2);
4127 }
4128 l = strstr(chopt,"X+");
4129 if (l) {
4130 Hoption.AxisPos = 10;
4131 memcpy(l," ",2);
4132 }
4133 l = strstr(chopt,"Y+");
4134 if (l) {
4135 Hoption.AxisPos += 1;
4136 memcpy(l," ",2);
4137 }
4138 if ((Hoption.AxisPos == 10 || Hoption.AxisPos == 1) && (nch == 2)) Hoption.Hist = 1;
4139 if (Hoption.AxisPos == 11 && nch == 4) Hoption.Hist = 1;
4140
4141 l = strstr(chopt,"SAMES");
4142 if (l) {
4143 if (nch == 5) Hoption.Hist = 1;
4144 Hoption.Same = 2;
4145 memcpy(l," ",5);
4146 if (l[5] == '0') { Hoption.Same += 10; l[5] = ' '; }
4147 }
4148 l = strstr(chopt,"SAME");
4149 if (l) {
4150 if (nch == 4) Hoption.Hist = 1;
4151 Hoption.Same = 1;
4152 memcpy(l," ",4);
4153 if (l[4] == '0') { Hoption.Same += 10; l[4] = ' '; }
4154 }
4155
4156 l = strstr(chopt,"SCAT");
4157 if (l) {
4158 Warning("MakeChopt","option SCAT is deprecated.");
4159 Hoption.Scat = 1;
4160 memcpy(l," ",4);
4161 Hoption.Color = 0;
4162 }
4163
4164 l = strstr(chopt,"PIE");
4165 if (l) {
4166 Hoption.Pie = 1;
4167 memcpy(l," ",3);
4168 }
4169
4170
4171 l = strstr(chopt,"CANDLE");
4172 if (l) {
4174 Hoption.Candle = candle.ParseOption(l);
4175 Hoption.Color = 0;
4176 }
4177
4178 l = strstr(chopt,"VIOLIN");
4179 if (l) {
4181 Hoption.Candle = candle.ParseOption(l);
4182 Hoption.Color = 0;
4183 }
4184
4185 l = strstr(chopt,"LEGO");
4186 if (l) {
4187 Hoption.Color = 0;
4188 Hoption.Lego = 1; memcpy(l," ",4);
4189 if (l[4] == '1') { Hoption.Lego = 11; l[4] = ' '; }
4190 if (l[4] == '2') { Hoption.Lego = 12; l[4] = ' '; }
4191 if (l[4] == '3') { Hoption.Lego = 13; l[4] = ' '; }
4192 if (l[4] == '4') { Hoption.Lego = 14; l[4] = ' '; }
4193 if (l[4] == '9') { Hoption.Lego = 19; l[4] = ' '; }
4194 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4195 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4196 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4197 }
4198
4199 l = strstr(chopt,"SURF");
4200 if (l) {
4201 Hoption.Color = 0;
4202 Hoption.Surf = 1; memcpy(l," ",4);
4203 if (l[4] == '1') { Hoption.Surf = 11; l[4] = ' '; }
4204 if (l[4] == '2') { Hoption.Surf = 12; l[4] = ' '; }
4205 if (l[4] == '3') { Hoption.Surf = 13; l[4] = ' '; }
4206 if (l[4] == '4') { Hoption.Surf = 14; l[4] = ' '; }
4207 if (l[4] == '5') { Hoption.Surf = 15; l[4] = ' '; }
4208 if (l[4] == '6') { Hoption.Surf = 16; l[4] = ' '; }
4209 if (l[4] == '7') { Hoption.Surf = 17; l[4] = ' '; }
4210 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4211 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4212 }
4213
4214 l = strstr(chopt,"TF3");
4215 if (l) {
4216 memcpy(l," ",3);
4217 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4218 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4219 }
4220
4221 l = strstr(chopt,"ISO");
4222 if (l) {
4223 memcpy(l," ",3);
4224 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4225 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4226 Hoption.Color = 0;
4227 }
4228
4229 l = strstr(chopt,"LIST"); if (l) { Hoption.List = 1; memcpy(l," ",4);}
4230
4231 l = strstr(chopt,"CONT");
4232 if (l) {
4233 memcpy(l," ",4);
4234 if (hdim>1) {
4235 Hoption.Color = 0;
4236 Hoption.Contour = 1;
4237 if (l[4] == '1') { Hoption.Contour = 11; l[4] = ' '; }
4238 if (l[4] == '2') { Hoption.Contour = 12; l[4] = ' '; }
4239 if (l[4] == '3') { Hoption.Contour = 13; l[4] = ' '; }
4240 if (l[4] == '4') { Hoption.Contour = 14; l[4] = ' '; }
4241 if (l[4] == '5') { Hoption.Contour = 15; l[4] = ' '; }
4242 } else {
4243 Hoption.Hist = 1;
4244 }
4245 }
4246 l = strstr(chopt,"HBAR");
4247 if (l) {
4248 Hoption.Hist = 0;
4249 Hoption.Bar = 20; memcpy(l," ",4);
4250 if (l[4] == '1') { Hoption.Bar = 21; l[4] = ' '; }
4251 if (l[4] == '2') { Hoption.Bar = 22; l[4] = ' '; }
4252 if (l[4] == '3') { Hoption.Bar = 23; l[4] = ' '; }
4253 if (l[4] == '4') { Hoption.Bar = 24; l[4] = ' '; }
4254 }
4255 l = strstr(chopt,"BAR");
4256 if (l) {
4257 Hoption.Hist = 0;
4258 Hoption.Bar = 10; memcpy(l," ",3);
4259 if (l[3] == '1') { Hoption.Bar = 11; l[3] = ' '; }
4260 if (l[3] == '2') { Hoption.Bar = 12; l[3] = ' '; }
4261 if (l[3] == '3') { Hoption.Bar = 13; l[3] = ' '; }
4262 if (l[3] == '4') { Hoption.Bar = 14; l[3] = ' '; }
4263 }
4264
4265 l = strstr(chopt,"ARR" );
4266 if (l) {
4267 memcpy(l," ", 3);
4268 if (hdim>1) {
4269 Hoption.Arrow = 1;
4270 Hoption.Color = 0;
4271 l = strstr(chopt,"COL"); if (l) { Hoption.Arrow = 2; memcpy(l," ",3); }
4272 l = strstr(chopt,"Z"); if (l) { Hoption.Zscale = 1; memcpy(l," ",1); }
4273 } else {
4274 Hoption.Hist = 1;
4275 }
4276 }
4277 l = strstr(chopt,"BOX" );
4278 if (l) {
4279 memcpy(l," ", 3);
4280 if (hdim>1) {
4281 Hoption.Color = 0;
4282 Hoption.Box = 1;
4283 if (l[3] == '1') { Hoption.Box = 11; l[3] = ' '; }
4284 if (l[3] == '2') { Hoption.Box = 12; l[3] = ' '; }
4285 if (l[3] == '3') { Hoption.Box = 13; l[3] = ' '; }
4286 } else {
4287 Hoption.Hist = 1;
4288 }
4289 }
4290 l = strstr(chopt,"TEXT");
4291 if (l) {
4292 Int_t angle;
4293 if (sscanf(&l[4],"%d",&angle) > 0) {
4294 if (angle < 0) angle=0;
4295 if (angle > 90) angle=90;
4296 Hoption.Text = 1000+angle;
4297 } else {
4298 Hoption.Text = 1;
4299 }
4300 memcpy(l," ", 4);
4301 l = strstr(chopt,"N");
4302 if (l && fH->InheritsFrom(TH2Poly::Class())) Hoption.Text = 3000 + (Hoption.Text != 1 ? Hoption.Text : 0);
4303 Hoption.Color = 0;
4304 }
4305 l = strstr(chopt,"COLZ");
4306 if (l) {
4307 memcpy(l," ",4);
4308 if (hdim > 1) {
4310 Hoption.Color = 1;
4311 Hoption.Zscale = 1;
4312 if (l[4] == '2') { Hoption.Color = 3; l[4] = ' '; }
4313 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4314 l = strstr(chopt,"1"); if (l) { Hoption.Color = 2; memcpy(l," ",1); }
4315 } else {
4316 Hoption.Hist = 1;
4317 }
4318 }
4319 l = strstr(chopt,"COL" );
4320 if (l) {
4321 memcpy(l," ", 3);
4322 if (hdim > 1) {
4324 Hoption.Color = 1;
4325 if (l[3] == '2') { Hoption.Color = 3; l[3] = ' '; }
4326 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4327 l = strstr(chopt,"1"); if (l) { Hoption.Color = 2; memcpy(l," ",1); }
4328 } else {
4329 Hoption.Hist = 1;
4330 }
4331 }
4332 l = strstr(chopt,"FUNC"); if (l) { Hoption.Func = 2; memcpy(l," ",4); Hoption.Hist = 0; }
4333 l = strstr(chopt,"HIST"); if (l) { Hoption.Hist = 2; memcpy(l," ",4); Hoption.Func = 0; Hoption.Error = 0;}
4334 l = strstr(chopt,"AXIS"); if (l) { Hoption.Axis = 1; memcpy(l," ",4); }
4335 l = strstr(chopt,"AXIG"); if (l) { Hoption.Axis = 2; memcpy(l," ",4); }
4336 l = strstr(chopt,"SCAT"); if (l) { Hoption.Scat = 1; memcpy(l," ",4); }
4337 l = strstr(chopt,"POL"); if (l) { Hoption.System = kPOLAR; memcpy(l," ",3); }
4338 l = strstr(chopt,"CYL"); if (l) { Hoption.System = kCYLINDRICAL; memcpy(l," ",3); }
4339 l = strstr(chopt,"SPH"); if (l) { Hoption.System = kSPHERICAL; memcpy(l," ",3); }
4340 l = strstr(chopt,"PSR"); if (l) { Hoption.System = kRAPIDITY; memcpy(l," ",3); }
4341
4342 l = strstr(chopt,"TRI");
4343 if (l) {
4344 if (!explicitColor) Hoption.Color = 0;
4345 Hoption.Tri = 1; memcpy(l," ",3);
4346 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4347 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4348 l = strstr(chopt,"ERR"); if (l) memcpy(l," ",3);
4349 }
4350
4351 l = strstr(chopt,"AITOFF");
4352 if (l) {
4353 Hoption.Proj = 1; memcpy(l," ",6); //Aitoff projection
4354 }
4355 l = strstr(chopt,"MERCATOR");
4356 if (l) {
4357 Hoption.Proj = 2; memcpy(l," ",8); //Mercator projection
4358 }
4359 l = strstr(chopt,"SINUSOIDAL");
4360 if (l) {
4361 Hoption.Proj = 3; memcpy(l," ",10); //Sinusoidal projection
4362 }
4363 l = strstr(chopt,"PARABOLIC");
4364 if (l) {
4365 Hoption.Proj = 4; memcpy(l," ",9); //Parabolic projection
4366 }
4367 l = strstr(chopt,"MOLLWEIDE");
4368 if (l) {
4369 Hoption.Proj = 5; memcpy(l," ",9); //Mollweide projection
4370 }
4371 if (Hoption.Proj > 0) {
4372 if (!explicitColor) Hoption.Color = 0;
4373 Hoption.Contour = 14;
4374 }
4375
4376 if (strstr(chopt,"A")) Hoption.Axis = -1;
4377 if (strstr(chopt,"B")) Hoption.Bar = 1;
4378 if (strstr(chopt,"C") && !strstr(chopt,"CJUST")) { Hoption.Curve =1; Hoption.Hist = -1;}
4379 if (strstr(chopt,"F")) Hoption.Fill =1;
4380 if (strstr(chopt,"][")) {Hoption.Off =1; Hoption.Hist =1;}
4381 if (strstr(chopt,"F2")) Hoption.Fill =2;
4382 if (strstr(chopt,"L")) { Hoption.Line =1; Hoption.Hist = -1;}
4383 if (strstr(chopt,"P")) { Hoption.Mark =1; Hoption.Hist = -1;}
4384 if (strstr(chopt,"Z")) Hoption.Zscale =1;
4385 if (strstr(chopt,"*")) Hoption.Star =1;
4386 if (strstr(chopt,"H")) Hoption.Hist =2;
4387 if (strstr(chopt,"P0")) Hoption.Mark =10;
4388
4389 if (fH->InheritsFrom(TH2Poly::Class())) {
4391 }
4392
4393 if (strstr(chopt,"E")) {
4394 if (hdim == 1) {
4395 Hoption.Error = 1;
4396 if (strstr(chopt,"E1")) Hoption.Error = 11;
4397 if (strstr(chopt,"E2")) Hoption.Error = 12;
4398 if (strstr(chopt,"E3")) Hoption.Error = 13;
4399 if (strstr(chopt,"E4")) Hoption.Error = 14;
4400 if (strstr(chopt,"E5")) Hoption.Error = 15;
4401 if (strstr(chopt,"E6")) Hoption.Error = 16;
4402 if (strstr(chopt,"E0")) Hoption.Error += 40;
4403 if (strstr(chopt,"X0")) {
4404 if (Hoption.Error == 1) Hoption.Error += 20;
4405 Hoption.Error += 10;
4406 }
4408 Hoption.Text += 2000;
4409 Hoption.Error = 0;
4410 }
4411 } else {
4412 if (Hoption.Error == 0) {
4413 Hoption.Error = 100;
4414 if (!explicitColor) Hoption.Color = 0;
4415 }
4416 if (Hoption.Text) {
4417 Hoption.Text += 2000;
4418 Hoption.Error = 0;
4419 }
4420 }
4421 }
4422
4423 if (Hoption.Surf == 15) {
4425 Hoption.Surf = 13;
4426 Warning("MakeChopt","option SURF5 is not supported in Cartesian and Polar modes");
4427 }
4428 }
4429
4430 // Copy options from current style
4431 Hoption.Logx = gPad->GetLogx();
4432 Hoption.Logy = gPad->GetLogy();
4433 Hoption.Logz = gPad->GetLogz();
4434
4435 // Check options incompatibilities
4436 if (Hoption.Bar == 1) Hoption.Hist = -1;
4437 return 1;
4438}
4439
4440////////////////////////////////////////////////////////////////////////////////
4441/// Decode string `choptin` and fill Graphical cuts structure.
4442
4444{
4445
4446 fNcuts = 0;
4447 char *left = (char*)strchr(choptin,'[');
4448 if (!left) return 0;
4449 char *right = (char*)strchr(choptin,']');
4450 if (!right) return 0;
4451 Int_t nch = right-left;
4452 if (nch < 2) return 0;
4453 char *cuts = left+1;
4454 *right = 0;
4455 char *comma, *minus;
4456 Int_t i;
4457 while (true) {
4458 comma = strchr(cuts,',');
4459 if (comma) *comma = 0;
4460 minus = strchr(cuts,'-');
4461 if (minus) cuts = minus+1;
4462 while (*cuts == ' ') cuts++;
4463 Int_t nc = strlen(cuts);
4464 while (cuts[nc-1] == ' ') {cuts[nc-1] = 0; nc--;}
4465 TIter next(gROOT->GetListOfSpecials());
4466 TCutG *cut=nullptr;
4467 TObject *obj;
4468 while ((obj = next())) {
4469 if (!obj->InheritsFrom(TCutG::Class())) continue;
4470 if (strcmp(obj->GetName(),cuts)) continue;
4471 cut = (TCutG*)obj;
4472 break;
4473 }
4474 if (cut) {
4475 fCuts[fNcuts] = cut;
4476 fCutsOpt[fNcuts] = 1;
4477 if (minus) fCutsOpt[fNcuts] = -1;
4478 fNcuts++;
4479 }
4480 if (!comma) break;
4481 cuts = comma+1;
4482 }
4483 for (i=0;i<=nch;i++) left[i] = ' ';
4484 return fNcuts;
4485}
4486
4487////////////////////////////////////////////////////////////////////////////////
4488/// [Control routine to paint any kind of histograms](\ref HP00)
4489
4491{
4492
4493 if (fH->GetBuffer()) fH->BufferEmpty(-1);
4494
4495 //For iOS: put the histogram on the top of stack of pickable objects.
4497
4498 gPad->SetVertical(kTRUE);
4499
4501 gCurrentHist = fH;
4502 TH1 *hsave = fH;
4504
4505 if (!MakeChopt(option)) return; //check options and fill Hoption structure
4506
4507 // Paint using TSpectrum2Painter
4508 if (Hoption.Spec) {
4509 if (!TableInit()) return;
4510 if (!TClass::GetClass("TSpectrum2Painter")) gSystem->Load("libSpectrumPainter");
4511 gROOT->ProcessLineFast(TString::Format("TSpectrum2Painter::PaintSpectrum((TH2F*)0x%zx,\"%s\",%d)",
4512 (size_t)fH, option, Hoption.Spec).Data());
4513 return;
4514 }
4515
4516 // Deflate the labels in case of alphanumeric labels
4520
4521 if (Hoption.Pie) {
4522 if (fH->GetDimension() == 1) {
4523 if (!fPie)
4524 fPie = std::make_unique<TPie>(fH);
4525 fPie->Paint(option);
4526 } else {
4527 Error("Paint", "Option PIE is for 1D histograms only");
4528 }
4529 return;
4530 } else {
4531 fPie.reset();
4532 }
4533
4534 fXbuf.resize(kNMAX);
4535 fYbuf.resize(kNMAX);
4536 if (fH->GetDimension() > 2) {
4537 PaintH3(option);
4539 if (Hoption.Func) {
4544 Hoption = hoptsave;
4545 Hparam = hparsave;
4546 }
4548 fXbuf.clear();
4549 fYbuf.clear();
4550 return;
4551 }
4552 TView *view = gPad->GetView();
4553 if (view) {
4554 if (!Hoption.Lego && !Hoption.Surf && !Hoption.Tri) {
4555 delete view;
4556 gPad->SetView(nullptr);
4557 }
4558 }
4559 if (fH->GetDimension() > 1 || Hoption.Lego || Hoption.Surf) {
4560 // In case of 1D histogram, Z axis becomes Y axis.
4561 Int_t logysav=0, logzsav=0;
4562 if (fH->GetDimension() == 1) {
4565 Hoption.Logz = 0;
4566 if (Hoption.Logy) {
4567 Hoption.Logz = 1;
4568 Hoption.Logy = 0;
4569 }
4570 }
4572 if (Hoption.Func) {
4577 Hoption = hoptsave;
4578 Hparam = hparsave;
4579 }
4582 fXbuf.clear();
4583 fYbuf.clear();
4584 if (fH->GetDimension() == 1) {
4587 }
4588 return;
4589 }
4590
4591 if (Hoption.Bar >= 20) {
4593 fXbuf.clear();
4594 fYbuf.clear();
4595 return;
4596 }
4597
4598 gPad->RangeAxisChanged(); //emit RangeAxisChanged() signal to sync axes
4599 // fill Hparam structure with histo parameters
4600 if (!PaintInit()) {
4601 fXbuf.clear();
4602 fYbuf.clear();
4603 return;
4604 }
4605
4606 // Picture surround (if new page) and page number (if requested).
4607 // Histogram surround (if not option "Same").
4608 PaintFrame();
4609
4610 // Paint histogram axis only
4611 Bool_t gridx = gPad->GetGridx();
4612 Bool_t gridy = gPad->GetGridy();
4613 if (Hoption.Axis > 0) {
4614 if (Hoption.Axis > 1) PaintAxis(kTRUE); //axis with grid
4615 else {
4616 if (gridx) gPad->SetGridx(0);
4617 if (gridy) gPad->SetGridy(0);
4619 if (gridx) gPad->SetGridx(1);
4620 if (gridy) gPad->SetGridy(1);
4621 }
4622 if ((Hoption.Same%10) ==1) Hoption.Same += 1;
4623 goto paintstat;
4624 }
4625 if (gridx || gridy) PaintAxis(kTRUE); // Draw the grid only
4626
4627 // test for options BAR or HBAR
4628 if (Hoption.Bar >= 10) {
4630 }
4631
4632 // do not draw histogram if error bars required
4633 if (!Hoption.Error) {
4634 if (Hoption.Hist && Hoption.Bar<10) PaintHist(option);
4635 }
4636
4637 // test for error bars or option E
4638 if (Hoption.Error) {
4640 if (Hoption.Hist == 2) PaintHist(option);
4641 }
4642
4644
4645 // test for associated function
4646 if (Hoption.Func) {
4651 Hoption = hoptsave;
4652 Hparam = hparsave;
4653 }
4654
4655 if (gridx) gPad->SetGridx(0);
4656 if (gridy) gPad->SetGridy(0);
4658 if (gridx) gPad->SetGridx(1);
4659 if (gridy) gPad->SetGridy(1);
4660
4661 PaintTitle(); // Draw histogram title
4662
4663 // Draw box with histogram statistics and/or fit parameters
4664paintstat:
4665 if ((Hoption.Same%10) != 1 && !fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
4666 TIter next(fFunctions);
4667 TObject *obj = nullptr;
4668 while ((obj = next())) {
4669 if (obj->InheritsFrom(TF1::Class())) break;
4670 obj = nullptr;
4671 }
4672
4673 //Stat is painted twice (first, it will be in canvas' list of primitives),
4674 //second, it will be here, this is not required on iOS.
4675 //Condition is ALWAYS true on a platform different from iOS.
4676 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode())
4677 PaintStat(gStyle->GetOptStat(),(TF1*)obj);
4678 }
4681 fXbuf.clear();
4682 fYbuf.clear();
4683}
4684
4685////////////////////////////////////////////////////////////////////////////////
4686/// [Control function to draw a table as an arrow plot](\ref HP12)
4687
4689{
4691 Double_t dx, dy, x1, x2, y1, y2, xc, yc, dxn, dyn;
4694 Double_t xrg = gPad->GetUxmin();
4695 Double_t yrg = gPad->GetUymin();
4696 Double_t xln = gPad->GetUxmax() - xrg;
4697 Double_t yln = gPad->GetUymax() - yrg;
4698 Double_t cx = (xln/Double_t(ncx))/2.;
4699 Double_t cy = (yln/Double_t(ncy))/2.;
4700 Double_t dn = 1.E-30;
4701
4702 auto arrow = new TArrow();
4703 arrow->SetAngle(30);
4704 arrow->SetFillStyle(1001);
4705 arrow->SetFillColor(fH->GetLineColor());
4706 arrow->SetLineColor(fH->GetLineColor());
4707 arrow->SetLineWidth(fH->GetLineWidth());
4708
4709 // Initialize the levels on the Z axis
4710 Int_t ncolors=0, ndivz=0;
4711 Double_t scale=0.;
4712 if (Hoption.Arrow>1) {
4713 ncolors = gStyle->GetNumberOfColors();
4714 Int_t ndiv = fH->GetContour();
4715 if (ndiv == 0 ) {
4716 ndiv = gStyle->GetNumberContours();
4717 fH->SetContour(ndiv);
4718 }
4719 ndivz = TMath::Abs(ndiv);
4720 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
4722 }
4723
4724 for (Int_t id=1;id<=2;id++) {
4725 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
4728 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
4729 xk = fXaxis->GetBinLowEdge(i);
4730 xstep = fXaxis->GetBinWidth(i);
4731 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
4732 if (i == Hparam.xfirst) {
4733 dx = fH->GetBinContent(i+1, j) - fH->GetBinContent(i, j);
4734 } else if (i == Hparam.xlast) {
4735 dx = fH->GetBinContent(i, j) - fH->GetBinContent(i-1, j);
4736 } else {
4737 dx = 0.5*(fH->GetBinContent(i+1, j) - fH->GetBinContent(i-1, j));
4738 }
4739 if (j == Hparam.yfirst) {
4740 dy = fH->GetBinContent(i, j+1) - fH->GetBinContent(i, j);
4741 } else if (j == Hparam.ylast) {
4742 dy = fH->GetBinContent(i, j) - fH->GetBinContent(i, j-1);
4743 } else {
4744 dy = 0.5*(fH->GetBinContent(i, j+1) - fH->GetBinContent(i, j-1));
4745 }
4746 if (id == 1) {
4749 } else if (id == 2) {
4750 xc = xrg + xln*(Double_t(i - Hparam.xfirst+1)-0.5)/Double_t(ncx);
4751 dxn = cx*dx/dn;
4752 x1 = xc - dxn;
4753 x2 = xc + dxn;
4754 yc = yrg + yln*(Double_t(j - Hparam.yfirst+1)-0.5)/Double_t(ncy);
4755 dyn = cy*dy/dn;
4756 y1 = yc - dyn;
4757 y2 = yc + dyn;
4758 if (Hoption.Arrow>1) {
4759 int color = Int_t(0.01+(fH->GetBinContent(i, j)-fH->GetMinimum())*scale);
4760 Int_t theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
4761 if (theColor > ncolors-1) theColor = ncolors-1;
4762 arrow->SetFillColor(gStyle->GetColorPalette(theColor));
4763 arrow->SetLineColor(gStyle->GetColorPalette(theColor));
4764 }
4765 if (TMath::Abs(x2-x1) > 0. || TMath::Abs(y2-y1) > 0.) {
4766 arrow->PaintArrow(x1, y1, x2, y2, 0.015, "|>");
4767 } else {
4768 arrow->PaintArrow(x1, y1, x2, y2, 0.005, "|>");
4769 }
4770 }
4771 }
4772 }
4773 }
4774
4776}
4777
4778////////////////////////////////////////////////////////////////////////////////
4779/// Draw axis (2D case) of an histogram.
4780///
4781/// If `drawGridOnly` is `TRUE`, only the grid is painted (if needed). This allows
4782/// to draw the grid and the axis separately. In `THistPainter::Paint` this
4783/// feature is used to make sure that the grid is drawn in the background and
4784/// the axis tick marks in the foreground of the pad.
4785
4787{
4788
4789 //On iOS, grid should not be pickable and can not be highlighted.
4790 //Condition is never true on a platform different from iOS.
4791 if (drawGridOnly && (gPad->PadInHighlightMode() || gPad->PadInSelectionMode()))
4792 return;
4793
4794 if (Hoption.Axis == -1) return;
4795 if (Hoption.Same && Hoption.Axis <= 0) return;
4796
4797 // Repainting alphanumeric labels axis on a plot done with
4798 // the option HBAR (horizontal) needs some adjustments.
4799 TAxis *xaxis = nullptr;
4800 TAxis *yaxis = nullptr;
4801 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4802 if (fXaxis->GetLabels() || fYaxis->GetLabels()) { // One axis has alphanumeric labels
4803 TIter next(gPad->GetListOfPrimitives());
4804 TObject *obj;
4805 // Check if the first TH1 of THStack in the pad is drawn with the option HBAR
4806 while ((obj = next())) {
4807 if (!obj->InheritsFrom(TH1::Class()) &&
4808 !obj->InheritsFrom(THStack::Class())) continue;
4809 TString opt = obj->GetDrawOption();
4810 opt.ToLower();
4811 // if drawn with HBAR, the axis should be inverted and the pad set to horizontal
4812 if (strstr(opt,"hbar")) {
4813 gPad->SetVertical(kFALSE);
4814 xaxis = fXaxis;
4815 yaxis = fYaxis;
4816 if (!strcmp(xaxis->GetName(),"xaxis")) {
4817 fXaxis = yaxis;
4818 fYaxis = xaxis;
4819 }
4820 }
4821 break;
4822 }
4823 }
4824 }
4825
4826 static char chopt[10] = "";
4827 Double_t gridl = 0;
4828 Int_t ndiv, ndivx, ndivy, nx1, nx2, ndivsave;
4829 Int_t useHparam = 0;
4833
4834 Double_t axmin = gPad->GetUxmin();
4835 Double_t axmax = gPad->GetUxmax();
4836 Double_t aymin = gPad->GetUymin();
4837 Double_t aymax = gPad->GetUymax();
4838 char *cw = nullptr;
4839 TGaxis axis;
4840
4841 // In case of option 'cont4' or in case of option 'same' over a 'cont4 plot'
4842 // Hparam must be use for the axis limits.
4843 if (Hoption.Contour == 14) useHparam = 1;
4844 if (Hoption.Same) {
4845 TObject *obj;
4846 TIter next(gPad->GetListOfPrimitives());
4847 while ((obj=next())) {
4848 if (strstr(obj->GetDrawOption(),"cont4")) {
4849 useHparam = 1;
4850 break;
4851 }
4852 }
4853 }
4854
4855 // Paint X axis
4856
4857 //To make X-axis selectable on iOS device.
4858 if (gPad->PadInSelectionMode())
4859 gPad->PushSelectableObject(fXaxis);
4860
4861 //This condition is ALWAYS true, unless it works on iOS (can be false on iOS).
4862 if (gPad->PadInSelectionMode() || !gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && gPad->GetSelected() == fXaxis)) {
4864 if (ndivx > 1000) {
4865 nx2 = ndivx/100;
4866 nx1 = TMath::Max(1, ndivx%100);
4867 ndivx = 100*nx2 + Int_t(Float_t(nx1)*gPad->GetAbsWNDC());
4868 }
4869 axis.SetTextAngle(0);
4871
4872 chopt[0] = 0;
4873 strlcat(chopt, "SDH",10);
4874 if (ndivx < 0) strlcat(chopt, "N",10);
4875 if (gPad->GetGridx()) {
4876 gridl = (aymax-aymin)/(gPad->GetY2() - gPad->GetY1());
4877 strlcat(chopt, "W",10);
4878 }
4879
4880 // Define X-Axis limits
4881 if (Hoption.Logx) {
4882 strlcat(chopt, "G",10);
4883 ndiv = TMath::Abs(ndivx);
4884 if (useHparam) {
4887 } else {
4888 umin = TMath::Power(10,axmin);
4889 umax = TMath::Power(10,axmax);
4890 }
4891 } else {
4892 ndiv = TMath::Abs(ndivx);
4893 if (useHparam) {
4894 umin = Hparam.xmin;
4895 umax = Hparam.xmax;
4896 } else {
4897 umin = axmin;
4898 umax = axmax;
4899 }
4900 }
4901
4902 // Display axis as time
4903 if (fXaxis->GetTimeDisplay()) {
4904 strlcat(chopt,"t",10);
4905 if (strlen(fXaxis->GetTimeFormatOnly()) == 0) {
4907 }
4908 }
4909
4910 // The main X axis can be on the bottom or on the top of the pad
4912 if (xAxisPos == 1) {
4913 // Main X axis top
4914 xAxisYPos1 = aymax;
4915 xAxisYPos2 = aymin;
4916 } else {
4917 // Main X axis bottom
4918 xAxisYPos1 = aymin;
4919 xAxisYPos2 = aymax;
4920 }
4921
4922 // Paint the main X axis (always)
4923 uminsave = umin;
4924 umaxsave = umax;
4925 ndivsave = ndiv;
4926 axis.SetOption(chopt);
4927 if (xAxisPos) {
4928 strlcat(chopt, "-",10);
4929 gridl = -gridl;
4930 }
4931 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4932 axis.SetLabelSize(0.);
4933 axis.SetTitle("");
4934 }
4937 umin, umax, ndiv, chopt, gridl, drawGridOnly);
4938
4939 // Paint additional X axis (if needed)
4940 // On iOS, this additional X axis is neither pickable, nor highlighted.
4941 // Additional checks PadInSelectionMode etc. does not effect non-iOS platform.
4942 if (gPad->GetTickx() && !gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
4943 if (xAxisPos) {
4944 cw=strstr(chopt,"-");
4945 *cw='z';
4946 } else {
4947 strlcat(chopt, "-",10);
4948 }
4949 if (gPad->GetTickx() < 2) strlcat(chopt, "U",10);
4950 if ((cw=strstr(chopt,"W"))) *cw='z';
4951 axis.SetTitle("");
4955 }
4956 }//End of "if pad in selection mode etc".
4957
4958 // Paint Y axis
4959 //On iOS, Y axis must pushed into the stack of selectable objects.
4960 if (gPad->PadInSelectionMode())
4961 gPad->PushSelectableObject(fYaxis);
4962
4963 //This conditions is ALWAYS true on a platform, different from iOS (on iOS can be true, can be false).
4964 if (gPad->PadInSelectionMode() || !gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && gPad->GetSelected() == fYaxis)) {
4967
4968 chopt[0] = 0;
4969 strlcat(chopt, "SDH",10);
4970 if (ndivy < 0) strlcat(chopt, "N",10);
4971 if (gPad->GetGridy()) {
4972 gridl = (axmax-axmin)/(gPad->GetX2() - gPad->GetX1());
4973 strlcat(chopt, "W",10);
4974 }
4975
4976 // Define Y-Axis limits
4977 if (Hoption.Logy) {
4978 strlcat(chopt, "G",10);
4979 ndiv = TMath::Abs(ndivy);
4980 if (useHparam) {
4983 } else {
4984 umin = TMath::Power(10,aymin);
4985 umax = TMath::Power(10,aymax);
4986 }
4987 } else {
4988 ndiv = TMath::Abs(ndivy);
4989 if (useHparam) {
4990 umin = Hparam.ymin;
4991 umax = Hparam.ymax;
4992 } else {
4993 umin = aymin;
4994 umax = aymax;
4995 }
4996 }
4997
4998 // Display axis as time
4999 if (fYaxis->GetTimeDisplay()) {
5000 strlcat(chopt,"t",10);
5001 if (strlen(fYaxis->GetTimeFormatOnly()) == 0) {
5003 }
5004 }
5005
5006 // The main Y axis can be on the left or on the right of the pad
5008 if (yAxisPos == 1) {
5009 // Main Y axis left
5010 yAxisXPos1 = axmax;
5011 yAxisXPos2 = axmin;
5012 } else {
5013 // Main Y axis right
5014 yAxisXPos1 = axmin;
5015 yAxisXPos2 = axmax;
5016 }
5017
5018 // Paint the main Y axis (always)
5019 uminsave = umin;
5020 umaxsave = umax;
5021 ndivsave = ndiv;
5022 axis.SetOption(chopt);
5023 if (yAxisPos) {
5024 strlcat(chopt, "+L",10);
5025 gridl = -gridl;
5026 }
5027 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
5028 axis.SetLabelSize(0.);
5029 axis.SetTitle("");
5030 }
5033 umin, umax, ndiv, chopt, gridl, drawGridOnly);
5034
5035 // Paint the additional Y axis (if needed)
5036 // Additional checks for pad mode are required on iOS: this "second" axis is
5037 // neither pickable, nor highlighted. Additional checks have no effect on non-iOS platform.
5038 if (gPad->GetTicky() && !gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
5039 if (gPad->GetTicky() < 2) {
5040 strlcat(chopt, "U",10);
5042 } else {
5043 strlcat(chopt, "+L",10);
5044 }
5045 if ((cw=strstr(chopt,"W"))) *cw='z';
5046 axis.SetTitle("");
5050 }
5051 }//End of "if pad is in selection mode etc."
5052
5053 // Reset the axis if they have been inverted in case of option HBAR
5054 if (xaxis) {
5055 fXaxis = xaxis;
5056 fYaxis = yaxis;
5057 }
5058}
5059
5060////////////////////////////////////////////////////////////////////////////////
5061/// [Draw a bar-chart in a normal pad.](\ref HP10)
5062
5064{
5065
5066 Int_t bar = Hoption.Bar - 10;
5070 TBox box;
5072 if (hcolor == gPad->GetFrameFillColor()) ++hcolor;
5074 box.SetFillColor(hcolor);
5075 box.SetFillStyle(hstyle);
5076 box.SetLineStyle(fH->GetLineStyle());
5077 box.SetLineColor(fH->GetLineColor());
5078 box.SetLineWidth(fH->GetLineWidth());
5079 for (Int_t bin=fXaxis->GetFirst();bin<=fXaxis->GetLast();bin++) {
5080 y = fH->GetBinContent(bin);
5081 xmin = gPad->XtoPad(fXaxis->GetBinLowEdge(bin));
5082 xmax = gPad->XtoPad(fXaxis->GetBinUpEdge(bin));
5083 ymin = gPad->GetUymin();
5084 ymax = gPad->YtoPad(y);
5085 if (ymax < gPad->GetUymin()) continue;
5086 if (ymax > gPad->GetUymax()) ymax = gPad->GetUymax();
5087 if (ymin < gPad->GetUymin()) ymin = gPad->GetUymin();
5088 if (Hoption.MinimumZero && ymin < 0)
5089 ymin=TMath::Min(0.,gPad->GetUymax());
5090 w = (xmax-xmin)*width;
5091 xmin += offset*(xmax-xmin);
5092 xmax = xmin + w;
5093 if (bar < 1) {
5094 box.PaintBox(xmin,ymin,xmax,ymax);
5095 } else {
5096 umin = xmin + bar*(xmax-xmin)/10.;
5097 umax = xmax - bar*(xmax-xmin)/10.;
5098 box.SetFillColor(TColor::GetColorBright(hcolor)); //bright
5099 box.PaintBox(xmin,ymin,umin,ymax);
5100 box.SetFillColor(hcolor);
5101 box.PaintBox(umin,ymin,umax,ymax);
5102 box.SetFillColor(TColor::GetColorDark(hcolor)); //dark
5103 box.PaintBox(umax,ymin,xmax,ymax);
5104 }
5105 }
5106}
5107
5108////////////////////////////////////////////////////////////////////////////////
5109/// [Draw a bar char in a rotated pad (X vertical, Y horizontal)](\ref HP10)
5110
5112{
5113
5114 gPad->SetVertical(kFALSE);
5115
5116 PaintInitH();
5117
5118 TAxis *xaxis = fXaxis;
5119 TAxis *yaxis = fYaxis;
5120 if (!strcmp(xaxis->GetName(),"xaxis")) {
5121 fXaxis = yaxis;
5122 fYaxis = xaxis;
5123 }
5124
5125 PaintFrame();
5127
5128 Int_t bar = Hoption.Bar - 20;
5132 TBox box;
5134 if (hcolor == gPad->GetFrameFillColor()) ++hcolor;
5136 box.SetFillColor(hcolor);
5137 box.SetFillStyle(hstyle);
5138 box.SetLineStyle(fH->GetLineStyle());
5139 box.SetLineColor(fH->GetLineColor());
5140 box.SetLineWidth(fH->GetLineWidth());
5141 for (Int_t bin=fYaxis->GetFirst();bin<=fYaxis->GetLast();bin++) {
5142 ymin = gPad->YtoPad(fYaxis->GetBinLowEdge(bin));
5143 ymax = gPad->YtoPad(fYaxis->GetBinUpEdge(bin));
5144 xmin = gPad->GetUxmin();
5145 xmax = gPad->XtoPad(fH->GetBinContent(bin));
5146 if (xmax < gPad->GetUxmin()) continue;
5147 if (xmax > gPad->GetUxmax()) xmax = gPad->GetUxmax();
5148 if (xmin < gPad->GetUxmin()) xmin = gPad->GetUxmin();
5149 if (Hoption.MinimumZero && xmin < 0)
5150 xmin=TMath::Min(0.,gPad->GetUxmax());
5151 w = (ymax-ymin)*width;
5152 ymin += offset*(ymax-ymin);
5153 ymax = ymin + w;
5154 if (bar < 1) {
5155 box.PaintBox(xmin,ymin,xmax,ymax);
5156 } else {
5157 umin = ymin + bar*(ymax-ymin)/10.;
5158 umax = ymax - bar*(ymax-ymin)/10.;
5159 box.SetFillColor(TColor::GetColorDark(hcolor)); //dark
5160 box.PaintBox(xmin,ymin,xmax,umin);
5161 box.SetFillColor(hcolor);
5162 box.PaintBox(xmin,umin,xmax,umax);
5163 box.SetFillColor(TColor::GetColorBright(hcolor)); //bright
5164 box.PaintBox(xmin,umax,xmax,ymax);
5165 }
5166 }
5167
5168 PaintTitle();
5169
5170 // Draw box with histogram statistics and/or fit parameters
5171 if ((Hoption.Same%10) != 1 && !fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
5172 TIter next(fFunctions);
5173 TObject *obj = nullptr;
5174 while ((obj = next())) {
5175 if (obj->InheritsFrom(TF1::Class())) break;
5176 obj = nullptr;
5177 }
5178 PaintStat(gStyle->GetOptStat(),(TF1*)obj);
5179 }
5180
5181 fXaxis = xaxis;
5182 fYaxis = yaxis;
5183}
5184
5185////////////////////////////////////////////////////////////////////////////////
5186/// [Control function to draw a 2D histogram as a box plot](\ref HP13)
5187
5189{
5190
5193 if (fH->GetFillColor() == 0) fH->SetFillStyle(0);
5194 if (Hoption.Box == 11) fH->SetFillStyle(1001);
5195 fH->TAttLine::Modify();
5196 fH->TAttFill::Modify();
5197
5198 Double_t z, xk,xstep, yk, ystep, xcent, ycent, xlow, xup, ylow, yup;
5199 Double_t ux1 = gPad->PixeltoX(1);
5200 Double_t ux0 = gPad->PixeltoX(0);
5201 Double_t uy1 = gPad->PixeltoY(1);
5202 Double_t uy0 = gPad->PixeltoY(0);
5203 Double_t dxmin = 0.51*(gPad->PadtoX(ux1)-gPad->PadtoX(ux0));
5204 Double_t dymin = 0.51*(gPad->PadtoY(uy0)-gPad->PadtoY(uy1));
5205
5206 Double_t zmin = TMath::Max(fH->GetMinimum(),0.);
5209 Double_t zminlin = zmin, zmaxlin = zmax;
5210
5211 // In case of option SAME, zmin and zmax values are taken from the
5212 // first plotted 2D histogram.
5213 if (Hoption.Same > 0 && Hoption.Same < 10) {
5214 TH2 *h2;
5215 TIter next(gPad->GetListOfPrimitives());
5216 while ((h2 = (TH2 *)next())) {
5217 if (!h2->InheritsFrom(TH2::Class())) continue;
5218 zmin = TMath::Max(h2->GetMinimum(), 0.);
5219 zmax = TMath::Max(TMath::Abs(h2->GetMaximum()),
5220 TMath::Abs(h2->GetMinimum()));
5221 zminlin = zmin;
5222 zmaxlin = zmax;
5223 if (Hoption.Logz) {
5224 if (zmin <= 0) {
5225 zmin = TMath::Log10(zmax*0.001);
5226 } else {
5227 zmin = TMath::Log10(zmin);
5228 }
5229 zmax = TMath::Log10(zmax);
5230 }
5231 break;
5232 }
5233 } else {
5234 if (Hoption.Logz) {
5235 if (zmin > 0) {
5236 zmin = TMath::Log10(zmin);
5237 zmax = TMath::Log10(zmax);
5238 } else {
5239 return;
5240 }
5241 }
5242 }
5243
5244 Double_t zratio, dz = zmax - zmin;
5246 if (fH->GetMinimum()<0) kZminNeg = kTRUE;
5248
5249 // Define the dark and light colors the "button style" boxes.
5250 Color_t color = fH->GetFillColor();
5251 Color_t light=0, dark=0;
5252 if (Hoption.Box == 11) {
5254 dark = TColor::GetColorDark(color);
5255 }
5256
5257 // Loop over all the bins and draw the boxes
5258 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
5261 ycent = 0.5*ystep;
5262 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
5263 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
5264 xk = fXaxis->GetBinLowEdge(i);
5265 xstep = fXaxis->GetBinWidth(i);
5266 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
5267 xcent = 0.5*xstep;
5268 z = Hparam.factor*fH->GetBinContent(bin);
5269 kZNeg = kFALSE;
5270
5271 if (TMath::Abs(z) < zminlin) continue; // Can be the case with ...
5272 if (TMath::Abs(z) > zmaxlin) z = zmaxlin; // ... option Same
5273 if (kZminNeg && z==0) continue; // Do not draw empty bins if case of histo with negative bins.
5274
5275 if (z < 0) {
5276 if (Hoption.Logz) continue;
5277 z = -z;
5278 kZNeg = kTRUE;
5279 }
5280 if (Hoption.Logz) {
5281 if (z != 0) z = TMath::Log10(z);
5282 else z = zmin;
5283 }
5284
5285 if (dz == 0) continue;
5286 zratio = TMath::Sqrt((z-zmin)/dz);
5287 if (zratio == 0) continue;
5288
5289 xup = xcent*zratio + xk + xcent;
5290 xlow = 2*(xk + xcent) - xup;
5291 if (xup-xlow < dxmin) xup = xlow+dxmin;
5292 if (Hoption.Logx) {
5293 if (xup > 0) xup = TMath::Log10(xup);
5294 else continue;
5295 if (xlow > 0) xlow = TMath::Log10(xlow);
5296 else continue;
5297 }
5298
5299 yup = ycent*zratio + yk + ycent;
5300 ylow = 2*(yk + ycent) - yup;
5301 if (yup-ylow < dymin) yup = ylow+dymin;
5302 if (Hoption.Logy) {
5303 if (yup > 0) yup = TMath::Log10(yup);
5304 else continue;
5305 if (ylow > 0) ylow = TMath::Log10(ylow);
5306 else continue;
5307 }
5308
5309 xlow = TMath::Max(xlow, gPad->GetUxmin());
5310 ylow = TMath::Max(ylow, gPad->GetUymin());
5311 xup = TMath::Min(xup , gPad->GetUxmax());
5312 yup = TMath::Min(yup , gPad->GetUymax());
5313
5314 if (xlow >= xup) continue;
5315 if (ylow >= yup) continue;
5316
5317 if (Hoption.Box == 1) {
5318 fH->SetFillColor(color);
5319 fH->TAttFill::Modify();
5320 gPad->PaintBox(xlow, ylow, xup, yup);
5321 if (kZNeg) {
5322 gPad->PaintLine(xlow, ylow, xup, yup);
5323 gPad->PaintLine(xlow, yup, xup, ylow);
5324 }
5325 } else if (Hoption.Box == 11) {
5326 // Draw the center of the box
5327 fH->SetFillColor(color);
5328 fH->TAttFill::Modify();
5329 gPad->PaintBox(xlow, ylow, xup, yup);
5330
5331 // Draw top&left part of the box
5332 Double_t x[7], y[7];
5333 Double_t bwidth = 0.1;
5334 x[0] = xlow; y[0] = ylow;
5335 x[1] = xlow + bwidth*(xup-xlow); y[1] = ylow + bwidth*(yup-ylow);
5336 x[2] = x[1]; y[2] = yup - bwidth*(yup-ylow);
5337 x[3] = xup - bwidth*(xup-xlow); y[3] = y[2];
5338 x[4] = xup; y[4] = yup;
5339 x[5] = xlow; y[5] = yup;
5340 x[6] = xlow; y[6] = ylow;
5341 if (kZNeg) fH->SetFillColor(dark);
5342 else fH->SetFillColor(light);
5343 fH->TAttFill::Modify();
5344 gPad->PaintFillArea(7, x, y);
5345
5346 // Draw bottom&right part of the box
5347 x[0] = xlow; y[0] = ylow;
5348 x[1] = xlow + bwidth*(xup-xlow); y[1] = ylow + bwidth*(yup-ylow);
5349 x[2] = xup - bwidth*(xup-xlow); y[2] = y[1];
5350 x[3] = x[2]; y[3] = yup - bwidth*(yup-ylow);
5351 x[4] = xup; y[4] = yup;
5352 x[5] = xup; y[5] = ylow;
5353 x[6] = xlow; y[6] = ylow;
5354 if (kZNeg) fH->SetFillColor(light);
5355 else fH->SetFillColor(dark);
5356 fH->TAttFill::Modify();
5357 gPad->PaintFillArea(7, x, y);
5358 }
5359 }
5360 }
5361
5365 fH->TAttFill::Modify();
5366}
5367
5368
5369
5370////////////////////////////////////////////////////////////////////////////////
5371/// [Control function to draw a 2D histogram as a candle (box) plot or violin plot](\ref HP14)
5372
5374{
5375 TH1D *hproj = nullptr;
5376 TH2D *h2 = (TH2D*)fH;
5377
5380 myCandle.SetMarkerColor(fH->GetLineColor());
5381 myCandle.SetLineColor(fH->GetLineColor());
5382 myCandle.SetLineWidth(fH->GetLineWidth());
5383 myCandle.SetFillColor(fH->GetFillColor());
5384 myCandle.SetFillStyle(fH->GetFillStyle());
5385 myCandle.SetMarkerSize(fH->GetMarkerSize());
5386 myCandle.SetMarkerStyle(fH->GetMarkerStyle());
5388
5389 Bool_t swapXY = myCandle.IsHorizontal();
5390 const Double_t standardCandleWidth = 0.66;
5391 const Double_t standardHistoWidth = 0.8;
5392
5393 double allMaxContent = 0, allMaxIntegral = 0;
5394 if (myCandle.IsViolinScaled())
5395 allMaxContent = h2->GetBinContent(h2->GetMaximumBin());
5396
5397 if (!swapXY) { // Vertical candle
5398 //Determining the slice with the maximum integral - if necessary
5399 if (myCandle.IsCandleScaled())
5400 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast; i++) {
5401 hproj = h2->ProjectionY("_px", i, i);
5402 if (hproj->Integral() > allMaxIntegral) allMaxIntegral = hproj->Integral();
5403 }
5404 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast; i++) {
5406 Double_t binWidth = fXaxis->GetBinWidth(i);
5407 hproj = h2->ProjectionY("_px", i, i);
5408 if (hproj->GetEntries() != 0) {
5410 Double_t offset = fH->GetBarOffset()*binWidth;
5411 double myMaxContent = hproj->GetBinContent(hproj->GetMaximumBin());
5412 double myIntegral = hproj->Integral();
5414 if (candleWidth > 0.999 && candleWidth < 1.001) {
5417 }
5418 if (Hoption.Logz && myMaxContent > 0) {
5420 if (myCandle.IsViolinScaled() && myMaxContent > 0 && allMaxContent > 0)
5422 } else if (myCandle.IsViolinScaled() && (allMaxContent > 0))
5424 if (myCandle.IsCandleScaled() && (allMaxIntegral > 0))
5426
5427 myCandle.SetAxisPosition(binPosX+binWidth/2. + offset);
5428 myCandle.SetCandleWidth(candleWidth*binWidth);
5429 myCandle.SetHistoWidth(histoWidth*binWidth);
5430 myCandle.SetHistogram(hproj);
5431 myCandle.Paint();
5432 }
5433 }
5434 } else { // Horizontal candle
5435 //Determining the slice with the maximum integral - if necessary
5436 if (myCandle.IsCandleScaled())
5437 for (Int_t i=Hparam.yfirst; i<=Hparam.ylast; i++) {
5438 hproj = h2->ProjectionX("_py", i, i);
5439 if (hproj->Integral() > allMaxIntegral) allMaxIntegral = hproj->Integral();
5440 }
5441 for (Int_t i=Hparam.yfirst; i<=Hparam.ylast; i++) {
5443 Double_t binWidth = fYaxis->GetBinWidth(i);
5444 hproj = h2->ProjectionX("_py", i, i);
5445 if (hproj->GetEntries() != 0) {
5447 Double_t offset = fH->GetBarOffset()*binWidth;
5448 double myMaxContent = hproj->GetBinContent(hproj->GetMaximumBin());
5449 double myIntegral = hproj->Integral();
5451 if (candleWidth > 0.999 && candleWidth < 1.001) {
5454 }
5455 if (Hoption.Logz && myMaxContent > 0) {
5457 if (myCandle.IsViolinScaled() && myMaxContent > 0 && allMaxContent > 0)
5459 } else if (myCandle.IsViolinScaled() && (allMaxContent > 0))
5461 if (myCandle.IsCandleScaled() && (allMaxIntegral > 0))
5463
5464 myCandle.SetAxisPosition(binPosY+binWidth/2. + offset);
5465 myCandle.SetCandleWidth(candleWidth*binWidth);
5466 myCandle.SetHistoWidth(histoWidth*binWidth);
5467 myCandle.SetHistogram(hproj);
5468 myCandle.Paint();
5469 }
5470 }
5471 }
5472 delete hproj;
5473}
5474
5475
5476
5477////////////////////////////////////////////////////////////////////////////////
5478/// Returns the rendering regions for an axis to use in the COL2 option
5479///
5480/// The algorithm analyses the size of the axis compared to the size of
5481/// the rendering region. It figures out the boundaries to use for each color
5482/// of the rendering region. Only one axis is computed here.
5483///
5484/// This allows for a single computation of the boundaries before iterating
5485/// through all of the bins.
5486///
5487/// \param pAxis the axis to consider
5488/// \param nPixels the number of pixels to render axis into
5489/// \param isLog whether the axis is log scale
5490
5491std::vector<THistRenderingRegion>
5493{
5494 std::vector<THistRenderingRegion> regions;
5495
5496 enum STRATEGY { Bins, Pixels } strategy;
5497
5498 Int_t nBins = (pAxis->GetLast() - pAxis->GetFirst() + 1);
5499
5500 if (nBins >= nPixels) {
5501 // more bins than pixels... we should loop over pixels and sample
5502 strategy = Pixels;
5503 } else {
5504 // fewer bins than pixels... we should loop over bins
5505 strategy = Bins;
5506 }
5507
5508 if (isLog) {
5509
5510 Double_t xMin = pAxis->GetBinLowEdge(pAxis->GetFirst());
5511 Int_t binOffset=0;
5512 while (xMin <= 0 && ((pAxis->GetFirst()+binOffset) != pAxis->GetLast()) ) {
5513 binOffset++;
5514 xMin = pAxis->GetBinLowEdge(pAxis->GetFirst()+binOffset);
5515 }
5516 if (xMin <= 0) {
5517 // this should cause an error if we have
5518 return regions;
5519 }
5520 Double_t xMax = pAxis->GetBinUpEdge(pAxis->GetLast());
5521
5522 if (strategy == Bins) {
5523 // logarithmic plot. we find the pixel for the bin
5524 // pixel = eta * log10(V) - alpha
5525 // where eta = nPixels/(log10(Vmax)-log10(Vmin))
5526 // and alpha = nPixels*log10(Vmin)/(log10(Vmax)-log10(Vmin))
5527 // and V is axis value
5529 Double_t offset = -1.0 * eta * TMath::Log10(xMin);
5530
5531 for (Int_t bin=pAxis->GetFirst()+binOffset; bin<=pAxis->GetLast(); bin++) {
5532
5533 // linear plot. we simply need to find the appropriate bin
5534 // for the
5535 Double_t xLowValue = pAxis->GetBinLowEdge(bin);
5536 Double_t xUpValue = pAxis->GetBinUpEdge(bin);
5539 THistRenderingRegion region = {std::make_pair(xPx0, xPx1),
5540 std::make_pair(bin, bin+1)};
5541 regions.push_back(region);
5542 }
5543
5544 } else {
5545
5546 // loop over pixels
5547
5549
5550 for (Int_t pixelIndex=0; pixelIndex<(nPixels-1); pixelIndex++) {
5551 // linear plot
5552 Int_t binLow = pAxis->FindBin(xMin*TMath::Power(10.0, beta*pixelIndex));
5553 Int_t binHigh = pAxis->FindBin(xMin*TMath::Power(10.0, beta*(pixelIndex+1)));
5554 THistRenderingRegion region = { std::make_pair(pixelIndex, pixelIndex+1),
5555 std::make_pair(binLow, binHigh)};
5556 regions.push_back(region);
5557 }
5558 }
5559 } else {
5560 // standard linear plot
5561
5562 if (strategy == Bins) {
5563 // loop over bins
5564 for (Int_t bin=pAxis->GetFirst(); bin<=pAxis->GetLast(); bin++) {
5565
5566 // linear plot. we simply need to find the appropriate bin
5567 // for the
5568 Int_t xPx0 = ((bin - pAxis->GetFirst()) * nPixels)/nBins;
5569 Int_t xPx1 = xPx0 + nPixels/nBins;
5570
5571 // make sure we don't compute beyond our bounds
5572 if (xPx1>= nPixels) xPx1 = nPixels-1;
5573
5574 THistRenderingRegion region = {std::make_pair(xPx0, xPx1),
5575 std::make_pair(bin, bin+1)};
5576 regions.push_back(region);
5577 }
5578 } else {
5579 // loop over pixels
5581 // linear plot
5582 Int_t binLow = (nBins*pixelIndex)/nPixels + pAxis->GetFirst();
5583 Int_t binHigh = binLow + nBins/nPixels;
5584 THistRenderingRegion region = { std::make_pair(pixelIndex, pixelIndex+1),
5585 std::make_pair(binLow, binHigh)};
5586 regions.push_back(region);
5587 }
5588 }
5589 }
5590
5591 return regions;
5592}
5593
5594////////////////////////////////////////////////////////////////////////////////
5595/// [Rendering scheme for the COL2 and COLZ2 options] (\ref HP14)
5596
5598{
5599
5600 if (Hoption.System != kCARTESIAN) {
5601 Error("THistPainter::PaintColorLevelsFast(Option_t*)",
5602 "Only cartesian coordinates supported by 'COL2' option. Using 'COL' option instead.");
5603 PaintColorLevels(nullptr);
5604 return;
5605 }
5606
5607 Double_t z;
5608
5609 // Use existing max or min values. If either is already set
5610 // the appropriate value to use.
5611 Double_t zmin = fH->GetMinimumStored();
5612 Double_t zmax = fH->GetMaximumStored();
5613 Double_t originalZMin = zmin;
5614 Double_t originalZMax = zmax;
5615 if ((zmin == -1111) && (zmax == -1111)) {
5616 fH->GetMinimumAndMaximum(zmin, zmax);
5617 fH->SetMinimum(zmin);
5618 fH->SetMaximum(zmax);
5619 } else if (zmin == -1111) {
5620 zmin = fH->GetMinimum();
5621 fH->SetMinimum(zmin);
5622 } else if (zmax == -1111) {
5623 zmax = fH->GetMaximum();
5624 fH->SetMaximum(zmax);
5625 }
5626
5627 Double_t dz = zmax - zmin;
5628 if (dz <= 0) { // Histogram filled with a constant value
5629 zmax += 0.1*TMath::Abs(zmax);
5630 zmin -= 0.1*TMath::Abs(zmin);
5631 dz = zmax - zmin;
5632 }
5633
5634 if (Hoption.Logz) {
5635 if (zmin > 0) {
5636 zmin = TMath::Log10(zmin);
5637 zmax = TMath::Log10(zmax);
5638 dz = zmax - zmin;
5639 } else {
5640 Error("THistPainter::PaintColorLevelsFast(Option_t*)",
5641 "Cannot plot logz because bin content is less than 0.");
5642 return;
5643 }
5644 }
5645
5646 // Initialize the levels on the Z axis
5647 Int_t ndiv = fH->GetContour();
5648 if (ndiv == 0 ) {
5649 ndiv = gStyle->GetNumberContours();
5650 fH->SetContour(ndiv);
5651 }
5652 std::vector<Double_t> colorBounds(ndiv);
5653 std::vector<Double_t> contours(ndiv, 0);
5654 if (!fH->TestBit(TH1::kUserContour)) {
5655 fH->SetContour(ndiv);
5656 } else {
5657 fH->GetContour(contours.data());
5658 }
5659
5660 Double_t step = 1.0/ndiv;
5661 for (Int_t i=0; i<ndiv; ++i) {
5662 colorBounds[i] = step*i;
5663 }
5664
5665 auto pFrame = gPad->GetFrame();
5666 Int_t px0 = gPad->XtoPixel(pFrame->GetX1());
5667 Int_t px1 = gPad->XtoPixel(pFrame->GetX2());
5668 Int_t py0 = gPad->YtoPixel(pFrame->GetY1());
5669 Int_t py1 = gPad->YtoPixel(pFrame->GetY2());
5670 Int_t nXPixels = px1-px0;
5671 Int_t nYPixels = py0-py1; // y=0 is at the top of the screen
5672
5673 std::vector<Double_t> buffer(nXPixels*nYPixels, 0);
5674
5677 if (xRegions.empty() || yRegions.empty()) {
5678 Error("THistPainter::PaintColorLevelFast(Option_t*)",
5679 "Encountered error while computing rendering regions.");
5680 return;
5681 }
5682
5685 Double_t minValue = 1.;
5686 Double_t maxValue = 0.;
5687 for (auto& yRegion : yRegions) {
5688 for (auto& xRegion : xRegions ) {
5689
5690 const auto& xBinRange = xRegion.fBinRange;
5691 const auto& yBinRange = yRegion.fBinRange;
5692
5693 // sample the range
5694 z = fH->GetBinContent(xBinRange.second-1, yBinRange.second-1);
5695
5696 if (Hoption.Logz) {
5697 if (z > 0) z = TMath::Log10(z);
5698 else z = zmin;
5699 }
5700
5701 // obey the user's max and min values if they were set
5702 if (z > zmax) z = zmax;
5703 if (z < zmin) z = zmin;
5704
5706 // contours are absolute values
5707 auto index = TMath::BinarySearch(contours.size(), contours.data(), z);
5708 z = colorBounds[index];
5709 } else {
5710 Int_t index = 0;
5711 if (dz != 0) {
5712 index = 0.001 + ((z - zmin)/dz)*ndiv;
5713 }
5714
5715 if (index == static_cast<Int_t>(colorBounds.size())) {
5716 index--;
5717 }
5718
5719 // Do a little bookkeeping to use later for getting libAfterImage to produce
5720 // the correct colors
5721 if (index == 0) {
5722 minExists = kTRUE;
5723 } else if (index == static_cast<Int_t>(colorBounds.size()-1)) {
5724 maxExists = kTRUE;
5725 }
5726
5727 z = colorBounds[index];
5728
5729 if (z < minValue) {
5730 minValue = z;
5731 }
5732 if (z > maxValue) {
5733 maxValue = z;
5734 }
5735 }
5736
5737 // fill in the actual pixels
5738 const auto& xPixelRange = xRegion.fPixelRange;
5739 const auto& yPixelRange = yRegion.fPixelRange;
5740 for (Int_t xPx = xPixelRange.first; xPx <= xPixelRange.second; ++xPx) {
5741 for (Int_t yPx = yPixelRange.first; yPx <= yPixelRange.second; ++yPx) {
5743 buffer[pixel] = z;
5744 }
5745 }
5746 } // end px loop
5747 } // end py loop
5748
5749 // This is a bit of a hack to ensure that we span the entire color range and
5750 // don't screw up the colors for a sparse histogram. No one will notice that I set a
5751 // single pixel on the edge of the image to a different color. This is even more
5752 // true because the chosen pixels will be covered by the axis.
5753 if (minValue != maxValue) {
5754 if ( !minExists) {
5755 buffer.front() = 0;
5756 }
5757
5758 if ( !maxExists) {
5759 buffer[buffer.size()-nXPixels] = 0.95;
5760 }
5761 }
5762
5763 // Generate the TImage
5766 pImage->SetImageQuality(TAttImage::kImgBest);
5767 pImage->SetImage(buffer.data(), nXPixels, nYPixels, pPalette);
5768 delete pPalette;
5769
5770 Window_t wid = static_cast<Window_t>(gVirtualX->GetWindowID(gPad->GetPixmapID()));
5771 pImage->PaintImage(wid, px0, py1, 0, 0, nXPixels, nYPixels);
5772 delete pImage;
5773
5775
5776 // Reset the maximum and minimum values to their original values
5777 // when this function was called. If we don't do this, an initial
5778 // value of -1111 will be replaced with the true max or min values.
5781}
5782
5783////////////////////////////////////////////////////////////////////////////////
5784/// [Control function to draw a 2D histogram as a color plot.](\ref HP14)
5785
5787{
5788 Double_t z, e, zc, xk, xstep, yk, ystep, xlow, xup, ylow, yup;
5789
5790 Double_t zmin = fH->GetMinimum();
5791 Double_t zmax = fH->GetMaximum();
5792
5793 Double_t dz = zmax - zmin;
5794 if (dz <= 0) { // Histogram filled with a constant value
5795 zmax += 0.1*TMath::Abs(zmax);
5796 zmin -= 0.1*TMath::Abs(zmin);
5797 dz = zmax - zmin;
5798 }
5799
5800 // In case of option SAME, zmin and zmax values are taken from the
5801 // first plotted 2D histogram.
5802 if (Hoption.Same > 0 && Hoption.Same < 10) {
5803 TH2 *h2;
5804 TIter next(gPad->GetListOfPrimitives());
5805 while ((h2 = (TH2 *)next())) {
5806 if (!h2->InheritsFrom(TH2::Class())) continue;
5807 zmin = h2->GetMinimum();
5808 zmax = h2->GetMaximum();
5809 fH->SetMinimum(zmin);
5810 fH->SetMaximum(zmax);
5811 if (Hoption.Logz) {
5812 if (zmin <= 0) {
5813 zmin = TMath::Log10(zmax*0.001);
5814 } else {
5815 zmin = TMath::Log10(zmin);
5816 }
5817 zmax = TMath::Log10(zmax);
5818 }
5819 dz = zmax - zmin;
5820 break;
5821 }
5822 } else {
5823 if (Hoption.Logz) {
5824 if (zmin > 0) {
5825 zmin = TMath::Log10(zmin);
5826 zmax = TMath::Log10(zmax);
5827 dz = zmax - zmin;
5828 } else {
5829 return;
5830 }
5831 }
5832 }
5833
5836 fH->SetFillStyle(1001);
5837 fH->TAttFill::Modify();
5838
5839 // Initialize the levels on the Z axis
5840 Int_t ncolors = gStyle->GetNumberOfColors();
5841 Int_t ndiv = fH->GetContour();
5842 if (ndiv == 0 ) {
5843 ndiv = gStyle->GetNumberContours();
5844 fH->SetContour(ndiv);
5845 }
5846 Int_t ndivz = TMath::Abs(ndiv);
5847 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
5848 Double_t scale = (dz ? ndivz / dz : 1.0);
5849
5850 Int_t color;
5851 TProfile2D* prof2d = dynamic_cast<TProfile2D*>(fH);
5852 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
5855 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
5856 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
5857 xk = fXaxis->GetBinLowEdge(i);
5858 xstep = fXaxis->GetBinWidth(i);
5859 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
5860 z = fH->GetBinContent(bin);
5861 e = fH->GetBinError(bin);
5862 // if fH is a profile histogram do not draw empty bins
5863 if (prof2d) {
5864 const Double_t binEntries = prof2d->GetBinEntries(bin);
5865 if (binEntries == 0)
5866 continue;
5867 } else {
5868 // don't draw the empty bins for non-profile histograms
5869 // with positive content
5870 if (z == 0 && e == 0) {
5871 if (zmin >= 0 || Hoption.Logz) continue;
5872 if (Hoption.Color == 2) continue;
5873 }
5874 }
5875
5876 if (Hoption.Logz) {
5877 if (z > 0) z = TMath::Log10(z);
5878 else z = zmin;
5879 }
5880 if (z < zmin && !Hoption.Zero) continue;
5881 xup = xk + xstep;
5882 xlow = xk;
5883 if (Hoption.Logx) {
5884 if (xup > 0) xup = TMath::Log10(xup);
5885 else continue;
5886 if (xlow > 0) xlow = TMath::Log10(xlow);
5887 else continue;
5888 }
5889 yup = yk + ystep;
5890 ylow = yk;
5891 if (Hoption.Logy) {
5892 if (yup > 0) yup = TMath::Log10(yup);
5893 else continue;
5894 if (ylow > 0) ylow = TMath::Log10(ylow);
5895 else continue;
5896 }
5897 if (xup < gPad->GetUxmin()) continue;
5898 if (yup < gPad->GetUymin()) continue;
5899 if (xlow > gPad->GetUxmax()) continue;
5900 if (ylow > gPad->GetUymax()) continue;
5901 if (xlow < gPad->GetUxmin()) xlow = gPad->GetUxmin();
5902 if (ylow < gPad->GetUymin()) ylow = gPad->GetUymin();
5903 if (xup > gPad->GetUxmax()) xup = gPad->GetUxmax();
5904 if (yup > gPad->GetUymax()) yup = gPad->GetUymax();
5905
5907 zc = fH->GetContourLevelPad(0);
5908 if (z < zc) continue;
5909 color = -1;
5910 for (Int_t k=0; k<ndiv; k++) {
5911 zc = fH->GetContourLevelPad(k);
5912 if (z < zc) {
5913 continue;
5914 } else {
5915 color++;
5916 }
5917 }
5918 } else {
5919 color = Hoption.Zero ? Int_t(0.01+(std::max(z, zmin)-zmin)*scale) : Int_t(0.01+(z-zmin)*scale);
5920 }
5921
5922 Int_t theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
5923 if (theColor > ncolors-1) theColor = ncolors-1;
5925 if (Hoption.System != kPOLAR) {
5927 fH->TAttFill::Modify();
5928 gPad->PaintBox(xlow, ylow, xup, yup);
5929 } else {
5930 Double_t midx = (gPad->GetUxmin() + gPad->GetUxmax()) / 2,
5931 midy = (gPad->GetUymin() + gPad->GetUymax()) / 2,
5932 a1 = (xlow - gPad->GetUxmin()) / (gPad->GetUxmax() - gPad->GetUxmin()) * 360,
5933 a2 = (xup - gPad->GetUxmin()) / (gPad->GetUxmax() - gPad->GetUxmin()) * 360,
5934 rx = gPad->GetUxmax() - gPad->GetUxmin(),
5935 ry = gPad->GetUymax() - gPad->GetUymin(),
5936 r1 = (ylow - gPad->GetUymin()) / (gPad->GetUymax() - gPad->GetUymin()) * rx / 2,
5937 r2 = (yup - gPad->GetUymin()) / (gPad->GetUymax() - gPad->GetUymin()) * rx / 2;
5938
5939 TCrown crown(midx, midy, r1, r2, a1, a2);
5940 crown.SetYXRatio(rx > 0 ? ry / rx : 1);
5941 crown.SetFillColor(fillColor);
5942 crown.SetLineColor(fH->GetLineColor());
5943 crown.SetLineWidth(fH->GetLineWidth());
5944 crown.SetLineStyle(fH->GetLineStyle());
5945 crown.Paint();
5946 }
5947 }
5948 }
5949
5951
5954 fH->TAttFill::Modify();
5955
5956}
5957
5958////////////////////////////////////////////////////////////////////////////////
5959/// [Control function to draw a 2D histogram as a contour plot.](\ref HP16)
5960
5962{
5963
5964 Int_t i, j, count, ncontour, icol, n, lj, m, ix, jx, ljfill;
5965 Int_t itars, mode, ir[4];
5966 Double_t xsave, ysave, thesave,phisave,x[4], y[4], zc[4];
5967
5968 if (Hoption.Contour == 14) {
5969 Hoption.Surf = 12;
5970 Hoption.Axis = 1;
5971 thesave = gPad->GetTheta();
5972 phisave = gPad->GetPhi();
5973 gPad->SetPhi(0.);
5974 gPad->SetTheta(90.);
5976 gPad->SetPhi(phisave);
5977 gPad->SetTheta(thesave);
5978 TView *view = gPad->GetView();
5979 if (view) view->SetBit(kCannotRotate); //tested in ExecuteEvent
5980 PaintAxis();
5981 return;
5982 }
5983
5984 if (Hoption.Same) {
5985 // If the contour is painted on a 3d plot, the contour lines are
5986 // paint in 3d too.
5987 TObject *obj;
5988 TIter next(gPad->GetListOfPrimitives());
5989 while ((obj=next())) {
5990 if (strstr(obj->GetDrawOption(),"surf") ||
5991 strstr(obj->GetDrawOption(),"lego") ||
5992 strstr(obj->GetDrawOption(),"tri")) {
5993 Hoption.Surf = 16;
5995 return;
5996 }
5997 }
5998 }
5999
6000 if (Hoption.Contour == 15) {
6001 TGraphDelaunay2D *dt = nullptr;
6002 TGraphDelaunay *dtOld = nullptr;
6004 dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
6005 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
6006 if (!dt && !dtOld) return;
6007 if (!fGraph2DPainter)
6008 fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
6009 fGraph2DPainter->Paint(option);
6010 return;
6011 }
6012
6013 gPad->SetBit(TGraph::kClipFrame);
6014
6015 std::vector<Double_t> levels(2*kMAXCONTOUR);
6016 std::vector<Double_t> xarr(2*kMAXCONTOUR);
6017 std::vector<Double_t> yarr(2*kMAXCONTOUR);
6018 std::vector<Int_t> itarr(2*kMAXCONTOUR);
6019
6020 Int_t npmax = 0;
6021 for (i=0;i<2*kMAXCONTOUR;i++) itarr[i] = 0;
6022
6023 ncontour = fH->GetContour();
6024 if (ncontour == 0) {
6027 }
6028 if (ncontour > kMAXCONTOUR) {
6029 Warning("PaintContour", "maximum number of contours is %d, asked for %d",
6032 }
6034
6035 for (i=0;i<ncontour;i++) levels[i] = fH->GetContourLevelPad(i);
6039 if (Hoption.Contour == 13) {
6040 fH->TAttLine::Modify();
6041 }
6042
6043 std::vector<std::unique_ptr<TPolyLine>> polys;
6044 TObjArray *contours = nullptr;
6045 TList *list = nullptr;
6046 TGraph *graph = nullptr;
6047 std::vector<Int_t> np;
6048 if (Hoption.Contour == 1) {
6049 np.resize(ncontour);
6050 for (i=0;i<ncontour;i++)
6051 np[i] = 0;
6052 for (i=0;i<ncontour;i++)
6053 polys.emplace_back(std::make_unique<TPolyLine>(100));
6054 if (Hoption.List == 1) {
6055 contours = (TObjArray*)gROOT->GetListOfSpecials()->FindObject("contours");
6056 if (contours) {
6057 gROOT->GetListOfSpecials()->Remove(contours);
6058 count = contours->GetSize();
6059 for (i=0;i<count;i++) {
6060 list = (TList*)contours->At(i);
6061 if (list) list->Delete();
6062 }
6063 contours->Delete();
6064 delete contours;
6065 }
6067 contours->SetName("contours");
6068 gROOT->GetListOfSpecials()->Add(contours);
6069 for (i=0;i<ncontour;i++) {
6070 list = new TList();
6071 contours->Add(list);
6072 }
6073 }
6074 }
6076 Int_t ncolors = gStyle->GetNumberOfColors();
6078
6079 Int_t k,ipoly;
6080 for (j=Hparam.yfirst; j<Hparam.ylast; j++) {
6081 y[0] = fYaxis->GetBinCenter(j);
6082 y[1] = y[0];
6083 y[2] = fYaxis->GetBinCenter(j+1);
6084 y[3] = y[2];
6085 for (i=Hparam.xfirst; i<Hparam.xlast; i++) {
6086 zc[0] = fH->GetBinContent(i, j);
6087 zc[1] = fH->GetBinContent(i+1, j);
6088 zc[2] = fH->GetBinContent(i+1, j+1);
6089 zc[3] = fH->GetBinContent(i, j+1);
6090 if (!IsInside(fXaxis->GetBinCenter(i),fYaxis->GetBinCenter(j))) continue;
6091 if (Hoption.Logz) {
6092 if (zc[0] > 0) zc[0] = TMath::Log10(zc[0]);
6093 else zc[0] = Hparam.zmin;
6094 if (zc[1] > 0) zc[1] = TMath::Log10(zc[1]);
6095 else zc[1] = Hparam.zmin;
6096 if (zc[2] > 0) zc[2] = TMath::Log10(zc[2]);
6097 else zc[2] = Hparam.zmin;
6098 if (zc[3] > 0) zc[3] = TMath::Log10(zc[3]);
6099 else zc[3] = Hparam.zmin;
6100 }
6101 for (k=0;k<4;k++) {
6102 ir[k] = TMath::BinarySearch(ncontour, levels.data(), zc[k]);
6103 }
6104 if (ir[0] != ir[1] || ir[1] != ir[2] || ir[2] != ir[3] || ir[3] != ir[0]) {
6105 x[0] = fXaxis->GetBinCenter(i);
6106 x[3] = x[0];
6107 x[1] = fXaxis->GetBinCenter(i+1);
6108 x[2] = x[1];
6109 if (zc[0] <= zc[1]) n = 0; else n = 1;
6110 if (zc[2] <= zc[3]) m = 2; else m = 3;
6111 if (zc[n] > zc[m]) n = m;
6112 n++;
6113 lj=1;
6114 for (ix=1;ix<=4;ix++) {
6115 m = n%4 + 1;
6116 ljfill = PaintContourLine(zc[n-1],ir[n-1],x[n-1],y[n-1],zc[m-1],
6117 ir[m-1],x[m-1],y[m-1], xarr.data()+lj-1,yarr.data()+lj-1,itarr.data()+lj-1, levels.data());
6118 lj += 2*ljfill;
6119 n = m;
6120 }
6121
6122 if (zc[0] <= zc[1]) n = 0; else n = 1;
6123 if (zc[2] <= zc[3]) m = 2; else m = 3;
6124 if (zc[n] > zc[m]) n = m;
6125 n++;
6126 lj=2;
6127 for (ix=1;ix<=4;ix++) {
6128 if (n == 1) m = 4;
6129 else m = n-1;
6130 ljfill = PaintContourLine(zc[n-1],ir[n-1],x[n-1],y[n-1],zc[m-1],
6131 ir[m-1],x[m-1],y[m-1],xarr.data()+lj-1,yarr.data()+lj-1,itarr.data()+lj-1, levels.data());
6132 lj += 2*ljfill;
6133 n = m;
6134 }
6135
6136 // Re-order endpoints
6137
6138 count = 0;
6139 for (ix=1; ix<=lj-5; ix +=2) {
6140 //count = 0;
6141 while (itarr[ix-1] != itarr[ix]) {
6142 xsave = xarr[ix];
6143 ysave = yarr[ix];
6144 itars = itarr[ix];
6145 for (jx=ix; jx<=lj-5; jx +=2) {
6146 xarr[jx] = xarr[jx+2];
6147 yarr[jx] = yarr[jx+2];
6148 itarr[jx] = itarr[jx+2];
6149 }
6150 xarr[lj-3] = xsave;
6151 yarr[lj-3] = ysave;
6152 itarr[lj-3] = itars;
6153 if (count > 100) break;
6154 count++;
6155 }
6156 }
6157
6158 if (count > 100) continue;
6159 for (ix=1; ix<=lj-2; ix +=2) {
6160 theColor = Int_t((itarr[ix-1]+0.99)*Float_t(ncolors)/Float_t(ndivz));
6162 if (Hoption.Contour == 11) {
6164 }
6165 if (Hoption.Contour == 12) {
6166 mode = icol%5;
6167 if (mode == 0) mode = 5;
6169 }
6170 if (Hoption.Contour != 1) {
6171 fH->TAttLine::Modify();
6172 gPad->PaintPolyLine(2,xarr.data()+ix-1,yarr.data()+ix-1);
6173 continue;
6174 }
6175
6176 ipoly = itarr[ix-1];
6177 if (ipoly >=0 && ipoly <ncontour) {
6178 polys[ipoly]->SetPoint(np[ipoly] ,xarr[ix-1],yarr[ix-1]);
6179 polys[ipoly]->SetPoint(np[ipoly]+1,xarr[ix], yarr[ix]);
6180 np[ipoly] += 2;
6181 if (npmax < np[ipoly]) npmax = np[ipoly];
6182 }
6183 }
6184 } // end of if (ir[0]
6185 } //end of for (i
6186 } //end of for (j
6187
6189 std::vector<Double_t> xp, yp;
6191 Int_t istart;
6192 Int_t first = ncontour;
6193 std::vector<Int_t> polysort;
6195 if (Hoption.Contour != 1) goto theEND;
6196
6197 //The 2 points line generated above are now sorted/merged to generate
6198 //a list of consecutive points.
6199 // If the option "List" has been specified, the list of points is saved
6200 // in the form of TGraph objects in the ROOT list of special objects.
6201 xmin = gPad->GetUxmin();
6202 ymin = gPad->GetUymin();
6203 xp.resize(2*npmax);
6204 yp.resize(2*npmax);
6205 polysort.resize(ncontour);
6206 //find first positive contour
6207 for (ipoly=0;ipoly<ncontour;ipoly++) {
6208 if (levels[ipoly] >= 0) {first = ipoly; break;}
6209 }
6210 //store negative contours from 0 to minimum, then all positive contours
6211 k = 0;
6212 for (ipoly=first-1;ipoly>=0;ipoly--) {polysort[k] = ipoly; k++;}
6213 for (ipoly=first;ipoly<ncontour;ipoly++) {polysort[k] = ipoly; k++;}
6214 // we can now draw sorted contours
6215 contListNb = 0;
6216 fH->SetFillStyle(1001);
6217 for (k=0;k<ncontour;k++) {
6218 ipoly = polysort[k];
6219 if (np[ipoly] == 0) continue;
6220 if (Hoption.List) list = (TList*)contours->At(contListNb);
6221 contListNb++;
6222 Double_t *xx = polys[ipoly]->GetX();
6223 Double_t *yy = polys[ipoly]->GetY();
6224 istart = 0;
6225 while (true) {
6226 iminus = npmax;
6227 iplus = iminus+1;
6228 xp[iminus]= xx[istart]; yp[iminus] = yy[istart];
6229 xp[iplus] = xx[istart+1]; yp[iplus] = yy[istart+1];
6230 xx[istart] = xmin; yy[istart] = ymin;
6231 xx[istart+1] = xmin; yy[istart+1] = ymin;
6232 while (true) {
6233 nadd = 0;
6234 for (i=2;i<np[ipoly];i+=2) {
6235 if ((iplus < 2*npmax-1) && (xx[i] == xp[iplus]) && (yy[i] == yp[iplus])) {
6236 iplus++;
6237 xp[iplus] = xx[i+1]; yp[iplus] = yy[i+1];
6238 xx[i] = xmin; yy[i] = ymin;
6239 xx[i+1] = xmin; yy[i+1] = ymin;
6240 nadd++;
6241 }
6242 if ((iminus > 0) && (xx[i+1] == xp[iminus]) && (yy[i+1] == yp[iminus])) {
6243 iminus--;
6244 xp[iminus] = xx[i]; yp[iminus] = yy[i];
6245 xx[i] = xmin; yy[i] = ymin;
6246 xx[i+1] = xmin; yy[i+1] = ymin;
6247 nadd++;
6248 }
6249 }
6250 if (nadd == 0) break;
6251 }
6252 theColor = Int_t((ipoly+0.99)*Float_t(ncolors)/Float_t(ndivz));
6254 if (ndivz > 1) fH->SetFillColor(icol);
6255 fH->TAttFill::Modify();
6256 gPad->PaintFillArea(iplus-iminus+1,xp.data()+iminus,yp.data()+iminus);
6257 if (Hoption.List) {
6258 graph = new TGraph(iplus-iminus+1,xp.data()+iminus,yp.data()+iminus);
6259 graph->SetFillColor(icol);
6260 graph->SetLineWidth(fH->GetLineWidth());
6261 list->Add(graph);
6262 }
6263 //check if more points are left
6264 istart = 0;
6265 for (i=2;i<np[ipoly];i+=2) {
6266 if (xx[i] != xmin && yy[i] != ymin) {
6267 istart = i;
6268 break;
6269 }
6270 }
6271 if (istart == 0) break;
6272 }
6273 }
6274
6275theEND:
6276 gPad->ResetBit(TGraph::kClipFrame);
6281}
6282
6283////////////////////////////////////////////////////////////////////////////////
6284/// Fill the matrix `xarr` and `yarr` for Contour Plot.
6285
6289{
6290
6291 Bool_t vert;
6293 Int_t n, i, icount;
6294
6295 if (x1 == x2) {
6296 vert = kTRUE;
6297 tlen = y2 - y1;
6298 } else {
6299 vert = kFALSE;
6300 tlen = x2 - x1;
6301 }
6302
6303 n = icont1 +1;
6304 tdif = elev2 - elev1;
6305 i = 0;
6306 icount = 0;
6307 while (n <= icont2 && i <= kMAXCONTOUR/2 -3) {
6308 //elev = fH->GetContourLevel(n);
6309 elev = levels[n];
6310 diff = elev - elev1;
6311 pdif = diff/tdif;
6312 xlen = tlen*pdif;
6313 if (vert) {
6314 if (Hoption.Logx)
6315 xarr[i] = TMath::Log10(x1);
6316 else
6317 xarr[i] = x1;
6318 if (Hoption.Logy)
6319 yarr[i] = TMath::Log10(y1 + xlen);
6320 else
6321 yarr[i] = y1 + xlen;
6322 } else {
6323 if (Hoption.Logx)
6324 xarr[i] = TMath::Log10(x1 + xlen);
6325 else
6326 xarr[i] = x1 + xlen;
6327 if (Hoption.Logy)
6328 yarr[i] = TMath::Log10(y1);
6329 else
6330 yarr[i] = y1;
6331 }
6332 itarr[i] = n;
6333 icount++;
6334 i +=2;
6335 n++;
6336 }
6337 return icount;
6338}
6339
6340////////////////////////////////////////////////////////////////////////////////
6341/// [Draw 1D histograms error bars.](\ref HP09)
6342
6344{
6345
6346 // On iOS, we do not highlight histogram, if it's not picked at the moment
6347 // (but part of histogram (axis or pavestat) was picked, that's why this code
6348 // is called at all. This conditional statement never executes on non-iOS platform.
6349 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH) return;
6350
6351 const Int_t kBASEMARKER=8;
6352 Double_t xp, yp, ex1, ex2, ey1, ey2;
6353 Double_t delta;
6355 Double_t xi1, xi2, xi3, xi4, yi1, yi2, yi3, yi4;
6357 Double_t logxmin = 0;
6358 Double_t logymin = 0;
6359 Double_t offset = 0.;
6360 Double_t width = 0.;
6361 Int_t i, k, npoints, first, last, fixbin;
6362 Int_t if1 = 0;
6363 Int_t if2 = 0;
6366 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};
6367 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};
6368
6369 std::vector<Double_t> xline, yline;
6371 if (Hoption.Error >= 40) {Hoption.Error -=40; option0 = 1;}
6372 if (Int_t(Hoption.Error/10) == 2) {optionEX0 = 1; Hoption.Error -= 10;}
6373 if (Hoption.Error == 31) {optionEX0 = 1; Hoption.Error = 1;}
6374 if (Hoption.Error == 11) option1 = 1;
6375 if (Hoption.Error == 12) option2 = 1;
6376 if (Hoption.Error == 13) option3 = 1;
6377 if (Hoption.Error == 14) {option4 = 1; option3 = 1;}
6378 if (Hoption.Error == 15) {optionI0 = 1; option3 = 1;}
6379 if (Hoption.Error == 16) {optionI0 = 1; option4 = 1; option3 = 1;}
6380 if (option2+option3 == 0) optionE = 1;
6381 if (Hoption.Error == 0) optionE = 0;
6382 if (fXaxis->GetXbins()->fN) fixbin = 0;
6383 else fixbin = 1;
6384
6385 offset = fH->GetBarOffset();
6386 width = fH->GetBarWidth();
6387
6389 if (optionEX0) {
6390 xerror = 0;
6391 } else {
6392 xerror = gStyle->GetErrorX();
6393 }
6395 if (errormarker == 1) symbolsize = 0.01;
6397 if (errormarker >= 20 && errormarker <= 49) {
6398 sbasex *= cxx[errormarker-20];
6399 sbasey *= cyy[errormarker-20];
6400 }
6401 // set the graphics attributes
6402
6403 fH->TAttLine::Modify();
6404 fH->TAttFill::Modify();
6405 fH->TAttMarker::Modify();
6406
6407 // set the first and last bin
6408
6409 Double_t factor = Hparam.factor;
6410 first = Hparam.xfirst;
6411 last = Hparam.xlast;
6412 npoints = last - first +1;
6413 xmin = gPad->GetUxmin();
6414 xmax = gPad->GetUxmax();
6415 ymin = gPad->GetUymin();
6416 ymax = gPad->GetUymax();
6417
6418
6419 if (option3) {
6420 xline.resize(2*npoints);
6421 yline.resize(2*npoints);
6422 if ((npoints > 0) && (xline.empty() || yline.empty())) {
6423 Error("PaintErrors", "too many points, out of memory");
6424 return;
6425 }
6426 if1 = 1;
6427 if2 = 2*npoints;
6428 }
6429
6430 // compute the offset of the error bars due to the symbol size
6431 s2x = gPad->PixeltoX(Int_t(0.5*sbasex)) - gPad->PixeltoX(0);
6432 s2y =-gPad->PixeltoY(Int_t(0.5*sbasey)) + gPad->PixeltoY(0);
6433
6434 // compute size of the lines at the end of the error bars
6436 bxsize = gPad->PixeltoX(dxend) - gPad->PixeltoX(0);
6437 bysize =-gPad->PixeltoY(dxend) + gPad->PixeltoY(0);
6438
6439
6440 if (fixbin) {
6442 else xp = Hparam.xmin + 0.5*Hparam.xbinsize;
6443 } else {
6444 delta = fH->GetBinWidth(first);
6445 xp = fH->GetBinLowEdge(first) + 0.5*delta;
6446 }
6447
6448 // if errormarker = 0 or symbolsize = 0. no symbol is drawn
6451
6452 // ---------------------- Loop over the points---------------------
6453 for (k=first; k<=last; k++) {
6454
6455 // get the data
6456 // xp = X position of the current point
6457 // yp = Y position of the current point
6458 // ex1 = Low X error
6459 // ex2 = Up X error
6460 // ey1 = Low Y error
6461 // ey2 = Up Y error
6462 // (xi,yi) = Error bars coordinates
6463
6464 // apply offset on errors for bar histograms
6465 Double_t xminTmp = gPad->XtoPad(fXaxis->GetBinLowEdge(k));
6466 Double_t xmaxTmp = gPad->XtoPad(fXaxis->GetBinUpEdge(k));
6467 if (Hoption.Logx) {
6470 }
6473 xmaxTmp = xminTmp + w;
6474 xp = (xminTmp+xmaxTmp)/2.;
6475
6476 if (Hoption.Logx) {
6477 if (xp <= 0) goto L30;
6478 if (xp < logxmin) goto L30;
6479 if (xp > TMath::Power(10,xmax)) break;
6480 } else {
6481 if (xp < xmin) goto L30;
6482 if (xp > xmax) break;
6483 }
6484 yp = factor*fH->GetBinContent(k);
6485 if (optionI0 && yp==0) goto L30;
6486 if (fixbin) {
6488 } else {
6489 delta = fH->GetBinWidth(k);
6490 ex1 = xerror*delta;
6491 }
6492 if (fH->GetBinErrorOption() == TH1::kNormal) {
6493 ey1 = factor*fH->GetBinError(k);
6494 ey2 = ey1;
6495 } else {
6496 ey1 = factor*fH->GetBinErrorLow(k);
6497 ey2 = factor*fH->GetBinErrorUp(k);
6498 }
6499 ex2 = ex1;
6500
6501 xi4 = xp;
6502 xi3 = xp;
6503 xi2 = xp + ex2;
6504 xi1 = xp - ex1;
6505
6506 yi1 = yp;
6507 yi2 = yp;
6508 yi3 = yp - ey1;
6509 yi4 = yp + ey2;
6510
6511 // take the LOG if necessary
6512 if (Hoption.Logx) {
6517 }
6518 if (Hoption.Logy) {
6523 }
6524
6525 // test if error bars are not outside the limits
6526 // otherwise they are truncated
6527
6532
6533 // test if the marker is on the frame limits. If "Yes", the
6534 // marker will not be drawn and the error bars will be readjusted.
6535
6536 drawmarker = kTRUE;
6537 if (!option0 && !option3) {
6538 if (Hoption.Logy && yp < logymin) goto L30;
6539 if (yi1 < ymin || yi1 > ymax) goto L30;
6540 if (Hoption.Error != 0 && yp == 0 && ey1 <= 0) drawmarker = kFALSE;
6541 }
6543
6544 // draw the error rectangles
6545 if (option2) {
6546 if (yi3 >= ymax) goto L30;
6547 if (yi4 <= ymin) goto L30;
6548 gPad->PaintBox(xi1,yi3,xi2,yi4);
6549 }
6550
6551 // keep points for fill area drawing
6552 if (option3) {
6553 xline[if1-1] = xi3;
6554 xline[if2-1] = xi3;
6555 yline[if1-1] = yi4;
6556 yline[if2-1] = yi3;
6557 if1++;
6558 if2--;
6559 }
6560
6561 // draw the error bars
6562 if (Hoption.Logy && yp < logymin) drawmarker = kFALSE;
6563 if (optionE && drawmarker) {
6564 if ((yi3 < yi1 - s2y) && (yi3 < ymax)) gPad->PaintLine(xi3,yi3,xi4,TMath::Min(yi1 - s2y,ymax));
6565 if ((yi1 + s2y < yi4) && (yi4 > ymin)) gPad->PaintLine(xi3,TMath::Max(yi1 + s2y, ymin),xi4,yi4);
6566 // don't duplicate the horizontal line
6567 if (Hoption.Hist != 2) {
6569 if (xi1 < xi3 - s2x) gPad->PaintLine(xi1,yi1,xi3 - s2x,yi2);
6570 if (xi3 + s2x < xi2) gPad->PaintLine(xi3 + s2x,yi1,xi2,yi2);
6571 }
6572 }
6573 }
6574 if (optionE && !drawmarker && (ey1 != 0 || ey2 !=0)) {
6575 if ((yi3 < yi1) && (yi3 < ymax)) gPad->PaintLine(xi3,yi3,xi4,TMath::Min(yi1,ymax));
6576 if ((yi1 < yi4) && (yi4 > ymin)) gPad->PaintLine(xi3,TMath::Max(yi1,ymin),xi4,yi4);
6577 // don't duplicate the horizontal line
6578 if (Hoption.Hist != 2) {
6580 if (xi1 < xi3) gPad->PaintLine(xi1,yi1,xi3,yi2);
6581 if (xi3 < xi2) gPad->PaintLine(xi3,yi1,xi2,yi2);
6582 }
6583 }
6584 }
6585
6586 // draw line at the end of the error bars
6587
6588 if (option1 && drawmarker) {
6589
6590 if (yi3 < yi1-s2y && yi3 < ymax && yi3 > ymin) gPad->PaintLine(xi3 - bxsize, yi3 , xi3 + bxsize, yi3);
6591 if (yi4 > yi1+s2y && yi4 < ymax && yi4 > ymin) gPad->PaintLine(xi3 - bxsize, yi4 , xi3 + bxsize, yi4);
6593 if (xi1 < xi3-s2x) gPad->PaintLine(xi1 , yi1 - bysize, xi1 , yi1 + bysize);
6594 if (xi2 > xi3+s2x) gPad->PaintLine(xi2 , yi1 - bysize, xi2 , yi1 + bysize);
6595 }
6596 }
6597
6598 // draw the marker
6599
6600 if (drawmarker) gPad->PaintPolyMarker(1, &xi3, &yi1);
6601
6602L30:
6603 if (fixbin) xp += Hparam.xbinsize;
6604 else {
6605 if (k < last) {
6606 delta = fH->GetBinWidth(k+1);
6607 xp = fH->GetBinLowEdge(k+1) + 0.5*delta;
6608 }
6609 }
6610 } //end of for loop
6611
6612 // draw the filled area
6613
6614 if (option3) {
6615 TGraph graph;
6616 graph.SetLineStyle(fH->GetLineStyle());
6617 graph.SetLineColor(fH->GetLineColor());
6618 graph.SetLineWidth(fH->GetLineWidth());
6619 graph.SetFillStyle(fH->GetFillStyle());
6620 graph.SetFillColor(fH->GetFillColor());
6621 Int_t logx = gPad->GetLogx();
6622 Int_t logy = gPad->GetLogy();
6623 gPad->SetLogx(0);
6624 gPad->SetLogy(0);
6625
6626 // In some cases the number of points in the fill area is smaller than
6627 // 2*npoints. In such cases the array xline and yline must be arranged
6628 // before being plotted. The next loop does that.
6629 if (if2 > npoints) {
6630 for (i=1; i<if1; i++) {
6631 xline[if1-2+i] = xline[if2-1+i];
6632 yline[if1-2+i] = yline[if2-1+i];
6633 }
6634 npoints = if1-1;
6635 }
6636 if (option4) graph.PaintGraph(2*npoints,xline.data(),yline.data(),"FC");
6637 else graph.PaintGraph(2*npoints,xline.data(),yline.data(),"F");
6638 gPad->SetLogx(logx);
6639 gPad->SetLogy(logy);
6640 }
6641}
6642
6643////////////////////////////////////////////////////////////////////////////////
6644/// Draw 2D histograms errors.
6645
6647{
6648
6649 fH->TAttMarker::Modify();
6650 fH->TAttLine::Modify();
6651
6652 // Define the 3D view
6653 fXbuf[0] = Hparam.xmin;
6654 fYbuf[0] = Hparam.xmax;
6655 fXbuf[1] = Hparam.ymin;
6656 fYbuf[1] = Hparam.ymax;
6657 fXbuf[2] = Hparam.zmin;
6658 fYbuf[2] = Hparam.zmax*(1. + gStyle->GetHistTopMargin());
6659 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
6660 TView *view = gPad ? gPad->GetView() : nullptr;
6661 if (!view) {
6662 Error("Paint2DErrors", "no TView in current pad");
6663 return;
6664 }
6665 Double_t thedeg = 90 - gPad->GetTheta();
6666 Double_t phideg = -90 - gPad->GetPhi();
6667 Double_t psideg = view->GetPsi();
6668 Int_t irep;
6669 view->SetView(phideg, thedeg, psideg, irep);
6670
6671 // Set color/style for back box
6672 fLego->SetFillStyle(gPad->GetFrameFillStyle());
6673 fLego->SetFillColor(gPad->GetFrameFillColor());
6674 fLego->TAttFill::Modify();
6675 Int_t backcolor = gPad->GetFrameFillColor();
6676 if (Hoption.System != kCARTESIAN) backcolor = 0;
6677 view->PadRange(backcolor);
6678 fLego->SetFillStyle(fH->GetFillStyle());
6679 fLego->SetFillColor(fH->GetFillColor());
6680 fLego->TAttFill::Modify();
6681
6682 // Paint the Back Box if needed
6683 if (Hoption.BackBox && !Hoption.Same && !Hoption.Lego && !Hoption.Surf) {
6684 fLego->InitMoveScreen(-1.1,1.1);
6685 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
6687 fLego->BackBox(90);
6688 }
6689
6690 // Paint the Errors
6691 Double_t x, ex, x1, x2;
6692 Double_t y, ey, y1, y2;
6693 Double_t z, ez1, ez2, z1, z2;
6694 Double_t temp1[3],temp2[3];
6696 if (Hoption.Error == 110) {
6697 xyerror = 0;
6698 } else {
6700 }
6701
6703 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
6704 y = fYaxis->GetBinCenter(j);
6706 y1 = y-ey;
6707 y2 = y+ey;
6708 if (Hoption.Logy) {
6709 if (y > 0) y = TMath::Log10(y);
6710 else continue;
6711 if (y1 > 0) y1 = TMath::Log10(y1);
6712 else y1 = Hparam.ymin;
6713 if (y2 > 0) y2 = TMath::Log10(y2);
6714 else y2 = Hparam.ymin;
6715 }
6718 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
6719 xk = fXaxis->GetBinLowEdge(i);
6720 xstep = fXaxis->GetBinWidth(i);
6721 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
6722 Int_t bin = fH->GetBin(i,j);
6723 x = fXaxis->GetBinCenter(i);
6725 x1 = x-ex;
6726 x2 = x+ex;
6727 if (Hoption.Logx) {
6728 if (x > 0) x = TMath::Log10(x);
6729 else continue;
6730 if (x1 > 0) x1 = TMath::Log10(x1);
6731 else x1 = Hparam.xmin;
6732 if (x2 > 0) x2 = TMath::Log10(x2);
6733 else x2 = Hparam.xmin;
6734 }
6735 z = fH->GetBinContent(bin);
6736 if (fH->GetBinErrorOption() == TH1::kNormal) {
6737 ez1 = fH->GetBinError(bin);
6738 ez2 = ez1;
6739 }
6740 else {
6741 ez1 = fH->GetBinErrorLow(bin);
6742 ez2 = fH->GetBinErrorUp(bin);
6743 }
6744 z1 = z - ez1;
6745 z2 = z + ez2;
6746 if (Hoption.Logz) {
6747 if (z > 0) z = TMath::Log10(z);
6748 else z = Hparam.zmin;
6749 if (z1 > 0) z1 = TMath::Log10(z1);
6750 else z1 = Hparam.zmin;
6751 if (z2 > 0) z2 = TMath::Log10(z2);
6752 else z2 = Hparam.zmin;
6753
6754 }
6755 if (z <= Hparam.zmin) continue;
6756 if (z > Hparam.zmax) z = Hparam.zmax;
6757
6758 temp1[0] = x1;
6759 temp1[1] = y;
6760 temp1[2] = z;
6761 temp2[0] = x2;
6762 temp2[1] = y;
6763 temp2[2] = z;
6764 gPad->PaintLine3D(temp1, temp2);
6765 temp1[0] = x;
6766 temp1[1] = y1;
6767 temp1[2] = z;
6768 temp2[0] = x;
6769 temp2[1] = y2;
6770 temp2[2] = z;
6771 gPad->PaintLine3D(temp1, temp2);
6772 temp1[0] = x;
6773 temp1[1] = y;
6774 temp1[2] = z1;
6775 temp2[0] = x;
6776 temp2[1] = y;
6777 temp2[2] = z2;
6778 gPad->PaintLine3D(temp1, temp2);
6779 temp1[0] = x;
6780 temp1[1] = y;
6781 temp1[2] = z;
6782 view->WCtoNDC(temp1, &temp2[0]);
6783 gPad->PaintPolyMarker(1, &temp2[0], &temp2[1]);
6784 }
6785 }
6786
6787 // Paint the Front Box if needed
6788 if (Hoption.FrontBox) {
6789 fLego->InitMoveScreen(-1.1,1.1);
6791 fLego->FrontBox(90);
6792 }
6793
6794 // Paint the Axis if needed
6795 if (!Hoption.Axis && !Hoption.Same && !Hoption.Lego && !Hoption.Surf) {
6796 TGaxis axis;
6797 PaintLegoAxis(&axis, 90);
6798 }
6799
6800 fLego.reset();
6801}
6802
6803////////////////////////////////////////////////////////////////////////////////
6804/// Calculate range and clear pad (canvas).
6805
6807{
6808
6809 if (Hoption.Same) return;
6810
6812
6813 if (Hoption.Lego || Hoption.Surf || Hoption.Tri ||
6814 Hoption.Contour == 14 || Hoption.Error >= 100) {
6815 TObject *frame = gPad->FindObject("TFrame");
6816 if (frame) gPad->Remove(frame);
6817 return;
6818 }
6819
6820 //The next statement is always executed on non-iOS platform,
6821 //on iOS depends on pad mode.
6822 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode())
6823 gPad->PaintPadFrame(Hparam.xmin,Hparam.ymin,Hparam.xmax,Hparam.ymax);
6824}
6825
6826////////////////////////////////////////////////////////////////////////////////
6827/// [Paint functions associated to an histogram.](\ref HP28")
6828
6830{
6831 auto lnk = fFunctions->FirstLink();
6832
6833 while (lnk) {
6834 auto obj = lnk->GetObject();
6836 if (obj->InheritsFrom(TF2::Class())) {
6837 if (!obj->TestBit(TF2::kNotDraw)) {
6838 if (Hoption.Lego || Hoption.Surf || Hoption.Error >= 100) {
6839 TF2 *f2 = (TF2*)obj;
6840 f2->SetMinimum(fH->GetMinimum());
6841 f2->SetMaximum(fH->GetMaximum());
6842 f2->SetRange(fH->GetXaxis()->GetXmin(), fH->GetYaxis()->GetXmin(), fH->GetXaxis()->GetXmax(), fH->GetYaxis()->GetXmax() );
6843 f2->Paint("surf same");
6844 } else {
6845 obj->Paint("cont3 same");
6846 }
6847 }
6848 } else if (obj->InheritsFrom(TF1::Class())) {
6849 if (!obj->TestBit(TF1::kNotDraw)) obj->Paint("lsame");
6850 } else {
6851 //Let's make this 'function' selectable on iOS device (for example, it can be TPaveStat).
6852 gPad->PushSelectableObject(obj);
6853
6854 //The next statement is ALWAYS executed on non-iOS platform, on iOS it depends on pad's mode
6855 //and picked object.
6856 if (!gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && obj == gPad->GetSelected()))
6857 obj->Paint(lnk->GetOption());
6858 }
6859 lnk = lnk->Next();
6860 }
6861}
6862
6863////////////////////////////////////////////////////////////////////////////////
6864/// [Control routine to draw 1D histograms](\ref HP01b)
6865
6867{
6868
6869 //On iOS: do not highlight hist, if part of it was selected.
6870 //Never executes on non-iOS platform.
6871 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
6872 return;
6873
6874 static char chopth[17];
6875
6877 Int_t i, j, first, last, nbins, fixbin;
6878 Double_t c1, yb;
6879 yb = 0;
6880
6881 strlcpy(chopth, " ",17);
6882
6885 Double_t baroffset = fH->GetBarOffset();
6886 Double_t barwidth = fH->GetBarWidth();
6889 gStyle->SetBarOffset(baroffset);
6890 gStyle->SetBarWidth(barwidth);
6891
6892 // Create "LIFE" structure to keep current histogram status
6893
6894 first = Hparam.xfirst;
6895 last = Hparam.xlast;
6896 nbins = last - first + 1;
6897
6898 std::vector<Double_t> keepx, keepy;
6899 if (fXaxis->GetXbins()->fN) fixbin = 0;
6900 else fixbin = 1;
6901 if (fixbin) keepx.resize(2);
6902 else keepx.resize(nbins+1);
6903 keepy.resize(nbins);
6904 Double_t logymin = 0;
6906
6907 // Loop on histogram bins
6908
6909 for (j=first; j<=last;j++) {
6911 if (TMath::Abs(ymax-ymin) > 0) {
6913 else yb = c1;
6914 }
6915 if (!Hoption.Line) {
6916 yb = TMath::Max(yb, ymin);
6917 yb = TMath::Min(yb, ymax);
6918 }
6919 keepy[j-first] = yb;
6920 }
6921
6922 // Draw histogram according to value of FillStyle and FillColor
6923
6924 if (fixbin) { keepx[0] = Hparam.xmin; keepx[1] = Hparam.xmax; }
6925 else {
6926 for (i=0; i<nbins; i++) keepx[i] = fXaxis->GetBinLowEdge(i+first);
6927 keepx[nbins] = fXaxis->GetBinUpEdge(nbins-1+first);
6928 }
6929
6930 // Prepare Fill area (systematic with option "Bar").
6931
6933 htype = oldhtype;
6934 if (Hoption.Bar) {
6935 if (htype == 0 || htype == 1000) htype = 1001;
6936 }
6937
6939
6940 // Code option for GrapHist
6941
6942 if (Hoption.Line) chopth[0] = 'L';
6943 if (Hoption.Star) chopth[1] = '*';
6944 if (Hoption.Mark) chopth[2] = 'P';
6945 if (Hoption.Mark == 10) chopth[3] = '0';
6947 if (Hoption.Curve) chopth[3] = 'C';
6948 if (Hoption.Hist > 0) chopth[4] = 'H';
6949 else if (Hoption.Bar) chopth[5] = 'B';
6950 if (Hoption.Logy) chopth[6] = '1';
6951 if (fH->GetFillColor() && htype) {
6952 if (Hoption.Hist > 0 || Hoption.Curve || Hoption.Line) {
6953 chopth[7] = 'F';
6954 }
6955 }
6956 }
6957 if (!fixbin && strlen(chopth)) {
6958 chopth[8] = 'N';
6959 }
6960
6961 if (Hoption.Fill == 2) chopth[13] = '2';
6962
6963 // Option LOGX
6964
6965 if (Hoption.Logx) {
6966 chopth[9] = 'G';
6967 chopth[10] = 'X';
6968 if (fixbin) {
6969 keepx[0] = TMath::Power(10,keepx[0]);
6970 keepx[1] = TMath::Power(10,keepx[1]);
6971 }
6972 }
6973
6974 if (Hoption.Off) {
6975 chopth[11] = ']';
6976 chopth[12] = '[';
6977 }
6978
6979 // Draw the histogram
6980
6981 TGraph graph;
6982 graph.SetLineWidth(lw);
6983 graph.SetLineStyle(fH->GetLineStyle());
6984 graph.SetLineColor(fH->GetLineColor());
6985 graph.SetFillStyle(htype);
6986 graph.SetFillColor(fH->GetFillColor());
6988 graph.SetMarkerSize(fH->GetMarkerSize());
6991
6992 graph.PaintGrapHist(nbins, keepx.data(), keepy.data() ,chopth);
6993
6996
6998}
6999
7000////////////////////////////////////////////////////////////////////////////////
7001/// [Control function to draw a 3D histograms.](\ref HP01d)
7002
7004{
7005
7006 TString cmd;
7007 TString opt = option;
7008 opt.ToLower();
7009 Int_t irep;
7010 Float_t NEntries = fH->GetEntries();
7011
7012 if (fCurrentF3 || strstr(opt,"tf3")) {
7013 PaintTF3();
7014 return;
7015 }
7016
7017 if (NEntries > 0) {
7018 if (Hoption.Box || Hoption.Lego || Hoption.Color) {
7019 if (Hoption.Box == 11 || Hoption.Lego == 11) {
7020 PaintH3Box(1);
7021 } else if (Hoption.Box == 12 || Hoption.Lego == 12 || Hoption.Color == 1) {
7022 PaintH3Box(2);
7023 } else if (Hoption.Box == 13 || Hoption.Lego == 13) {
7024 PaintH3Box(3);
7025 } else {
7027 }
7028 return;
7029 }
7030
7031 if (strstr(opt,"iso")) {
7032 PaintH3Iso();
7033 return;
7034 }
7035 }
7036
7037 TView *view = gPad ? gPad->GetView() : nullptr;
7038 if (!view) return;
7039
7040 if (strstr(opt,"fb")) Hoption.FrontBox = 0;
7041 if (strstr(opt,"bb")) Hoption.BackBox = 0;
7042
7043 Double_t thedeg = 90 - gPad->GetTheta();
7044 Double_t phideg = -90 - gPad->GetPhi();
7045 Double_t psideg = view->GetPsi();
7046 view->SetView(phideg, thedeg, psideg, irep);
7047
7048 if(NEntries > 0) { // Paint as 3D scatter plot
7049 cmd.Form("TPolyMarker3D::PaintH3((TH1 *)0x%zx,\"%s\");",(size_t)fH,option);
7050 gROOT->ProcessLine(cmd.Data());
7051 } else {
7052 TAxis* xAxis = fH->GetXaxis();
7053 TAxis* yAxis = fH->GetYaxis();
7054 TAxis* zAxis = fH->GetZaxis();
7055 Double_t xmin = xAxis->GetXmin();
7056 Double_t xmax = xAxis->GetXmax();
7057 Double_t ymin = yAxis->GetXmin();
7058 Double_t ymax = yAxis->GetXmax();
7059 Double_t zmin = zAxis->GetXmin();
7060 Double_t zmax = zAxis->GetXmax();
7061 view->SetRange(xmin, ymin, zmin, xmax, ymax, zmax); // Set the axis limits (Xmin, Ymin, Zmin, Xmax, Ymax, Zmax)
7062 }
7063
7064 if (Hoption.Same) return;
7065
7066 // Draw axis
7067 view->SetOutlineToCube();
7068 TSeqCollection *ol = view->GetOutline();
7069 if (ol && Hoption.BackBox && Hoption.FrontBox) ol->Paint(option);
7071
7072 if (!Hoption.Axis && !Hoption.Same) {
7073 TGaxis axis;
7074 PaintLegoAxis(&axis, 90);
7075 }
7076
7077 // Draw palette. In case of 4D plot with TTree::Draw() the palette should
7078 // be painted with the option colz.
7079 if (fH->GetDrawOption() && strstr(opt,"colz")) {
7080 Int_t ndiv = fH->GetContour();
7081 if (ndiv == 0 ) {
7082 ndiv = gStyle->GetNumberContours();
7083 fH->SetContour(ndiv);
7084 }
7085 PaintPalette();
7086 }
7087
7088 // Draw title
7089 PaintTitle();
7090
7091 //Draw stats and fit results
7092 TF1 *fit = nullptr;
7093 TIter next(fFunctions);
7094 while (auto obj = next()) {
7095 if (obj->InheritsFrom(TF1::Class())) {
7096 fit = (TF1*)obj;
7097 break;
7098 }
7099 }
7100 if ((Hoption.Same%10) != 1) {
7101 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7103 }
7104 }
7105
7106}
7107
7108////////////////////////////////////////////////////////////////////////////////
7109/// Compute histogram parameters used by the drawing routines.
7110
7112{
7113
7114 if (fH->GetDimension() > 1 || Hoption.Lego || Hoption.Surf) return 1;
7115
7116 Int_t i;
7117 static const char *where = "PaintInit";
7119 Int_t maximum = 0;
7120 Int_t minimum = 0;
7121 if (fH->GetMaximumStored() != -1111) maximum = 1;
7122 if (fH->GetMinimumStored() != -1111) minimum = 1;
7123
7124 // Compute X axis parameters
7125
7126 Int_t last = fXaxis->GetLast();
7127 Int_t first = fXaxis->GetFirst();
7130 Hparam.xlast = last;
7131 Hparam.xfirst = first;
7134
7135 // if log scale in X, replace xmin,max by the log
7136 if (Hoption.Logx) {
7137 if (Hparam.xmax<=0) {
7138 Error(where, "cannot set X axis to log scale");
7139 return 0;
7140 }
7141 if (Hparam.xlowedge <=0 ) {
7142 if (Hoption.Same) {
7143 TH1* h1 = nullptr;
7144 TObject *obj;
7145 TIter next(gPad->GetListOfPrimitives());
7146 while ((obj = (TObject *)next())) {
7147 if (obj->InheritsFrom(TH1::Class())) { h1 = (TH1*)(obj) ; break; }
7148 if (obj->InheritsFrom(THStack::Class())) { h1 = ((THStack*)(obj))->GetHistogram() ; break; }
7149 if (obj->InheritsFrom(TGraph::Class())) { h1 = ((TGraph*)(obj))->GetHistogram() ; break; }
7150 if (obj->InheritsFrom(TMultiGraph::Class())) { h1 = ((TMultiGraph*)(obj))->GetHistogram(); break; }
7151 if (obj->InheritsFrom(TGraph2D::Class())) { h1 = ((TGraph2D*)(obj))->GetHistogram(); break; }
7152 if (obj->InheritsFrom(TF1::Class())) { h1 = ((TF1*)(obj))->GetHistogram(); break; }
7153 }
7154 if (h1) {
7156 } else {
7157 Error(where, "undefined user's coordinates. Cannot use option SAME");
7158 return 0;
7159 }
7160 } else {
7161 for (i=first; i<=last; i++) {
7162 Double_t binLow = fXaxis->GetBinLowEdge(i);
7163 if (binLow>0) {
7164 Hparam.xlowedge = binLow;
7165 break;
7166 }
7167 if (binLow == 0 && fH->GetBinContent(i) !=0) {
7168 Hparam.xlowedge = fXaxis->GetBinUpEdge(i)*0.001;
7169 break;
7170 }
7171 }
7172 if (Hparam.xlowedge<=0) {
7173 Error(where, "cannot set X axis to log scale");
7174 return 0;
7175 }
7176 }
7178 }
7183 if (Hparam.xlast > last) Hparam.xlast = last;
7184 if (Hparam.xfirst < first) Hparam.xfirst = first;
7185 }
7186
7187 // Compute Y axis parameters
7188 Double_t bigp = TMath::Power(10,32);
7189 Double_t ymax = -bigp;
7190 Double_t ymin = bigp;
7191 Double_t c1, e1;
7192 Double_t xv[1];
7193 Double_t fval;
7194 TObject *f;
7195 TF1 *f1;
7196 Double_t allchan = 0;
7197 Int_t nonNullErrors = 0;
7198 TIter next(fFunctions);
7199 for (i=first; i<=last;i++) {
7200 c1 = fH->GetBinContent(i);
7202 if (Hoption.Logy) {
7203 if (c1 > 0) ymin = TMath::Min(ymin,c1);
7204 } else {
7206 }
7207 if (Hoption.Error) {
7209 e1 = fH->GetBinError(i);
7210 else
7211 e1 = fH->GetBinErrorUp(i);
7212 if (e1 > 0) nonNullErrors++;
7215 e1 = fH->GetBinErrorLow(i);
7216
7217 if (Hoption.Logy) {
7218 if (c1-e1>0.01*TMath::Abs(c1)) ymin = TMath::Min(ymin,c1-e1);
7219 } else {
7221 }
7222 }
7223 if (Hoption.Func) {
7224 xv[0] = fXaxis->GetBinCenter(i);
7225 while ((f = (TObject*) next())) {
7226 if (f->IsA() == TF1::Class()) {
7227 f1 = (TF1*)f;
7228 if (xv[0] < f1->GetXmin() || xv[0] > f1->GetXmax()) continue;
7229 fval = f1->Eval(xv[0],0,0);
7230 if (f1->GetMaximumStored() != -1111) fval = TMath::Min(f1->GetMaximumStored(), fval);
7232 if (Hoption.Logy) {
7233 if (c1 > 0 && fval > 0.3*c1) ymin = TMath::Min(ymin,fval);
7234 }
7235 }
7236 }
7237 next.Reset();
7238 }
7239 allchan += c1;
7240 }
7241 if (!nonNullErrors) {
7242 if (Hoption.Error) {
7243 if (!Hoption.Mark && !Hoption.Line && !Hoption.Star && !Hoption.Curve) Hoption.Hist = 2;
7244 Hoption.Error=0;
7245 }
7246 }
7247
7248
7249 // Take into account maximum , minimum
7250
7251 if (Hoption.Logy && ymin <= 0) {
7252 if (ymax >= 1) ymin = TMath::Max(.005,ymax*1e-10);
7253 else ymin = 0.001*ymax;
7254 }
7255
7256 Double_t xm = ymin;
7257 if (maximum) ymax = fH->GetMaximumStored();
7258 if (minimum) xm = fH->GetMinimumStored();
7259 if (Hoption.Logy && xm < 0) {
7260 Error(where, "log scale requested with a negative argument (%f)", xm);
7261 return 0;
7262 } else if (Hoption.Logy && xm>=0 && ymax==0) { // empty histogram in log scale
7263 ymin = 0.01;
7264 ymax = 10.;
7265 } else {
7266 ymin = xm;
7267 }
7268
7269 if (ymin >= ymax) {
7270 if (Hoption.Logy) {
7271 if (ymax > 0) ymin = 0.001*ymax;
7272 else {
7273 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", ymax);
7274 return 0;
7275 }
7276 }
7277 else {
7278 if (ymin > 0) {
7279 ymin = 0;
7280 ymax *= 2;
7281 } else if (ymin < 0) {
7282 ymax = 0;
7283 ymin *= 2;
7284 } else {
7285 ymin = 0;
7286 ymax = 1;
7287 }
7288 }
7289 }
7290
7291 // In some cases, mainly because of precision issues, ymin and ymax could almost equal.
7292 if (TMath::AreEqualRel(ymin,ymax,1E-15)) {
7293 ymin = ymin*(1-1E-14);
7294 ymax = ymax*(1+1E-14);
7295 }
7296
7297 // take into account normalization factor
7298 Hparam.allchan = allchan;
7299 Double_t factor = allchan;
7300 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
7301 if (allchan) factor /= allchan;
7302 if (factor == 0) factor = 1;
7303 Hparam.factor = factor;
7304 ymax = factor*ymax;
7305 ymin = factor*ymin;
7306 //just in case the norm factor is negative
7307 // this may happen with a positive norm factor and a negative integral !
7308 if (ymax < ymin) {
7309 Double_t temp = ymax;
7310 ymax = ymin;
7311 ymin = temp;
7312 }
7313
7314 // For log scales, histogram coordinates are LOG10(ymin) and
7315 // LOG10(ymax). Final adjustment (if not option "Same"
7316 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
7317 // Maximum and Minimum are not defined.
7318 if (Hoption.Logy) {
7319 if (ymin <=0 || ymax <=0) {
7320 Error(where, "Cannot set Y axis to log scale");
7321 return 0;
7322 }
7324 if (!minimum) ymin += TMath::Log10(0.5);
7326 if (!maximum) ymax += TMath::Log10(2*(0.9/0.95));
7327 if (!Hoption.Same) {
7328 Hparam.ymin = ymin;
7329 Hparam.ymax = ymax;
7330 }
7331 return 1;
7332 }
7333
7334 // final adjustment of ymin for linear scale.
7335 // if minimum is not set , then ymin is set to zero if >0
7336 // or to ymin - margin if <0.
7337 if (!minimum) {
7338 if (Hoption.MinimumZero) {
7339 if (ymin >= 0) ymin = 0;
7340 else ymin -= yMARGIN*(ymax-ymin);
7341 } else {
7343 if (ymin >= 0 && (ymin-dymin <= 0)) ymin = 0;
7344 else ymin -= dymin;
7345 }
7346 }
7347
7348 // final adjustment of YMAXI for linear scale (if not option "Same"):
7349 // decrease histogram height to MAX% of allowed height if HMAXIM
7350 // has not been called.
7351 if (!maximum) {
7352 ymax += yMARGIN*(ymax-ymin);
7353 }
7354
7355 Hparam.ymin = ymin;
7356 Hparam.ymax = ymax;
7357 return 1;
7358}
7359
7360////////////////////////////////////////////////////////////////////////////////
7361/// Compute histogram parameters used by the drawing routines for a rotated pad.
7362
7364{
7365
7366 static const char *where = "PaintInitH";
7368 Int_t maximum = 0;
7369 Int_t minimum = 0;
7370 if (fH->GetMaximumStored() != -1111) maximum = 1;
7371 if (fH->GetMinimumStored() != -1111) minimum = 1;
7372
7373 // Compute X axis parameters
7374
7375 Int_t last = fXaxis->GetLast();
7376 Int_t first = fXaxis->GetFirst();
7379 Hparam.xlast = last;
7380 Hparam.xfirst = first;
7383
7384 // if log scale in Y, replace ymin,max by the log
7385 if (Hoption.Logy) {
7386 if (Hparam.xlowedge <=0 ) {
7389 }
7390 if (Hparam.ymin <=0 || Hparam.ymax <=0) {
7391 Error(where, "cannot set Y axis to log scale");
7392 return 0;
7393 }
7398 if (Hparam.xlast > last) Hparam.xlast = last;
7399 }
7400
7401 // Compute Y axis parameters
7402 Double_t bigp = TMath::Power(10,32);
7403 Double_t xmax = -bigp;
7404 Double_t xmin = bigp;
7405 Double_t c1, e1;
7406 Double_t xv[1];
7407 Double_t fval;
7408 Int_t i;
7409 TObject *f;
7410 TF1 *f1;
7411 Double_t allchan = 0;
7412 TIter next(fFunctions);
7413 for (i=first; i<=last;i++) {
7414 c1 = fH->GetBinContent(i);
7417 if (Hoption.Error) {
7418 e1 = fH->GetBinError(i);
7421 }
7422 if (Hoption.Func) {
7423 xv[0] = fXaxis->GetBinCenter(i);
7424 while ((f = (TObject*) next())) {
7425 if (f->IsA() == TF1::Class()) {
7426 f1 = (TF1*)f;
7427 if (xv[0] < f1->GetXmin() || xv[0] > f1->GetXmax()) continue;
7428 fval = f1->Eval(xv[0],0,0);
7430 if (Hoption.Logy) {
7431 if (fval > 0.3*c1) xmin = TMath::Min(xmin,fval);
7432 }
7433 }
7434 }
7435 next.Reset();
7436 }
7437 allchan += c1;
7438 }
7439
7440 // Take into account maximum , minimum
7441
7442 if (Hoption.Logx && xmin <= 0) {
7443 if (xmax >= 1) xmin = TMath::Max(.5,xmax*1e-10);
7444 else xmin = 0.001*xmax;
7445 }
7446 Double_t xm = xmin;
7447 if (maximum) xmax = fH->GetMaximumStored();
7448 if (minimum) xm = fH->GetMinimumStored();
7449 if (Hoption.Logx && xm <= 0) {
7450 Error(where, "log scale requested with zero or negative argument (%f)", xm);
7451 return 0;
7452 }
7453 else xmin = xm;
7454 if (xmin >= xmax) {
7455 if (Hoption.Logx) {
7456 if (xmax > 0) xmin = 0.001*xmax;
7457 else {
7458 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", xmax);
7459 return 0;
7460 }
7461 }
7462 else {
7463 if (xmin > 0) {
7464 xmin = 0;
7465 xmax *= 2;
7466 } else if (xmin < 0) {
7467 xmax = 0;
7468 xmin *= 2;
7469 } else {
7470 xmin = 0;
7471 xmax = 1;
7472 }
7473 }
7474 }
7475
7476 // take into account normalization factor
7477 Hparam.allchan = allchan;
7478 Double_t factor = allchan;
7479 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
7480 if (allchan) factor /= allchan;
7481 if (factor == 0) factor = 1;
7482 Hparam.factor = factor;
7483 xmax = factor*xmax;
7484 xmin = factor*xmin;
7485
7486 // For log scales, histogram coordinates are LOG10(ymin) and
7487 // LOG10(ymax). Final adjustment (if not option "Same"
7488 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
7489 // Maximum and Minimum are not defined.
7490 if (Hoption.Logx) {
7491 if (xmin <=0 || xmax <=0) {
7492 Error(where, "Cannot set Y axis to log scale");
7493 return 0;
7494 }
7496 if (!minimum) xmin += TMath::Log10(0.5);
7498 if (!maximum) xmax += TMath::Log10(2*(0.9/0.95));
7499 if (!Hoption.Same) {
7500 Hparam.xmin = xmin;
7501 Hparam.xmax = xmax;
7502 }
7503 return 1;
7504 }
7505
7506 // final adjustment of ymin for linear scale.
7507 // if minimum is not set , then ymin is set to zero if >0
7508 // or to ymin - margin if <0.
7509 if (!minimum) {
7510 if (xmin >= 0) xmin = 0;
7511 else xmin -= yMARGIN*(xmax-xmin);
7512 }
7513
7514 // final adjustment of YMAXI for linear scale (if not option "Same"):
7515 // decrease histogram height to MAX% of allowed height if HMAXIM
7516 // has not been called.
7517 if (!maximum) {
7518 xmax += yMARGIN*(xmax-xmin);
7519 }
7520 Hparam.xmin = xmin;
7521 Hparam.xmax = xmax;
7522 return 1;
7523}
7524
7525////////////////////////////////////////////////////////////////////////////////
7526/// [Control function to draw a 3D histogram with boxes.](\ref HP25)
7527
7529{
7530 // Predefined box structure
7531 Double_t wxyz[8][3] = { {-1,-1,-1}, {1,-1,-1}, {1,1,-1}, {-1,1,-1},
7532 {-1,-1, 1}, {1,-1, 1}, {1,1, 1}, {-1,1, 1} };
7533 Int_t iface[6][4] = { {0,3,2,1}, {4,5,6,7},
7534 {0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7} };
7535
7536 // Define dimensions of world space
7537 TAxis *xaxis = fH->GetXaxis();
7538 TAxis *yaxis = fH->GetYaxis();
7539 TAxis *zaxis = fH->GetZaxis();
7540
7541 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7542 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7543 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7544 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7545 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7546 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7547
7548 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7549
7550 // Set view
7551 TView *view = gPad ? gPad->GetView() : nullptr;
7552 if (!view) {
7553 Error("PaintH3", "no TView in current pad");
7554 return;
7555 }
7556 Double_t thedeg = 90 - gPad->GetTheta();
7557 Double_t phideg = -90 - gPad->GetPhi();
7558 Double_t psideg = view->GetPsi();
7559 Int_t irep;
7560 view->SetView(phideg, thedeg, psideg, irep);
7561
7562 Int_t backcolor = gPad->GetFrameFillColor();
7563 view->PadRange(backcolor);
7564
7565 // Draw back surfaces of frame box
7566 fLego->InitMoveScreen(-1.1,1.1);
7567 if (Hoption.BackBox) {
7568 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
7570 fLego->BackBox(90);
7571 }
7572
7574
7575 // Define order of drawing
7576 Double_t *tnorm = view->GetTnorm();
7577 if (!tnorm) return;
7578 Int_t incrx = (tnorm[ 8] < 0.) ? -1 : +1;
7579 Int_t incry = (tnorm[ 9] < 0.) ? -1 : +1;
7580 Int_t incrz = (tnorm[10] < 0.) ? -1 : +1;
7581 Int_t ix1 = (incrx == +1) ? xaxis->GetFirst() : xaxis->GetLast();
7582 Int_t iy1 = (incry == +1) ? yaxis->GetFirst() : yaxis->GetLast();
7583 Int_t iz1 = (incrz == +1) ? zaxis->GetFirst() : zaxis->GetLast();
7584 Int_t ix2 = (incrx == +1) ? xaxis->GetLast() : xaxis->GetFirst();
7585 Int_t iy2 = (incry == +1) ? yaxis->GetLast() : yaxis->GetFirst();
7586 Int_t iz2 = (incrz == +1) ? zaxis->GetLast() : zaxis->GetFirst();
7587
7588 // Set graphic attributes (colour, style, etc.)
7593
7594 fH->SetFillStyle(1001);
7595 fH->TAttFill::Modify();
7596 fH->TAttLine::Modify();
7597 Int_t ncolors = gStyle->GetNumberOfColors();
7599
7600 // Create bin boxes and draw
7604
7605 Double_t pmin[3], pmax[3], sxyz[8][3];
7606 for (Int_t ix = ix1; ix !=ix2+incrx; ix += incrx) {
7607 pmin[0] = xaxis->GetBinLowEdge(ix);
7608 pmax[0] = xaxis->GetBinUpEdge(ix);
7609 for (Int_t iy = iy1; iy != iy2+incry; iy += incry) {
7610 pmin[1] = yaxis->GetBinLowEdge(iy);
7611 pmax[1] = yaxis->GetBinUpEdge(iy);
7612 for (Int_t iz = iz1; iz != iz2+incrz; iz += incrz) {
7613 pmin[2] = zaxis->GetBinLowEdge(iz);
7614 pmax[2] = zaxis->GetBinUpEdge(iz);
7615 Double_t w = fH->GetBinContent(fH->GetBin(ix,iy,iz));
7616 Bool_t neg = kFALSE;
7617 Int_t n = 5;
7618 if (w<0) {
7619 w = -w;
7620 neg = kTRUE;
7621 }
7622 if (w < wmin) continue;
7623 if (w > wmax) w = wmax;
7624 Double_t scale = (TMath::Power((w-wmin)/(wmax-wmin),1./3.))/2.;
7625 if (scale == 0) continue;
7626 for (Int_t i=0; i<3; ++i) {
7627 Double_t c = (pmax[i] + pmin[i])*0.5;
7628 Double_t d = (pmax[i] - pmin[i])*scale;
7629 for (Int_t k=0; k<8; ++k) { // set bin box vertices
7630 sxyz[k][i] = wxyz[k][i]*d + c;
7631 }
7632 }
7633 for (Int_t k=0; k<8; ++k) { // transform to normalized space
7634 view->WCtoNDC(&sxyz[k][0],&sxyz[k][0]);
7635 }
7636 Double_t x[8], y[8]; // draw bin box faces
7637 for (Int_t k=0; k<6; ++k) {
7638 for (Int_t i=0; i<4; ++i) {
7639 Int_t iv = iface[k][i];
7640 x[i] = sxyz[iv][0];
7641 y[i] = sxyz[iv][1];
7642 }
7643 x[4] = x[0] ; y[4] = y[0];
7644 if (neg) {
7645 x[5] = x[2] ; y[5] = y[2];
7646 x[6] = x[3] ; y[6] = y[3];
7647 x[7] = x[1] ; y[7] = y[1];
7648 n = 8;
7649 } else {
7650 n = 5;
7651 }
7652 Double_t z = (x[2]-x[0])*(y[3]-y[1]) - (y[2]-y[0])*(x[3]-x[1]);
7653 if (z <= 0.) continue;
7654 if (iopt == 2) {
7655 theColor = ncolors*((w-wmin)/(wmax-wmin)) -1;
7657 } else {
7658 if (k == 3 || k == 5) {
7660 } else if (k == 0 || k == 1) {
7662 } else {
7664 }
7665 }
7666 fH->TAttFill::Modify();
7667 gPad->PaintFillArea(4, x, y);
7668 if (iopt != 3)gPad->PaintPolyLine(n, x, y);
7669 }
7670 }
7671 }
7672 }
7673
7674 // Draw front surfaces of frame box
7675 if (Hoption.FrontBox) fLego->FrontBox(90);
7676
7677 // Draw axis and title
7678 if (!Hoption.Axis && !Hoption.Same) {
7679 TGaxis axis;
7680 PaintLegoAxis(&axis, 90);
7681 }
7682 PaintTitle();
7683
7684 // Draw palette. if needed.
7685 if (Hoption.Zscale) {
7686 Int_t ndiv = fH->GetContour();
7687 if (ndiv == 0 ) {
7688 ndiv = gStyle->GetNumberContours();
7689 fH->SetContour(ndiv);
7690 }
7691 PaintPalette();
7692 }
7693
7694 //Draw stats and fit results
7695 TF1 *fit = nullptr;
7696 TIter next(fFunctions);
7697 while (auto obj = next()) {
7698 if (obj->InheritsFrom(TF1::Class())) {
7699 fit = (TF1*)obj;
7700 break;
7701 }
7702 }
7703 if ((Hoption.Same%10) != 1) {
7704 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7706 }
7707 }
7708
7709 fLego.reset();
7710
7713 fH->TAttFill::Modify();
7714}
7715
7716////////////////////////////////////////////////////////////////////////////////
7717/// [Control function to draw a 3D histogram with boxes.](\ref HP25)
7718
7720{
7721 // Predefined box structure
7722 Double_t wxyz[8][3] = {
7723 {-1,-1,-1}, {1,-1,-1}, {1,1,-1}, {-1,1,-1}, // bottom vertices
7724 {-1,-1, 1}, {1,-1, 1}, {1,1, 1}, {-1,1, 1} // top vertices
7725 };
7726 Int_t iface[6][4] = {
7727 {0,3,2,1}, {4,5,6,7}, // bottom and top faces
7728 {0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7} // side faces
7729 };
7730 Double_t normal[6][3] = {
7731 {0,0,-1}, {0,0,1}, // Z-, Z+
7732 {0,-1,0}, {1,0,0}, {0,1,0}, {-1,0,0} // Y-, X+, Y+, X-
7733 };
7734
7735 // Define dimensions of world space
7736 TAxis *xaxis = fH->GetXaxis();
7737 TAxis *yaxis = fH->GetYaxis();
7738 TAxis *zaxis = fH->GetZaxis();
7739
7740 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7741 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7742 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7743 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7744 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7745 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7746
7747 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7748
7749 // Set view
7750 TView *view = gPad ? gPad->GetView() : nullptr;
7751 if (!view) {
7752 Error("PaintH3", "no TView in current pad");
7753 return;
7754 }
7755 Double_t thedeg = 90 - gPad->GetTheta();
7756 Double_t phideg = -90 - gPad->GetPhi();
7757 Double_t psideg = view->GetPsi();
7758 Int_t irep;
7759 view->SetView(phideg, thedeg, psideg, irep);
7760
7761 Int_t backcolor = gPad->GetFrameFillColor();
7762 view->PadRange(backcolor);
7763
7764 // Draw front surfaces of frame box
7765 if (Hoption.FrontBox) {
7766 fLego->InitMoveScreen(-1.1,1.1);
7768 }
7769
7770 // Initialize hidden line removal algorithm "raster screen"
7771 fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
7772
7773 // Define order of drawing
7774 Double_t *tnorm = view->GetTnorm();
7775 if (!tnorm) return;
7776 Int_t incrx = (tnorm[ 8] < 0.) ? +1 : -1;
7777 Int_t incry = (tnorm[ 9] < 0.) ? +1 : -1;
7778 Int_t incrz = (tnorm[10] < 0.) ? +1 : -1;
7779 Int_t ix1 = (incrx == +1) ? xaxis->GetFirst() : xaxis->GetLast();
7780 Int_t iy1 = (incry == +1) ? yaxis->GetFirst() : yaxis->GetLast();
7781 Int_t iz1 = (incrz == +1) ? zaxis->GetFirst() : zaxis->GetLast();
7782 Int_t ix2 = (incrx == +1) ? xaxis->GetLast() : xaxis->GetFirst();
7783 Int_t iy2 = (incry == +1) ? yaxis->GetLast() : yaxis->GetFirst();
7784 Int_t iz2 = (incrz == +1) ? zaxis->GetLast() : zaxis->GetFirst();
7785
7786 // Set line attributes (colour, style, etc.)
7787 fH->TAttLine::Modify();
7788
7789 // Create bin boxes and draw
7790 const Int_t NTMAX = 100;
7791 Double_t tt[NTMAX][2];
7795 Double_t pmin[3], pmax[3], sxyz[8][3], pp[4][2];
7796 for (Int_t ix = ix1; ix !=ix2+incrx; ix += incrx) {
7797 pmin[0] = xaxis->GetBinLowEdge(ix);
7798 pmax[0] = xaxis->GetBinUpEdge(ix);
7799 for (Int_t iy = iy1; iy != iy2+incry; iy += incry) {
7800 pmin[1] = yaxis->GetBinLowEdge(iy);
7801 pmax[1] = yaxis->GetBinUpEdge(iy);
7802 for (Int_t iz = iz1; iz != iz2+incrz; iz += incrz) {
7803 pmin[2] = zaxis->GetBinLowEdge(iz);
7804 pmax[2] = zaxis->GetBinUpEdge(iz);
7805 Double_t w = fH->GetBinContent(fH->GetBin(ix,iy,iz));
7806 Bool_t neg = kFALSE;
7807 if (w<0) {
7808 w = -w;
7809 neg = kTRUE;
7810 }
7811 if (w < wmin) continue;
7812 if (w > wmax) w = wmax;
7813 Double_t scale = (TMath::Power((w-wmin)/(wmax-wmin),1./3.))/2.;
7814 if (scale == 0) continue;
7815 for (Int_t i=0; i<3; ++i) {
7816 Double_t c = (pmax[i] + pmin[i])*0.5;
7817 Double_t d = (pmax[i] - pmin[i])*scale;
7818 for (Int_t k=0; k<8; ++k) { // set bin box vertices
7819 sxyz[k][i] = wxyz[k][i]*d + c;
7820 }
7821 }
7822 for (Int_t k=0; k<8; ++k) { // transform to normalized space
7823 view->WCtoNDC(&sxyz[k][0],&sxyz[k][0]);
7824 }
7825 for (Int_t k=0; k<6; ++k) { // draw box faces
7826 Double_t zn;
7827 view->FindNormal(normal[k][0], normal[k][1], normal[k][2], zn);
7828 if (zn <= 0) continue;
7829 for (Int_t i=0; i<4; ++i) {
7830 Int_t ip = iface[k][i];
7831 pp[i][0] = sxyz[ip][0];
7832 pp[i][1] = sxyz[ip][1];
7833 }
7834 for (Int_t i=0; i<4; ++i) {
7835 Int_t i1 = i;
7836 Int_t i2 = (i == 3) ? 0 : i + 1;
7837 Int_t nt;
7838 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7839 Double_t xdel = pp[i2][0] - pp[i1][0];
7840 Double_t ydel = pp[i2][1] - pp[i1][1];
7841 Double_t x[2], y[2];
7842 for (Int_t it = 0; it < nt; ++it) {
7843 x[0] = pp[i1][0] + xdel*tt[it][0];
7844 y[0] = pp[i1][1] + ydel*tt[it][0];
7845 x[1] = pp[i1][0] + xdel*tt[it][1];
7846 y[1] = pp[i1][1] + ydel*tt[it][1];
7847 gPad->PaintPolyLine(2, x, y);
7848 }
7849 }
7850 if (neg) {
7851 Int_t i1 = 0;
7852 Int_t i2 = 2;
7853 Int_t nt;
7854 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7855 Double_t xdel = pp[i2][0] - pp[i1][0];
7856 Double_t ydel = pp[i2][1] - pp[i1][1];
7857 Double_t x[2], y[2];
7858 for (Int_t it = 0; it < nt; ++it) {
7859 x[0] = pp[i1][0] + xdel*tt[it][0];
7860 y[0] = pp[i1][1] + ydel*tt[it][0];
7861 x[1] = pp[i1][0] + xdel*tt[it][1];
7862 y[1] = pp[i1][1] + ydel*tt[it][1];
7863 gPad->PaintPolyLine(2, x, y);
7864 }
7865 i1 = 1;
7866 i2 = 3;
7867 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7868 xdel = pp[i2][0] - pp[i1][0];
7869 ydel = pp[i2][1] - pp[i1][1];
7870 for (Int_t it = 0; it < nt; ++it) {
7871 x[0] = pp[i1][0] + xdel*tt[it][0];
7872 y[0] = pp[i1][1] + ydel*tt[it][0];
7873 x[1] = pp[i1][0] + xdel*tt[it][1];
7874 y[1] = pp[i1][1] + ydel*tt[it][1];
7875 gPad->PaintPolyLine(2, x, y);
7876 }
7877 }
7878 fLego->FillPolygonBorder(4, &pp[0][0]); // update raster screen
7879 }
7880 }
7881 }
7882 }
7883
7884 // Draw frame box
7885 if (Hoption.BackBox) {
7886 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
7888 fLego->BackBox(90);
7889 }
7890
7891 if (Hoption.FrontBox) fLego->FrontBox(90);
7892
7893 // Draw axis and title
7894 if (!Hoption.Axis && !Hoption.Same) {
7895 TGaxis axis;
7896 PaintLegoAxis(&axis, 90);
7897 }
7898 PaintTitle();
7899
7900 //Draw stats and fit results
7901 TF1 *fit = nullptr;
7902 TIter next(fFunctions);
7903 while (auto obj = next()) {
7904 if (obj->InheritsFrom(TF1::Class())) {
7905 fit = (TF1*)obj;
7906 break;
7907 }
7908 }
7909 if ((Hoption.Same%10) != 1) {
7910 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7912 }
7913 }
7914
7915 fLego.reset();
7916}
7917
7918////////////////////////////////////////////////////////////////////////////////
7919/// [Control function to draw a 3D histogram with Iso Surfaces.](\ref HP25)
7920
7922{
7923
7924 const Double_t ydiff = 1;
7925 const Double_t yligh1 = 10;
7926 const Double_t qa = 0.15;
7927 const Double_t qd = 0.15;
7928 const Double_t qs = 0.8;
7930 Int_t i, irep;
7931 Int_t nbcol = 28;
7932 Int_t icol1 = 201;
7933 Int_t ic1 = icol1;
7934 Int_t ic2 = ic1+nbcol;
7935 Int_t ic3 = ic2+nbcol;
7936
7937 TAxis *xaxis = fH->GetXaxis();
7938 TAxis *yaxis = fH->GetYaxis();
7939 TAxis *zaxis = fH->GetZaxis();
7940
7941 Int_t nx = fH->GetNbinsX();
7942 Int_t ny = fH->GetNbinsY();
7943 Int_t nz = fH->GetNbinsZ();
7944
7945 std::vector<Double_t> x(nx);
7946 std::vector<Double_t> y(ny);
7947 std::vector<Double_t> z(nz);
7948
7949 for (i=0; i<nx; i++) x[i] = xaxis->GetBinCenter(i+1);
7950 for (i=0; i<ny; i++) y[i] = yaxis->GetBinCenter(i+1);
7951 for (i=0; i<nz; i++) z[i] = zaxis->GetBinCenter(i+1);
7952
7953 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7954 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7955 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7956 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7957 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7958 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7959
7960 Double_t s[3];
7961 s[0] = fH->GetSumOfWeights()/(fH->GetNbinsX()*fH->GetNbinsY()*fH->GetNbinsZ());
7962 s[1] = 0.5*s[0];
7963 s[2] = 1.5*s[0];
7964
7965 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7966
7967 TView *view = gPad ? gPad->GetView() : nullptr;
7968 if (!view) {
7969 Error("PaintH3Iso", "no TView in current pad");
7970 return;
7971 }
7972 Double_t thedeg = 90 - gPad->GetTheta();
7973 Double_t phideg = -90 - gPad->GetPhi();
7974 Double_t psideg = view->GetPsi();
7975 view->SetView(phideg, thedeg, psideg, irep);
7976
7977 Int_t backcolor = gPad->GetFrameFillColor();
7978 if (Hoption.System != kCARTESIAN) backcolor = 0;
7979 view->PadRange(backcolor);
7980
7981 Double_t dcol = 0.5/Double_t(nbcol);
7982 TColor *colref = gROOT->GetColor(fH->GetFillColor());
7983 if (!colref) {
7984 return;
7985 }
7986 Float_t r, g, b, hue, light, satur;
7987 colref->GetRGB(r,g,b);
7989 TColor *acol;
7990 for (Int_t col=0;col<nbcol;col++) {
7991 acol = gROOT->GetColor(col+icol1);
7992 TColor::HLStoRGB(hue, .4+col*dcol, satur, r, g, b);
7993 if (acol) acol->SetRGB(r, g, b);
7994 }
7995
7996 fLego->InitMoveScreen(-1.1,1.1);
7997
7998 if (Hoption.BackBox) {
7999 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
8001 fLego->BackBox(90);
8002 }
8003
8004 fLego->LightSource(0, ydiff, 0, 0, 0, irep);
8005 fLego->LightSource(1, yligh1, 1, 1, 1, irep);
8006 fLego->SurfaceProperty(qa, qd, qs, 1, irep);
8007 fmin = ydiff*qa;
8008 fmax = ydiff*qa + (yligh1+0.1)*(qd+qs);
8009 fLego->SetIsoSurfaceParameters(fmin, fmax, nbcol, ic1, ic2, ic3);
8010
8011 fLego->IsoSurface(1, s, nx, ny, nz, x.data(), y.data(), z.data(), "BF");
8012
8013 if (Hoption.FrontBox) {
8014 fLego->InitMoveScreen(-1.1,1.1);
8016 fLego->FrontBox(90);
8017 }
8018 if (!Hoption.Axis && !Hoption.Same) {
8019 TGaxis axis;
8020 PaintLegoAxis(&axis, 90);
8021 }
8022
8023 PaintTitle();
8024
8025 //Draw stats and fit results
8026 TF1 *fit = nullptr;
8027 TIter next(fFunctions);
8028 while (auto obj = next()) {
8029 if (obj->InheritsFrom(TF1::Class())) {
8030 fit = (TF1*)obj;
8031 break;
8032 }
8033 }
8034 if ((Hoption.Same%10) != 1) {
8035 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
8037 }
8038 }
8039
8040 fLego.reset();
8041}
8042
8043////////////////////////////////////////////////////////////////////////////////
8044/// [Control function to draw a 2D histogram as a lego plot.](\ref HP17)
8045
8047{
8048
8049 Int_t raster = 1;
8050 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
8051 Int_t nx = Hparam.xlast - Hparam.xfirst + 1;
8052 Int_t ny = Hparam.ylast - Hparam.yfirst + 1;
8053 Double_t zmin = Hparam.zmin;
8054 Double_t zmax = Hparam.zmax;
8059 Double_t dangle = 10*3.141592/180; //Delta angle for Rapidity option
8060 Double_t deltaz = TMath::Abs(zmin);
8061 if (deltaz == 0) deltaz = 1;
8062 if (zmin >= zmax) {
8063 zmin -= 0.5*deltaz;
8064 zmax += 0.5*deltaz;
8065 }
8066 Double_t z1c = zmin;
8067 Double_t z2c = zmin + (zmax-zmin)*(1+gStyle->GetHistTopMargin());
8068
8069 // Compute the lego limits and instantiate a lego object
8070 fXbuf[0] = -1;
8071 fYbuf[0] = 1;
8072 fXbuf[1] = -1;
8073 fYbuf[1] = 1;
8074 if (Hoption.System == kPOLAR) {
8075 fXbuf[2] = z1c;
8076 fYbuf[2] = z2c;
8077 } else if (Hoption.System == kCYLINDRICAL) {
8078 if (Hoption.Logy) {
8079 if (ylab1 > 0) fXbuf[2] = TMath::Log10(ylab1);
8080 else fXbuf[2] = 0;
8081 if (ylab2 > 0) fYbuf[2] = TMath::Log10(ylab2);
8082 else fYbuf[2] = 0;
8083 } else {
8084 fXbuf[2] = ylab1;
8085 fYbuf[2] = ylab2;
8086 }
8087 z1c = 0; z2c = 1;
8088 } else if (Hoption.System == kSPHERICAL) {
8089 fXbuf[2] = -1;
8090 fYbuf[2] = 1;
8091 z1c = 0; z2c = 1;
8092 } else if (Hoption.System == kRAPIDITY) {
8093 fXbuf[2] = -1/TMath::Tan(dangle);
8094 fYbuf[2] = 1/TMath::Tan(dangle);
8095 } else {
8096 fXbuf[0] = xlab1;
8097 fYbuf[0] = xlab2;
8098 fXbuf[1] = ylab1;
8099 fYbuf[1] = ylab2;
8100 fXbuf[2] = z1c;
8101 fYbuf[2] = z2c;
8102 raster = 0;
8103 }
8104
8105 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data(), Hoption.System);
8106
8107 Int_t nids = -1;
8108 TH1 * hid = nullptr;
8109 Color_t colormain = -1, colordark = -1;
8111
8112 // LEGO3 is like LEGO1 except that the black lines around each lego are not drawn.
8113 if (Hoption.Lego == 13) {
8114 Hoption.Lego = 11;
8115 fLego->SetMesh(0);
8116 }
8117 // LEGO4 is like LEGO1 except no shadows are drawn.
8118 if (Hoption.Lego == 14) {
8119 Hoption.Lego = 11;
8121 }
8122
8123 // Initialize the levels on the Z axis
8124 Int_t ndiv = fH->GetContour();
8125 if (ndiv == 0 ) {
8126 ndiv = gStyle->GetNumberContours();
8127 fH->SetContour(ndiv);
8128 }
8129 Int_t ndivz = TMath::Abs(ndiv);
8130 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
8131
8132 // Initialize colors
8133 if (!fStack) {
8134 fLego->SetEdgeAtt(fH->GetLineColor(),fH->GetLineStyle(),fH->GetLineWidth(),0);
8135 } else {
8136 for (Int_t id=0;id<=fStack->GetSize();id++) {
8137 hid = (TH1*)fStack->At((id==0)?id:id-1);
8138 fLego->SetEdgeAtt(hid->GetLineColor(),hid->GetLineStyle(),hid->GetLineWidth(),id);
8139 }
8140 }
8141
8142 if (Hoption.Lego == 11) {
8143 nids = 1;
8144 if (fStack) nids = fStack->GetSize();
8145 hid = fH;
8146 for (Int_t id=0;id<=nids;id++) {
8147 if (id > 0 && fStack) hid = (TH1*)fStack->At(id-1);
8148 colormain = hid->GetFillColor();
8149 if (colormain == 1) colormain = 17; //avoid drawing with black
8151 else colordark = colormain;
8152 fLego->SetColorMain(colormain,id);
8153 fLego->SetColorDark(colordark,id);
8154 if (id <= 1) fLego->SetColorMain(colormain,-1); // Set Bottom color
8155 if (id == nids) fLego->SetColorMain(colormain,99); // Set Top color
8156 }
8157 }
8158
8159 // Now ready to draw the lego plot
8160 Int_t irep = 0;
8161
8162 TView *view = gPad ? gPad->GetView() : nullptr;
8163 if (!view) {
8164 Error("PaintLego", "no TView in current pad");
8165 return;
8166 }
8167
8168 Double_t thedeg = 90 - gPad->GetTheta();
8169 Double_t phideg = -90 - gPad->GetPhi();
8170 Double_t psideg = view->GetPsi();
8171 view->SetView(phideg, thedeg, psideg, irep);
8172
8173 fLego->SetLineColor(kBlack); // zgrid color for lego1 & lego2
8174 fLego->SetFillStyle(fH->GetFillStyle());
8175
8176 // Set color/style for back box
8177 fLego->SetFillStyle(gPad->GetFrameFillStyle());
8178 fLego->SetFillColor(gPad->GetFrameFillColor());
8179 fLego->TAttFill::Modify();
8180
8181 Int_t backcolor = gPad->GetFrameFillColor();
8182 if (Hoption.System != kCARTESIAN) backcolor = 0;
8183 view->PadRange(backcolor);
8184
8185 fLego->SetFillStyle(fH->GetFillStyle());
8186 fLego->SetFillColor(fH->GetFillColor());
8187 fLego->TAttFill::Modify();
8188
8189 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
8190
8191 if (raster) fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
8192 else fLego->InitMoveScreen(-1.1,1.1);
8193
8194 if (Hoption.Lego == 19) {
8196 if (Hoption.BackBox) fLego->BackBox(90);
8197 if (Hoption.FrontBox) fLego->FrontBox(90);
8198 if (!Hoption.Axis) { TGaxis axis; PaintLegoAxis(&axis, 90); }
8199 return;
8200 }
8201
8202 if (Hoption.Lego == 11 || Hoption.Lego == 12) {
8205 fLego->BackBox(90);
8206 }
8207 }
8208
8209 if (Hoption.Lego == 12) DefineColorLevels(ndivz);
8210
8211 fLego->SetLegoFunction(&TPainter3dAlgorithms::LegoFunction);
8213 if (Hoption.Lego == 11) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode3);
8214 if (Hoption.Lego == 12) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode2);
8215 if (Hoption.System == kPOLAR) {
8216 if (Hoption.Lego == 1) fLego->LegoPolar(1,nx,ny,"FB");
8217 if (Hoption.Lego == 11) fLego->LegoPolar(1,nx,ny,"BF");
8218 if (Hoption.Lego == 12) fLego->LegoPolar(1,nx,ny,"BF");
8219 } else if (Hoption.System == kCYLINDRICAL) {
8220 if (Hoption.Lego == 1) fLego->LegoCylindrical(1,nx,ny,"FB");
8221 if (Hoption.Lego == 11) fLego->LegoCylindrical(1,nx,ny,"BF");
8222 if (Hoption.Lego == 12) fLego->LegoCylindrical(1,nx,ny,"BF");
8223 } else if (Hoption.System == kSPHERICAL) {
8224 if (Hoption.Lego == 1) fLego->LegoSpherical(0,1,nx,ny,"FB");
8225 if (Hoption.Lego == 11) fLego->LegoSpherical(0,1,nx,ny,"BF");
8226 if (Hoption.Lego == 12) fLego->LegoSpherical(0,1,nx,ny,"BF");
8227 } else if (Hoption.System == kRAPIDITY) {
8228 if (Hoption.Lego == 1) fLego->LegoSpherical(1,1,nx,ny,"FB");
8229 if (Hoption.Lego == 11) fLego->LegoSpherical(1,1,nx,ny,"BF");
8230 if (Hoption.Lego == 12) fLego->LegoSpherical(1,1,nx,ny,"BF");
8231 } else {
8232 if (Hoption.Lego == 1) {
8234 fLego->LegoCartesian(90,nx,ny,"FB");}
8235 if (Hoption.Lego == 11) fLego->LegoCartesian(90,nx,ny,"BF");
8236 if (Hoption.Lego == 12) fLego->LegoCartesian(90,nx,ny,"BF");
8237 }
8238
8239 if (Hoption.Lego == 1 || Hoption.Lego == 11) {
8242 fLego->BackBox(90);
8243 }
8244 }
8245 if (Hoption.System == kCARTESIAN) {
8246 fLego->InitMoveScreen(-1.1,1.1);
8248 if (Hoption.FrontBox) fLego->FrontBox(90);
8249 }
8250 if (!Hoption.Axis && !Hoption.Same) {
8251 TGaxis axis;
8252 PaintLegoAxis(&axis, 90);
8253 }
8255 fLego.reset();
8256}
8257
8258////////////////////////////////////////////////////////////////////////////////
8259/// Draw the axis for legos and surface plots.
8260
8262{
8263
8264 static Double_t epsil = 0.001;
8265
8268 Double_t r[24] /* was [3][8] */;
8269 Int_t ndivx, ndivy, ndivz, i;
8270 Double_t x1[3], x2[3], y1[3], y2[3], z1[3], z2[3], av[24] /* was [3][8] */;
8271 static char chopax[8], chopay[8], chopaz[8];
8272 Int_t ix1, ix2, iy1, iy2, iz1, iz2;
8273 Double_t rad;
8274
8275 TView *view = gPad ? gPad->GetView() : nullptr;
8276 if (!view) {
8277 Error("PaintLegoAxis", "no TView in current pad");
8278 return;
8279 }
8280
8281 // In polar coordinates, draw a short line going from the external circle
8282 // corresponding to r = 1 up to r = 1.1
8283 if (Hoption.System == kPOLAR) {
8284 r[0] = 1;
8285 r[1] = 0;
8286 r[2] = 0;
8287 view->WCtoNDC(r, x1);
8288 r[0] = 1.1;
8289 r[1] = 0;
8290 r[2] = 0;
8291 view->WCtoNDC(r, x2);
8292 gPad->PaintLine(x1[0],x1[1],x2[0],x2[1]);
8293 return;
8294 }
8295
8296 if (Hoption.System != kCARTESIAN) return;
8297
8298 rad = TMath::ATan(1.) * 4. /180.;
8299 cosa = TMath::Cos(ang*rad);
8300 sina = TMath::Sin(ang*rad);
8301
8302 view->AxisVertex(ang, av, ix1, ix2, iy1, iy2, iz1, iz2);
8303 for (i = 1; i <= 8; ++i) {
8304 r[i*3 - 3] = av[i*3 - 3] + av[i*3 - 2]*cosa;
8305 r[i*3 - 2] = av[i*3 - 2]*sina;
8306 r[i*3 - 1] = av[i*3 - 1];
8307 }
8308
8309 view->WCtoNDC(&r[ix1*3 - 3], x1);
8310 view->WCtoNDC(&r[ix2*3 - 3], x2);
8311 view->WCtoNDC(&r[iy1*3 - 3], y1);
8312 view->WCtoNDC(&r[iy2*3 - 3], y2);
8313 view->WCtoNDC(&r[iz1*3 - 3], z1);
8314 view->WCtoNDC(&r[iz2*3 - 3], z2);
8315
8316 view->SetAxisNDC(x1, x2, y1, y2, z1, z2);
8317
8318 Double_t *rmin = view->GetRmin();
8319 Double_t *rmax = view->GetRmax();
8320 if (!rmin || !rmax) return;
8321
8322 // Initialize the axis options
8323 if (x1[0] > x2[0]) strlcpy(chopax, "SDH=+",8);
8324 else strlcpy(chopax, "SDH=-",8);
8325 if (y1[0] > y2[0]) strlcpy(chopay, "SDH=+",8);
8326 else strlcpy(chopay, "SDH=-",8);
8327 if (z2[1] > z1[1]) strlcpy(chopaz, "SDH=+",8);
8328 else strlcpy(chopaz, "SDH=-",8);
8329
8330 // Option LOG is required ?
8331 if (Hoption.Logx) strlcat(chopax,"G",8);
8332 if (Hoption.Logy) strlcat(chopay,"G",8);
8333 if (Hoption.Logz) strlcat(chopaz,"G",8);
8334
8335 // Initialize the number of divisions. If the
8336 // number of divisions is negative, option 'N' is required.
8340 if (ndivx < 0) {
8342 strlcat(chopax, "N",8);
8343 }
8344 if (ndivy < 0) {
8346 strlcat(chopay, "N",8);
8347 }
8348 if (ndivz < 0) {
8350 strlcat(chopaz, "N",8);
8351 }
8352
8353 // Set Axis attributes.
8354 // The variable SCALE rescales the VSIZ
8355 // in order to have the same label size for all angles.
8356
8357 axis->SetLineWidth(1);
8358
8359 // X axis drawing
8360 if (TMath::Abs(x1[0] - x2[0]) >= epsil || TMath::Abs(x1[1] - x2[1]) > epsil) {
8363 if (Hoption.Logx && !fH->InheritsFrom(TH3::Class())) {
8364 bmin = TMath::Power(10, rmin[0]);
8365 bmax = TMath::Power(10, rmax[0]);
8366 } else {
8367 bmin = rmin[0];
8368 bmax = rmax[0];
8369 }
8370 // Option time display is required ?
8371 if (fXaxis->GetTimeDisplay()) {
8372 strlcat(chopax,"t",8);
8373 if (strlen(fXaxis->GetTimeFormatOnly()) == 0) {
8375 } else {
8377 }
8378 }
8379 axis->SetOption(chopax);
8380 axis->PaintAxis(x1[0], x1[1], x2[0], x2[1], bmin, bmax, ndivx, chopax);
8381 }
8382
8383 // Y axis drawing
8384 if (TMath::Abs(y1[0] - y2[0]) >= epsil || TMath::Abs(y1[1] - y2[1]) > epsil) {
8387 if (fYaxis->GetTitleOffset() == 0) axis->SetTitleOffset(1.5);
8388
8389 if (fH->GetDimension() < 2) {
8390 strlcpy(chopay, "V=+UN",8);
8391 ndivy = 0;
8392 }
8393 if (TMath::Abs(y1[0] - y2[0]) < epsil) {
8394 y2[0] = y1[0];
8395 }
8396 if (Hoption.Logy && !fH->InheritsFrom(TH3::Class())) {
8397 bmin = TMath::Power(10, rmin[1]);
8398 bmax = TMath::Power(10, rmax[1]);
8399 } else {
8400 bmin = rmin[1];
8401 bmax = rmax[1];
8402 }
8403 // Option time display is required ?
8404 if (fYaxis->GetTimeDisplay()) {
8405 strlcat(chopay,"t",8);
8406 if (strlen(fYaxis->GetTimeFormatOnly()) == 0) {
8408 } else {
8410 }
8411 }
8412 axis->SetOption(chopay);
8413 axis->PaintAxis(y1[0], y1[1], y2[0], y2[1], bmin, bmax, ndivy, chopay);
8414 }
8415
8416 // Z axis drawing
8417 if (TMath::Abs(z1[0] - z2[0]) >= 100*epsil || TMath::Abs(z1[1] - z2[1]) > 100*epsil) {
8419 if (Hoption.Logz && !fH->InheritsFrom(TH3::Class())) {
8420 bmin = TMath::Power(10, rmin[2]);
8421 bmax = TMath::Power(10, rmax[2]);
8422 } else {
8423 bmin = rmin[2];
8424 bmax = rmax[2];
8425 }
8426 // Option time display is required ?
8427 if (fZaxis->GetTimeDisplay()) {
8428 strlcat(chopaz,"t",8);
8429 if (strlen(fZaxis->GetTimeFormatOnly()) == 0) {
8431 } else {
8433 }
8434 }
8435 axis->SetOption(chopaz);
8437 if (ztit.Index(";")>0) {
8438 ztit.Remove(ztit.Index(";"),ztit.Length());
8439 axis->SetTitle(ztit.Data());
8440 }
8441 axis->PaintAxis(z1[0], z1[1], z2[0], z2[1], bmin, bmax, ndivz, chopaz);
8442 }
8443
8444 //fH->SetLineStyle(1); /// otherwise fEdgeStyle[i] gets overwritten!
8445}
8446
8447////////////////////////////////////////////////////////////////////////////////
8448/// [Paint the color palette on the right side of the pad.](\ref HP22)
8449
8451{
8453 TView *view = gPad ? gPad->GetView() : nullptr;
8454 if (palette) {
8455 if (view) {
8456 if (!palette->TestBit(TPaletteAxis::kHasView)) {
8458 delete palette; palette = nullptr;
8459 }
8460 } else {
8461 if (palette->TestBit(TPaletteAxis::kHasView)) {
8463 delete palette; palette = nullptr;
8464 }
8465 }
8466 // make sure the histogram member of the palette is setup correctly. It may not be after a Clone()
8467 if (palette && !palette->GetHistogram()) palette->SetHistogram(fH);
8468 }
8469
8470 if (!palette) {
8471 Double_t xup = gPad->GetUxmax();
8472 Double_t x2 = gPad->PadtoX(gPad->GetX2());
8473 Double_t ymin = gPad->PadtoY(gPad->GetUymin());
8474 Double_t ymax = gPad->PadtoY(gPad->GetUymax());
8475 Double_t xr = 0.05*(gPad->GetX2() - gPad->GetX1());
8476 Double_t xmin = gPad->PadtoX(xup +0.1*xr);
8477 Double_t xmax = gPad->PadtoX(xup + xr);
8478 if (xmax > x2) xmax = gPad->PadtoX(gPad->GetX2()-0.01*xr);
8481 palette->Paint();
8482 }
8483}
8484
8485////////////////////////////////////////////////////////////////////////////////
8486/// [Control function to draw a 2D histogram as a scatter plot.](\ref HP11)
8487
8489{
8490
8491 fH->TAttMarker::Modify();
8492
8493 Int_t k, marker;
8494 Double_t dz, z, xk,xstep, yk, ystep;
8495 Double_t scale = 1;
8497 Double_t zmax = fH->GetMaximum();
8498 Double_t zmin = fH->GetMinimum();
8499 if (zmin == 0 && zmax == 0) return;
8500 if (zmin == zmax) {
8501 zmax += 0.1*TMath::Abs(zmax);
8502 zmin -= 0.1*TMath::Abs(zmin);
8503 }
8505 if (Hoption.Logz) {
8506 if (zmin > 0) zmin = TMath::Log10(zmin);
8507 else zmin = 0;
8508 if (zmax > 0) zmax = TMath::Log10(zmax);
8509 else zmax = 0;
8510 if (zmin == 0 && zmax == 0) return;
8511 dz = zmax - zmin;
8512 scale = 100/dz;
8513 if (ncells > 10000) scale /= 5;
8514 ltest = kTRUE;
8515 } else {
8516 dz = zmax - zmin;
8517 if (dz >= kNMAX || zmax < 1) {
8518 scale = (kNMAX-1)/dz;
8519 if (ncells > 10000) scale /= 5;
8520 ltest = kTRUE;
8521 }
8522 }
8523 if (fH->GetMinimumStored() == -1111) {
8525 if (Hoption.MinimumZero) {
8526 if (zmin >= 0) zmin = 0;
8527 else zmin -= yMARGIN*(zmax-zmin);
8528 } else {
8529 Double_t dzmin = yMARGIN*(zmax-zmin);
8530 if (zmin >= 0 && (zmin-dzmin <= 0)) zmin = 0;
8531 else zmin -= dzmin;
8532 }
8533 }
8534
8535 TString opt = option;
8536 opt.ToLower();
8537 if (opt.Contains("scat=")) {
8538 char optscat[100];
8539 strlcpy(optscat,opt.Data(),100);
8540 char *oscat = strstr(optscat,"scat=");
8541 char *blank = strstr(oscat," "); if (blank) *blank = 0;
8542 sscanf(oscat+5,"%lg",&scale);
8543 }
8544 // use an independent instance of a random generator
8545 // instead of gRandom to avoid conflicts and
8546 // to get same random numbers when drawing the same histogram
8548 marker=0;
8549 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
8552 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
8553 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
8554 xk = fXaxis->GetBinLowEdge(i);
8555 xstep = fXaxis->GetBinWidth(i);
8556 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
8557 z = fH->GetBinContent(bin);
8558 if (z < zmin) z = zmin;
8559 if (z > zmax) z = zmax;
8560 if (Hoption.Logz) {
8561 if (z > 0) z = TMath::Log10(z) - zmin;
8562 } else {
8563 z -= zmin;
8564 }
8565 if (z <= 0) continue;
8566 k = Int_t(z*scale);
8567 if (ltest) k++;
8568 if (k > 0) {
8569 for (Int_t loop=0; loop<k; loop++) {
8570 if (k+marker >= kNMAX) {
8571 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
8572 marker=0;
8573 }
8574 fXbuf[marker] = (random.Rndm()*xstep) + xk;
8575 fYbuf[marker] = (random.Rndm()*ystep) + yk;
8576 if (Hoption.Logx) {
8577 if (fXbuf[marker] > 0) fXbuf[marker] = TMath::Log10(fXbuf[marker]);
8578 else break;
8579 }
8580 if (Hoption.Logy) {
8581 if (fYbuf[marker] > 0) fYbuf[marker] = TMath::Log10(fYbuf[marker]);
8582 else break;
8583 }
8584 if (fXbuf[marker] < gPad->GetUxmin()) break;
8585 if (fYbuf[marker] < gPad->GetUymin()) break;
8586 if (fXbuf[marker] > gPad->GetUxmax()) break;
8587 if (fYbuf[marker] > gPad->GetUymax()) break;
8588 marker++;
8589 }
8590 }
8591 }
8592 }
8593 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
8594
8596}
8597
8598////////////////////////////////////////////////////////////////////////////////
8599/// Static function to paint special objects like vectors and matrices.
8600/// This function is called via `gROOT->ProcessLine` to paint these objects
8601/// without having a direct dependency of the graphics or histogramming
8602/// system.
8603
8605{
8606
8607 if (!obj) return;
8610
8611 if (obj->InheritsFrom(TMatrixFBase::Class())) {
8612 // case TMatrixF
8613 TH2F *R__TMatrixFBase = new TH2F((TMatrixFBase &)*obj);
8614 R__TMatrixFBase->SetBit(kCanDelete);
8615 R__TMatrixFBase->Draw(option);
8616
8617 } else if (obj->InheritsFrom(TMatrixDBase::Class())) {
8618 // case TMatrixD
8619 TH2D *R__TMatrixDBase = new TH2D((TMatrixDBase &)*obj);
8620 R__TMatrixDBase->SetBit(kCanDelete);
8621 R__TMatrixDBase->Draw(option);
8622
8623 } else if (obj->InheritsFrom(TVectorF::Class())) {
8624 //case TVectorF
8625 TH1F *R__TVectorF = new TH1F((TVectorF &)*obj);
8626 R__TVectorF->SetBit(kCanDelete);
8627 R__TVectorF->Draw(option);
8628
8629 } else if (obj->InheritsFrom(TVectorD::Class())) {
8630 //case TVectorD
8631 TH1D *R__TVectorD = new TH1D((TVectorD &)*obj);
8632 R__TVectorD->SetBit(kCanDelete);
8633 R__TVectorD->Draw(option);
8634 }
8635
8636 TH1::AddDirectory(status);
8637}
8638
8639////////////////////////////////////////////////////////////////////////////////
8640/// [Draw the statistics box for 1D and profile histograms.](\ref HP07)
8641
8643{
8644 TString tt, tf;
8645 Int_t dofit;
8646 TPaveStats *stats = nullptr;
8647 TIter next(fFunctions);
8648 while (auto obj = next()) {
8649 if (obj->InheritsFrom(TPaveStats::Class())) {
8650 stats = (TPaveStats*)obj;
8651 break;
8652 }
8653 }
8654
8655 if (stats && dostat) {
8656 dofit = stats->GetOptFit();
8657 dostat = stats->GetOptStat();
8658 } else {
8659 dofit = gStyle->GetOptFit();
8660 }
8661 if (!dofit) fit = nullptr;
8662 if (dofit == 1) dofit = 111;
8663 if (dostat == 1) dostat = 1111;
8664 Int_t print_name = dostat%10;
8665 Int_t print_entries = (dostat/10)%10;
8666 Int_t print_mean = (dostat/100)%10;
8667 Int_t print_stddev = (dostat/1000)%10;
8668 Int_t print_under = (dostat/10000)%10;
8669 Int_t print_over = (dostat/100000)%10;
8670 Int_t print_integral= (dostat/1000000)%10;
8671 Int_t print_skew = (dostat/10000000)%10;
8672 Int_t print_kurt = (dostat/100000000)%10;
8676 Int_t print_fval = dofit%10;
8677 Int_t print_ferrors = (dofit/10)%10;
8678 Int_t print_fchi2 = (dofit/100)%10;
8679 Int_t print_fprob = (dofit/1000)%10;
8681 if (fit) {
8682 if (print_fval < 2) nlinesf += fit->GetNumberFreeParameters();
8683 else nlinesf += fit->GetNpar();
8684 }
8686
8687 // Pavetext with statistics
8688 Bool_t done = kFALSE;
8689 if (!dostat && !fit) {
8690 if (stats) { fFunctions->Remove(stats); delete stats;}
8691 return;
8692 }
8694 if (fit) statw = 1.8*gStyle->GetStatW();
8696 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
8697 stath = 0.25*(nlines+nlinesf)*gStyle->GetStatH();
8698 }
8699 if (stats) {
8700 stats->Clear();
8701 done = kTRUE;
8702 } else {
8703 stats = new TPaveStats(
8706 gStyle->GetStatX(),
8707 gStyle->GetStatY(),"brNDC");
8708
8709 stats->SetParent(fH);
8710 stats->SetOptFit(dofit);
8711 stats->SetOptStat(dostat);
8712 stats->SetFillColor(gStyle->GetStatColor());
8713 stats->SetFillStyle(gStyle->GetStatStyle());
8714 stats->SetBorderSize(gStyle->GetStatBorderSize());
8715 stats->SetTextFont(gStyle->GetStatFont());
8716 if (gStyle->GetStatFont()%10 > 2)
8717 stats->SetTextSize(gStyle->GetStatFontSize());
8718 stats->SetFitFormat(gStyle->GetFitFormat());
8719 stats->SetStatFormat(gStyle->GetStatFormat());
8720 stats->SetName("stats");
8721
8722 stats->SetTextColor(gStyle->GetStatTextColor());
8723 stats->SetTextAlign(12);
8724 stats->SetBit(kCanDelete);
8725 stats->SetBit(kMustCleanup);
8726 }
8727 if (print_name) stats->AddText(fH->GetName());
8728 if (print_entries) {
8729 if (fH->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(fH->GetEntries()+0.5));
8730 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(fH->GetEntries()));
8731 stats->AddText(tt.Data());
8732 }
8733 if (print_mean) {
8734 if (print_mean == 1) {
8735 tf.Form("%s = %s%s",gStringMean.Data(),"%",stats->GetStatFormat());
8736 tt.Form(tf.Data(),fH->GetMean(1));
8737 } else {
8738 tf.Form("%s = %s%s #pm %s%s",gStringMean.Data(),"%",stats->GetStatFormat()
8739 ,"%",stats->GetStatFormat());
8740 tt.Form(tf.Data(),fH->GetMean(1),fH->GetMeanError(1));
8741 }
8742 stats->AddText(tt.Data());
8744 if (print_mean == 1) {
8745 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
8746 tt.Form(tf.Data(),fH->GetMean(2));
8747 } else {
8748 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
8749 ,"%",stats->GetStatFormat());
8750 tt.Form(tf.Data(),fH->GetMean(2),fH->GetMeanError(2));
8751 }
8752 stats->AddText(tt.Data());
8753 }
8754 }
8755 if (print_stddev) {
8756 if (print_stddev == 1) {
8757 tf.Form("%s = %s%s",gStringStdDev.Data(),"%",stats->GetStatFormat());
8758 tt.Form(tf.Data(),fH->GetStdDev(1));
8759 } else {
8760 tf.Form("%s = %s%s #pm %s%s",gStringStdDev.Data(),"%",stats->GetStatFormat()
8761 ,"%",stats->GetStatFormat());
8762 tt.Form(tf.Data(),fH->GetStdDev(1),fH->GetStdDevError(1));
8763 }
8764 stats->AddText(tt.Data());
8766 if (print_stddev == 1) {
8767 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
8768 tt.Form(tf.Data(),fH->GetStdDev(2));
8769 } else {
8770 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
8771 ,"%",stats->GetStatFormat());
8772 tt.Form(tf.Data(),fH->GetStdDev(2),fH->GetStdDevError(2));
8773 }
8774 stats->AddText(tt.Data());
8775 }
8776 }
8777 if (print_under) {
8778 tf.Form("%s = %s%s",gStringUnderflow.Data(),"%",stats->GetStatFormat());
8779 tt.Form(tf.Data(),fH->GetBinContent(0));
8780 stats->AddText(tt.Data());
8781 }
8782 if (print_over) {
8783 tf.Form("%s = %s%s",gStringOverflow.Data(),"%",stats->GetStatFormat());
8784 tt.Form(tf.Data(),fH->GetBinContent(fXaxis->GetNbins()+1));
8785 stats->AddText(tt.Data());
8786 }
8787 if (print_integral) {
8788 if (print_integral == 1) {
8789 tf.Form("%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
8790 tt.Form(tf.Data(),fH->Integral());
8791 } else {
8792 tf.Form("%s = %s%s",gStringIntegralBinWidth.Data(),"%",stats->GetStatFormat());
8793 tt.Form(tf.Data(),fH->Integral("width"));
8794 }
8795 stats->AddText(tt.Data());
8796 }
8797 if (print_skew) {
8798 if (print_skew == 1) {
8799 tf.Form("%s = %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat());
8800 tt.Form(tf.Data(),fH->GetSkewness(1));
8801 } else {
8802 tf.Form("%s = %s%s #pm %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat()
8803 ,"%",stats->GetStatFormat());
8804 tt.Form(tf.Data(),fH->GetSkewness(1),fH->GetSkewness(11));
8805 }
8806 stats->AddText(tt.Data());
8807 }
8808 if (print_kurt) {
8809 if (print_kurt == 1) {
8810 tf.Form("%s = %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat());
8811 tt.Form(tf.Data(),fH->GetKurtosis(1));
8812 } else {
8813 tf.Form("%s = %s%s #pm %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat()
8814 ,"%",stats->GetStatFormat());
8815 tt.Form(tf.Data(),fH->GetKurtosis(1),fH->GetKurtosis(11));
8816 }
8817 stats->AddText(tt.Data());
8818 }
8819
8820 // Draw Fit parameters
8821 if (fit) {
8822 Int_t ndf = fit->GetNDF();
8823 tf.Form("#chi^{2} / ndf = %s%s / %d","%",stats->GetFitFormat(),ndf);
8824 tt.Form(tf.Data(),fit->GetChisquare());
8825 if (print_fchi2) stats->AddText(tt.Data());
8826 if (print_fprob) {
8827 tf.Form("Prob = %s%s","%",stats->GetFitFormat());
8828 tt.Form(tf.Data(),TMath::Prob(fit->GetChisquare(),ndf));
8829 stats->AddText(tt.Data());
8830 }
8831 if (print_fval || print_ferrors) {
8833 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
8834 fit->GetParLimits(ipar,parmin,parmax);
8836 if (print_ferrors) {
8837 tf.Form("%-8s = %s%s #pm %s ", fit->GetParName(ipar), "%",stats->GetFitFormat(),
8838 GetBestFormat(fit->GetParameter(ipar), fit->GetParError(ipar), stats->GetFitFormat()));
8839 tt.Form(tf.Data(),fit->GetParameter(ipar)
8840 ,fit->GetParError(ipar));
8841 } else {
8842 tf.Form("%-8s = %s%s ",fit->GetParName(ipar), "%",stats->GetFitFormat());
8843 tt.Form(tf.Data(),fit->GetParameter(ipar));
8844 }
8845 stats->AddText(tt.Data());
8846 }
8847 }
8848 }
8849
8850 if (!done) fFunctions->Add(stats);
8851 stats->Paint(stats->GetOption());
8852}
8853
8854////////////////////////////////////////////////////////////////////////////////
8855/// [Draw the statistics box for 2D histograms.](\ref HP07)
8856
8858{
8859
8860 if (fH->GetDimension() != 2) return;
8861 TH2 *h2 = (TH2*)fH;
8862
8863 TString tt, tf;
8864 Int_t dofit;
8865 TPaveStats *stats = nullptr;
8866 TIter next(fFunctions);
8867 while (auto obj = next()) {
8868 if (obj->InheritsFrom(TPaveStats::Class())) {
8869 stats = (TPaveStats*)obj;
8870 break;
8871 }
8872 }
8873 if (stats && dostat) {
8874 dofit = stats->GetOptFit();
8875 dostat = stats->GetOptStat();
8876 } else {
8877 dofit = gStyle->GetOptFit();
8878 }
8879 if (dostat == 1) dostat = 1111;
8880 Int_t print_name = dostat%10;
8881 Int_t print_entries = (dostat/10)%10;
8882 Int_t print_mean = (dostat/100)%10;
8883 Int_t print_stddev = (dostat/1000)%10;
8884 Int_t print_under = (dostat/10000)%10;
8885 Int_t print_over = (dostat/100000)%10;
8886 Int_t print_integral= (dostat/1000000)%10;
8887 Int_t print_skew = (dostat/10000000)%10;
8888 Int_t print_kurt = (dostat/100000000)%10;
8890 if (print_under || print_over) nlines += 3;
8891
8892 // Pavetext with statistics
8893 if (!gStyle->GetOptFit()) fit = nullptr;
8894 Bool_t done = kFALSE;
8895 if (!dostat && !fit) {
8896 if (stats) { fFunctions->Remove(stats); delete stats;}
8897 return;
8898 }
8900 if (fit) statw = 1.8*gStyle->GetStatW();
8902 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
8903 stath = 0.25*nlines*gStyle->GetStatH();
8904 }
8905 if (fit) stath += gStyle->GetStatH();
8906 if (stats) {
8907 stats->Clear();
8908 done = kTRUE;
8909 } else {
8910 stats = new TPaveStats(
8913 gStyle->GetStatX(),
8914 gStyle->GetStatY(),"brNDC");
8915
8916 stats->SetParent(fH);
8917 stats->SetOptFit(dofit);
8918 stats->SetOptStat(dostat);
8919 stats->SetFillColor(gStyle->GetStatColor());
8920 stats->SetFillStyle(gStyle->GetStatStyle());
8921 stats->SetBorderSize(gStyle->GetStatBorderSize());
8922 stats->SetName("stats");
8923
8924 stats->SetTextColor(gStyle->GetStatTextColor());
8925 stats->SetTextAlign(12);
8926 stats->SetTextFont(gStyle->GetStatFont());
8927 if (gStyle->GetStatFont()%10 > 2)
8928 stats->SetTextSize(gStyle->GetStatFontSize());
8929 stats->SetFitFormat(gStyle->GetFitFormat());
8930 stats->SetStatFormat(gStyle->GetStatFormat());
8931 stats->SetBit(kCanDelete);
8932 stats->SetBit(kMustCleanup);
8933 }
8934 if (print_name) stats->AddText(h2->GetName());
8935 if (print_entries) {
8936 if (h2->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(h2->GetEntries()+0.5));
8937 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(h2->GetEntries()));
8938 stats->AddText(tt.Data());
8939 }
8940 if (print_mean) {
8941 if (print_mean == 1) {
8942 tf.Form("%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
8943 tt.Form(tf.Data(),h2->GetMean(1));
8944 stats->AddText(tt.Data());
8945 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
8946 tt.Form(tf.Data(),h2->GetMean(2));
8947 stats->AddText(tt.Data());
8948 } else {
8949 tf.Form("%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
8950 ,"%",stats->GetStatFormat());
8951 tt.Form(tf.Data(),h2->GetMean(1),h2->GetMeanError(1));
8952 stats->AddText(tt.Data());
8953 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
8954 ,"%",stats->GetStatFormat());
8955 tt.Form(tf.Data(),h2->GetMean(2),h2->GetMeanError(2));
8956 stats->AddText(tt.Data());
8957 }
8958 }
8959 if (print_stddev) {
8960 if (print_stddev == 1) {
8961 tf.Form("%s = %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat());
8962 tt.Form(tf.Data(),h2->GetStdDev(1));
8963 stats->AddText(tt.Data());
8964 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
8965 tt.Form(tf.Data(),h2->GetStdDev(2));
8966 stats->AddText(tt.Data());
8967 } else {
8968 tf.Form("%s = %s%s #pm %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat()
8969 ,"%",stats->GetStatFormat());
8970 tt.Form(tf.Data(),h2->GetStdDev(1),h2->GetStdDevError(1));
8971 stats->AddText(tt.Data());
8972 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
8973 ,"%",stats->GetStatFormat());
8974 tt.Form(tf.Data(),h2->GetStdDev(2),h2->GetStdDevError(2));
8975 stats->AddText(tt.Data());
8976 }
8977 }
8978 if (print_integral) {
8979 tf.Form("%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
8980 tt.Form(tf.Data(),fH->Integral());
8981 stats->AddText(tt.Data());
8982 }
8983 if (print_skew) {
8984 if (print_skew == 1) {
8985 tf.Form("%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
8986 tt.Form(tf.Data(),h2->GetSkewness(1));
8987 stats->AddText(tt.Data());
8988 tf.Form("%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
8989 tt.Form(tf.Data(),h2->GetSkewness(2));
8990 stats->AddText(tt.Data());
8991 } else {
8992 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
8993 ,"%",stats->GetStatFormat());
8994 tt.Form(tf.Data(),h2->GetSkewness(1),h2->GetSkewness(11));
8995 stats->AddText(tt.Data());
8996 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
8997 ,"%",stats->GetStatFormat());
8998 tt.Form(tf.Data(),h2->GetSkewness(2),h2->GetSkewness(12));
8999 stats->AddText(tt.Data());
9000 }
9001 }
9002 if (print_kurt) {
9003 if (print_kurt == 1) {
9004 tf.Form("%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
9005 tt.Form(tf.Data(),h2->GetKurtosis(1));
9006 stats->AddText(tt.Data());
9007 tf.Form("%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
9008 tt.Form(tf.Data(),h2->GetKurtosis(2));
9009 stats->AddText(tt.Data());
9010 } else {
9011 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
9012 ,"%",stats->GetStatFormat());
9013 tt.Form(tf.Data(),h2->GetKurtosis(1),h2->GetKurtosis(11));
9014 stats->AddText(tt.Data());
9015 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
9016 ,"%",stats->GetStatFormat());
9017 tt.Form(tf.Data(),h2->GetKurtosis(2),h2->GetKurtosis(12));
9018 stats->AddText(tt.Data());
9019 }
9020 }
9021 if (print_under || print_over) {
9022 //get 3*3 under/overflows for 2d hist
9023 Double_t unov[9];
9024
9025 Int_t cellsX = h2->GetXaxis()->GetNbins() + 1;
9026 Int_t cellsY = h2->GetYaxis()->GetNbins() + 1;
9027 Int_t firstX = std::max(1, h2->GetXaxis()->GetFirst());
9028 Int_t firstY = std::max(1, h2->GetYaxis()->GetFirst());
9029 Int_t lastX = std::min(h2->GetXaxis()->GetLast(), h2->GetXaxis()->GetNbins());
9030 Int_t lastY = std::min(h2->GetYaxis()->GetLast(), h2->GetYaxis()->GetNbins());
9031
9032 unov[0] = h2->Integral( 0, firstX-1, lastY+1, cellsY );
9033 unov[1] = h2->Integral(firstX , lastX , lastY+1, cellsY );
9034 unov[2] = h2->Integral(lastX+1, cellsX , lastY+1, cellsY );
9035 unov[3] = h2->Integral( 0, firstX-1, firstY , lastY );
9036 unov[4] = h2->Integral(firstX , lastX , firstY , lastY );
9037 unov[5] = h2->Integral(lastX+1, cellsX , firstY , lastY );
9038 unov[6] = h2->Integral( 0, firstX-1, 0, firstY-1);
9039 unov[7] = h2->Integral(firstX, lastX, 0, firstY-1);
9040 unov[8] = h2->Integral(lastX+1, cellsX , 0, firstY-1);
9041
9042 tt.Form("%g|%g|%g\n", unov[0], unov[1], unov[2]);
9043 stats->AddText(tt.Data());
9044 tt.Form("%g|%g|%g\n", unov[3], unov[4], unov[5]);
9045 stats->AddText(tt.Data());
9046 tt.Form("%g|%g|%g\n", unov[6], unov[7], unov[8]);
9047 stats->AddText(tt.Data());
9048 }
9049
9050 // Draw Fit parameters
9051 if (fit) {
9052 Int_t ndf = fit->GetNDF();
9053 tt.Form("#chi^{2} / ndf = %6.4g / %d",fit->GetChisquare(),ndf);
9054 stats->AddText(tt.Data());
9055 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
9056 tt.Form("%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
9057 ,fit->GetParameter(ipar)
9058 ,fit->GetParError(ipar));
9059 stats->AddText(tt.Data());
9060 }
9061 }
9062
9063 if (!done) fFunctions->Add(stats);
9064 stats->Paint(stats->GetOption());
9065}
9066
9067////////////////////////////////////////////////////////////////////////////////
9068/// [Draw the statistics box for 3D histograms.](\ref HP07)
9069
9071{
9072
9073 if (fH->GetDimension() != 3) return;
9074 TH3 *h3 = (TH3*)fH;
9075
9076 TString tt, tf;
9077 Int_t dofit;
9078 TPaveStats *stats = nullptr;
9079 TIter next(fFunctions);
9080 while (auto obj = next()) {
9081 if (obj->InheritsFrom(TPaveStats::Class())) {
9082 stats = (TPaveStats*)obj;
9083 break;
9084 }
9085 }
9086 if (stats && dostat) {
9087 dofit = stats->GetOptFit();
9088 dostat = stats->GetOptStat();
9089 } else {
9090 dofit = gStyle->GetOptFit();
9091 }
9092 if (dostat == 1) dostat = 1111;
9093 Int_t print_name = dostat%10;
9094 Int_t print_entries = (dostat/10)%10;
9095 Int_t print_mean = (dostat/100)%10;
9096 Int_t print_stddev = (dostat/1000)%10;
9097 Int_t print_under = (dostat/10000)%10;
9098 Int_t print_over = (dostat/100000)%10;
9099 Int_t print_integral= (dostat/1000000)%10;
9100 Int_t print_skew = (dostat/10000000)%10;
9101 Int_t print_kurt = (dostat/100000000)%10;
9103 if (print_under || print_over) nlines += 3;
9104
9105 // Pavetext with statistics
9106 if (!gStyle->GetOptFit()) fit = nullptr;
9107 Bool_t done = kFALSE;
9108 if (!dostat && !fit) {
9109 if (stats) { fFunctions->Remove(stats); delete stats;}
9110 return;
9111 }
9113 if (fit) statw = 1.8*gStyle->GetStatW();
9115 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
9116 stath = 0.25*nlines*gStyle->GetStatH();
9117 }
9118 if (fit) stath += gStyle->GetStatH();
9119 if (stats) {
9120 stats->Clear();
9121 done = kTRUE;
9122 } else {
9123 stats = new TPaveStats(
9126 gStyle->GetStatX(),
9127 gStyle->GetStatY(),"brNDC");
9128
9129 stats->SetParent(fH);
9130 stats->SetOptFit(dofit);
9131 stats->SetOptStat(dostat);
9132 stats->SetFillColor(gStyle->GetStatColor());
9133 stats->SetFillStyle(gStyle->GetStatStyle());
9134 stats->SetBorderSize(gStyle->GetStatBorderSize());
9135 stats->SetName("stats");
9136
9137 stats->SetTextColor(gStyle->GetStatTextColor());
9138 stats->SetTextAlign(12);
9139 stats->SetTextFont(gStyle->GetStatFont());
9140 stats->SetFitFormat(gStyle->GetFitFormat());
9141 stats->SetStatFormat(gStyle->GetStatFormat());
9142 stats->SetBit(kCanDelete);
9143 stats->SetBit(kMustCleanup);
9144 }
9145 if (print_name) stats->AddText(h3->GetName());
9146 if (print_entries) {
9147 if (h3->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(h3->GetEntries()+0.5));
9148 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(h3->GetEntries()+0.5));
9149 stats->AddText(tt.Data());
9150 }
9151 if (print_mean) {
9152 if (print_mean == 1) {
9153 tf.Form("%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
9154 tt.Form(tf.Data(),h3->GetMean(1));
9155 stats->AddText(tt.Data());
9156 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
9157 tt.Form(tf.Data(),h3->GetMean(2));
9158 stats->AddText(tt.Data());
9159 tf.Form("%s = %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat());
9160 tt.Form(tf.Data(),h3->GetMean(3));
9161 stats->AddText(tt.Data());
9162 } else {
9163 tf.Form("%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
9164 ,"%",stats->GetStatFormat());
9165 tt.Form(tf.Data(),h3->GetMean(1),h3->GetMeanError(1));
9166 stats->AddText(tt.Data());
9167 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
9168 ,"%",stats->GetStatFormat());
9169 tt.Form(tf.Data(),h3->GetMean(2),h3->GetMeanError(2));
9170 stats->AddText(tt.Data());
9171 tf.Form("%s = %s%s #pm %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat()
9172 ,"%",stats->GetStatFormat());
9173 tt.Form(tf.Data(),h3->GetMean(3),h3->GetMeanError(3));
9174 stats->AddText(tt.Data());
9175 }
9176 }
9177 if (print_stddev) {
9178 if (print_stddev == 1) {
9179 tf.Form("%s = %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat());
9180 tt.Form(tf.Data(),h3->GetStdDev(1));
9181 stats->AddText(tt.Data());
9182 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
9183 tt.Form(tf.Data(),h3->GetStdDev(2));
9184 stats->AddText(tt.Data());
9185 tf.Form("%s = %s%s",gStringStdDevZ.Data(),"%",stats->GetStatFormat());
9186 tt.Form(tf.Data(),h3->GetStdDev(3));
9187 stats->AddText(tt.Data());
9188 } else {
9189 tf.Form("%s = %s%s #pm %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat()
9190 ,"%",stats->GetStatFormat());
9191 tt.Form(tf.Data(),h3->GetStdDev(1),h3->GetStdDevError(1));
9192 stats->AddText(tt.Data());
9193 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
9194 ,"%",stats->GetStatFormat());
9195 tt.Form(tf.Data(),h3->GetStdDev(2),h3->GetStdDevError(2));
9196 stats->AddText(tt.Data());
9197 tf.Form("%s = %s%s #pm %s%s",gStringStdDevZ.Data(),"%",stats->GetStatFormat()
9198 ,"%",stats->GetStatFormat());
9199 tt.Form(tf.Data(),h3->GetStdDev(3),h3->GetStdDevError(3));
9200 stats->AddText(tt.Data());
9201 }
9202 }
9203 if (print_integral) {
9204 tt.Form("%s = %6.4g",gStringIntegral.Data(),h3->Integral());
9205 stats->AddText(tt.Data());
9206 }
9207 if (print_skew) {
9208 if (print_skew == 1) {
9209 tf.Form("%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
9210 tt.Form(tf.Data(),h3->GetSkewness(1));
9211 stats->AddText(tt.Data());
9212 tf.Form("%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
9213 tt.Form(tf.Data(),h3->GetSkewness(2));
9214 stats->AddText(tt.Data());
9215 tf.Form("%s = %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat());
9216 tt.Form(tf.Data(),h3->GetSkewness(3));
9217 stats->AddText(tt.Data());
9218 } else {
9219 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
9220 ,"%",stats->GetStatFormat());
9221 tt.Form(tf.Data(),h3->GetSkewness(1),h3->GetSkewness(11));
9222 stats->AddText(tt.Data());
9223 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
9224 ,"%",stats->GetStatFormat());
9225 tt.Form(tf.Data(),h3->GetSkewness(2),h3->GetSkewness(12));
9226 stats->AddText(tt.Data());
9227 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat()
9228 ,"%",stats->GetStatFormat());
9229 tt.Form(tf.Data(),h3->GetSkewness(3),h3->GetSkewness(13));
9230 stats->AddText(tt.Data());
9231 }
9232 }
9233 if (print_kurt) {
9234 if (print_kurt == 1) {
9235 tf.Form("%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
9236 tt.Form(tf.Data(),h3->GetKurtosis(1));
9237 stats->AddText(tt.Data());
9238 tf.Form("%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
9239 tt.Form(tf.Data(),h3->GetKurtosis(2));
9240 stats->AddText(tt.Data());
9241 tf.Form("%s = %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat());
9242 tt.Form(tf.Data(),h3->GetKurtosis(3));
9243 stats->AddText(tt.Data());
9244 } else {
9245 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
9246 ,"%",stats->GetStatFormat());
9247 tt.Form(tf.Data(),h3->GetKurtosis(1),h3->GetKurtosis(11));
9248 stats->AddText(tt.Data());
9249 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
9250 ,"%",stats->GetStatFormat());
9251 tt.Form(tf.Data(),h3->GetKurtosis(2),h3->GetKurtosis(12));
9252 stats->AddText(tt.Data());
9253 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat()
9254 ,"%",stats->GetStatFormat());
9255 tt.Form(tf.Data(),h3->GetKurtosis(3),h3->GetKurtosis(13));
9256 stats->AddText(tt.Data());
9257 }
9258 }
9259 if (print_under || print_over) {
9260 // no underflow - overflow printing for a 3D histogram
9261 // one would need a 3D table
9262 }
9263
9264 // Draw Fit parameters
9265 if (fit) {
9266 Int_t ndf = fit->GetNDF();
9267 tt.Form("#chi^{2} / ndf = %6.4g / %d",fit->GetChisquare(),ndf);
9268 stats->AddText(tt.Data());
9269 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
9270 tt.Form("%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
9271 ,fit->GetParameter(ipar)
9272 ,fit->GetParError(ipar));
9273 stats->AddText(tt.Data());
9274 }
9275 }
9276
9277 if (!done) fFunctions->Add(stats);
9278 stats->Paint(stats->GetOption());
9279}
9280
9281////////////////////////////////////////////////////////////////////////////////
9282/// [Control function to draw a 2D histogram as a surface plot.](\ref HP18)
9283
9285{
9286
9287 const Double_t ydiff = 1;
9288 const Double_t yligh1 = 10;
9289 const Double_t qa = 0.15;
9290 const Double_t qd = 0.15;
9291 const Double_t qs = 0.8;
9293 Int_t raster = 0;
9294 Int_t irep = 0;
9295
9296 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
9299 Double_t zmin = Hparam.zmin;
9300 Double_t zmax = Hparam.zmax;
9305 Double_t dangle = 10*3.141592/180; //Delta angle for Rapidity option
9306 Double_t deltaz = TMath::Abs(zmin);
9307 if (deltaz == 0) deltaz = 1;
9308 if (zmin >= zmax) {
9309 zmin -= 0.5*deltaz;
9310 zmax += 0.5*deltaz;
9311 }
9312 Double_t z1c = zmin;
9313 Double_t z2c = zmin + (zmax-zmin)*(1+gStyle->GetHistTopMargin());
9314 // Compute the lego limits and instantiate a lego object
9315 fXbuf[0] = -1;
9316 fYbuf[0] = 1;
9317 fXbuf[1] = -1;
9318 fYbuf[1] = 1;
9319 if (Hoption.System >= kPOLAR && (Hoption.Surf == 1 || Hoption.Surf == 13)) raster = 1;
9320 if (Hoption.System == kPOLAR) {
9321 fXbuf[2] = z1c;
9322 fYbuf[2] = z2c;
9323 } else if (Hoption.System == kCYLINDRICAL) {
9324 if (Hoption.Logy) {
9325 if (ylab1 > 0) fXbuf[2] = TMath::Log10(ylab1);
9326 else fXbuf[2] = 0;
9327 if (ylab2 > 0) fYbuf[2] = TMath::Log10(ylab2);
9328 else fYbuf[2] = 0;
9329 } else {
9330 fXbuf[2] = ylab1;
9331 fYbuf[2] = ylab2;
9332 }
9333 z1c = 0; z2c = 1;
9334 } else if (Hoption.System == kSPHERICAL) {
9335 fXbuf[2] = -1;
9336 fYbuf[2] = 1;
9337 z1c = 0; z2c = 1;
9338 } else if (Hoption.System == kRAPIDITY) {
9339 fXbuf[2] = -1/TMath::Tan(dangle);
9340 fYbuf[2] = 1/TMath::Tan(dangle);
9341 } else {
9342 fXbuf[0] = xlab1;
9343 fYbuf[0] = xlab2;
9344 fXbuf[1] = ylab1;
9345 fYbuf[1] = ylab2;
9346 fXbuf[2] = z1c;
9347 fYbuf[2] = z2c;
9348 }
9349
9350 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data(), Hoption.System);
9351 fLego->SetEdgeAtt(fH->GetLineColor(),fH->GetLineStyle(),fH->GetLineWidth(),0);
9352 fLego->SetFillColor(fH->GetFillColor());
9353
9354 // Initialize the levels on the Z axis
9355 Int_t ndiv = fH->GetContour();
9356 if (ndiv == 0 ) {
9357 ndiv = gStyle->GetNumberContours();
9358 fH->SetContour(ndiv);
9359 }
9360 Int_t ndivz = TMath::Abs(ndiv);
9361 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
9362
9363 if (Hoption.Surf == 13 || Hoption.Surf == 15) fLego->SetMesh(3);
9364 if (Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) fLego->SetMesh(0);
9365
9366 // Close the surface in case of non cartesian coordinates.
9367
9368 if (Hoption.System != kCARTESIAN) {nx++; ny++;}
9369
9370 // Now ready to draw the surface plot
9371
9372 TView *view = gPad ? gPad->GetView() : nullptr;
9373 if (!view) {
9374 Error("PaintSurface", "no TView in current pad");
9375 return;
9376 }
9377
9378 Double_t thedeg = 90 - gPad->GetTheta();
9379 Double_t phideg = -90 - gPad->GetPhi();
9380 Double_t psideg = view->GetPsi();
9381 view->SetView(phideg, thedeg, psideg, irep);
9382
9383 // Set color/style for back box
9384 if (Hoption.Same) {
9385 fLego->SetFillStyle(0);
9386 fLego->SetFillColor(1);
9387 } else {
9388 fLego->SetFillStyle(gPad->GetFrameFillStyle());
9389 fLego->SetFillColor(gPad->GetFrameFillColor());
9390 }
9391 fLego->TAttFill::Modify();
9392
9393 Int_t backcolor = gPad->GetFrameFillColor();
9394 if (Hoption.System != kCARTESIAN) backcolor = 0;
9395 view->PadRange(backcolor);
9396
9397 fLego->SetFillStyle(fH->GetFillStyle());
9398 fLego->SetFillColor(fH->GetFillColor());
9399 fLego->TAttFill::Modify();
9400
9401 // Draw the filled contour on top
9403
9405 if (Hoption.Surf == 13 || Hoption.Surf == 15) {
9407 Hoption.Surf = 23;
9408 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9410 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"BF");
9411 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9412 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9413 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9414 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"BF");
9416 fLego->SetMesh(1);
9417 }
9418
9419 if (raster) fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
9420 else fLego->InitMoveScreen(-1.1,1.1);
9421
9422 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) {
9423 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9426 fLego->BackBox(90);
9427 }
9428 }
9429
9430 // Gouraud Shading surface
9431 if (Hoption.Surf == 14) {
9432 // Set light sources
9433 fLego->LightSource(0, ydiff, 0,0,0,irep);
9434 fLego->LightSource(1, yligh1 ,1,1,1,irep);
9435 fLego->SurfaceProperty(qa, qd, qs, 1, irep);
9436 fmin = ydiff*qa;
9437 fmax = fmin + (yligh1+0.1)*(qd+qs);
9438 Int_t nbcol = 28;
9439 icol1 = 201;
9440 Double_t dcol = 0.5/Double_t(nbcol);
9441 TColor *colref = gROOT->GetColor(fH->GetFillColor());
9442 if (!colref) return;
9444 colref->GetRGB(r,g,b);
9446 TColor *acol;
9447 for (Int_t col=0;col<nbcol;col++) {
9448 acol = gROOT->GetColor(col+icol1);
9449 TColor::HLStoRGB(hue,.4+col*dcol,satur,r,g,b);
9450 if (acol) acol->SetRGB(r,g,b);
9451 }
9452 fLego->Spectrum(nbcol, fmin, fmax, icol1, 1, irep);
9453 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::GouraudFunction);
9455 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"BF");
9456 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9457 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9458 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9459 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"BF");
9460 } else if (Hoption.Surf == 15) {
9461 // The surface is not drawn in this case.
9462 } else {
9463 // Draw the surface
9464 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 16 || Hoption.Surf == 17) {
9466 } else {
9467 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9468 }
9469 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9470 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceRaster1);
9471 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode2);
9472 if (Hoption.System == kPOLAR) {
9473 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfacePolar(1,nx,ny,"FB");
9474 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfacePolar(1,nx,ny,"BF");
9475 } else if (Hoption.System == kCYLINDRICAL) {
9476 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceCylindrical(1,nx,ny,"FB");
9477 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9478 } else if (Hoption.System == kSPHERICAL) {
9479 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceSpherical(0,1,nx,ny,"FB");
9480 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9481 } else if (Hoption.System == kRAPIDITY) {
9482 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceSpherical(1,1,nx,ny,"FB");
9483 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9484 } else {
9485 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove1);
9486 if (Hoption.Surf == 16) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove3);
9487 if (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16) fLego->SurfaceCartesian(90,nx,ny,"FB");
9488 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCartesian(90,nx,ny,"BF");
9489 }
9490 }
9491
9492 // Paint the line contour on top for option SURF7
9493 if (Hoption.Surf == 17) {
9494 fLego->InitMoveScreen(-1.1,1.1);
9495 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9496 Hoption.Surf = 23;
9497 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9499 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"FB");
9500 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"FB");
9501 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"FB");
9502 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"FB");
9503 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"FB");
9504 }
9505
9506 if ((!Hoption.Same) &&
9507 (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16)) {
9510 fLego->BackBox(90);
9511 }
9512 }
9513 if (Hoption.System == kCARTESIAN) {
9514 fLego->InitMoveScreen(-1.1,1.1);
9516 if (Hoption.FrontBox) fLego->FrontBox(90);
9517 }
9518 if (!Hoption.Axis && !Hoption.Same) {
9519 TGaxis axis;
9520 PaintLegoAxis(&axis, 90);
9521 }
9522
9524
9525 fLego.reset();
9526}
9527
9528////////////////////////////////////////////////////////////////////////////////
9529/// Control function to draw a table using Delaunay triangles.
9530
9532{
9533
9534 TGraphDelaunay2D *dt = nullptr;
9535 TGraphDelaunay *dtOld = nullptr;
9536
9537 // Check if fH contains a TGraphDelaunay2D
9539 dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
9540 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
9541 if (!dt && !dtOld) return;
9542
9543 // If needed, create a TGraph2DPainter
9544 if (!fGraph2DPainter)
9545 fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
9546
9547 // Define the 3D view
9548 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
9549 if (Hoption.Same) {
9550 TView *viewsame = gPad ? gPad->GetView() : nullptr;
9551 if (!viewsame) {
9552 Error("PaintTriangles", "no TView in current pad, do not use option SAME");
9553 return;
9554 }
9555 Double_t *rmin = viewsame->GetRmin();
9556 Double_t *rmax = viewsame->GetRmax();
9557 if (!rmin || !rmax) return;
9558 fXbuf[0] = rmin[0];
9559 fYbuf[0] = rmax[0];
9560 fXbuf[1] = rmin[1];
9561 fYbuf[1] = rmax[1];
9562 fXbuf[2] = rmin[2];
9563 fYbuf[2] = rmax[2];
9564 fH->SetMaximum(rmax[2]);
9565 fH->SetMinimum(rmin[2]);
9566 fH->GetXaxis()->SetRangeUser(rmin[0],rmax[0]);
9567 fH->GetYaxis()->SetRangeUser(rmin[1],rmax[1]);
9568 } else {
9569 fXbuf[0] = Hparam.xmin;
9570 fYbuf[0] = Hparam.xmax;
9571 fXbuf[1] = Hparam.ymin;
9572 fYbuf[1] = Hparam.ymax;
9573 fXbuf[2] = Hparam.zmin;
9574 fYbuf[2] = Hparam.zmax;
9575 }
9576
9577 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
9578 TView *view = gPad ? gPad->GetView() : nullptr;
9579 if (!view) {
9580 Error("PaintTriangles", "no TView in current pad");
9581 return;
9582 }
9583 Double_t thedeg = 90 - gPad->GetTheta();
9584 Double_t phideg = -90 - gPad->GetPhi();
9585 Double_t psideg = view->GetPsi();
9586 Int_t irep;
9587 view->SetView(phideg, thedeg, psideg, irep);
9588
9589 // Set color/style for back box
9590 fLego->SetFillStyle(gPad->GetFrameFillStyle());
9591 fLego->SetFillColor(gPad->GetFrameFillColor());
9592 fLego->TAttFill::Modify();
9593 Int_t backcolor = gPad->GetFrameFillColor();
9594 if (Hoption.System != kCARTESIAN) backcolor = 0;
9595 view->PadRange(backcolor);
9596 fLego->SetFillStyle(fH->GetFillStyle());
9597 fLego->SetFillColor(fH->GetFillColor());
9598 fLego->TAttFill::Modify();
9599
9600 // Paint the Back Box if needed
9601 if (Hoption.BackBox && !Hoption.Same) {
9602 fLego->InitMoveScreen(-1.1,1.1);
9603 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9605 fLego->BackBox(90);
9606 }
9607
9608 // Paint the triangles
9609 fGraph2DPainter->Paint(option);
9610
9611 // Paint the Front Box if needed
9612 if (Hoption.FrontBox) {
9613 fLego->InitMoveScreen(-1.1,1.1);
9615 fLego->FrontBox(90);
9616 }
9617
9618 // Paint the Axis if needed
9619 if (!Hoption.Axis && !Hoption.Same) {
9620 TGaxis axis;
9621 PaintLegoAxis(&axis, 90);
9622 }
9623
9625
9626 fLego.reset();
9627}
9628
9629////////////////////////////////////////////////////////////////////////////////
9630/// Define the color levels used to paint legos, surfaces etc..
9631
9633{
9634
9635 Int_t i, irep;
9636
9637 // Initialize the color levels
9638 if (ndivz >= 100) {
9639 Warning("PaintSurface", "too many color levels, %d >= 100, reset to 99", ndivz);
9640 ndivz = 99;
9641 }
9642 std::vector<Double_t> funlevel(ndivz+1);
9643 std::vector<Int_t> colorlevel(ndivz+1);
9645 Int_t ncolors = gStyle->GetNumberOfColors();
9646 for (i = 0; i < ndivz; ++i) {
9648 theColor = Int_t((i+0.99)*Float_t(ncolors)/Float_t(ndivz));
9650 }
9651 colorlevel[ndivz] = gStyle->GetColorPalette(ncolors-1);
9652 fLego->ColorFunction(ndivz, funlevel.data(), colorlevel.data(), irep);
9653}
9654
9655////////////////////////////////////////////////////////////////////////////////
9656/// [Control function to draw 2D/3D histograms (tables).](\ref HP01c)
9657
9659{
9660
9661 // Fill Hparam structure with histo parameters
9662 if (!TableInit()) return;
9663
9664 // Draw histogram frame
9665 PaintFrame();
9666
9667 // If palette option not specified, delete a possible existing palette
9668 if (!Hoption.Zscale) {
9669 TObject *palette = fFunctions->FindObject("palette");
9670 if (palette) { fFunctions->Remove(palette); delete palette;}
9671 }
9672
9673 // Do not draw the histogram. Only the attached functions will be drawn.
9674 if (Hoption.Func == 2) {
9675 if (Hoption.Zscale) {
9676 Int_t ndiv = fH->GetContour();
9677 if (ndiv == 0 ) {
9678 ndiv = gStyle->GetNumberContours();
9679 fH->SetContour(ndiv);
9680 }
9681 PaintPalette();
9682 }
9683
9684 // Draw the histogram according to the option
9685 } else {
9686 if (fH->InheritsFrom(TH2Poly::Class()) && Hoption.Axis<=0) {
9687 if (Hoption.Fill) PaintTH2PolyBins("f");
9691 if (Hoption.Line) PaintTH2PolyBins("l");
9692 if (Hoption.Mark) PaintTH2PolyBins("P");
9693 } else if (Hoption.Axis<=0) {
9697 if (Hoption.Color) {
9700 }
9703 if (Hoption.Error >= 100) Paint2DErrors(option);
9705 }
9709 }
9710
9711 // Draw histogram title
9712 PaintTitle();
9713
9714 // Draw the axes
9715 if (!Hoption.Lego && !Hoption.Surf &&
9716 !Hoption.Tri && !(Hoption.Error >= 100)) PaintAxis(kFALSE);
9717
9718 TF1 *fit = nullptr;
9719 TIter next(fFunctions);
9720 while (auto obj = next()) {
9721 if (obj->InheritsFrom(TF1::Class())) {
9722 fit = (TF1*)obj;
9723 break;
9724 }
9725 }
9726 if ((Hoption.Same%10) != 1) {
9727 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
9728 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
9729 //ALWAYS executed on non-iOS platform.
9730 //On iOS, depends on mode.
9732 }
9733 }
9734 }
9735}
9736
9737////////////////////////////////////////////////////////////////////////////////
9738/// Control function to draw a TH2Poly bins' contours.
9739///
9740/// - option = "F" draw the bins as filled areas.
9741/// - option = "L" draw the bins as line.
9742/// - option = "P" draw the bins as markers.
9743
9745{
9746
9747 //Do not highlight the histogram, if its part was picked.
9748 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH) return;
9749
9750 TString opt = option;
9751 opt.ToLower();
9752 Bool_t line = kFALSE;
9753 Bool_t fill = kFALSE;
9754 Bool_t mark = kFALSE;
9755 if (opt.Contains("l")) line = kTRUE;
9756 if (opt.Contains("f")) fill = kTRUE;
9757 if (opt.Contains("p")) mark = kTRUE;
9758
9759 TH2PolyBin *b;
9760 Double_t z;
9761
9762 TIter next(((TH2Poly*)fH)->GetBins());
9763 TObject *obj, *poly;
9764
9765 while ((obj=next())) {
9766 b = (TH2PolyBin*)obj;
9767 z = b->GetContent();
9768 if (z==0 && Hoption.Zero) continue; // Do not draw empty bins in case of option "COL0 L"
9769 poly = b->GetPolygon();
9770
9771 // Paint the TGraph bins.
9772 if (poly->IsA() == TGraph::Class()) {
9773 TGraph *g = (TGraph*)poly;
9774 g->TAttLine::Modify();
9775 g->TAttMarker::Modify();
9776 g->TAttFill::Modify();
9777 if (line) {
9778 Int_t fs = g->GetFillStyle();
9780 g->SetFillStyle(0);
9782 g->Paint("F");
9784 g->SetFillStyle(fs);
9785 }
9786 if (fill) g->Paint("F");
9787 if (mark) g->Paint("P");
9788 }
9789
9790 // Paint the TMultiGraph bins.
9791 if (poly->IsA() == TMultiGraph::Class()) {
9793 TList *gl = mg->GetListOfGraphs();
9794 if (!gl) return;
9795 TGraph *g;
9796 TIter nextg(gl);
9797 while ((g = (TGraph*) nextg())) {
9798 g->TAttLine::Modify();
9799 g->TAttMarker::Modify();
9800 g->TAttFill::Modify();
9801 if (line) {
9802 Int_t fs = g->GetFillStyle();
9804 g->SetFillStyle(0);
9806 g->Paint("F");
9808 g->SetFillStyle(fs);
9809 }
9810 if (fill) g->Paint("F");
9811 if (mark) g->Paint("P");
9812 }
9813 }
9814 }
9815}
9816
9817////////////////////////////////////////////////////////////////////////////////
9818/// [Control function to draw a TH2Poly as a color plot.](\ref HP20a)
9819
9821{
9822
9823 //Do not highlight the histogram, if its part was picked.
9824 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
9825 return;
9826
9827 Int_t ncolors, color, theColor;
9828 Double_t z, zc;
9829 Double_t zmin = fH->GetMinimum();
9830 Double_t zmax = fH->GetMaximum();
9831 if (Hoption.Logz) {
9832 if (zmax > 0) {
9833 if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
9834 zmin = TMath::Log10(zmin);
9835 zmax = TMath::Log10(zmax);
9836 } else {
9837 return;
9838 }
9839 }
9840 Double_t dz = zmax - zmin;
9841
9842 // Initialize the levels on the Z axis
9843 ncolors = gStyle->GetNumberOfColors();
9844 Int_t ndiv = fH->GetContour();
9845 if (ndiv == 0 ) {
9846 ndiv = gStyle->GetNumberContours();
9847 fH->SetContour(ndiv);
9848 }
9849 Int_t ndivz = TMath::Abs(ndiv);
9850 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
9852
9853 TIter next(((TH2Poly*)fH)->GetBins());
9854
9855 while (auto obj = next()) {
9856 TH2PolyBin *b = (TH2PolyBin*)obj;
9857 TObject *poly = b->GetPolygon();
9858
9859 z = b->GetContent();
9860 if (z==0 && Hoption.Zero) continue;
9861 if (Hoption.Logz) {
9862 if (z > 0) z = TMath::Log10(z);
9863 else z = zmin;
9864 }
9865 if (z < zmin) continue;
9866
9867 // Define the bin color.
9869 zc = fH->GetContourLevelPad(0);
9870 if (z < zc) continue;
9871 color = -1;
9872 for (Int_t k=0; k<ndiv; k++) {
9873 zc = fH->GetContourLevelPad(k);
9874 if (z < zc) {
9875 continue;
9876 } else {
9877 color++;
9878 }
9879 }
9880 } else {
9881 color = Int_t(0.01+(z-zmin)*scale);
9882 }
9883 theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
9884 if (theColor > ncolors-1) theColor = ncolors-1;
9885
9886 // Paint the TGraph bins.
9887 if (poly->IsA() == TGraph::Class()) {
9888 TGraph *g = (TGraph*)poly;
9889 g->SetFillColor(gStyle->GetColorPalette(theColor));
9890 g->TAttFill::Modify();
9891 g->Paint("F");
9892 }
9893
9894 // Paint the TMultiGraph bins.
9895 if (poly->IsA() == TMultiGraph::Class()) {
9897 TList *gl = mg->GetListOfGraphs();
9898 if (!gl) return;
9899 TGraph *g;
9900 TIter nextg(gl);
9901 while ((g = (TGraph*) nextg())) {
9902 g->SetFillColor(gStyle->GetColorPalette(theColor));
9903 g->TAttFill::Modify();
9904 g->Paint("F");
9905 }
9906 }
9907 }
9909}
9910
9911////////////////////////////////////////////////////////////////////////////////
9912/// [Control function to draw a TH2Poly as a scatter plot.](\ref HP20a)
9913
9915{
9916
9917 //Do not highlight the histogram, if its part was selected.
9918 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
9919 return;
9920
9921 Int_t k, loop, marker=0;
9922 Double_t z, xk,xstep, yk, ystep, xp, yp;
9923 Double_t scale = 1;
9924 Double_t zmin = fH->GetMinimum();
9925 Double_t zmax = fH->GetMaximum();
9926 if (Hoption.Logz) {
9927 if (zmax > 0) {
9928 if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
9929 zmin = TMath::Log10(zmin);
9930 zmax = TMath::Log10(zmax);
9931 } else {
9932 return;
9933 }
9934 }
9935 Double_t dz = zmax - zmin;
9936 scale = (kNMAX-1)/dz;
9937
9938
9939 // use an independent instance of a random generator
9940 // instead of gRandom to avoid conflicts and
9941 // to get same random numbers when drawing the same histogram
9943
9944 TH2PolyBin *b;
9945
9946 TIter next(((TH2Poly*)fH)->GetBins());
9947 TObject *obj, *poly;
9948
9949 Double_t maxarea = 0, a;
9950 while ((obj=next())) {
9951 b = (TH2PolyBin*)obj;
9952 a = b->GetArea();
9953 if (a>maxarea) maxarea = a;
9954 }
9955
9956 next.Reset();
9957
9958 while ((obj=next())) {
9959 b = (TH2PolyBin*)obj;
9960 poly = b->GetPolygon();
9961 z = b->GetContent();
9962 if (z < zmin) z = zmin;
9963 if (z > zmax) z = zmax;
9964 if (Hoption.Logz) {
9965 if (z > 0) z = TMath::Log10(z) - zmin;
9966 } else {
9967 z -= zmin;
9968 }
9969 k = Int_t((z*scale)*(b->GetArea()/maxarea));
9970 xk = b->GetXMin();
9971 yk = b->GetYMin();
9972 xstep = b->GetXMax()-xk;
9973 ystep = b->GetYMax()-yk;
9974
9975 // Paint the TGraph bins.
9976 if (poly->IsA() == TGraph::Class()) {
9977 TGraph *g = (TGraph*)poly;
9978 if (k <= 0 || z <= 0) continue;
9979 loop = 0;
9980 while (loop<k) {
9981 if (k+marker >= kNMAX) {
9982 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
9983 marker=0;
9984 }
9985 xp = (random.Rndm()*xstep) + xk;
9986 yp = (random.Rndm()*ystep) + yk;
9987 if (g->IsInside(xp,yp)) {
9988 fXbuf[marker] = xp;
9989 fYbuf[marker] = yp;
9990 marker++;
9991 loop++;
9992 }
9993 }
9994 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
9995 }
9996
9997 // Paint the TMultiGraph bins.
9998 if (poly->IsA() == TMultiGraph::Class()) {
10000 TList *gl = mg->GetListOfGraphs();
10001 if (!gl) return;
10002 if (k <= 0 || z <= 0) continue;
10003 loop = 0;
10004 while (loop<k) {
10005 if (k+marker >= kNMAX) {
10006 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10007 marker=0;
10008 }
10009 xp = (random.Rndm()*xstep) + xk;
10010 yp = (random.Rndm()*ystep) + yk;
10011 if (mg->IsInside(xp,yp)) {
10012 fXbuf[marker] = xp;
10013 fYbuf[marker] = yp;
10014 marker++;
10015 loop++;
10016 }
10017 }
10018 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10019 }
10020 }
10021 PaintTH2PolyBins("l");
10022}
10023
10024////////////////////////////////////////////////////////////////////////////////
10025/// [Control function to draw a TH2Poly as a text plot.](\ref HP20a)
10026
10028{
10029
10030 TLatex text;
10031 text.SetTextFont(gStyle->GetTextFont());
10032 text.SetTextColor(fH->GetMarkerColor());
10033 text.SetTextSize(0.02*fH->GetMarkerSize());
10034
10035 Double_t x, y, z, e, angle = 0;
10036 TString tt, tf;
10037 tf.Form("%s%s","%",gStyle->GetPaintTextFormat());
10038 if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
10039 Int_t opt = (Int_t)Hoption.Text/1000;
10040
10041 text.SetTextAlign(22);
10042 if (Hoption.Text == 1) angle = 0;
10043 text.SetTextAngle(angle);
10044 text.TAttText::Modify();
10045
10046 TH2PolyBin *b;
10047
10048 TIter next(((TH2Poly*)fH)->GetBins());
10049 TObject *obj, *p;
10050
10051 while ((obj=next())) {
10052 b = (TH2PolyBin*)obj;
10053 p = b->GetPolygon();
10054 x = (b->GetXMin()+b->GetXMax())/2;
10055 if (Hoption.Logx) {
10056 if (x > 0) x = TMath::Log10(x);
10057 else continue;
10058 }
10059 y = (b->GetYMin()+b->GetYMax())/2;
10060 if (Hoption.Logy) {
10061 if (y > 0) y = TMath::Log10(y);
10062 else continue;
10063 }
10064 z = b->GetContent();
10065 if (z < fH->GetMinimum() || (z == 0 && !Hoption.MinimumZero)) continue;
10066 if (opt==2) {
10067 e = fH->GetBinError(b->GetBinNumber());
10068 tf.Form("#splitline{%s%s}{#pm %s%s}",
10070 "%",gStyle->GetPaintTextFormat());
10071 tt.Form(tf.Data(),z,e);
10072 } else {
10073 tt.Form(tf.Data(),z);
10074 }
10075 if (opt==3) text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),p->GetName());
10076 else text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),tt.Data());
10077 }
10078
10079 PaintTH2PolyBins("l");
10080}
10081
10082////////////////////////////////////////////////////////////////////////////////
10083/// [Control function to draw a 1D/2D histograms with the bin values.](\ref HP15)
10084
10086{
10087
10088 TLatex text;
10089 text.SetTextFont(((int)gStyle->GetTextFont()/10)*10+2); // font precision must be 2
10090 text.SetTextColor(fH->GetMarkerColor());
10091 text.SetTextSize(0.02*fH->GetMarkerSize());
10092
10093 Double_t x, y, z, e, angle = 0;
10094 TString tt, tf;
10095 tf.Form("%s%s","%",gStyle->GetPaintTextFormat());
10096 if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
10097
10098 // 1D histograms
10099 if (fH->GetDimension() == 1) {
10101 Double_t yt;
10102 TProfile *hp = (TProfile*)fH;
10103 if (Hoption.Text>2000 && fH->InheritsFrom(TProfile::Class())) {
10104 Hoption.Text = Hoption.Text-2000;
10105 getentries = kTRUE;
10106 }
10107 if (Hoption.Text == 1) angle = 90;
10108 text.SetTextAlign(11);
10109 if (angle == 90) text.SetTextAlign(12);
10110 if (angle == 0) text.SetTextAlign(21);
10111 text.TAttText::Modify();
10112 Double_t dt = 0.02*(gPad->GetY2()-gPad->GetY1());
10113 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10114 if (Hoption.Bar) {
10115 x = fH->GetXaxis()->GetBinLowEdge(i)+
10116 fH->GetXaxis()->GetBinWidth(i)*
10117 (fH->GetBarOffset()+0.5*fH->GetBarWidth());
10118 } else {
10119 x = fH->GetXaxis()->GetBinCenter(i);
10120 }
10121 y = fH->GetBinContent(i);
10122 yt = y;
10123 if (Hoption.MinimumZero && y<0) y = 0;
10124 if (getentries) yt = hp->GetBinEntries(i);
10125 if (yt == 0.) continue;
10126 tt.Form(tf.Data(),yt);
10127 if (Hoption.Logx) {
10128 if (x > 0) x = TMath::Log10(x);
10129 else continue;
10130 }
10131 if (Hoption.Logy) {
10132 if (y > 0) y = TMath::Log10(y);
10133 else continue;
10134 }
10135 if (y >= gPad->GetY2()) continue;
10136 if (y <= gPad->GetY1()) continue;
10137 text.PaintLatex(x,y+0.2*dt,angle,0.02*fH->GetMarkerSize(),tt.Data());
10138 }
10139
10140 // 2D histograms
10141 } else {
10142 Double_t zmin = Hparam.zmin;
10143 if (Hoption.Logz) zmin = TMath::Power(10,Hparam.zmin);
10144
10145 text.SetTextAlign(22);
10146 if (Hoption.Text == 1) angle = 0;
10147 text.SetTextAngle(angle);
10148 text.TAttText::Modify();
10149 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
10150 y = fYaxis->GetBinCenter(j);
10151 if (Hoption.Logy) {
10152 if (y > 0) y = TMath::Log10(y);
10153 else continue;
10154 }
10155 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10156 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
10157 x = fXaxis->GetBinCenter(i);
10158 if (Hoption.Logx) {
10159 if (x > 0) x = TMath::Log10(x);
10160 else continue;
10161 }
10162 if (!IsInside(x,y)) continue;
10163 z = fH->GetBinContent(bin);
10164 if (z < zmin || (z == 0 && !Hoption.MinimumZero)) continue;
10165 if (Hoption.Text>2000) {
10166 e = fH->GetBinError(bin);
10167 tf.Form("#splitline{%s%s}{#pm %s%s}",
10169 "%",gStyle->GetPaintTextFormat());
10170 tt.Form(tf.Data(),z,e);
10171 } else {
10172 tt.Form(tf.Data(),z);
10173 }
10174 text.PaintLatex(x,y+fH->GetBarOffset()*fYaxis->GetBinWidth(j),
10175 angle,0.02*fH->GetMarkerSize(),tt.Data());
10176 }
10177 }
10178 }
10179}
10180
10181////////////////////////////////////////////////////////////////////////////////
10182/// [Control function to draw a 3D implicit functions.](\ref HP27)
10183
10185{
10186
10187 Int_t irep;
10188
10189 TAxis *xaxis = fH->GetXaxis();
10190 TAxis *yaxis = fH->GetYaxis();
10191 TAxis *zaxis = fH->GetZaxis();
10192
10193 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
10194 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
10195 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
10196 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
10197 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
10198 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
10199
10200 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
10201
10202 TView *view = gPad ? gPad->GetView() : nullptr;
10203 if (!view) {
10204 Error("PaintTF3", "no TView in current pad");
10205 return;
10206 }
10207 Double_t thedeg = 90 - gPad->GetTheta();
10208 Double_t phideg = -90 - gPad->GetPhi();
10209 Double_t psideg = view->GetPsi();
10210 view->SetView(phideg, thedeg, psideg, irep);
10211
10212 fLego->InitMoveScreen(-1.1,1.1);
10213
10214 if (Hoption.BackBox) {
10215 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
10217 fLego->BackBox(90);
10218 }
10219
10221
10222 fLego->ImplicitFunction(fCurrentF3, fXbuf.data(), fYbuf.data(), fH->GetNbinsX(),
10223 fH->GetNbinsY(),
10224 fH->GetNbinsZ(), "BF");
10225
10226 if (Hoption.FrontBox) {
10227 fLego->InitMoveScreen(-1.1,1.1);
10229 fLego->FrontBox(90);
10230 }
10231 if (!Hoption.Axis && !Hoption.Same) {
10232 TGaxis axis;
10233 PaintLegoAxis(&axis, 90);
10234 }
10235
10236 PaintTitle();
10237
10238 fLego.reset();
10239}
10240
10241/////////////////////////////////////////////////////////////new TGaxis///////////////////
10242/// Draw the histogram title
10243///
10244/// The title is drawn according to the title alignment returned by
10245/// `GetTitleAlign()`. It is a 2 digits integer): hv
10246///
10247/// where `h` is the horizontal alignment and `v` is the
10248/// vertical alignment.
10249///
10250/// - `h` can get the values 1 2 3 for left, center, and right
10251/// - `v` can get the values 1 2 3 for bottom, middle and top
10252///
10253/// for instance the default alignment is: 13 (left top)
10254
10256{
10257 // probably best place for calls PaintHighlightBin
10258 // calls after paint histo (1D or 2D) and before paint title and stats
10259 if (!gPad->GetView()) PaintHighlightBin();
10260
10261 if (Hoption.Same) return;
10262 if (fH->TestBit(TH1::kNoTitle)) return;
10263 Int_t nt = strlen(fH->GetTitle());
10264 TPaveText *title = nullptr;
10265 TObject *obj;
10266 TIter next(gPad->GetListOfPrimitives());
10267 while ((obj = next())) {
10268 if (!obj->InheritsFrom(TPaveText::Class())) continue;
10269 title = (TPaveText*)obj;
10270 if (strcmp(title->GetName(),"title")) {title = nullptr; continue;}
10271 break;
10272 }
10273 if (nt == 0 || gStyle->GetOptTitle() <= 0) {
10274 if (title) delete title;
10275 return;
10276 }
10279
10280 if (ht <= 0) {
10281 if (gStyle->GetTitleFont("")%10 == 3) {
10282 Double_t hw = TMath::Max((Double_t)gPad->XtoPixel(gPad->GetX2()),
10283 (Double_t)gPad->YtoPixel(gPad->GetY1()));
10284 ht = 1.1*(gStyle->GetTitleSize("")/hw);
10285 } else {
10286 ht = 1.1*gStyle->GetTitleFontSize();
10287 }
10288 }
10289 if (ht <= 0) ht = 0.05;
10290 if (wt <= 0) {
10291 TLatex l;
10292 l.SetTextSize(ht);
10293 l.SetTitle(fH->GetTitle());
10294 // adjustment in case the title has several lines (#splitline)
10295 ht = TMath::Max(ht, 1.2*l.GetYsize()/(gPad->GetY2() - gPad->GetY1()));
10296 Double_t wndc = l.GetXsize()/(gPad->GetX2() - gPad->GetX1());
10297 wt = TMath::Min(0.7, 0.02+wndc);
10298 }
10299 if (title) {
10300 TText *t0 = (TText*)title->GetLine(0);
10301 if (t0) {
10302 if (!strcmp(t0->GetTitle(),fH->GetTitle())) return;
10303 t0->SetTitle(fH->GetTitle());
10304 if (wt > 0) title->SetX2NDC(title->GetX1NDC()+wt);
10305 }
10306 return;
10307 }
10308
10310 if (talh < 1) talh = 1; else if (talh > 3) talh = 3;
10312 if (talv < 1) talv = 1; else if (talv > 3) talv = 3;
10314 xpos = gStyle->GetTitleX();
10315 ypos = gStyle->GetTitleY();
10316 if (talh == 2) xpos = xpos-wt/2.;
10317 if (talh == 3) xpos = xpos-wt;
10318 if (talv == 2) ypos = ypos+ht/2.;
10319 if (talv == 1) ypos = ypos+ht;
10320
10321 TPaveText *ptitle = new TPaveText(xpos, ypos-ht, xpos+wt, ypos,"blNDC");
10322
10323 // box with the histogram title
10324 ptitle->SetFillColor(gStyle->GetTitleFillColor());
10325 ptitle->SetFillStyle(gStyle->GetTitleStyle());
10326 ptitle->SetName("title");
10327 ptitle->SetBorderSize(gStyle->GetTitleBorderSize());
10328 ptitle->SetTextColor(gStyle->GetTitleTextColor());
10329 ptitle->SetTextFont(gStyle->GetTitleFont(""));
10330 if (gStyle->GetTitleFont("")%10 > 2)
10331 ptitle->SetTextSize(gStyle->GetTitleFontSize());
10332 ptitle->AddText(fH->GetTitle());
10333 ptitle->SetBit(kCanDelete);
10334 ptitle->Draw();
10335 ptitle->Paint("blNDC");
10336
10337 if(!gPad->IsEditable()) delete ptitle;
10338}
10339
10340////////////////////////////////////////////////////////////////////////////////
10341/// Process message `mess`.
10342
10343void THistPainter::ProcessMessage(const char *mess, const TObject *obj)
10344{
10345 if (!strcmp(mess,"SetF3")) {
10346 fCurrentF3 = (TF3 *)obj;
10347 }
10348}
10349
10350////////////////////////////////////////////////////////////////////////////////
10351/// Static function.
10352///
10353/// Convert Right Ascension, Declination to X,Y using an AITOFF projection.
10354/// This procedure can be used to create an all-sky map in Galactic
10355/// coordinates with an equal-area Aitoff projection. Output map
10356/// coordinates are zero longitude centered.
10357/// Also called Hammer-Aitoff projection (first presented by Ernst von Hammer in 1892)
10358///
10359/// source: GMT
10360///
10361/// code from Ernst-Jan Buis
10362
10364{
10365
10366 Double_t x, y;
10367
10369 Double_t delta = b*TMath::DegToRad();
10370 Double_t r2 = TMath::Sqrt(2.);
10371 Double_t f = 2*r2/TMath::Pi();
10372 Double_t cdec = TMath::Cos(delta);
10375 y = TMath::Sin(delta)*r2/denom;
10376 x *= TMath::RadToDeg()/f;
10377 y *= TMath::RadToDeg()/f;
10378 // x *= -1.; // for a skymap swap left<->right
10379 Al = x;
10380 Ab = y;
10381
10382 return 0;
10383}
10384
10385////////////////////////////////////////////////////////////////////////////////
10386/// Static function
10387///
10388/// Probably the most famous of the various map projections, the Mercator projection
10389/// takes its name from Mercator who presented it in 1569. It is a cylindrical, conformal projection
10390/// with no distortion along the equator.
10391/// The Mercator projection has been used extensively for world maps in which the distortion towards
10392/// the polar regions grows rather large, thus incorrectly giving the impression that, for example,
10393/// Greenland is larger than South America. In reality, the latter is about eight times the size of
10394/// Greenland. Also, the Former Soviet Union looks much bigger than Africa or South America. One may wonder
10395/// whether this illusion has had any influence on U.S. foreign policy.' (Source: GMT)
10396/// code from Ernst-Jan Buis
10397
10399{
10400
10401 Al = l;
10403 Ab = TMath::Log(aid);
10404 return 0;
10405}
10406
10407////////////////////////////////////////////////////////////////////////////////
10408/// Static function code for sinusoidal projection
10409/// from Ernst-Jan Buis
10410/// Source https://en.wikipedia.org/wiki/Sinusoidal_projection
10411
10413{
10414
10415 Al = l*cos(b*TMath::DegToRad());
10416 Ab = b;
10417 return 0;
10418}
10419
10420////////////////////////////////////////////////////////////////////////////////
10421/// Static function code for parabolic projection
10422/// from Ernst-Jan Buis
10423
10425{
10426
10427 Al = l*(2.*TMath::Cos(2*b*TMath::DegToRad()/3) - 1);
10428 Ab = 180*TMath::Sin(b*TMath::DegToRad()/3);
10429 return 0;
10430}
10431
10432////////////////////////////////////////////////////////////////////////////////
10433/// Static function.
10434///
10435/// Convert Right Ascension, Declination to X,Y using an MOLLWEIDE projection.
10436/// This procedure can be used to create an all-sky map in Galactic
10437/// coordinates with an equal-area Mollweide projection. Output map
10438/// coordinates are zero longitude centered.
10439/// It is also known as the Babinet projection, homalographic projection, homolographic projection, and elliptical projection.
10440/// Source: https://en.wikipedia.org/wiki/Mollweide_projection
10441///
10442/// code from Marco Meyer-Conde
10443
10445{
10446
10447 Double_t theta0 = b * TMath::DegToRad(), theta = theta0;
10448
10449 for (int i = 0; i < 100; i++) {
10450 Double_t num = 2 * theta + TMath::Sin(2 * theta) - TMath::Pi() * TMath::Sin(theta0);
10451 Double_t den = 4 * TMath::Power(TMath::Cos(theta), 2);
10452
10453 if (den < 1e-20) {
10454 theta = theta0;
10455 break;
10456 }
10457
10458 theta -= num / den;
10459
10460 if (TMath::Abs(num / den) < 1e-4) break;
10461 }
10462
10463 Al = l * TMath::Cos(theta);
10464 Ab = 90 * TMath::Sin(theta);
10465
10466 return 0;
10467}
10468
10469////////////////////////////////////////////////////////////////////////////////
10470/// Recompute the histogram range following graphics operations.
10471
10473{
10474
10475 if (Hoption.Same) return;
10476
10477 // Compute x,y range
10479 xmax = Hparam.xmax,
10480 ymin = Hparam.ymin,
10481 ymax = Hparam.ymax,
10482 xscale = 1;
10483
10484 std::function<Int_t(Double_t,Double_t,Double_t&,Double_t&)> func;
10485
10486 if (Hoption.Proj == 1) {
10487 func = ProjectAitoff2xy;
10488 xscale = 0.9999;
10489 } else if (Hoption.Proj == 2) {
10490 if (Hparam.ymin <= -90 || Hparam.ymax >= 90) {
10491 Warning("Mercator Projection", "Latitude out of range %f or %f", Hparam.ymin, Hparam.ymax);
10492 Hoption.Proj = 0;
10493 } else {
10496 }
10497 } else if (Hoption.Proj == 3) {
10498 func = ProjectSinusoidal2xy;
10499 } else if (Hoption.Proj == 4) {
10500 func = ProjectParabolic2xy;
10501 } else if (Hoption.Proj == 5) {
10502 func = ProjectMollweide2xy;
10503 }
10504
10505 if (func) {
10507
10511 func(Hparam.xmax, Hparam.ymin, xmax, ymin);
10512
10513 if (xmin > xmin_aid) xmin = xmin_aid;
10514 if (ymin > ymin_aid) ymin = ymin_aid;
10515 if (xmax < xmax_aid) xmax = xmax_aid;
10516 if (ymax < ymax_aid) ymax = ymax_aid;
10517 if (Hparam.ymin < 0 && Hparam.ymax > 0) {
10518 // there is an 'equator', check its range in the plot..
10519 func(Hparam.xmin*xscale, 0, xmin_aid, ymin_aid);
10520 func(Hparam.xmax*xscale, 0, xmax_aid, ymin_aid);
10521 if (xmin > xmin_aid) xmin = xmin_aid;
10522 if (xmax < xmax_aid) xmax = xmax_aid;
10523 }
10524 if (Hparam.xmin < 0 && Hparam.xmax > 0) {
10525 func(0, Hparam.ymin, xmin_aid, ymin_aid);
10526 func(0, Hparam.ymax, xmax_aid, ymax_aid);
10527 if (ymin > ymin_aid) ymin = ymin_aid;
10528 if (ymax < ymax_aid) ymax = ymax_aid;
10529 }
10530 }
10531
10532 Hparam.xmin = xmin;
10533 Hparam.xmax = xmax;
10534 Hparam.ymin = ymin;
10535 Hparam.ymax = ymax;
10536
10537 Double_t dx = xmax-xmin;
10538 Double_t dy = ymax-ymin;
10539 Double_t dxr = dx/(1 - gPad->GetLeftMargin() - gPad->GetRightMargin());
10540 Double_t dyr = dy/(1 - gPad->GetBottomMargin() - gPad->GetTopMargin());
10541
10542 // Range() could change the size of the pad pixmap and therefore should
10543 // be called before the other paint routines
10544 gPad->Range(xmin - dxr*gPad->GetLeftMargin(),
10545 ymin - dyr*gPad->GetBottomMargin(),
10546 xmax + dxr*gPad->GetRightMargin(),
10547 ymax + dyr*gPad->GetTopMargin());
10548 gPad->RangeAxis(xmin, ymin, xmax, ymax);
10549}
10550
10551////////////////////////////////////////////////////////////////////////////////
10552/// Set current histogram to `h`
10553
10555{
10556
10557 if (h == nullptr) return;
10558 fH = h;
10559 fXaxis = h->GetXaxis();
10560 fYaxis = h->GetYaxis();
10561 fZaxis = h->GetZaxis();
10563}
10564
10565////////////////////////////////////////////////////////////////////////////////
10566/// Initialize various options to draw 2D histograms.
10567
10569{
10570
10571 static const char *where = "TableInit";
10572
10573 Int_t first, last;
10575 Double_t zmin, zmax;
10576 Int_t maximum = 0;
10577 Int_t minimum = 0;
10578 if (fH->GetMaximumStored() != -1111) maximum = 1;
10579 if (fH->GetMinimumStored() != -1111) minimum = 1;
10580
10581 // ----------------- Compute X axis parameters
10582 first = fXaxis->GetFirst();
10583 last = fXaxis->GetLast();
10584 Hparam.xlast = last;
10585 Hparam.xfirst = first;
10590
10591 // if log scale in X, replace xmin,max by the log
10592 if (Hoption.Logx) {
10593 // find the first edge of a bin that is > 0
10594 if (Hparam.xlowedge <=0 ) {
10597 }
10598 if (Hparam.xmin <=0 || Hparam.xmax <=0) {
10599 Error(where, "cannot set X axis to log scale");
10600 return 0;
10601 }
10603 if (Hparam.xfirst < first) Hparam.xfirst = first;
10605 if (Hparam.xlast > last) Hparam.xlast = last;
10608 }
10609
10610 // ----------------- Compute Y axis parameters
10611 first = fYaxis->GetFirst();
10612 last = fYaxis->GetLast();
10613 Hparam.ylast = last;
10614 Hparam.yfirst = first;
10617 if (!Hparam.ybinsize) Hparam.ybinsize = 1;
10620
10621 // if log scale in Y, replace ymin,max by the log
10622 if (Hoption.Logy) {
10623 if (Hparam.ylowedge <=0 ) {
10626 }
10627 if (Hparam.ymin <=0 || Hparam.ymax <=0) {
10628 Error(where, "cannot set Y axis to log scale");
10629 return 0;
10630 }
10632 if (Hparam.yfirst < first) Hparam.yfirst = first;
10634 if (Hparam.ylast > last) Hparam.ylast = last;
10637 }
10638
10639
10640 // ----------------- Compute Z axis parameters
10641 Double_t bigp = TMath::Power(10,32);
10642 zmax = -bigp;
10643 zmin = bigp;
10644 Double_t c1, e1;
10645 Double_t allchan = 0;
10646 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
10647 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10648 c1 = fH->GetBinContent(i,j);
10649 zmax = TMath::Max(zmax,c1);
10650 if (Hoption.Error) {
10651 e1 = fH->GetBinError(i,j);
10652 zmax = TMath::Max(zmax,c1+e1);
10653 }
10654 zmin = TMath::Min(zmin,c1);
10655 allchan += c1;
10656 }
10657 }
10658
10659 // Take into account maximum , minimum
10660
10661 if (maximum) zmax = fH->GetMaximumStored();
10662 if (minimum) zmin = fH->GetMinimumStored();
10663 if (Hoption.Logz && zmax < 0) {
10664 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10665 return 0;
10666 } else if (Hoption.Logz && zmin>=0 && zmax==0) { // empty histogram in log scale
10667 zmin = 0.01;
10668 zmax = 10.;
10669 }
10670 if (zmin >= zmax) {
10671 if (Hoption.Logz) {
10672 if (zmax > 0) zmin = 0.001*zmax;
10673 else {
10674 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10675 return 0;
10676 }
10677 }
10678 }
10679
10680 // take into account normalization factor
10681 Hparam.allchan = allchan;
10682 Double_t factor = allchan;
10683 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
10684 if (allchan) factor /= allchan;
10685 if (factor == 0) factor = 1;
10686 Hparam.factor = factor;
10687 zmax = factor*zmax;
10688 zmin = factor*zmin;
10689 c1 = zmax;
10690 if (TMath::Abs(zmin) > TMath::Abs(c1)) c1 = zmin;
10691
10692 // For log scales, histogram coordinates are log10(ymin) and
10693 // log10(ymax). Final adjustment (if not option "Same")
10694 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
10695 // Maximum and Minimum are not defined.
10696 if (Hoption.Logz) {
10697 if (zmin <= 0) {
10698 zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
10699 fH->SetMinimum(zmin);
10700 }
10701 zmin = TMath::Log10(zmin);
10702 if (!minimum) zmin += TMath::Log10(0.5);
10703 zmax = TMath::Log10(zmax);
10704 if (!maximum) zmax += TMath::Log10(2*(0.9/0.95));
10705 goto LZMIN;
10706 }
10707
10708 // final adjustment of YMAXI for linear scale (if not option "Same"):
10709 // decrease histogram height to MAX% of allowed height if HMAXIM
10710 // has not been called.
10711 // MAX% is the value in percent which has been set in HPLSET
10712 // (default is 90%).
10713 if (!maximum) {
10714 zmax += yMARGIN*(zmax-zmin);
10715 }
10716
10717 // final adjustment of ymin for linear scale.
10718 // if minimum is not set , then ymin is set to zero if >0
10719 // or to ymin - yMARGIN if <0.
10720 if (!minimum) {
10721 if (Hoption.MinimumZero) {
10722 if (zmin >= 0) zmin = 0;
10723 else zmin -= yMARGIN*(zmax-zmin);
10724 } else {
10725 Double_t dzmin = yMARGIN*(zmax-zmin);
10726 if (zmin >= 0 && (zmin-dzmin <= 0)) zmin = 0;
10727 else zmin -= dzmin;
10728 }
10729 }
10730
10731LZMIN:
10732 Hparam.zmin = zmin;
10733 Hparam.zmax = zmax;
10734
10735 // Set bar offset and width
10738
10739 return 1;
10740}
10741
10742////////////////////////////////////////////////////////////////////////////////
10743/// This function returns the best format to print the error value (e)
10744/// knowing the parameter value (v) and the format (f) used to print it.
10745
10747{
10748
10749 static TString ef;
10750 TString tf, tv;
10751
10752 // print v with the format f in tv.
10753 tf.Form("%s%s","%",f);
10754 tv.Form(tf.Data(),v);
10755
10756 // Analyse tv.
10757 int ie = tv.Index("e");
10758 int iE = tv.Index("E");
10759 int id = tv.Index(".");
10760
10761 // v has been printed with the exponent notation.
10762 // There is 2 cases, the exponent is positive or negative
10763 if (ie >= 0 || iE >= 0) {
10764 if (tv.Index("+") >= 0) {
10765 if (e < 1) {
10766 ef.Form("%s.1f","%");
10767 } else {
10768 if (ie >= 0) {
10769 ef.Form("%s.%de","%",ie-id-1);
10770 } else {
10771 ef.Form("%s.%dE","%",iE-id-1);
10772 }
10773 }
10774 } else {
10775 if (ie >= 0) {
10776 ef.Form("%s.%de","%",ie-id-1);
10777 } else {
10778 ef.Form("%s.%dE","%",iE-id-1);
10779 }
10780 }
10781
10782 // There is not '.' in tv. e will be printed with one decimal digit.
10783 } else if (id < 0) {
10784 ef.Form("%s.1f","%");
10785
10786 // There is a '.' in tv and no exponent notation. e's decimal part will
10787 // have the same number of digits as v's one.
10788 } else {
10789 ef.Form("%s.%df","%",tv.Length()-id-1);
10790 }
10791
10792 return ef.Data();
10793}
10794
10795////////////////////////////////////////////////////////////////////////////////
10796/// Set projection.
10797
10799{
10800 if (fShowProjection2) {
10801 auto name2 = TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2);
10802 auto c2 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name2.Data()));
10803 if (c2) c2->Close();
10804 fShowProjection2 = 0;
10805 }
10806 if (fShowProjection) {
10807 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10808 auto c1 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name1.Data()));
10809 if (c1) c1->Close();
10810 fShowProjection = 0;
10811 }
10812
10813 if (nbins <= 0) return;
10814
10815 TString opt = option;
10816 opt.ToLower();
10817 Int_t projection = 0;
10818 if (opt.Contains("x")) projection = 1;
10819 if (opt.Contains("y")) projection = 2;
10820 if (opt.Contains("z")) projection = 3;
10821 if (opt.Contains("xy")) projection = 4;
10822 if (opt.Contains("yx")) projection = 5;
10823 if (opt.Contains("xz")) projection = 6;
10824 if (opt.Contains("zx")) projection = 7;
10825 if (opt.Contains("yz")) projection = 8;
10826 if (opt.Contains("zy")) projection = 9;
10827 if (projection < 4) fShowOption = option+1;
10828 else fShowOption = option+2;
10829 fShowProjection = projection+100*nbins;
10830 fShowProjection2 = 0;
10831 gROOT->MakeDefCanvas();
10832 gPad->SetName(TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection).Data());
10833 gPad->SetGrid();
10834}
10835
10837{
10838 if (fShowProjection2) {
10839 auto name2 = TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2);
10840 auto c2 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name2.Data()));
10841 if (c2) c2->Close();
10842 fShowProjection2 = 0;
10843 }
10844 if (fShowProjection) {
10845 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10846 auto c1 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name1.Data()));
10847 if (c1) c1->Close();
10848 fShowProjection = 0;
10849 }
10850
10851 if ((nbinsX <= 0) || (nbinsY <= 0)) return;
10852
10853
10854 TString opt = option;
10855 opt.ToLower();
10856 Int_t projection = 0;
10857 if (opt.Contains("x")) projection = 1;
10858 if (opt.Contains("y")) projection = 2;
10859 if (opt.Contains("z")) projection = 3;
10860 if (opt.Contains("xy")) projection = 4;
10861 if (opt.Contains("yx")) projection = 5;
10862 if (opt.Contains("xz")) projection = 6;
10863 if (opt.Contains("zx")) projection = 7;
10864 if (opt.Contains("yz")) projection = 8;
10865 if (opt.Contains("zy")) projection = 9;
10866 if (projection < 4) fShowOption = option+1;
10867 else fShowOption = option+2;
10870 gROOT->MakeDefCanvas();
10871 gPad->SetName(TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection).Data());
10872 gPad->SetGrid();
10873 gROOT->MakeDefCanvas();
10874 gPad->SetName(TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2).Data());
10875 gPad->SetGrid();
10876}
10877
10878
10879////////////////////////////////////////////////////////////////////////////////
10880/// Show projection onto X.
10881
10883{
10884
10885 Int_t nbins = (Int_t)fShowProjection/100;
10886 gPad->SetDoubleBuffer(0); // turn off double buffer mode
10887 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
10888
10889 // Erase old position and draw a line at current position
10890 static int pyold1 = 0;
10891 static int pyold2 = 0;
10892 float uxmin = gPad->GetUxmin();
10893 float uxmax = gPad->GetUxmax();
10894 int pxmin = gPad->XtoAbsPixel(uxmin);
10895 int pxmax = gPad->XtoAbsPixel(uxmax);
10896 Float_t upy = gPad->AbsPixeltoY(py);
10897 Float_t y = gPad->PadtoY(upy);
10898 Int_t biny1 = fH->GetYaxis()->FindBin(y);
10899 Int_t biny2 = TMath::Min(biny1+nbins-1, fH->GetYaxis()->GetNbins());
10900 Int_t py1 = gPad->YtoAbsPixel(gPad->GetLogy() ? TMath::Log10(fH->GetYaxis()->GetBinLowEdge(biny1)) : fH->GetYaxis()->GetBinLowEdge(biny1));
10901 Int_t py2 = gPad->YtoAbsPixel(gPad->GetLogy() ? TMath::Log10(fH->GetYaxis()->GetBinUpEdge(biny2)) : fH->GetYaxis()->GetBinUpEdge(biny2));
10902
10904 gVirtualX->DrawBox(pxmin,py1,pxmax,py2,TVirtualX::kFilled);
10905 pyold1 = py1;
10906 pyold2 = py2;
10907
10908 // Create or set the new canvas proj x
10910 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10911 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(name1.Data());
10912 if (c) {
10913 c->Clear();
10914 } else {
10915 fShowProjection = 0;
10916 fShowProjection2 = 0;
10917 pyold1 = 0;
10918 pyold2 = 0;
10919 return;
10920 }
10921 c->cd();
10922 c->SetLogy(ctxt.GetSaved()->GetLogz());
10923 c->SetLogx(ctxt.GetSaved()->GetLogx());
10924
10925 // Draw slice corresponding to mouse position
10926 TString prjName = TString::Format("slice_px_of_%s",fH->GetName());
10927 TH1D *hp = ((TH2*)fH)->ProjectionX(prjName, biny1, biny2);
10928 if (hp) {
10929 hp->SetFillColor(38);
10930 // apply a patch from Oliver Freyermuth to set the title in the projection
10931 // using the range of the projected Y values
10932 if (biny1 == biny2) {
10935 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
10937 if (fH->GetYaxis()->GetLabels() != nullptr) {
10938 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf] %s", biny1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetYaxis()->GetBinLabel(biny1)));
10939 } else {
10940 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf]", biny1, valuePrecision, valueFrom, valuePrecision, valueTo));
10941 }
10942 } else {
10945 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
10946 // biny1 is used here to get equal precision no matter how large the binrange is,
10947 // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
10949 if (fH->GetYaxis()->GetLabels() != nullptr) {
10950 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)));
10951 } else {
10952 hp->SetTitle(TString::Format("ProjectionX of biny=[%d,%d] [y=%.*lf..%.*lf]", biny1, biny2, valuePrecision, valueFrom, valuePrecision, valueTo));
10953 }
10954 }
10955 hp->SetXTitle(fH->GetXaxis()->GetTitle());
10956 hp->SetYTitle(((TH2*)fH)->GetZaxis()->GetTitle() ? ((TH2*)fH)->GetZaxis()->GetTitle() : "Number of Entries");
10957 hp->Draw();
10958 c->Update();
10959 }
10960}
10961
10962////////////////////////////////////////////////////////////////////////////////
10963/// Show projection onto Y.
10964
10966{
10967
10968 Int_t nbins = (Int_t)fShowProjection/100;
10969 if (fShowProjection2)
10970 nbins = (Int_t)fShowProjection2/100;
10971 gPad->SetDoubleBuffer(0); // turn off double buffer mode
10972 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
10973
10974 // Erase old position and draw a line at current position
10975 static int pxold1 = 0;
10976 static int pxold2 = 0;
10977 float uymin = gPad->GetUymin();
10978 float uymax = gPad->GetUymax();
10979 int pymin = gPad->YtoAbsPixel(uymin);
10980 int pymax = gPad->YtoAbsPixel(uymax);
10981 Float_t upx = gPad->AbsPixeltoX(px);
10982 Float_t x = gPad->PadtoX(upx);
10983 Int_t binx1 = fH->GetXaxis()->FindBin(x);
10984 Int_t binx2 = TMath::Min(binx1+nbins-1, fH->GetXaxis()->GetNbins());
10985 Int_t px1 = gPad->XtoAbsPixel(gPad->GetLogx() ? TMath::Log10(fH->GetXaxis()->GetBinLowEdge(binx1)) : fH->GetXaxis()->GetBinLowEdge(binx1));
10986 Int_t px2 = gPad->XtoAbsPixel(gPad->GetLogx() ? TMath::Log10(fH->GetXaxis()->GetBinUpEdge(binx2)) : fH->GetXaxis()->GetBinUpEdge(binx2));
10987
10989 gVirtualX->DrawBox(px1,pymin,px2,pymax,TVirtualX::kFilled);
10990 pxold1 = px1;
10991 pxold2 = px2;
10992
10993 // Create or set the new canvas proj y
10995
10996 TString name2 = fShowProjection2 ? TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2)
10997 : TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10998
10999 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(name2.Data());
11000 if (c) {
11001 c->Clear();
11002 } else {
11003 fShowProjection = 0;
11004 fShowProjection2 = 0;
11005 pxold1 = 0;
11006 pxold2 = 0;
11007 return;
11008 }
11009 c->cd();
11010 c->SetLogy(ctxt.GetSaved()->GetLogz());
11011 c->SetLogx(ctxt.GetSaved()->GetLogy());
11012
11013 // Draw slice corresponding to mouse position
11014 TString prjName = TString::Format("slice_py_of_%s",fH->GetName());
11015 TH1D *hp = ((TH2*)fH)->ProjectionY(prjName, binx1, binx2);
11016 if (hp) {
11017 hp->SetFillColor(38);
11018 // apply a patch from Oliver Freyermuth to set the title in the projection
11019 // using the range of the projected X values
11020 if (binx1 == binx2) {
11023 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11025 if (fH->GetXaxis()->GetLabels() != nullptr) {
11026 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf] [%s]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetXaxis()->GetBinLabel(binx1)));
11027 } else {
11028 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo));
11029 }
11030 } else {
11033 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11034 // binx1 is used here to get equal precision no matter how large the binrange is,
11035 // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
11037 if (fH->GetXaxis()->GetLabels() != nullptr) {
11038 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)));
11039 } else {
11040 hp->SetTitle(TString::Format("ProjectionY of binx=[%d,%d] [x=%.*lf..%.*lf]", binx1, binx2, valuePrecision, valueFrom, valuePrecision, valueTo));
11041 }
11042 }
11043 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11044 hp->SetYTitle(((TH2*)fH)->GetZaxis()->GetTitle() ? ((TH2*)fH)->GetZaxis()->GetTitle() : "Number of Entries");
11045 hp->Draw(fShowProjection2 ? "hbar" : "");
11046 c->Update();
11047 }
11048}
11049
11050////////////////////////////////////////////////////////////////////////////////
11051/// Show projection (specified by `fShowProjection`) of a `TH3`.
11052/// The drawing option for the projection is in `fShowOption`.
11053///
11054/// First implementation; R.Brun
11055///
11056/// Full implementation: Tim Tran (timtran@jlab.org) April 2006
11057
11059{
11060
11061 Int_t nbins=(Int_t)fShowProjection/100; //decode nbins
11062 if (fH->GetDimension() < 3) {
11063 if (fShowProjection2 % 100 == 1) {
11064 ShowProjectionY(px, py);
11065 }
11066 if (fShowProjection % 100 == 1) {
11067 ShowProjectionX(px, py);
11068 return;
11069 }
11070 if (fShowProjection % 100 == 2) {
11071 ShowProjectionY(px, py);
11072 return;
11073 }
11074 }
11075
11076 gPad->SetDoubleBuffer(0); // turn off double buffer mode
11077 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
11078
11079 // Erase old position and draw a line at current position
11080 TView *view = gPad->GetView();
11081 if (!view) return;
11082 TH3 *h3 = (TH3*)fH;
11083 TAxis *xaxis = h3->GetXaxis();
11084 TAxis *yaxis = h3->GetYaxis();
11085 TAxis *zaxis = h3->GetZaxis();
11086 Double_t u[3],xx[3];
11087
11088 static TPoint line1[2];//store end points of a line, initialised 0 by default
11089 static TPoint line2[2];// second line when slice thickness > 1 bin thickness
11090 static TPoint line3[2];
11091 static TPoint line4[2];
11092 static TPoint endface1[5];
11093 static TPoint endface2[5];
11094 static TPoint rect1[5];//store vertices of the polyline (rectangle), initialsed 0 by default
11095 static TPoint rect2[5];// second rectangle when slice thickness > 1 bin thickness
11096
11097 Double_t uxmin = gPad->GetUxmin();
11098 Double_t uxmax = gPad->GetUxmax();
11099 Double_t uymin = gPad->GetUymin();
11100 Double_t uymax = gPad->GetUymax();
11101
11102 int pxmin = gPad->XtoAbsPixel(uxmin);
11103 int pxmax = gPad->XtoAbsPixel(uxmax);
11104 if (pxmin==pxmax) return;
11105 int pymin = gPad->YtoAbsPixel(uymin);
11106 int pymax = gPad->YtoAbsPixel(uymax);
11107 if (pymin==pymax) return;
11110 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(TString::Format("c_%zx_projection_%d",
11111 (size_t)fH, fShowProjection).Data());
11112 if (!c) {
11113 fShowProjection = 0;
11114 return;
11115 }
11116
11118
11119 switch ((Int_t)fShowProjection%100) {
11120 case 1:
11121 // "x"
11122 {
11123 Int_t firstY = yaxis->GetFirst();
11124 Int_t lastY = yaxis->GetLast();
11126 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11127 yaxis->SetRange(biny,biny2);
11128 Int_t firstZ = zaxis->GetFirst();
11129 Int_t lastZ = zaxis->GetLast();
11131 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11132 zaxis->SetRange(binz,binz2);
11133 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11134 if (nbins>1 && line1[0].GetX()) {
11135 gVirtualX->DrawPolyLine(2,line2);
11136 gVirtualX->DrawPolyLine(2,line3);
11137 gVirtualX->DrawPolyLine(2,line4);
11138 gVirtualX->DrawPolyLine(5,endface1);
11139 gVirtualX->DrawPolyLine(5,endface2);
11140 }
11141 xx[0] = xaxis->GetXmin();
11142 xx[2] = zaxis->GetBinCenter(binz);
11143 xx[1] = yaxis->GetBinCenter(biny);
11144 view->WCtoNDC(xx,u);
11145 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11146 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11147 xx[0] = xaxis->GetXmax();
11148 view->WCtoNDC(xx,u);
11149 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11150 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11151 gVirtualX->DrawPolyLine(2,line1);
11152 if (nbins>1) {
11153 xx[0] = xaxis->GetXmin();
11154 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11155 xx[1] = yaxis->GetBinCenter(biny);
11156 view->WCtoNDC(xx,u);
11157 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11158 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11159 xx[0] = xaxis->GetXmax();
11160 view->WCtoNDC(xx,u);
11161 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11162 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11163
11164 xx[0] = xaxis->GetXmin();
11165 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11166 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11167 view->WCtoNDC(xx,u);
11168 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11169 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11170 xx[0] = xaxis->GetXmax();
11171 view->WCtoNDC(xx,u);
11172 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11173 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11174
11175 xx[0] = xaxis->GetXmin();
11176 xx[2] = zaxis->GetBinCenter(binz);
11177 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11178 view->WCtoNDC(xx,u);
11179 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11180 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11181 xx[0] = xaxis->GetXmax();
11182 view->WCtoNDC(xx,u);
11183 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11184 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11185
11186 endface1[0].SetX(line1[0].GetX());
11187 endface1[0].SetY(line1[0].GetY());
11188 endface1[1].SetX(line2[0].GetX());
11189 endface1[1].SetY(line2[0].GetY());
11190 endface1[2].SetX(line3[0].GetX());
11191 endface1[2].SetY(line3[0].GetY());
11192 endface1[3].SetX(line4[0].GetX());
11193 endface1[3].SetY(line4[0].GetY());
11194 endface1[4].SetX(line1[0].GetX());
11195 endface1[4].SetY(line1[0].GetY());
11196
11197 endface2[0].SetX(line1[1].GetX());
11198 endface2[0].SetY(line1[1].GetY());
11199 endface2[1].SetX(line2[1].GetX());
11200 endface2[1].SetY(line2[1].GetY());
11201 endface2[2].SetX(line3[1].GetX());
11202 endface2[2].SetY(line3[1].GetY());
11203 endface2[3].SetX(line4[1].GetX());
11204 endface2[3].SetY(line4[1].GetY());
11205 endface2[4].SetX(line1[1].GetX());
11206 endface2[4].SetY(line1[1].GetY());
11207
11208 gVirtualX->DrawPolyLine(2,line2);
11209 gVirtualX->DrawPolyLine(2,line3);
11210 gVirtualX->DrawPolyLine(2,line4);
11211 gVirtualX->DrawPolyLine(5,endface1);
11212 gVirtualX->DrawPolyLine(5,endface2);
11213 }
11214 c->Clear();
11215 c->cd();
11216 TH1 *hp = h3->Project3D("x");
11217 yaxis->SetRange(firstY,lastY);
11218 zaxis->SetRange(firstZ,lastZ);
11219 if (hp) {
11220 hp->SetFillColor(38);
11221 if (nbins == 1)
11222 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny),
11223 binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
11224 else {
11225 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),
11226 binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
11227 }
11228 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11229 hp->SetYTitle("Number of Entries");
11230 hp->Draw(fShowOption.Data());
11231 }
11232 }
11233 break;
11234
11235 case 2:
11236 // "y"
11237 {
11238 Int_t firstX = xaxis->GetFirst();
11239 Int_t lastX = xaxis->GetLast();
11241 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11242 xaxis->SetRange(binx,binx2);
11243 Int_t firstZ = zaxis->GetFirst();
11244 Int_t lastZ = zaxis->GetLast();
11246 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11247 zaxis->SetRange(binz,binz2);
11248 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11249 if (nbins>1 && line1[0].GetX()) {
11250 gVirtualX->DrawPolyLine(2,line2);
11251 gVirtualX->DrawPolyLine(2,line3);
11252 gVirtualX->DrawPolyLine(2,line4);
11253 gVirtualX->DrawPolyLine(5,endface1);
11254 gVirtualX->DrawPolyLine(5,endface2);
11255 }
11256 xx[0]=xaxis->GetBinCenter(binx);
11257 xx[2] = zaxis->GetBinCenter(binz);
11258 xx[1] = yaxis->GetXmin();
11259 view->WCtoNDC(xx,u);
11260 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11261 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11262 xx[1] = yaxis->GetXmax();
11263 view->WCtoNDC(xx,u);
11264 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11265 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11266 gVirtualX->DrawPolyLine(2,line1);
11267 if (nbins>1) {
11268 xx[1] = yaxis->GetXmin();
11269 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11270 xx[0] = xaxis->GetBinCenter(binx);
11271 view->WCtoNDC(xx,u);
11272 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11273 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11274 xx[1] = yaxis->GetXmax();
11275 view->WCtoNDC(xx,u);
11276 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11277 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11278
11279 xx[1] = yaxis->GetXmin();
11280 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11281 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11282 view->WCtoNDC(xx,u);
11283 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11284 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11285 xx[1] = yaxis->GetXmax();
11286 view->WCtoNDC(xx,u);
11287 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11288 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11289
11290 xx[1] = yaxis->GetXmin();
11291 xx[2] = zaxis->GetBinCenter(binz);
11292 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11293 view->WCtoNDC(xx,u);
11294 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11295 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11296 xx[1] = yaxis->GetXmax();
11297 view->WCtoNDC(xx,u);
11298 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11299 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11300
11301 endface1[0].SetX(line1[0].GetX());
11302 endface1[0].SetY(line1[0].GetY());
11303 endface1[1].SetX(line2[0].GetX());
11304 endface1[1].SetY(line2[0].GetY());
11305 endface1[2].SetX(line3[0].GetX());
11306 endface1[2].SetY(line3[0].GetY());
11307 endface1[3].SetX(line4[0].GetX());
11308 endface1[3].SetY(line4[0].GetY());
11309 endface1[4].SetX(line1[0].GetX());
11310 endface1[4].SetY(line1[0].GetY());
11311
11312 endface2[0].SetX(line1[1].GetX());
11313 endface2[0].SetY(line1[1].GetY());
11314 endface2[1].SetX(line2[1].GetX());
11315 endface2[1].SetY(line2[1].GetY());
11316 endface2[2].SetX(line3[1].GetX());
11317 endface2[2].SetY(line3[1].GetY());
11318 endface2[3].SetX(line4[1].GetX());
11319 endface2[3].SetY(line4[1].GetY());
11320 endface2[4].SetX(line1[1].GetX());
11321 endface2[4].SetY(line1[1].GetY());
11322
11323 gVirtualX->DrawPolyLine(2,line2);
11324 gVirtualX->DrawPolyLine(2,line3);
11325 gVirtualX->DrawPolyLine(2,line4);
11326 gVirtualX->DrawPolyLine(5,endface1);
11327 gVirtualX->DrawPolyLine(5,endface2);
11328 }
11329 c->Clear();
11330 c->cd();
11331 TH1 *hp = h3->Project3D("y");
11332 xaxis->SetRange(firstX,lastX);
11333 zaxis->SetRange(firstZ,lastZ);
11334 if (hp) {
11335 hp->SetFillColor(38);
11336 if (nbins == 1)
11337 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
11338 binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
11339 else
11340 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),
11341 binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
11342 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11343 hp->SetYTitle("Number of Entries");
11344 hp->Draw(fShowOption.Data());
11345 }
11346 }
11347 break;
11348
11349 case 3:
11350 // "z"
11351 {
11352 Int_t firstX = xaxis->GetFirst();
11353 Int_t lastX = xaxis->GetLast();
11355 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11356 xaxis->SetRange(binx,binx2);
11357 Int_t firstY = yaxis->GetFirst();
11358 Int_t lastY = yaxis->GetLast();
11360 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11361 yaxis->SetRange(biny,biny2);
11362 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11363 if (nbins>1 && line1[0].GetX()) {
11364 gVirtualX->DrawPolyLine(2,line2);
11365 gVirtualX->DrawPolyLine(2,line3);
11366 gVirtualX->DrawPolyLine(2,line4);
11367 gVirtualX->DrawPolyLine(5,endface1);
11368 gVirtualX->DrawPolyLine(5,endface2);
11369 }
11370 xx[0] = xaxis->GetBinCenter(binx);
11371 xx[1] = yaxis->GetBinCenter(biny);
11372 xx[2] = zaxis->GetXmin();
11373 view->WCtoNDC(xx,u);
11374 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11375 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11376 xx[2] = zaxis->GetXmax();
11377 view->WCtoNDC(xx,u);
11378 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11379 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11380 gVirtualX->DrawPolyLine(2,line1);
11381 if (nbins>1) {
11382 xx[2] = zaxis->GetXmin();
11383 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11384 xx[0] = xaxis->GetBinCenter(binx);
11385 view->WCtoNDC(xx,u);
11386 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11387 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11388 xx[2] = zaxis->GetXmax();
11389 view->WCtoNDC(xx,u);
11390 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11391 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11392
11393 xx[2] = zaxis->GetXmin();
11394 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11395 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11396 view->WCtoNDC(xx,u);
11397 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11398 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11399 xx[2] = zaxis->GetXmax();
11400 view->WCtoNDC(xx,u);
11401 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11402 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11403
11404 xx[2] = zaxis->GetXmin();
11405 xx[1] = yaxis->GetBinCenter(biny);
11406 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11407 view->WCtoNDC(xx,u);
11408 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11409 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11410 xx[2] = zaxis->GetXmax();
11411 view->WCtoNDC(xx,u);
11412 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11413 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11414
11415 endface1[0].SetX(line1[0].GetX());
11416 endface1[0].SetY(line1[0].GetY());
11417 endface1[1].SetX(line2[0].GetX());
11418 endface1[1].SetY(line2[0].GetY());
11419 endface1[2].SetX(line3[0].GetX());
11420 endface1[2].SetY(line3[0].GetY());
11421 endface1[3].SetX(line4[0].GetX());
11422 endface1[3].SetY(line4[0].GetY());
11423 endface1[4].SetX(line1[0].GetX());
11424 endface1[4].SetY(line1[0].GetY());
11425
11426 endface2[0].SetX(line1[1].GetX());
11427 endface2[0].SetY(line1[1].GetY());
11428 endface2[1].SetX(line2[1].GetX());
11429 endface2[1].SetY(line2[1].GetY());
11430 endface2[2].SetX(line3[1].GetX());
11431 endface2[2].SetY(line3[1].GetY());
11432 endface2[3].SetX(line4[1].GetX());
11433 endface2[3].SetY(line4[1].GetY());
11434 endface2[4].SetX(line1[1].GetX());
11435 endface2[4].SetY(line1[1].GetY());
11436
11437 gVirtualX->DrawPolyLine(2,line2);
11438 gVirtualX->DrawPolyLine(2,line3);
11439 gVirtualX->DrawPolyLine(2,line4);
11440 gVirtualX->DrawPolyLine(5,endface1);
11441 gVirtualX->DrawPolyLine(5,endface2);
11442 }
11443 c->Clear();
11444 c->cd();
11445 TH1 *hp = h3->Project3D("z");
11446 xaxis->SetRange(firstX,lastX);
11447 yaxis->SetRange(firstY,lastY);
11448 if (hp) {
11449 hp->SetFillColor(38);
11450 if (nbins == 1)
11451 hp->SetTitle(TString::Format("ProjectionZ of binx=%d [x=%.1f..%.1f] biny=%d [y=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
11452 biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny)));
11453 else
11454 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),
11455 biny, biny2, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny2) ) );
11456 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11457 hp->SetYTitle("Number of Entries");
11458 hp->Draw(fShowOption.Data());
11459 }
11460 }
11461 break;
11462
11463 case 4:
11464 // "xy"
11465 {
11466 Int_t first = zaxis->GetFirst();
11467 Int_t last = zaxis->GetLast();
11468 Int_t binz = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11469 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11470 zaxis->SetRange(binz,binz2);
11471 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11472 if (nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11473 xx[0] = xaxis->GetXmin();
11474 xx[1] = yaxis->GetXmax();
11475 xx[2] = zaxis->GetBinCenter(binz);
11476 view->WCtoNDC(xx,u);
11477 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11478 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11479 rect1[4].SetX(rect1[0].GetX());
11480 rect1[4].SetY(rect1[0].GetY());
11481 xx[0] = xaxis->GetXmax();
11482 view->WCtoNDC(xx,u);
11483 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11484 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11485 xx[1] = yaxis->GetXmin();
11486 view->WCtoNDC(xx,u);
11487 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11488 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11489 xx[0] = xaxis->GetXmin();
11490 view->WCtoNDC(xx,u);
11491 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11492 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11493 gVirtualX->DrawPolyLine(5,rect1);
11494 if (nbins>1) {
11495 xx[0] = xaxis->GetXmin();
11496 xx[1] = yaxis->GetXmax();
11497 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11498 view->WCtoNDC(xx,u);
11499 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11500 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11501 rect2[4].SetX(rect2[0].GetX());
11502 rect2[4].SetY(rect2[0].GetY());
11503 xx[0] = xaxis->GetXmax();
11504 view->WCtoNDC(xx,u);
11505 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11506 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11507 xx[1] = yaxis->GetXmin();
11508 view->WCtoNDC(xx,u);
11509 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11510 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11511 xx[0] = xaxis->GetXmin();
11512 view->WCtoNDC(xx,u);
11513 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11514 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11515 gVirtualX->DrawPolyLine(5,rect2);
11516 }
11517
11518 c->Clear();
11519 c->cd();
11520 TH2 *hp = (TH2*)h3->Project3D("xy");
11521 zaxis->SetRange(first,last);
11522 if (hp) {
11523 hp->SetFillColor(38);
11524 if (nbins==1)hp->SetTitle(TString::Format("ProjectionXY of binz=%d [z=%.1f..%.f]", binz,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz)));
11525 else hp->SetTitle(TString::Format("ProjectionXY, binz=[%d,%d] [z=%.1f..%.1f]", binz,binz2,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz2)));
11526 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11527 hp->SetYTitle(fH->GetXaxis()->GetTitle());
11528 hp->SetZTitle("Number of Entries");
11529 hp->Draw(fShowOption.Data());
11530 }
11531 }
11532 break;
11533
11534 case 5:
11535 // "yx"
11536 {
11537 Int_t first = zaxis->GetFirst();
11538 Int_t last = zaxis->GetLast();
11539 Int_t binz = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11540 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11541 zaxis->SetRange(binz,binz2);
11542 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11543 if (nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11544 xx[0] = xaxis->GetXmin();
11545 xx[1] = yaxis->GetXmax();
11546 xx[2] = zaxis->GetBinCenter(binz);
11547 view->WCtoNDC(xx,u);
11548 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11549 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11550 rect1[4].SetX(rect1[0].GetX());
11551 rect1[4].SetY(rect1[0].GetY());
11552 xx[0] = xaxis->GetXmax();
11553 view->WCtoNDC(xx,u);
11554 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11555 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11556 xx[1] = yaxis->GetXmin();
11557 view->WCtoNDC(xx,u);
11558 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11559 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11560 xx[0] = xaxis->GetXmin();
11561 view->WCtoNDC(xx,u);
11562 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11563 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11564 gVirtualX->DrawPolyLine(5,rect1);
11565 if (nbins>1) {
11566 xx[0] = xaxis->GetXmin();
11567 xx[1] = yaxis->GetXmax();
11568 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11569 view->WCtoNDC(xx,u);
11570 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11571 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11572 rect2[4].SetX(rect2[0].GetX());
11573 rect2[4].SetY(rect2[0].GetY());
11574 xx[0] = xaxis->GetXmax();
11575 view->WCtoNDC(xx,u);
11576 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11577 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11578 xx[1] = yaxis->GetXmin();
11579 view->WCtoNDC(xx,u);
11580 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11581 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11582 xx[0] = xaxis->GetXmin();
11583 view->WCtoNDC(xx,u);
11584 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11585 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11586 gVirtualX->DrawPolyLine(5,rect2);
11587 }
11588 c->Clear();
11589 c->cd();
11590 TH2 *hp = (TH2*)h3->Project3D("yx");
11591 zaxis->SetRange(first,last);
11592 if (hp) {
11593 hp->SetFillColor(38);
11594 if (nbins==1)hp->SetTitle(TString::Format("ProjectionYX of binz=%d [z=%.1f..%.f]", binz,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz)));
11595 else hp->SetTitle(TString::Format("ProjectionYX, binz=[%d,%d] [z=%.1f..%.1f]", binz,binz2,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz2)));
11596 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11597 hp->SetYTitle(fH->GetYaxis()->GetTitle());
11598 hp->SetZTitle("Number of Entries");
11599 hp->Draw(fShowOption.Data());
11600 }
11601 }
11602 break;
11603
11604 case 6:
11605 // "xz"
11606 {
11607 Int_t first = yaxis->GetFirst();
11608 Int_t last = yaxis->GetLast();
11609 Int_t biny = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11610 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11611 yaxis->SetRange(biny,biny2);
11612 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11613 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11614 xx[0] = xaxis->GetXmin();
11615 xx[2] = zaxis->GetXmax();
11616 xx[1] = yaxis->GetBinCenter(biny);
11617 view->WCtoNDC(xx,u);
11618 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11619 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11620 rect1[4].SetX(rect1[0].GetX());
11621 rect1[4].SetY(rect1[0].GetY());
11622 xx[0] = xaxis->GetXmax();
11623 view->WCtoNDC(xx,u);
11624 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11625 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11626 xx[2] = zaxis->GetXmin();
11627 view->WCtoNDC(xx,u);
11628 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11629 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11630 xx[0] = xaxis->GetXmin();
11631 view->WCtoNDC(xx,u);
11632 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11633 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11634 gVirtualX->DrawPolyLine(5,rect1);
11635 if (nbins>1) {
11636 xx[0] = xaxis->GetXmin();
11637 xx[2] = zaxis->GetXmax();
11638 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11639 view->WCtoNDC(xx,u);
11640 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11641 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11642 rect2[4].SetX(rect2[0].GetX());
11643 rect2[4].SetY(rect2[0].GetY());
11644 xx[0] = xaxis->GetXmax();
11645 view->WCtoNDC(xx,u);
11646 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11647 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11648 xx[2] = zaxis->GetXmin();
11649 view->WCtoNDC(xx,u);
11650 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11651 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11652 xx[0] = xaxis->GetXmin();
11653 view->WCtoNDC(xx,u);
11654 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11655 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11656 gVirtualX->DrawPolyLine(5,rect2);
11657 }
11658 c->Clear();
11659 c->cd();
11660 TH2 *hp = (TH2*)h3->Project3D("xz");
11661 yaxis->SetRange(first,last);
11662 if (hp) {
11663 hp->SetFillColor(38);
11664 if (nbins==1)hp->SetTitle(TString::Format("ProjectionXZ of biny=%d [y=%.1f..%.f]", biny,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny)));
11665 else hp->SetTitle(TString::Format("ProjectionXZ, biny=[%d,%d] [y=%.1f..%.1f]", biny,biny2,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny2)));
11666 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11667 hp->SetYTitle(fH->GetXaxis()->GetTitle());
11668 hp->SetZTitle("Number of Entries");
11669 hp->Draw(fShowOption.Data());
11670 }
11671 }
11672 break;
11673
11674 case 7:
11675 // "zx"
11676 {
11677 Int_t first = yaxis->GetFirst();
11678 Int_t last = yaxis->GetLast();
11679 Int_t biny = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11680 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11681 yaxis->SetRange(biny,biny2);
11682 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11683 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11684 xx[0] = xaxis->GetXmin();
11685 xx[2] = zaxis->GetXmax();
11686 xx[1] = yaxis->GetBinCenter(biny);
11687 view->WCtoNDC(xx,u);
11688 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11689 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11690 rect1[4].SetX(rect1[0].GetX());
11691 rect1[4].SetY(rect1[0].GetY());
11692 xx[0] = xaxis->GetXmax();
11693 view->WCtoNDC(xx,u);
11694 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11695 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11696 xx[2] = zaxis->GetXmin();
11697 view->WCtoNDC(xx,u);
11698 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11699 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11700 xx[0] = xaxis->GetXmin();
11701 view->WCtoNDC(xx,u);
11702 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11703 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11704 gVirtualX->DrawPolyLine(5,rect1);
11705 if (nbins>1) {
11706 xx[0] = xaxis->GetXmin();
11707 xx[2] = zaxis->GetXmax();
11708 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11709 view->WCtoNDC(xx,u);
11710 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11711 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11712 rect2[4].SetX(rect2[0].GetX());
11713 rect2[4].SetY(rect2[0].GetY());
11714 xx[0] = xaxis->GetXmax();
11715 view->WCtoNDC(xx,u);
11716 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11717 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11718 xx[2] = zaxis->GetXmin();
11719 view->WCtoNDC(xx,u);
11720 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11721 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11722 xx[0] = xaxis->GetXmin();
11723 view->WCtoNDC(xx,u);
11724 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11725 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11726 gVirtualX->DrawPolyLine(5,rect2);
11727 }
11728 c->Clear();
11729 c->cd();
11730 TH2 *hp = (TH2*)h3->Project3D("zx");
11731 yaxis->SetRange(first,last);
11732 if (hp) {
11733 hp->SetFillColor(38);
11734 if (nbins==1)hp->SetTitle(TString::Format("ProjectionZX of biny=%d [y=%.1f..%.f]", biny,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny)));
11735 else hp->SetTitle(TString::Format("ProjectionZX, biny=[%d,%d] [y=%.1f..%.1f]", biny,biny2,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny2)));
11736 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11737 hp->SetYTitle(fH->GetZaxis()->GetTitle());
11738 hp->SetZTitle("Number of Entries");
11739 hp->Draw(fShowOption.Data());
11740 }
11741 }
11742 break;
11743
11744 case 8:
11745 // "yz"
11746 {
11747 Int_t first = xaxis->GetFirst();
11748 Int_t last = xaxis->GetLast();
11749 Int_t binx = first + Int_t((last-first)*(px-pxmin)/(pxmax-pxmin));
11750 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11751 xaxis->SetRange(binx,binx2);
11752 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11753 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11754 xx[2] = zaxis->GetXmin();
11755 xx[1] = yaxis->GetXmax();
11756 xx[0] = xaxis->GetBinCenter(binx);
11757 view->WCtoNDC(xx,u);
11758 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11759 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11760 rect1[4].SetX(rect1[0].GetX());
11761 rect1[4].SetY(rect1[0].GetY());
11762 xx[2] = zaxis->GetXmax();
11763 view->WCtoNDC(xx,u);
11764 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11765 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11766 xx[1] = yaxis->GetXmin();
11767 view->WCtoNDC(xx,u);
11768 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11769 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11770 xx[2] = zaxis->GetXmin();
11771 view->WCtoNDC(xx,u);
11772 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11773 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11774 gVirtualX->DrawPolyLine(5,rect1);
11775 if (nbins>1) {
11776 xx[2] = zaxis->GetXmin();
11777 xx[1] = yaxis->GetXmax();
11778 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11779 view->WCtoNDC(xx,u);
11780 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11781 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11782 rect2[4].SetX(rect2[0].GetX());
11783 rect2[4].SetY(rect2[0].GetY());
11784 xx[2] = zaxis->GetXmax();
11785 view->WCtoNDC(xx,u);
11786 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11787 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11788 xx[1] = yaxis->GetXmin();
11789 view->WCtoNDC(xx,u);
11790 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11791 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11792 xx[2] = zaxis->GetXmin();
11793 view->WCtoNDC(xx,u);
11794 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11795 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11796 gVirtualX->DrawPolyLine(5,rect2);
11797 }
11798 c->Clear();
11799 c->cd();
11800 TH2 *hp = (TH2*)h3->Project3D("yz");
11801 xaxis->SetRange(first,last);
11802 if (hp) {
11803 hp->SetFillColor(38);
11804 if (nbins==1)hp->SetTitle(TString::Format("ProjectionYZ of binx=%d [x=%.1f..%.f]", binx,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx)));
11805 else hp->SetTitle(TString::Format("ProjectionYZ, binx=[%d,%d] [x=%.1f..%.1f]", binx,binx2,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx2)));
11806 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11807 hp->SetYTitle(fH->GetYaxis()->GetTitle());
11808 hp->SetZTitle("Number of Entries");
11809 hp->Draw(fShowOption.Data());
11810 }
11811 }
11812 break;
11813
11814 case 9:
11815 // "zy"
11816 {
11817 Int_t first = xaxis->GetFirst();
11818 Int_t last = xaxis->GetLast();
11819 Int_t binx = first + Int_t((last-first)*(px-pxmin)/(pxmax-pxmin));
11820 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11821 xaxis->SetRange(binx,binx2);
11822 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11823 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11824 xx[2] = zaxis->GetXmin();
11825 xx[1] = yaxis->GetXmax();
11826 xx[0] = xaxis->GetBinCenter(binx);
11827 view->WCtoNDC(xx,u);
11828 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11829 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11830 rect1[4].SetX(rect1[0].GetX());
11831 rect1[4].SetY(rect1[0].GetY());
11832 xx[2] = zaxis->GetXmax();
11833 view->WCtoNDC(xx,u);
11834 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11835 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11836 xx[1] = yaxis->GetXmin();
11837 view->WCtoNDC(xx,u);
11838 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11839 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11840 xx[2] = zaxis->GetXmin();
11841 view->WCtoNDC(xx,u);
11842 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11843 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11844 gVirtualX->DrawPolyLine(5,rect1);
11845 if (nbins>1) {
11846 xx[2] = zaxis->GetXmin();
11847 xx[1] = yaxis->GetXmax();
11848 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11849 view->WCtoNDC(xx,u);
11850 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11851 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11852 rect2[4].SetX(rect2[0].GetX());
11853 rect2[4].SetY(rect2[0].GetY());
11854 xx[2] = zaxis->GetXmax();
11855 view->WCtoNDC(xx,u);
11856 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11857 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11858 xx[1] = yaxis->GetXmin();
11859 view->WCtoNDC(xx,u);
11860 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11861 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11862 xx[2] = zaxis->GetXmin();
11863 view->WCtoNDC(xx,u);
11864 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11865 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11866 gVirtualX->DrawPolyLine(5,rect2);
11867 }
11868 c->Clear();
11869 c->cd();
11870 TH2 *hp = (TH2*)h3->Project3D("zy");
11871 xaxis->SetRange(first,last);
11872 if (hp) {
11873 hp->SetFillColor(38);
11874 if (nbins==1)hp->SetTitle(TString::Format("ProjectionZY of binx=%d [x=%.1f..%.f]", binx,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx)));
11875 else hp->SetTitle(TString::Format("ProjectionZY, binx=[%d,%d] [x=%.1f..%.1f]", binx,binx2,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx2)));
11876 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11877 hp->SetYTitle(fH->GetZaxis()->GetTitle());
11878 hp->SetZTitle("Number of Entries");
11879 hp->Draw(fShowOption.Data());
11880 }
11881 }
11882 break;
11883 }
11884 c->Update();
11885}
@ 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
Definition RtypesCore.h:82
int Int_t
Definition RtypesCore.h:45
short Color_t
Definition RtypesCore.h:85
unsigned int UInt_t
Definition RtypesCore.h:46
short Width_t
Definition RtypesCore.h:84
float Float_t
Definition RtypesCore.h:57
short Short_t
Definition RtypesCore.h:39
constexpr Bool_t kFALSE
Definition RtypesCore.h:94
double Double_t
Definition RtypesCore.h:59
constexpr Bool_t kTRUE
Definition RtypesCore.h:93
const char Option_t
Definition RtypesCore.h:66
#define BIT(n)
Definition Rtypes.h:90
#define ClassImp(name)
Definition Rtypes.h:374
@ kBlack
Definition Rtypes.h:65
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
R__EXTERN TEnv * gEnv
Definition TEnv.h: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:414
R__EXTERN TStyle * gStyle
Definition TStyle.h:442
R__EXTERN TSystem * gSystem
Definition TSystem.h:572
const Int_t kCARTESIAN
Definition TView3D.cxx:33
const Int_t kPOLAR
Definition TView3D.cxx:34
#define gPad
#define gVirtualX
Definition TVirtualX.h:337
polygon * polys
Definition X3DBuffer.c:24
Draw all kinds of Arrows.
Definition TArrow.h:29
virtual Int_t GetNdivisions() const
Definition TAttAxis.h:37
virtual Float_t GetLabelOffset() const
Definition TAttAxis.h:41
virtual Float_t GetLabelSize() const
Definition TAttAxis.h:42
virtual Float_t GetTickLength() const
Definition TAttAxis.h:46
virtual Float_t GetTitleOffset() const
Definition TAttAxis.h:44
virtual Color_t GetFillColor() const
Return the fill area color.
Definition TAttFill.h:31
virtual Style_t GetFillStyle() const
Return the fill area style.
Definition TAttFill.h:32
virtual void SetFillColor(Color_t fcolor)
Set the fill area color.
Definition TAttFill.h:38
virtual void SetFillStyle(Style_t fstyle)
Set the fill area style.
Definition TAttFill.h:40
virtual Color_t GetLineColor() const
Return the line color.
Definition TAttLine.h:35
virtual void SetLineStyle(Style_t lstyle)
Set the line style.
Definition TAttLine.h:44
virtual Width_t GetLineWidth() const
Return the line width.
Definition TAttLine.h:37
virtual void SetLineWidth(Width_t lwidth)
Set the line width.
Definition TAttLine.h:45
virtual void SetLineColor(Color_t lcolor)
Set the line color.
Definition TAttLine.h:42
virtual Style_t GetLineStyle() const
Return the line style.
Definition TAttLine.h:36
virtual Style_t GetMarkerStyle() const
Return the marker style.
Definition TAttMarker.h:33
virtual void SetMarkerColor(Color_t mcolor=1)
Set the marker color.
Definition TAttMarker.h:39
virtual Color_t GetMarkerColor() const
Return the marker color.
Definition TAttMarker.h:32
virtual Size_t GetMarkerSize() const
Return the marker size.
Definition TAttMarker.h:34
virtual void SetMarkerStyle(Style_t mstyle=1)
Set the marker style.
Definition TAttMarker.h:41
virtual void SetMarkerSize(Size_t msize=1)
Set the marker size.
Definition TAttMarker.h:46
static Style_t GetMarkerStyleBase(Style_t style)
Internal helper function that returns the corresponding marker style with line width 1 for the given ...
virtual Font_t GetTextFont() const
Return the text font.
Definition TAttText.h:37
virtual void SetTextAngle(Float_t tangle=0)
Set the text angle.
Definition TAttText.h:45
Class to manage histogram axis.
Definition TAxis.h:32
virtual Bool_t GetTimeDisplay() const
Definition TAxis.h:133
Bool_t IsAlphanumeric() const
Definition TAxis.h:90
const char * GetTitle() const override
Returns title of object.
Definition TAxis.h:137
virtual Double_t GetBinCenter(Int_t bin) const
Return center of bin.
Definition TAxis.cxx:482
Bool_t CanExtend() const
Definition TAxis.h:88
const TArrayD * GetXbins() const
Definition TAxis.h:138
Double_t GetXmax() const
Definition TAxis.h:142
@ kAxisRange
Definition TAxis.h:66
const char * GetBinLabel(Int_t bin) const
Return label for bin.
Definition TAxis.cxx:444
virtual Int_t FindBin(Double_t x)
Find bin number corresponding to abscissa x.
Definition TAxis.cxx:296
virtual Double_t GetBinLowEdge(Int_t bin) const
Return low edge of bin.
Definition TAxis.cxx:522
virtual Int_t FindFixBin(Double_t x) const
Find bin number corresponding to abscissa x
Definition TAxis.cxx:423
const char * ChooseTimeFormat(Double_t axislength=0)
Choose a reasonable time format from the coordinates in the active pad and the number of divisions in...
Definition TAxis.cxx:127
Int_t GetLast() const
Return last bin on the axis i.e.
Definition TAxis.cxx:473
virtual const char * GetTimeFormatOnly() const
Return only the time format from the string fTimeFormat.
Definition TAxis.cxx:604
Double_t GetXmin() const
Definition TAxis.h:141
Int_t GetNbins() const
Definition TAxis.h:127
virtual void SetRangeUser(Double_t ufirst, Double_t ulast)
Set the viewing range for the axis from ufirst to ulast (in user coordinates, that is,...
Definition TAxis.cxx:1075
virtual const char * GetTimeFormat() const
Definition TAxis.h:134
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width.
Definition TAxis.cxx:546
virtual Double_t GetBinUpEdge(Int_t bin) const
Return up edge of bin.
Definition TAxis.cxx:532
Int_t GetFirst() const
Return first bin on the axis i.e.
Definition TAxis.cxx:462
THashList * GetLabels() const
Definition TAxis.h:123
Create a Box.
Definition TBox.h:22
The candle plot painter class.
Definition TCandle.h:27
CandleOption
Definition TCandle.h:30
static Bool_t SupportAlpha()
Static function returning "true" if transparency is supported.
Definition TCanvas.cxx:2475
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition TClass.cxx:3074
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
The color creation and management class.
Definition TColor.h:22
static void RGBtoHLS(Float_t r, Float_t g, Float_t b, Float_t &h, Float_t &l, Float_t &s)
Definition TColor.h:83
static Int_t GetColor(const char *hexcolor)
Static method returning color number for color specified by hex color string of form: "#rrggbb",...
Definition TColor.cxx:1927
static Int_t GetColorBright(Int_t color)
Static function: Returns the bright color number corresponding to n If the TColor object does not exi...
Definition TColor.cxx:2096
static Int_t GetColorDark(Int_t color)
Static function: Returns the dark color number corresponding to n If the TColor object does not exist...
Definition TColor.cxx:2139
static void HLStoRGB(Float_t h, Float_t l, Float_t s, Float_t &r, Float_t &g, Float_t &b)
Definition TColor.h:78
To draw a Crown.
Definition TCrown.h:19
Graphical cut class.
Definition TCutG.h:20
static TClass * Class()
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition TEnv.cxx:491
1-Dim function class
Definition TF1.h:234
virtual Double_t GetXmax() const
Definition TF1.h:592
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:1917
virtual void GetParLimits(Int_t ipar, Double_t &parmin, Double_t &parmax) const
Return limits for parameter ipar.
Definition TF1.cxx:1968
virtual Double_t GetParError(Int_t ipar) const
Return value of parameter number ipar.
Definition TF1.cxx:1958
static TClass * Class()
Double_t GetChisquare() const
Return the Chisquare after fitting. See ROOT::Fit::FitResult::Chi2()
Definition TF1.h:476
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:3426
virtual Double_t GetMaximumStored() const
Definition TF1.h:505
virtual Int_t GetNpar() const
Definition TF1.h:513
virtual Int_t GetNumberFreeParameters() const
Return the number of free parameters.
Definition TF1.cxx:1928
@ kNotDraw
Definition TF1.h:349
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:3439
virtual const char * GetParName(Int_t ipar) const
Definition TF1.h:561
virtual Double_t Eval(Double_t x, Double_t y=0, Double_t z=0, Double_t t=0) const
Evaluate this function.
Definition TF1.cxx:1447
virtual Double_t GetXmin() const
Definition TF1.h:588
virtual Double_t GetParameter(Int_t ipar) const
Definition TF1.h:544
A 2-Dim function with parameters.
Definition TF2.h:29
void Paint(Option_t *option="") override
Paint this 2-D function with its current attributes.
Definition TF2.cxx:752
void SetRange(Double_t xmin, Double_t xmax) override
Initialize the upper and lower bounds to draw the function.
Definition TF2.h:148
static TClass * Class()
A 3-Dim function with parameters.
Definition TF3.h:28
The axis painter class.
Definition TGaxis.h:26
void SetTimeFormat(const char *tformat)
Change the format used for time plotting.
Definition TGaxis.cxx:2944
virtual void PaintAxis(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax, Double_t &wmin, Double_t &wmax, Int_t &ndiv, Option_t *chopt="", Double_t gridlength=0, Bool_t drawGridOnly=kFALSE)
Control function to draw an axis.
Definition TGaxis.cxx:1008
void SetTitleOffset(Float_t titleoffset=1)
Definition TGaxis.h:130
virtual void SetTitle(const char *title="")
Change the title of the axis.
Definition TGaxis.cxx:2917
void SetLabelOffset(Float_t labeloffset)
Definition TGaxis.h:108
virtual void ImportAxisAttributes(TAxis *axis)
Internal method to import TAxis attributes to this TGaxis.
Definition TGaxis.cxx:955
void SetTickSize(Float_t ticksize)
Definition TGaxis.h:124
void SetLabelSize(Float_t labelsize)
Definition TGaxis.h:109
void SetOption(Option_t *option="")
To set axis options.
Definition TGaxis.cxx:2909
Graphics object made of three arrays X, Y and Z with the same number of points each.
Definition TGraph2D.h:41
static TClass * Class()
TGraphDelaunay2D generates a Delaunay triangulation of a TGraph2D.
TGraphDelaunay generates a Delaunay triangulation of a TGraph2D.
A TGraph is an object made of two arrays X and Y with npoints each.
Definition TGraph.h:41
static TClass * Class()
@ kClipFrame
Clip to the frame boundary.
Definition TGraph.h:75
void PaintGraph(Int_t npoints, const Double_t *x, const Double_t *y, Option_t *chopt)
Draw the (x,y) as a graph.
Definition TGraph.cxx:1987
void PaintGrapHist(Int_t npoints, const Double_t *x, const Double_t *y, Option_t *chopt)
Draw the (x,y) as a histogram.
Definition TGraph.cxx:1996
1-D histogram with a double per channel (see TH1 documentation)
Definition TH1.h:925
1-D histogram with a float per channel (see TH1 documentation)
Definition TH1.h:877
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:108
TAxis * GetZaxis()
Definition TH1.h:573
virtual EBinErrorOpt GetBinErrorOption() const
Definition TH1.h:517
virtual Float_t GetBarWidth() const
Definition TH1.h:501
virtual Double_t GetMinimumStored() const
Definition TH1.h:537
virtual Float_t GetBarOffset() const
Definition TH1.h:500
static TClass * Class()
virtual Double_t GetStdDev(Int_t axis=1) const
Returns the Standard Deviation (Sigma).
Definition TH1.cxx:7598
virtual Int_t GetNbinsY() const
Definition TH1.h:542
virtual Double_t GetBinError(Int_t bin) const
Return value of error associated to bin number bin.
Definition TH1.cxx:9056
virtual Int_t GetNbinsZ() const
Definition TH1.h:543
virtual Double_t GetNormFactor() const
Definition TH1.h:545
virtual Double_t GetMean(Int_t axis=1) const
For axis = 1,2 or 3 returns the mean value of the histogram along X,Y or Z axis.
Definition TH1.cxx:7526
virtual Double_t GetSkewness(Int_t axis=1) const
Definition TH1.cxx:7662
virtual Double_t GetContourLevelPad(Int_t level) const
Return the value of contour number "level" in Pad coordinates.
Definition TH1.cxx:8436
virtual Int_t GetDimension() const
Definition TH1.h:527
static void AddDirectory(Bool_t add=kTRUE)
Sets the flag controlling the automatic add of histograms in memory.
Definition TH1.cxx:1264
@ kNoTitle
Don't draw the histogram title.
Definition TH1.h:408
@ kUserContour
User specified contour levels.
Definition TH1.h:404
@ kNoStats
Don't draw stats box.
Definition TH1.h:403
TAxis * GetXaxis()
Definition TH1.h:571
virtual Double_t GetSumOfWeights() const
Return the sum of weights across all bins excluding under/overflows.
Definition TH1.h:559
virtual Int_t GetBin(Int_t binx, Int_t biny=0, Int_t binz=0) const
Return Global bin number corresponding to binx,y,z.
Definition TH1.cxx:4964
virtual Double_t GetMaximum(Double_t maxval=FLT_MAX) const
Return maximum value smaller than maxval of bins in the range, unless the value has been overridden b...
Definition TH1.cxx:8541
virtual Int_t GetNbinsX() const
Definition TH1.h:541
virtual void SetMaximum(Double_t maximum=-1111)
Definition TH1.h:651
TAxis * GetYaxis()
Definition TH1.h:572
virtual Double_t GetBinErrorLow(Int_t bin) const
Return lower error associated to bin number bin.
Definition TH1.cxx:9072
virtual void SetMinimum(Double_t minimum=-1111)
Definition TH1.h:652
virtual Double_t Integral(Option_t *option="") const
Return integral of bin contents.
Definition TH1.cxx:7937
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:9215
virtual Double_t GetBinLowEdge(Int_t bin) const
Return bin lower edge for 1D histogram.
Definition TH1.cxx:9145
virtual Double_t GetEntries() const
Return the current number of entries.
Definition TH1.cxx:4401
TList * GetListOfFunctions() const
Definition TH1.h:488
virtual Double_t GetMeanError(Int_t axis=1) const
Return standard error of mean of this histogram along the X axis.
Definition TH1.cxx:7566
virtual Double_t GetMaximumStored() const
Definition TH1.h:533
virtual void GetMinimumAndMaximum(Double_t &min, Double_t &max) const
Retrieve the minimum and maximum values in the histogram.
Definition TH1.cxx:8727
@ kNormal
Errors with Normal (Wald) approximation: errorUp=errorLow= sqrt(N)
Definition TH1.h:114
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition TH1.cxx:5064
virtual Int_t GetContour(Double_t *levels=nullptr)
Return contour values into array levels if pointer levels is non zero.
Definition TH1.cxx:8407
const Double_t * GetBuffer() const
Definition TH1.h:483
virtual Bool_t IsHighlight() const
Definition TH1.h:585
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width for 1D histogram.
Definition TH1.cxx:9156
virtual void SetContour(Int_t nlevels, const Double_t *levels=nullptr)
Set the number and values of contour levels.
Definition TH1.cxx:8479
virtual Double_t GetBinErrorUp(Int_t bin) const
Return upper error associated to bin number bin.
Definition TH1.cxx:9103
virtual Int_t GetSumw2N() const
Definition TH1.h:562
virtual Double_t GetStdDevError(Int_t axis=1) const
Return error of standard deviation estimation for Normal distribution.
Definition TH1.cxx:7646
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:8631
static Bool_t AddDirectoryStatus()
Static function: cannot be inlined on Windows/NT.
Definition TH1.cxx:742
virtual void LabelsDeflate(Option_t *axis="X")
Reduce the number of bins for the axis passed in the option to the number of bins having a label.
Definition TH1.cxx:5248
virtual Int_t BufferEmpty(Int_t action=0)
Fill histogram with all entries in the buffer.
Definition TH1.cxx:1384
virtual Double_t GetKurtosis(Int_t axis=1) const
Definition TH1.cxx:7735
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:31
static TClass * Class()
The Histogram stack class.
Definition THStack.h:40
static TClass * Class()
The histogram painter class.
static Int_t ProjectSinusoidal2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function code for sinusoidal projection from Ernst-Jan Buis Source https://en....
void Paint(Option_t *option="") override
Control routine to paint any kind of histograms
TAxis * fYaxis
Pointer to Y axis.
std::unique_ptr< TPainter3dAlgorithms > fLego
Pointer to a TPainter3dAlgorithms object.
std::vector< Double_t > fXbuf
X buffer coordinates.
Int_t fXHighlightBin
X highlight bin.
TF3 * fCurrentF3
Current TF3 function.
virtual void PaintErrors(Option_t *option)
Draw 1D histograms error bars.
~THistPainter() override
destructor.
Int_t fShowProjection2
True if a second projection must be drawn (when calling SetShowProjectionXY on a TH2)
virtual void PaintTF3()
Control function to draw a 3D implicit functions.
virtual Int_t TableInit()
Initialize various options to draw 2D histograms.
virtual void PaintTH2PolyScatterPlot(Option_t *option)
Control function to draw a TH2Poly as a scatter plot.
static Int_t ProjectMollweide2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
static Int_t ProjectAitoff2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
virtual void PaintText(Option_t *option)
Control function to draw a 1D/2D histograms with the bin values.
Int_t DistancetoPrimitive(Int_t px, Int_t py) override
Compute the distance from the point px,py to a line.
virtual void PaintAxis(Bool_t drawGridOnly=kFALSE)
Draw axis (2D case) of an histogram.
virtual void PaintColorLevelsFast(Option_t *option)
[Rendering scheme for the COL2 and COLZ2 options] (HP14)
virtual Int_t PaintInit()
Compute histogram parameters used by the drawing routines.
virtual void Paint2DErrors(Option_t *option)
Draw 2D histograms errors.
Int_t fYHighlightBin
Y highlight bin.
virtual void PaintCandlePlot(Option_t *option)
Control function to draw a 2D histogram as a candle (box) plot or violin plot
virtual void PaintScatterPlot(Option_t *option)
Control function to draw a 2D histogram as a scatter plot.
void SetShowProjectionXY(const char *option, Int_t nbinsY, Int_t nbinsX) override
virtual void PaintLego(Option_t *option)
Control function to draw a 2D histogram as a lego plot.
virtual void PaintH3(Option_t *option="")
Control function to draw a 3D histograms.
Int_t fNcuts
Number of graphical cuts.
TString fShowOption
Option to draw the projection.
virtual void PaintHighlightBin(Option_t *option="")
Paint highlight bin as TBox object.
virtual void PaintTH2PolyBins(Option_t *option)
Control function to draw a TH2Poly bins' contours.
virtual Int_t PaintContourLine(Double_t elev1, Int_t icont1, Double_t x1, Double_t y1, Double_t elev2, Int_t icont2, Double_t x2, Double_t y2, Double_t *xarr, Double_t *yarr, Int_t *itarr, Double_t *levels)
Fill the matrix xarr and yarr for Contour Plot.
Int_t fShowProjection
True if a projection must be drawn.
virtual void PaintLegoAxis(TGaxis *axis, Double_t ang)
Draw the axis for legos and surface plots.
virtual void PaintTriangles(Option_t *option)
Control function to draw a table using Delaunay triangles.
virtual void HighlightBin(Int_t px, Int_t py)
Check on highlight bin.
virtual void PaintH3Box(Int_t iopt)
Control function to draw a 3D histogram with boxes.
Int_t MakeCuts(char *cutsopt) override
Decode string choptin and fill Graphical cuts structure.
TList * fFunctions
Pointer to histogram list of functions.
void DrawPanel() override
Display a panel with all histogram drawing options.
std::unique_ptr< TPie > fPie
Pointer to a TPie in case of option PIE.
static void PaintSpecialObjects(const TObject *obj, Option_t *option)
Static function to paint special objects like vectors and matrices.
virtual void PaintTitle()
new TGaxis/////////////////// Draw the histogram title
virtual void PaintTH2PolyColorLevels(Option_t *option)
Control function to draw a TH2Poly as a color plot.
virtual std::vector< THistRenderingRegion > ComputeRenderingRegions(TAxis *pAxis, Int_t nPixels, bool isLog)
Returns the rendering regions for an axis to use in the COL2 option.
virtual void ShowProjectionX(Int_t px, Int_t py)
Show projection onto X.
virtual void PaintPalette()
Paint the color palette on the right side of the pad.
TAxis * fXaxis
Pointer to X axis.
virtual void PaintStat2(Int_t dostat, TF1 *fit)
Draw the statistics box for 2D histograms.
virtual void PaintArrows(Option_t *option)
Control function to draw a table as an arrow plot
virtual void RecalculateRange()
Recompute the histogram range following graphics operations.
void PaintStat(Int_t dostat, TF1 *fit) override
Draw the statistics box for 1D and profile histograms.
static Int_t ProjectParabolic2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function code for parabolic projection from Ernst-Jan Buis.
std::unique_ptr< TGraph2DPainter > fGraph2DPainter
Pointer to a TGraph2DPainter object.
virtual void PaintBarH(Option_t *option)
Draw a bar char in a rotated pad (X vertical, Y horizontal)
virtual void PaintStat3(Int_t dostat, TF1 *fit)
Draw the statistics box for 3D histograms.
virtual void PaintSurface(Option_t *option)
Control function to draw a 2D histogram as a surface plot.
TList * fStack
Pointer to stack of histograms (if any)
THistPainter()
Default constructor.
TH1 * fH
Pointer to histogram to paint.
virtual void PaintTH2PolyText(Option_t *option)
Control function to draw a TH2Poly as a text plot.
virtual void ShowProjection3(Int_t px, Int_t py)
Show projection (specified by fShowProjection) of a TH3.
TAxis * fZaxis
Pointer to Z axis.
void SetHistogram(TH1 *h) override
Set current histogram to h
virtual void PaintFunction(Option_t *option)
[Paint functions associated to an histogram.](HP28")
virtual void PaintBar(Option_t *option)
Draw a bar-chart in a normal pad.
static Int_t ProjectMercator2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
virtual void PaintBoxes(Option_t *option)
Control function to draw a 2D histogram as a box plot
virtual Int_t MakeChopt(Option_t *option)
Decode string choptin and fill Hoption structure.
char * GetObjectInfo(Int_t px, Int_t py) const override
Display the histogram info (bin number, contents, integral up to bin corresponding to cursor position...
TList * GetContourList(Double_t contour) const override
Get a contour (as a list of TGraphs) using the Delaunay triangulation.
void ProcessMessage(const char *mess, const TObject *obj) override
Process message mess.
void SetShowProjection(const char *option, Int_t nbins) override
Set projection.
virtual void ShowProjectionY(Int_t px, Int_t py)
Show projection onto Y.
static const char * GetBestFormat(Double_t v, Double_t e, const char *f)
This function returns the best format to print the error value (e) knowing the parameter value (v) an...
virtual void PaintContour(Option_t *option)
Control function to draw a 2D histogram as a contour plot.
TCutG * fCuts[kMaxCuts]
Pointers to graphical cuts.
virtual void PaintTable(Option_t *option)
Control function to draw 2D/3D histograms (tables).
void ExecuteEvent(Int_t event, Int_t px, Int_t py) override
Execute the actions corresponding to event.
virtual Int_t PaintInitH()
Compute histogram parameters used by the drawing routines for a rotated pad.
virtual void PaintFrame()
Calculate range and clear pad (canvas).
Int_t fCutsOpt[kMaxCuts]
Sign of each cut.
virtual void PaintH3Iso()
Control function to draw a 3D histogram with Iso Surfaces.
std::vector< Double_t > fYbuf
Y buffer coordinates.
virtual void PaintH3BoxRaster()
Control function to draw a 3D histogram with boxes.
virtual void PaintHist(Option_t *option)
Control routine to draw 1D histograms
void SetHighlight() override
Set highlight (enable/disable) mode for fH.
virtual void DefineColorLevels(Int_t ndivz)
Define the color levels used to paint legos, surfaces etc..
TString fObjectInfo
virtual void PaintColorLevels(Option_t *option)
Control function to draw a 2D histogram as a color plot.
Bool_t IsInside(Int_t x, Int_t y) override
Return kTRUE if the cell ix, iy is inside one of the graphical cuts.
A class to define a conversion from pixel values to pixel color.
Definition TAttImage.h:33
static TImagePalette * CreateCOLPalette(Int_t nContours)
Factory method to creates an image palette for histogram plotting.
An abstract interface to image processing library.
Definition TImage.h:29
static TImage * Create()
Create an image.
Definition TImage.cxx:35
void Reset()
To draw Mathematical Formula.
Definition TLatex.h:18
A doubly linked list.
Definition TList.h:38
TObject * FindObject(const char *name) const override
Find an object in this list using its name.
Definition TList.cxx:576
void Add(TObject *obj) override
Definition TList.h:81
TObject * Remove(TObject *obj) override
Remove object from the list.
Definition TList.cxx:820
TObject * First() const override
Return the first object in the list. Returns 0 when list is empty.
Definition TList.cxx:657
virtual TObjLink * FirstLink() const
Definition TList.h:102
TObject * At(Int_t idx) const override
Returns the object at position idx. Returns 0 if idx is out of range.
Definition TList.cxx:355
void AddFirst(TObject *obj) override
Add object at the beginning of the list.
Definition TList.cxx:98
TMatrixTBase.
static TClass * Class()
A TMultiGraph is a collection of TGraph (or derived) objects.
Definition TMultiGraph.h:34
TList * GetListOfGraphs() const
Definition TMultiGraph.h:68
static TClass * Class()
virtual Int_t IsInside(Double_t x, Double_t y) const
Return 1 if the point (x,y) is inside one of the graphs 0 otherwise.
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:50
An array of TObjects.
Definition TObjArray.h:31
Mother of all ROOT objects.
Definition TObject.h:41
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:457
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:205
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:204
@ kCannotPick
if object in a pad cannot be picked
Definition TObject.h:73
@ kCanDelete
if object in a list can be deleted
Definition TObject.h:68
@ kMustCleanup
if object destructor must call RecursiveRemove()
Definition TObject.h:70
void DrawFaceMove3(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 3rd variant for "MOVING SCREEN" algorithm (draw level lines only)
void DrawLevelLines(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw level lines without hidden line removal.
void SurfaceFunction(Int_t ia, Int_t ib, Double_t *f, Double_t *t)
Service function for Surfaces.
void DrawFaceMode1(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *t)
Draw face - 1st variant (2 colors: 1st for external surface, 2nd for internal)
void GouraudFunction(Int_t ia, Int_t ib, Double_t *f, Double_t *t)
Find part of surface with luminosity in the corners.
void DrawFaceMove1(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 1st variant for "MOVING SCREEN" algorithm (draw face with level lines)
void DrawFaceRaster2(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 2nd variant for "RASTER SCREEN" algorithm (draw face for stacked lego plot)
void LegoFunction(Int_t ia, Int_t ib, Int_t &nv, Double_t *ab, Double_t *vv, Double_t *t)
Service function for Legos.
void DrawFaceMove2(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 2nd variant for "MOVING SCREEN" algorithm (draw face for stacked lego plot)
void DrawFaceRaster1(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 1st variant for "RASTER SCREEN" algorithm (draw face with level lines)
void DrawFaceMode3(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *t)
Draw face - 3rd option (draw face for stacked lego plot)
void DrawFaceMode2(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *t)
Draw face - 2nd option (fill in correspondence with function levels)
The palette painting class.
The histogram statistics painter class.
Definition TPaveStats.h:18
static TClass * Class()
A Pave (see TPave) with text, lines or/and boxes inside.
Definition TPaveText.h:21
static TClass * Class()
virtual TText * GetLine(Int_t number) const
Get Pointer to line number in this pavetext.
const char * GetName() const override
Returns name of object.
Definition TPave.h:58
Double_t GetX1NDC() const
Definition TPave.h:61
virtual void SetX2NDC(Double_t x2)
Definition TPave.h:85
void SetX(SCoord_t x)
Definition TPoint.h:48
void SetY(SCoord_t y)
Definition TPoint.h:49
Profile2D histograms are used to display the mean value of Z and its error for each cell in X,...
Definition TProfile2D.h:27
static TClass * Class()
Profile Histogram.
Definition TProfile.h:32
static TClass * Class()
Random number generator class based on the maximally quidistributed combined Tausworthe generator by ...
Definition TRandom2.h:27
Sequenceable collection abstract base class.
Basic string class.
Definition TString.h:139
void ToLower()
Change string to lower-case.
Definition TString.cxx:1182
const char * Data() const
Definition TString.h:376
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2378
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2356
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:632
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:651
Int_t GetOptStat() const
Definition TStyle.h:247
Color_t GetStatTextColor() const
Definition TStyle.h:260
Float_t GetTitleX() const
Definition TStyle.h:282
Int_t GetOptTitle() const
Definition TStyle.h:248
Float_t GetStatFontSize() const
Definition TStyle.h:263
Float_t GetBarOffset() const
Definition TStyle.h:184
Float_t GetStatX() const
Definition TStyle.h:266
Float_t GetTitleSize(Option_t *axis="X") const
Return title size.
Definition TStyle.cxx:1242
Float_t GetTitleY() const
Definition TStyle.h:283
Style_t GetTitleFont(Option_t *axis="X") const
Return title font.
Definition TStyle.cxx:1218
Bool_t GetHistMinimumZero() const
Definition TStyle.h:239
Float_t GetStatY() const
Definition TStyle.h:267
Color_t GetTitleFillColor() const
Definition TStyle.h:273
Style_t GetTitleStyle() const
Definition TStyle.h:275
Color_t GetStatColor() const
Definition TStyle.h:259
Float_t GetBarWidth() const
Definition TStyle.h:185
void SetDrawBorder(Int_t drawborder=1)
Definition TStyle.h:346
Float_t GetStatH() const
Definition TStyle.h:269
Width_t GetTitleBorderSize() const
Definition TStyle.h:277
Int_t GetColorPalette(Int_t i) const
Return color number i in current palette.
Definition TStyle.cxx:1103
Float_t GetErrorX() const
Definition TStyle.h:188
Double_t GetHistTopMargin() const
Definition TStyle.h:240
void SetBarOffset(Float_t baroff=0.5)
Definition TStyle.h:339
Float_t GetEndErrorSize() const
Definition TStyle.h:187
Int_t GetDrawBorder() const
Definition TStyle.h:186
Width_t GetStatBorderSize() const
Definition TStyle.h:261
Color_t GetTitleTextColor() const
Definition TStyle.h:274
void SetBarWidth(Float_t barwidth=0.5)
Definition TStyle.h:340
Float_t GetTitleH() const
Definition TStyle.h:285
Style_t GetStatStyle() const
Definition TStyle.h:264
Float_t GetStatW() const
Definition TStyle.h:268
const char * GetFitFormat() const
Definition TStyle.h:201
const char * GetStatFormat() const
Definition TStyle.h:265
Int_t GetNumberOfColors() const
Return number of colors in the color palette.
Definition TStyle.cxx:1177
Int_t GetOptFit() const
Definition TStyle.h:246
Int_t GetNumberContours() const
Definition TStyle.h:243
const char * GetPaintTextFormat() const
Definition TStyle.h:252
Style_t GetStatFont() const
Definition TStyle.h:262
Float_t GetTitleFontSize() const
Definition TStyle.h:276
Int_t GetTitleAlign() const
Definition TStyle.h:272
Float_t GetTitleW() const
Definition TStyle.h:284
virtual int Load(const char *module, const char *entry="", Bool_t system=kFALSE)
Load a shared library.
Definition TSystem.cxx:1869
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:697
Short_t Max(Short_t a, Short_t b)
Returns the largest of a and b.
Definition TMathBase.h:250
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:644
constexpr Double_t PiOver2()
Definition TMath.h:51
Double_t Log(Double_t x)
Returns the natural logarithm of x.
Definition TMath.h:760
constexpr Double_t DegToRad()
Conversion from degree to radian: .
Definition TMath.h:79
Double_t Sqrt(Double_t x)
Returns the square root of x.
Definition TMath.h:666
LongDouble_t Power(LongDouble_t x, LongDouble_t y)
Returns x raised to the power y.
Definition TMath.h:725
Short_t Min(Short_t a, Short_t b)
Returns the smallest of a and b.
Definition TMathBase.h:198
Double_t Cos(Double_t)
Returns the cosine of an angle of x radians.
Definition TMath.h:598
constexpr Double_t Pi()
Definition TMath.h:37
Bool_t AreEqualRel(Double_t af, Double_t bf, Double_t relPrec)
Comparing floating points.
Definition TMath.h:426
Double_t Sin(Double_t)
Returns the sine of an angle of x radians.
Definition TMath.h:592
Double_t Tan(Double_t)
Returns the tangent of an angle of x radians.
Definition TMath.h:604
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:347
constexpr Double_t RadToDeg()
Conversion from radian to degree: .
Definition TMath.h:72
Double_t Log10(Double_t x)
Returns the common (base-10) logarithm of x.
Definition TMath.h:766
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:123
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