Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
THistPainter.cxx
Go to the documentation of this file.
1// @(#)root/histpainter:$Id$
2// Author: Rene Brun, Olivier Couet
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12#include <cstdlib>
13#include <cstring>
14#include <cstdio>
15#include <cctype>
16#include <iostream>
17
18#include "TROOT.h"
19#include "TSystem.h"
20#include "THistPainter.h"
21#include "TH2.h"
22#include "TH2Poly.h"
23#include "TH3.h"
24#include "TProfile.h"
25#include "TProfile2D.h"
26#include "THStack.h"
27#include "TF2.h"
28#include "TF3.h"
29#include "TCutG.h"
30#include "TMatrixDBase.h"
31#include "TMatrixFBase.h"
32#include "TVectorD.h"
33#include "TVectorF.h"
34#include "TCanvas.h"
35#include "TPad.h"
36#include "TPaveStats.h"
37#include "TFrame.h"
38#include "TLatex.h"
39#include "TPolyLine.h"
40#include "TPoints.h"
41#include "TStyle.h"
42#include "TGraph.h"
43#include "TMultiGraph.h"
44#include "TPie.h"
45#include "TGaxis.h"
46#include "TColor.h"
48#include "TGraph2D.h"
49#include "TGraph2DPainter.h"
50#include "TGraphDelaunay2D.h"
51#include "TView.h"
52#include "TMath.h"
53#include "TRandom2.h"
54#include "TObjArray.h"
55#include "Hoption.h"
56#include "Hparam.h"
57#include "TPluginManager.h"
58#include "TPaletteAxis.h"
59#include "TCrown.h"
60#include "TArrow.h"
61#include "TVirtualPadEditor.h"
62#include "TVirtualX.h"
63#include "TEnv.h"
64#include "TPoint.h"
65#include "TImage.h"
66#include "TCandle.h"
67#include "strlcpy.h"
68
69/*! \class THistPainter
70 \ingroup Histpainter
71 \brief The histogram painter class. Implements all histograms' drawing's options.
72
73- [Introduction](\ref HP00)
74- [Histograms' plotting options](\ref HP01)
75 - [Options supported for 1D and 2D histograms](\ref HP01a)
76 - [Options supported for 1D histograms](\ref HP01b)
77 - [Options supported for 2D histograms](\ref HP01c)
78 - [Options supported for 3D histograms](\ref HP01d)
79 - [Options supported for histograms' stacks (THStack)](\ref HP01e)
80- [Setting the Style](\ref HP02)
81- [Setting line, fill, marker, and text attributes](\ref HP03)
82- [Setting Tick marks on the histogram axis](\ref HP04)
83- [Giving titles to the X, Y and Z axis](\ref HP05)
84- [The option SAME](\ref HP060)
85 - [Limitations](\ref HP060a)
86- [Colors automatically picked in palette](\ref HP061)
87- [Superimposing two histograms with different scales in the same pad](\ref HP06)
88- [Statistics Display](\ref HP07)
89- [Fit Statistics](\ref HP08)
90- [The error bars options](\ref HP09)
91- [The bar chart option](\ref HP100)
92- [The BAR and HBAR options](\ref HP10)
93- [The SCATter plot option (legacy draw option)](\ref HP11)
94- [The ARRow option](\ref HP12)
95- [The BOX option](\ref HP13)
96- [The COLor option (default for 2D and 3D histograms)](\ref HP14)
97- [The CANDLE and VIOLIN options](\ref HP140)
98 - [The CANDLE option](\ref HP140a)
99 - [The VIOLIN option](\ref HP140b)
100- [The TEXT and TEXTnn Option](\ref HP15)
101- [The CONTour options](\ref HP16)
102 - [The LIST option](\ref HP16a)
103 - [The AITOFF, MERCATOR, SINUSOIDAL and PARABOLIC options](\ref HP16b)
104- [The LEGO options](\ref HP17)
105- [The SURFace options](\ref HP18)
106- [Cylindrical, Polar, Spherical and PseudoRapidity/Phi options](\ref HP19)
107- [Base line for bar-charts and lego plots](\ref HP20)
108- [TH2Poly Drawing](\ref HP20a)
109- [The SPEC option](\ref HP21)
110- [Option Z : Adding the color palette on the right side of the pad](\ref HP22)
111- [Setting the color palette](\ref HP23)
112- [Drawing a sub-range of a 2-D histogram; the [cutg] option](\ref HP24)
113- [Drawing options for 3D histograms](\ref HP25)
114- [Drawing option for histograms' stacks](\ref HP26)
115- [Drawing of 3D implicit functions](\ref HP27)
116- [Associated functions drawing](\ref HP28)
117- [Drawing using OpenGL](\ref HP29)
118 - [General information: plot types and supported options](\ref HP29a)
119 - [TH3 as color boxes](\ref HP290)
120 - [TH3 as boxes (spheres)](\ref HP29b)
121 - [TH3 as iso-surface(s)](\ref HP29c)
122 - [TF3 (implicit function)](\ref HP29d)
123 - [Parametric surfaces](\ref HP29e)
124 - [Interaction with the plots](\ref HP29f)
125 - [Selectable parts](\ref HP29g)
126 - [Rotation and zooming](\ref HP29h)
127 - [Panning](\ref HP29i)
128 - [Box cut](\ref HP29j)
129 - [Plot specific interactions (dynamic slicing etc.)](\ref HP29k)
130 - [Surface with option GLSURF](\ref HP29l)
131 - [TF3](\ref HP29m)
132 - [Box](\ref HP29n)
133 - [Iso](\ref HP29o)
134 - [Parametric plot](\ref HP29p)
135- [Highlight mode for histogram](\ref HP30)
136 - [Highlight mode and user function](\ref HP30a)
137
138
139\anchor HP00
140## Introduction
141
142
143Histograms are drawn via the `THistPainter` class. Each histogram has a
144pointer to its own painter (to be usable in a multithreaded program). When the
145canvas has to be redrawn, the `Paint` function of each objects in the
146pad is called. In case of histograms, `TH1::Paint` invokes directly
147`THistPainter::Paint`.
148
149To draw a histogram `h` it is enough to do:
150
151 h->Draw();
152
153`h` can be of any kind: 1D, 2D or 3D. To choose how the histogram will
154be drawn, the `Draw()` method can be invoked with an option. For instance
155to draw a 2D histogram as a lego plot it is enough to do:
156
157 h->Draw("lego");
158
159`THistPainter` offers many options to paint 1D, 2D and 3D histograms.
160
161When the `Draw()` method of a histogram is called for the first time
162(`TH1::Draw`), it creates a `THistPainter` object and saves a
163pointer to this "painter" as a data member of the histogram. The
164`THistPainter` class specializes in the drawing of histograms. It is
165separated from the histogram so that one can have histograms without the
166graphics overhead, for example in a batch program. Each histogram having its own
167painter (rather than a central singleton painter painting all histograms), allows
168two histograms to be drawn in two threads without overwriting the painter's
169values.
170
171When a displayed histogram is filled again, there is no need to call the
172`Draw()` method again; the image will be refreshed the next time the
173pad will be updated.
174
175A pad is updated after one of these three actions:
176
1771. a carriage control on the ROOT command line,
1782. a click inside the pad,
1793. a call to `TPad::Update`.
180
181
182By default a call to `TH1::Draw()` clears the pad of all objects
183before drawing the new image of the histogram. One can use the `SAME`
184option to leave the previous display intact and superimpose the new histogram.
185The same histogram can be drawn with different graphics options in different
186pads.
187
188When a displayed histogram is deleted, its image is automatically removed
189from the pad.
190
191To create a copy of the histogram when drawing it, one can use
192`TH1::DrawClone()`. This will clone the histogram and allow to change
193and delete the original one without affecting the clone.
194
195
196\anchor HP01
197### Histograms' plotting options
198
199
200Most options can be concatenated with or without spaces or commas, for example:
201
202 h->Draw("E1 SAME");
203
204The options are not case sensitive:
205
206 h->Draw("e1 same");
207
208
209The default drawing option can be set with `TH1::SetOption` and retrieve
210using `TH1::GetOption`:
211
212 root [0] h->Draw(); // Draw "h" using the standard histogram representation.
213 root [1] h->Draw("E"); // Draw "h" using error bars
214 root [3] h->SetOption("E"); // Change the default drawing option for "h"
215 root [4] h->Draw(); // Draw "h" using error bars
216 root [5] h->GetOption(); // Retrieve the default drawing option for "h"
217 (const Option_t* 0xa3ff948)"E"
218
219
220\anchor HP01a
221#### Options supported for 1D and 2D histograms
222
223| Option | Description |
224|----------|-------------------------------------------------------------------|
225| "E" | Draw error bars. |
226| "AXIS" | Draw only axis. |
227| "AXIG" | Draw only grid (if the grid is requested). |
228| \anchor OPTHIST "HIST" | When an histogram has errors it is visualized by default with error bars. To visualize it without errors use the option "HIST" together with the required option (eg "hist same c"). The "HIST" option can also be used to plot only the histogram and not the associated function(s). |
229| "FUNC" | When an histogram has a fitted function, this option allows to draw the fit result only. |
230| "SAME" | Superimpose on previous picture in the same pad. |
231| "SAMES" | Same as "SAME" and draw the statistics box|
232| "PFC" | Palette Fill Color: histogram's fill color is taken in the current palette. |
233| "PLC" | Palette Line Color: histogram's line color is taken in the current palette. |
234| "PMC" | Palette Marker Color: histogram's marker color is taken in the current palette. |
235| "LEGO" | Draw a lego plot with hidden line removal. |
236| "LEGO1" | Draw a lego plot with hidden surface removal. |
237| "LEGO2" | Draw a lego plot using colors to show the cell contents When the option "0" is used with any LEGO option, the empty bins are not drawn.|
238| "LEGO3" | Draw a lego plot with hidden surface removal, like LEGO1 but the border lines of each lego-bar are not drawn.|
239| "LEGO4" | Draw a lego plot with hidden surface removal, like LEGO1 but without the shadow effect on each lego-bar.|
240| "TEXT" | Draw bin contents as text (format set via `gStyle->SetPaintTextFormat`).|
241| "TEXTnn" | Draw bin contents as text at angle nn (0 < nn <= 90). |
242| "X+" | The X-axis is drawn on the top side of the plot. |
243| "Y+" | The Y-axis is drawn on the right side of the plot. |
244| "MIN0" | Set minimum value for the Y axis to 0, equivalent to gStyle->SetHistMinimumZero(). |
245
246
247\anchor HP01b
248#### Options supported for 1D histograms
249
250| Option | Description |
251|----------|-------------------------------------------------------------------|
252| " " | Default. |
253| "AH" | Draw histogram without axis. "A" can be combined with any drawing option. For instance, "AC" draws the histogram as a smooth Curve without axis.|
254| "][" | When this option is selected the first and last vertical lines of the histogram are not drawn.|
255| "B" | Bar chart option.|
256| "BAR" | Like option "B", but bars can be drawn with a 3D effect.|
257| "HBAR" | Like option "BAR", but bars are drawn horizontally.|
258| "C" | Draw a smooth Curve through the histogram bins.|
259| "E0" | Draw error bars. Markers are drawn for bins with 0 contents. Combined with E1 or E2 it avoids error bars clipping|
260| "E1" | Draw error bars with perpendicular lines at the edges.|
261| "E2" | Draw error bars with rectangles.|
262| "E3" | Draw a fill area through the end points of the vertical error bars.|
263| "E4" | Draw a smoothed filled area through the end points of the error bars.|
264| "E5" | Like E3 but ignore the bins with 0 contents.|
265| "E6" | Like E4 but ignore the bins with 0 contents.|
266| "X0" | When used with one of the "E" option, it suppress the error bar along X as `gStyle->SetErrorX(0)` would do.|
267| "L" | Draw a line through the bin contents.|
268| "P" | Draw current marker at each bin except empty bins.|
269| "P*" | Draw a star marker at each bin except empty bins.|
270| "P0" | Draw current marker at each bin including empty bins.|
271| "PIE" | Draw histogram as a Pie Chart.|
272| "*H" | Draw histogram with a * at each bin.|
273| "LF2" | Draw histogram like with option "L" but with a fill area. Note that "L" draws also a fill area if the hist fill color is set but the fill area corresponds to the histogram contour.|
274
275
276
277\anchor HP01c
278#### Options supported for 2D histograms
279
280| Option | Description |
281|--------------|------------------------------------------------------------------|
282| " " | Default (color plot).|
283| "ARR" | Arrow mode. Shows gradient between adjacent cells.|
284| "BOX" | A box is drawn for each cell with surface proportional to the content's absolute value. A negative content is marked with a X. |
285| "BOX1" | A button is drawn for each cell with surface proportional to content's absolute value. A sunken button is drawn for negative values a raised one for positive.|
286| "COL" | A box is drawn for each cell with a color scale varying with contents. All the none empty bins (bins with content and error equal to 0) are painted. Empty bins are not painted unless some bins have a negative content because in that case the null bins might be not empty. `TProfile2D` histograms are handled differently because, for this type of 2D histograms, it is possible to know if an empty bin has been filled or not. So even if all the bins' contents are positive some empty bins might be painted. And vice versa, if some bins have a negative content some empty bins might be not painted (default).|
287| "COL1" | Same as "COL" but in case of histogram with negative content the empty bins are not drawn.
288| "COLZ" | Same as "COL". In addition the color palette is also drawn.|
289| "COL2" | Alternative rendering algorithm to "COL". Can significantly improve rendering performance for large, non-sparse 2-D histograms.|
290| "COLZ2" | Same as "COL2". In addition the color palette is also drawn.|
291| "Z CJUST" | In combination with colored options "COL","CONT0" etc: Justify labels in the color palette at color boundaries. For more details see `TPaletteAxis`|
292| "CANDLE" | Draw a candle plot along X axis.|
293| "CANDLEX" | Same as "CANDLE".|
294| "CANDLEY" | Draw a candle plot along Y axis.|
295| "CANDLEXn" | Draw a candle plot along X axis. Different candle-styles with n from 1 to 6.|
296| "CANDLEYn" | Draw a candle plot along Y axis. Different candle-styles with n from 1 to 6.|
297| "VIOLIN" | Draw a violin plot along X axis.|
298| "VIOLINX" | Same as "VIOLIN".|
299| "VIOLINY" | Draw a violin plot along Y axis.|
300| "VIOLINXn" | Draw a violin plot along X axis. Different violin-styles with n being 1 or 2.|
301| "VIOLINYn" | Draw a violin plot along Y axis. Different violin-styles with n being 1 or 2.|
302| "CONT" | Draw a contour plot (same as CONT0).|
303| "CONT0" | Draw a contour plot using surface colors to distinguish contours.|
304| "CONT1" | Draw a contour plot using line styles to distinguish contours.|
305| "CONT2" | Draw a contour plot using the same line style for all contours.|
306| "CONT3" | Draw a contour plot using fill area colors.|
307| "CONT4" | Draw a contour plot using surface colors (SURF option at theta = 0).|
308| "LIST" | Generate a list of TGraph objects for each contour.|
309| "SAME0" | Same as "SAME" but do not use the z-axis range of the first plot. |
310| "SAMES0" | Same as "SAMES" but do not use the z-axis range of the first plot. |
311| "CYL" | Use Cylindrical coordinates. The X coordinate is mapped on the angle and the Y coordinate on the cylinder length.|
312| "POL" | Use Polar coordinates. The X coordinate is mapped on the angle and the Y coordinate on the radius.|
313| "SPH" | Use Spherical coordinates. The X coordinate is mapped on the latitude and the Y coordinate on the longitude.|
314| "PSR" | Use PseudoRapidity/Phi coordinates. The X coordinate is mapped on Phi.|
315| "SURF" | Draw a surface plot with hidden line removal.|
316| "SURF1" | Draw a surface plot with hidden surface removal.|
317| "SURF2" | Draw a surface plot using colors to show the cell contents.|
318| "SURF3" | Same as SURF with in addition a contour view drawn on the top.|
319| "SURF4" | Draw a surface using Gouraud shading.|
320| "SURF5" | Same as SURF3 but only the colored contour is drawn. Used with option CYL, SPH or PSR it allows to draw colored contours on a sphere, a cylinder or a in pseudo rapidity space. In cartesian or polar coordinates, option SURF3 is used.|
321| "AITOFF" | Draw a contour via an AITOFF projection.|
322| "MERCATOR" | Draw a contour via an Mercator projection.|
323| "SINUSOIDAL" | Draw a contour via an Sinusoidal projection.|
324| "PARABOLIC" | Draw a contour via an Parabolic projection.|
325| "MOLLWEIDE" | Draw a contour via an Mollweide projection.|
326| "LEGO9" | Draw the 3D axis only. Mainly needed for internal use |
327| "FB" | With LEGO or SURFACE, suppress the Front-Box.|
328| "BB" | With LEGO or SURFACE, suppress the Back-Box.|
329| "A" | With LEGO or SURFACE, suppress the axis.|
330| "SCAT" | Draw a scatter-plot (legacy draw option).|
331| "[cutg]" | Draw only the sub-range selected by the TCutG named "cutg".|
332
333
334
335\anchor HP01d
336#### Options supported for 3D histograms
337
338| Option | Description |
339|----------|-------------------------------------------------------------------|
340| " " | Default (color plot).|
341| "ISO" | Draw a Gouraud shaded 3d iso surface through a 3d histogram. It paints one surface at the value computed as follow: `SumOfWeights/(NbinsX*NbinsY*NbinsZ)`.|
342| "BOX" | Draw a for each cell with volume proportional to the content's absolute value. An hidden line removal algorithm is used|
343| "BOX1" | Same as BOX but an hidden surface removal algorithm is used|
344| "BOX2" | The boxes' colors are picked in the current palette according to the bins' contents|
345| "BOX2Z" | Same as "BOX2". In addition the color palette is also drawn.|
346| "BOX3" | Same as BOX1, but the border lines of each lego-bar are not drawn.|
347| "LEGO" | Same as `BOX`.|
348
349\anchor HP01e
350#### Options supported for histograms' stacks (`THStack`)
351
352| Option | Description |
353|------------|-----------------------------------------------------------------|
354| " " | Default, the histograms are drawn on top of each other (as lego plots for 2D histograms).|
355| "NOSTACK" | Histograms in the stack are all paint in the same pad as if the option `SAME` had been specified.|
356| "NOSTACKB" | Histograms are drawn next to each other as bar charts.|
357| "PADS" | The current pad/canvas is subdivided into a number of pads equal to the number of histograms in the stack and each histogram is paint into a separate pad.|
358| "PFC" | Palette Fill Color: stack's fill color is taken in the current palette. |
359| "PLC" | Palette Line Color: stack's line color is taken in the current palette. |
360| "PMC" | Palette Marker Color: stack's marker color is taken in the current palette. |
361
362
363
364\anchor HP02
365### Setting the Style
366
367
368Histograms use the current style (`gStyle`). When one changes the current
369style and would like to propagate the changes to the histogram,
370`TH1::UseCurrentStyle` should be called. Call `UseCurrentStyle` on
371each histogram is needed.
372
373To force all the histogram to use the current style use:
374
375 gROOT->ForceStyle();
376
377All the histograms read after this call will use the current style.
378
379
380\anchor HP03
381### Setting line, fill, marker, and text attributes
382
383
384The histogram classes inherit from the attribute classes:
385`TAttLine`, `TAttFill` and `TAttMarker`.
386See the description of these classes for the list of options.
387
388
389\anchor HP04
390### Setting Tick marks on the histogram axis
391
392
393The `TPad::SetTicks` method specifies the type of tick marks on the axis.
394If ` tx = gPad->GetTickx()` and `ty = gPad->GetTicky()` then:
395
396 tx = 1; tick marks on top side are drawn (inside)
397 tx = 2; tick marks and labels on top side are drawn
398 ty = 1; tick marks on right side are drawn (inside)
399 ty = 2; tick marks and labels on right side are drawn
400
401By default only the left Y axis and X bottom axis are drawn
402(`tx = ty = 0`)
403
404`TPad::SetTicks(tx,ty)` allows to set these options.
405See also The `TAxis` functions to set specific axis attributes.
406
407In case multiple color filled histograms are drawn on the same pad, the fill
408area may hide the axis tick marks. One can force a redraw of the axis over all
409the histograms by calling:
410
411 gPad->RedrawAxis();
412
413
414\anchor HP05
415### Giving titles to the X, Y and Z axis
416
417
418 h->GetXaxis()->SetTitle("X axis title");
419 h->GetYaxis()->SetTitle("Y axis title");
420
421The histogram title and the axis titles can be any `TLatex` string.
422The titles are part of the persistent histogram.
423
424
425\anchor HP060
426### The option "SAME"
427
428
429By default, when an histogram is drawn, the current pad is cleared before
430drawing. In order to keep the previous drawing and draw on top of it the
431option `SAME` should be use. The histogram drawn with the option
432`SAME` uses the coordinates system available in the current pad.
433
434This option can be used alone or combined with any valid drawing option but
435some combinations must be use with care.
436
437\anchor HP060a
438#### Limitations
439
440- It does not work when combined with the `LEGO` and `SURF` options unless the
441 histogram plotted with the option `SAME` has exactly the same
442 ranges on the X, Y and Z axis as the currently drawn histogram. To superimpose
443 lego plots [histograms' stacks](\ref HP26) should be used.
444
445
446\anchor HP061
447### Colors automatically picked in palette
448
449\since **ROOT version 6.09/01**
450
451When several histograms are painted in the same canvas thanks to the option "SAME"
452or via a `THStack` it might be useful to have an easy and automatic way to choose
453their color. The simplest way is to pick colors in the current active color
454palette. Palette coloring for histogram is activated thanks to the options `PFC`
455(Palette Fill Color), `PLC` (Palette Line Color) and `PMC` (Palette Marker Color).
456When one of these options is given to `TH1::Draw` the histogram get its color
457from the current color palette defined by `gStyle->SetPalette(...)`. The color
458is determined according to the number of objects having palette coloring in
459the current pad.
460
461Begin_Macro(source)
462../../../tutorials/hist/hist005_TH1_palettecolor.C
463End_Macro
464
465Begin_Macro(source)
466../../../tutorials/hist/hist027_THStack_palette_color.C
467End_Macro
468
469Begin_Macro(source)
470../../../tutorials/hist/hist025_THStack_2d_palette_color.C
471End_Macro
472
473\anchor HP06
474### Superimposing two histograms with different scales in the same pad
475
476
477The following example creates two histograms, the second histogram is the bins
478integral of the first one. It shows a procedure to draw the two histograms in
479the same pad and it draws the scale of the second histogram using a new vertical
480axis on the right side. See also the tutorial `transpad.C` for a variant
481of this example.
482
483Begin_Macro(source)
484{
485 auto c1 = new TCanvas("c1","c1",600,400);
486 // create/fill draw h1
487 gStyle->SetOptStat(kFALSE);
488 auto h1 = new TH1F("h1","Superimposing two histograms with different scales",100,-3,3);
489 Int_t i;
490 for (i=0;i<10000;i++) h1->Fill(gRandom->Gaus(0,1));
491 h1->Draw();
492 c1->Update();
493
494 // create hint1 filled with the bins integral of h1
495 auto hint1 = new TH1F("hint1","h1 bins integral",100,-3,3);
496 float sum = 0.f;
497 for (i=1;i<=100;i++) {
498 sum += h1->GetBinContent(i);
499 hint1->SetBinContent(i,sum);
500 }
501
502 // scale hint1 to the pad coordinates
503 float rightmax = 1.1*hint1->GetMaximum();
504 float scale = gPad->GetUymax()/rightmax;
505 hint1->SetLineColor(kRed);
506 hint1->Scale(scale);
507 hint1->Draw("same");
508
509 // draw an axis on the right side
510 auto axis = new TGaxis(gPad->GetUxmax(),gPad->GetUymin(),
511 gPad->GetUxmax(), gPad->GetUymax(),0,rightmax,510,"+L");
512 axis->SetLineColor(kRed);
513 axis->SetTextColor(kRed);
514 axis->Draw();
515}
516End_Macro
517
518
519\anchor HP07
520### Statistics Display
521
522
523The type of information shown in the histogram statistics box can be selected
524with:
525
526 gStyle->SetOptStat(mode);
527
528The `mode` has up to nine digits that can be set to on (1 or 2), off (0).
529
530 mode = ksiourmen (default = 000001111)
531 k = 1; kurtosis printed
532 k = 2; kurtosis and kurtosis error printed
533 s = 1; skewness printed
534 s = 2; skewness and skewness error printed
535 i = 1; integral of bins printed
536 i = 2; integral of bins with option "width" printed
537 o = 1; number of overflows printed
538 u = 1; number of underflows printed
539 r = 1; standard deviation printed
540 r = 2; standard deviation and standard deviation error printed
541 m = 1; mean value printed
542 m = 2; mean and mean error values printed
543 e = 1; number of entries printed
544 n = 1; name of histogram is printed
545
546For example:
547
548 gStyle->SetOptStat(11);
549
550displays only the name of histogram and the number of entries, whereas:
551
552 gStyle->SetOptStat(1101);
553
554displays the name of histogram, mean value and standard deviation.
555
556<b>WARNING 1:</b> never do:
557
558 gStyle->SetOptStat(0001111);
559
560but instead do:
561
562 gStyle->SetOptStat(1111);
563
564because `0001111` will be taken as an octal number!
565
566<b>WARNING 2:</b> for backward compatibility with older versions
567
568 gStyle->SetOptStat(1);
569
570is taken as:
571
572 gStyle->SetOptStat(1111)
573
574To print only the name of the histogram do:
575
576 gStyle->SetOptStat(1000000001);
577
578<b>NOTE</b> that in case of 2D histograms, when selecting only underflow
579(10000) or overflow (100000), the statistics box will show all combinations
580of underflow/overflows and not just one single number.
581
582The parameter mode can be any combination of the letters `kKsSiIourRmMen`
583
584 k : kurtosis printed
585 K : kurtosis and kurtosis error printed
586 s : skewness printed
587 S : skewness and skewness error printed
588 i : integral of bins printed
589 I : integral of bins with option "width" printed
590 o : number of overflows printed
591 u : number of underflows printed
592 r : standard deviation printed
593 R : standard deviation and standard deviation error printed
594 m : mean value printed
595 M : mean value mean error values printed
596 e : number of entries printed
597 n : name of histogram is printed
598
599For example, to print only name of histogram and number of entries do:
600
601 gStyle->SetOptStat("ne");
602
603To print only the name of the histogram do:
604
605 gStyle->SetOptStat("n");
606
607The default value is:
608
609 gStyle->SetOptStat("nemr");
610
611When a histogram is painted, a `TPaveStats` object is created and added
612to the list of functions of the histogram. If a `TPaveStats` object
613already exists in the histogram list of functions, the existing object is just
614updated with the current histogram parameters.
615
616Once a histogram is painted, the statistics box can be accessed using
617`h->FindObject("stats")`. In the command line it is enough to do:
618
619 Root > h->Draw()
620 Root > TPaveStats *st = (TPaveStats*)h->FindObject("stats")
621
622because after `h->Draw()` the histogram is automatically painted. But
623in a script file the painting should be forced using `gPad->Update()`
624in order to make sure the statistics box is created:
625
626 h->Draw();
627 gPad->Update();
628 TPaveStats *st = (TPaveStats*)h->FindObject("stats");
629
630Without `gPad->Update()` the line `h->FindObject("stats")` returns a null pointer.
631
632When a histogram is drawn with the option `SAME`, the statistics box
633is not drawn. To force the statistics box drawing with the option
634`SAME`, the option `SAMES` must be used.
635If the new statistics box hides the previous statistics box, one can change
636its position with these lines (`h` being the pointer to the histogram):
637
638 Root > TPaveStats *st = (TPaveStats*)h->FindObject("stats")
639 Root > st->SetX1NDC(newx1); //new x start position
640 Root > st->SetX2NDC(newx2); //new x end position
641
642To change the type of information for an histogram with an existing
643`TPaveStats` one should do:
644
645 st->SetOptStat(mode);
646
647Where `mode` has the same meaning than when calling `gStyle->SetOptStat(mode)`
648(see above).
649
650One can delete the statistics box for a histogram `TH1* h` with:
651
652 h->SetStats(0)
653
654and activate it again with:
655
656 h->SetStats(1).
657
658Labels used in the statistics box ("Mean", "Std Dev", ...) can be changed from
659`$ROOTSYS/etc/system.rootrc` or `.rootrc` (look for the string `Hist.Stats.`).
660
661
662\anchor HP08
663### Fit Statistics
664
665
666The type of information about fit parameters printed in the histogram statistics
667box can be selected via the parameter mode. The parameter mode can be
668`= pcev` (default `= 0111`)
669
670 p = 1; print Probability
671 c = 1; print Chisquare/Number of degrees of freedom
672 e = 1; print errors (if e=1, v must be 1)
673 v = 1; print name/values of parameters
674
675Example:
676
677 gStyle->SetOptFit(1011);
678
679print fit probability, parameter names/values and errors.
680
6811. When `v = 1` is specified, only the non-fixed parameters are shown.
6822. When `v = 2` all parameters are shown.
683
684Note: `gStyle->SetOptFit(1)` means "default value", so it is equivalent
685to `gStyle->SetOptFit(111)`
686
687
688\anchor HP09
689### The error bars options
690
691
692| Option | Description |
693|----------|-------------------------------------------------------------------|
694| "E" | Default. Shows only the error bars, not a marker.|
695| "E1" | Small lines are drawn at the end of the error bars.|
696| "E2" | Error rectangles are drawn.|
697| "E3" | A filled area is drawn through the end points of the vertical error bars.|
698| "E4" | A smoothed filled area is drawn through the end points of the vertical error bars.|
699| "E0" | Draw error bars. Markers are drawn for bins with 0 contents. Combined with E1 or E2 it avoids error bars clipping|
700| "E5" | Like E3 but ignore the bins with 0 contents.|
701| "E6" | Like E4 but ignore the bins with 0 contents.|
702| "X0" | When used with one of the "E" option, it suppress the error bar along X as `gStyle->SetErrorX(0)` would do.|
703
704Begin_Macro(source)
705{
706 auto c1 = new TCanvas("c1","c1",600,400);
707 auto he = new TH1F("he","Distribution drawn with error bars (option E1) ",100,-3,3);
708 for (int i=0; i<10000; i++) he->Fill(gRandom->Gaus(0,1));
709 gStyle->SetEndErrorSize(3);
710 gStyle->SetErrorX(1.);
711 he->SetMarkerStyle(20);
712 he->Draw("E1");
713}
714End_Macro
715
716The options "E3" and "E4" draw an error band through the end points of the
717vertical error bars. With "E4" the error band is smoothed. Because of the
718smoothing algorithm used some artefacts may appear at the end of the band
719like in the following example. In such cases "E3" should be used instead
720of "E4".
721
722Begin_Macro(source)
723{
724 auto ce4 = new TCanvas("ce4","ce4",600,400);
725 ce4->Divide(2,1);
726 auto he4 = new TH1F("he4","Distribution drawn with option E4",100,-3,3);
727 Int_t i;
728 for (i=0;i<10000;i++) he4->Fill(gRandom->Gaus(0,1));
729 he4->SetFillColor(kRed);
730 he4->GetXaxis()->SetRange(40,48);
731 ce4->cd(1);
732 he4->Draw("E4");
733 ce4->cd(2);
734 auto he3 = (TH1F*)he4->DrawClone("E3");
735 he3->SetTitle("Distribution drawn option E3");
736}
737End_Macro
738
7392D histograms can be drawn with error bars as shown is the following example:
740
741Begin_Macro(source)
742{
743 auto c2e = new TCanvas("c2e","c2e",600,400);
744 auto h2e = new TH2F("h2e","TH2 drawn with option E",40,-4,4,40,-20,20);
745 float px, py;
746 for (Int_t i = 0; i < 25000; i++) {
747 gRandom->Rannor(px,py);
748 h2e->Fill(px,5*py);
749 }
750 h2e->Draw("E");
751}
752End_Macro
753
754
755\anchor HP100
756### The bar chart option
757
758
759The option "B" allows to draw simple vertical bar charts.
760The bar width is controlled with `TH1::SetBarWidth()`,
761and the bar offset within the bin, with `TH1::SetBarOffset()`.
762These two settings are useful to draw several histograms on the
763same plot as shown in the following example:
764
765Begin_Macro(source)
766{
767 int i;
768 const Int_t nx = 8;
769 string os_X[nx] = {"8","32","128","512","2048","8192","32768","131072"};
770 float d_35_0[nx] = {0.75, -3.30, -0.92, 0.10, 0.08, -1.69, -1.29, -2.37};
771 float d_35_1[nx] = {1.01, -3.02, -0.65, 0.37, 0.34, -1.42, -1.02, -2.10};
772
773 auto cb = new TCanvas("cb","cb",600,400);
774 cb->SetGrid();
775
776 gStyle->SetHistMinimumZero();
777
778 auto h1b = new TH1F("h1b","Option B example",nx,0,nx);
779 h1b->SetFillColor(4);
780 h1b->SetBarWidth(0.4);
781 h1b->SetBarOffset(0.1);
782 h1b->SetStats(0);
783 h1b->SetMinimum(-5);
784 h1b->SetMaximum(5);
785
786 for (i=1; i<=nx; i++) {
787 h1b->SetBinContent(i, d_35_0[i-1]);
788 h1b->GetXaxis()->SetBinLabel(i,os_X[i-1].c_str());
789 }
790
791 h1b->Draw("b");
792
793 auto h2b = new TH1F("h2b","h2b",nx,0,nx);
794 h2b->SetFillColor(38);
795 h2b->SetBarWidth(0.4);
796 h2b->SetBarOffset(0.5);
797 h2b->SetStats(0);
798 for (i=1;i<=nx;i++) h2b->SetBinContent(i, d_35_1[i-1]);
799
800 h2b->Draw("b same");
801}
802End_Macro
803
804
805\anchor HP10
806### The "BAR" and "HBAR" options
807
808
809When the option `bar` or `hbar` is specified, a bar chart is drawn. A vertical
810bar-chart is drawn with the options `bar`, `bar0`, `bar1`, `bar2`, `bar3`, `bar4`.
811An horizontal bar-chart is drawn with the options `hbar`, `hbar0`, `hbar1`,
812`hbar2`, `hbar3`, `hbar4` (hist006_TH1_bar_charts.C).
813
814- The bar is filled with the histogram fill color.
815- The left side of the bar is drawn with a light fill color.
816- The right side of the bar is drawn with a dark fill color.
817- The percentage of the bar drawn with either the light or dark color is:
818 - 0% for option "(h)bar" or "(h)bar0"
819 - 10% for option "(h)bar1"
820 - 20% for option "(h)bar2"
821 - 30% for option "(h)bar3"
822 - 40% for option "(h)bar4"
823
824When an histogram has errors the option ["HIST"](\ref OPTHIST) together with the `(h)bar` option.
825
826Begin_Macro(source)
827../../../tutorials/hist/hist006_TH1_bar_charts.C
828End_Macro
829
830To control the bar width (default is the bin width) `TH1::SetBarWidth()`
831should be used.
832
833To control the bar offset (default is 0) `TH1::SetBarOffset()` should
834be used.
835
836These two parameters are useful when several histograms are plotted using
837the option `SAME`. They allow to plot the histograms next to each other.
838
839
840\anchor HP11
841### The SCATter plot option (legacy draw option)
842
843\attention
844Use of option `SCAT` has been deprecated. It was the default drawing option for 2D and
8453D histograms. The new default option is `COL` (heat-map).
846
847
848For each cell (i,j) a number of points proportional to the cell content is
849drawn. A maximum of `kNMAX` points per cell is drawn. If the maximum is above
850`kNMAX` contents are normalized to `kNMAX` (`kNMAX=2000`).
851If option is of the form `scat=ff`, (eg `scat=1.8`,
852`scat=1e-3`), then `ff` is used as a scale factor to compute the
853number of dots. `scat=1` is the default.
854
855By default the scatter plot is painted with a "dot marker" which not scalable
856(see the `TAttMarker` documentation). To change the marker size, a scalable marker
857type should be used. For instance a circle (marker style 20).
858
859Begin_Macro(source)
860{
861 auto c1 = new TCanvas("c1","c1",600,400);
862 auto hscat = new TH2F("hscat","Option SCATter example (default for 2D histograms) ",40,-4,4,40,-20,20);
863 float px, py;
864 for (Int_t i = 0; i < 25000; i++) {
865 gRandom->Rannor(px,py);
866 hscat->Fill(px,5*py);
867 hscat->Fill(3+0.5*px,2*py-10.);
868 }
869 hscat->Draw("scat=0.5"); // This a legacy draw option. Please consider using TScatter
870}
871End_Macro
872
873
874\anchor HP12
875### The ARRow option
876
877
878Shows gradient between adjacent cells. For each cell (i,j) an arrow is drawn
879The orientation of the arrow follows the cell gradient.
880
881Begin_Macro(source)
882{
883 auto c1 = new TCanvas("c1","c1",600,400);
884 auto harr = new TH2F("harr","Option ARRow example",20,-4,4,20,-20,20);
885 harr->SetLineColor(kRed);
886 float px, py;
887 for (Int_t i = 0; i < 25000; i++) {
888 gRandom->Rannor(px,py);
889 harr->Fill(px,5*py);
890 harr->Fill(3+0.5*px,2*py-10.,0.1);
891 }
892 harr->Draw("ARR");
893}
894End_Macro
895
896\since **ROOT version 6.17/01**
897
898The option `ARR` can be combined with the option `COL` or `COLZ`.
899
900Begin_Macro(source)
901{
902 auto c1 = new TCanvas("c1","c1",600,400);
903 auto harr = new TH2F("harr","Option ARR + COLZ example",20,-4,4,20,-20,20);
904 harr->SetStats(0);
905 float px, py;
906 for (Int_t i = 0; i < 25000; i++) {
907 gRandom->Rannor(px,py);
908 harr->Fill(px,5*py);
909 harr->Fill(3+0.5*px,2*py-10.,0.1);
910 }
911 harr->Draw("ARR COLZ");
912}
913End_Macro
914
915
916\anchor HP13
917### The BOX option
918
919
920For each cell (i,j) a box is drawn. The size (surface) of the box is
921proportional to the absolute value of the cell content.
922The cells with a negative content are drawn with a `X` on top of the box.
923
924Begin_Macro(source)
925{
926 auto c1 = new TCanvas("c1","c1",600,400);
927 auto hbox = new TH2F("hbox","Option BOX example",3,0,3,3,0,3);
928 hbox->SetFillColor(42);
929 hbox->Fill(0.5, 0.5, 1.);
930 hbox->Fill(0.5, 1.5, 4.);
931 hbox->Fill(0.5, 2.5, 3.);
932 hbox->Fill(1.5, 0.5, 2.);
933 hbox->Fill(1.5, 1.5, 12.);
934 hbox->Fill(1.5, 2.5, -6.);
935 hbox->Fill(2.5, 0.5, -4.);
936 hbox->Fill(2.5, 1.5, 6.);
937 hbox->Fill(2.5, 2.5, 0.5);
938 hbox->Draw("BOX");
939}
940End_Macro
941
942With option `BOX1` a button is drawn for each cell with surface
943proportional to content's absolute value. A sunken button is drawn for
944negative values a raised one for positive.
945
946Begin_Macro(source)
947{
948 auto c1 = new TCanvas("c1","c1",600,400);
949 auto hbox1 = new TH2F("hbox1","Option BOX1 example",3,0,3,3,0,3);
950 hbox1->SetFillColor(42);
951 hbox1->Fill(0.5, 0.5, 1.);
952 hbox1->Fill(0.5, 1.5, 4.);
953 hbox1->Fill(0.5, 2.5, 3.);
954 hbox1->Fill(1.5, 0.5, 2.);
955 hbox1->Fill(1.5, 1.5, 12.);
956 hbox1->Fill(1.5, 2.5, -6.);
957 hbox1->Fill(2.5, 0.5, -4.);
958 hbox1->Fill(2.5, 1.5, 6.);
959 hbox1->Fill(2.5, 2.5, 0.5);
960 hbox1->Draw("BOX1");
961}
962End_Macro
963
964When the option `SAME` (or "SAMES") is used with the option `BOX`,
965the boxes' sizes are computed taking the previous plots into account. The range
966along the Z axis is imposed by the first plot (the one without option
967`SAME`); therefore the order in which the plots are done is relevant.
968
969Begin_Macro(source)
970{
971 auto c1 = new TCanvas("c1","c1",600,400);
972 auto hb1 = new TH2F("hb1","Example of BOX plots with option SAME ",40,-3,3,40,-3,3);
973 auto hb2 = new TH2F("hb2","hb2",40,-3,3,40,-3,3);
974 auto hb3 = new TH2F("hb3","hb3",40,-3,3,40,-3,3);
975 auto hb4 = new TH2F("hb4","hb4",40,-3,3,40,-3,3);
976 for (Int_t i=0;i<1000;i++) {
977 double x,y;
978 gRandom->Rannor(x,y);
979 if (x>0 && y>0) hb1->Fill(x,y,4);
980 if (x<0 && y<0) hb2->Fill(x,y,3);
981 if (x>0 && y<0) hb3->Fill(x,y,2);
982 if (x<0 && y>0) hb4->Fill(x,y,1);
983 }
984 hb1->SetFillColor(1);
985 hb2->SetFillColor(2);
986 hb3->SetFillColor(3);
987 hb4->SetFillColor(4);
988 hb1->Draw("box");
989 hb2->Draw("box same");
990 hb3->Draw("box same");
991 hb4->Draw("box same");
992}
993End_Macro
994
995\since **ROOT version 6.17/01:**
996
997Sometimes the change of the range of the Z axis is unwanted, in which case, one
998can use `SAME0` (or `SAMES0`) option to opt out of this change.
999
1000Begin_Macro(source)
1001{
1002 auto h2 = new TH2F("h2"," ",10,0,10,10,20,30);
1003 auto hf = (TH2F*)h2->Clone("hf");
1004 h2->SetBit(TH1::kNoStats);
1005 hf->SetBit(TH1::kNoStats);
1006 h2->Fill(5,22);
1007 h2->Fill(5,23);
1008 h2->Fill(6,22);
1009 h2->Fill(6,23);
1010 hf->Fill(6,23);
1011 hf->Fill(6,23);
1012 hf->Fill(6,23);
1013 hf->Fill(6,23);
1014 hf->Fill(5,23);
1015
1016 auto hf_copy1 = hf->Clone("hf_copy1");
1017 TLatex lt;
1018
1019 auto cx = new TCanvas(); cx->Divide(2,1);
1020
1021 cx->cd(1);
1022 h2->Draw("box");
1023 hf->Draw("text colz same");
1024 lt.DrawLatexNDC(0.3,0.5,"SAME");
1025
1026 cx->cd(2);
1027 h2->Draw("box");
1028 hf_copy1->Draw("text colz same0");
1029 lt.DrawLatexNDC(0.3,0.5,"SAME0");
1030}
1031End_Macro
1032
1033
1034\anchor HP14
1035### The COLor option (default for 2D histograms)
1036
1037The magnitude of individual cell (i,j) is represented as a color picked in the current color palette.
1038This data visualization technique is often called a heat map (or heat-map).
1039
1040The color table used is defined in the current style.
1041
1042If the histogram's minimum and maximum are the same (flat histogram), the
1043mapping on colors is not possible, therefore nothing is painted. To paint a
1044flat histogram it is enough to set the histogram minimum
1045(`TH1::SetMinimum()`) different from the bins' content.
1046
1047The default number of color levels used to paint the cells is 20.
1048It can be changed with `TH1::SetContour()` or
1049`TStyle::SetNumberContours()`. The higher this number is, the smoother
1050is the color change between cells.
1051
1052The color palette in TStyle can be modified via `gStyle->SetPalette()`.
1053
1054All the non-empty bins are painted. Empty bins (bins with content and error equal to 0) are
1055not painted unless some bins have a negative content because in that case the null bins
1056might be not empty.
1057
1058`TProfile2D` histograms are handled differently because, for this type of 2D
1059histograms, it is possible to know if an empty bin has been filled or not. So even
1060if all the bins' contents are positive some empty bins might be painted. And vice versa,
1061if some bins have a negative content some empty bins might be not painted.
1062
1063Combined with the option `COL`, the option `Z` allows to
1064display the color palette defined by `gStyle->SetPalette()`.
1065
1066In the following example, the histogram has only positive bins; the empty
1067bins (containing 0) are not drawn.
1068
1069Begin_Macro(source)
1070{
1071 auto c1 = new TCanvas("c1","c1",600,400);
1072 auto hcol1 = new TH2F("hcol1","Option COLor example ",40,-4,4,40,-20,20);
1073 float px, py;
1074 for (Int_t i = 0; i < 25000; i++) {
1075 gRandom->Rannor(px,py);
1076 hcol1->Fill(px,5*py);
1077 }
1078 hcol1->Draw("COLZ");
1079}
1080End_Macro
1081
1082In the first plot of following example, the histogram has some negative bins;
1083the empty bins (containing 0) are drawn. In some cases one wants to not draw
1084empty bins (containing 0) of histograms having a negative minimum. The option
1085`1`, used to produce the second plot in the following picture, allows to do that.
1086
1087Begin_Macro(source)
1088{
1089 auto c1 = new TCanvas("c1","c1",600,600);
1090 c1->Divide(1,2);
1091 auto hcol23 = new TH2F("hcol23","Option COLZ example ",40,-4,4,40,-20,20);
1092 auto hcol24 = new TH2F("hcol24","Option COLZ1 example ",40,-4,4,40,-20,20);
1093 float px, py;
1094 for (Int_t i = 0; i < 25000; i++) {
1095 gRandom->Rannor(px,py);
1096 hcol23->Fill(px,5*py);
1097 hcol24->Fill(px,5*py);
1098 }
1099 hcol23->Fill(0.,0.,-200.);
1100 hcol24->Fill(0.,0.,-200.);
1101 c1->cd(1); hcol23->Draw("COLZ");
1102 c1->cd(2); hcol24->Draw("COLZ1");
1103}
1104End_Macro
1105
1106When the maximum of the histogram is set to a smaller value than the real maximum,
1107 the bins having a content between the new maximum and the real maximum are
1108painted with the color corresponding to the new maximum.
1109
1110When the minimum of the histogram is set to a greater value than the real minimum,
1111 the bins having a value between the real minimum and the new minimum are not drawn
1112 unless the option `0` is set.
1113
1114The following example illustrates the option `0` combined with the option `COL`.
1115
1116Begin_Macro(source)
1117{
1118 auto c1 = new TCanvas("c1","c1",600,600);
1119 c1->Divide(1,2);
1120 auto hcol21 = new TH2F("hcol21","Option COLZ",40,-4,4,40,-20,20);
1121 auto hcol22 = new TH2F("hcol22","Option COLZ0",40,-4,4,40,-20,20);
1122 float px, py;
1123 for (Int_t i = 0; i < 25000; i++) {
1124 gRandom->Rannor(px,py);
1125 hcol21->Fill(px,5*py);
1126 hcol22->Fill(px,5*py);
1127 }
1128 hcol21->SetBit(TH1::kNoStats);
1129 hcol22->SetBit(TH1::kNoStats);
1130 c1->cd(1); hcol21->Draw("COLZ");
1131 c1->cd(2); hcol22->Draw("COLZ0");
1132 hcol22->SetMaximum(100);
1133 hcol22->SetMinimum(40);
1134}
1135End_Macro
1136
1137\since **ROOT version 6.09/01:**
1138
1139When the option SAME (or "SAMES") is used with the option COL, the boxes' color
1140are computed taking the previous plots into account. The range along the Z axis
1141is imposed by the first plot (the one without option SAME); therefore the order
1142in which the plots are done is relevant. Same as [in the `BOX` option](\ref HP13), one can use
1143`SAME0` (or `SAMES0`) to opt out of this imposition.
1144
1145Begin_Macro(source)
1146{
1147 auto c = new TCanvas("c","Example of col plots with option SAME",200,10,700,500);
1148 auto h1 = new TH2F("h1","h1",40,-3,3,40,-3,3);
1149 auto h2 = new TH2F("h2","h2",40,-3,3,40,-3,3);
1150 auto h3 = new TH2F("h3","h3",40,-3,3,40,-3,3);
1151 auto h4 = new TH2F("h4","h4",40,-3,3,40,-3,3);
1152 h1->SetBit(TH1::kNoStats);
1153 for (Int_t i=0;i<5000;i++) {
1154 double x,y;
1155 gRandom->Rannor(x,y);
1156 if(x>0 && y>0) h1->Fill(x,y,4);
1157 if(x<0 && y<0) h2->Fill(x,y,3);
1158 if(x>0 && y<0) h3->Fill(x,y,2);
1159 if(x<0 && y>0) h4->Fill(x,y,1);
1160 }
1161 h1->Draw("colz");
1162 h2->Draw("col same");
1163 h3->Draw("col same");
1164 h4->Draw("col same");
1165}
1166End_Macro
1167
1168The option `COL` can be combined with the option `POL`:
1169
1170Begin_Macro(source)
1171{
1172 auto c1 = new TCanvas("c1","c1",600,400);
1173 auto hcol1 = new TH2F("hcol1","Option COLor combined with POL",40,-4,4,40,-4,4);
1174 float px, py;
1175 for (Int_t i = 0; i < 25000; i++) {
1176 gRandom->Rannor(px,py);
1177 hcol1->Fill(px,py);
1178 }
1179 hcol1->Draw("COLZPOL");
1180}
1181End_Macro
1182
1183\since **ROOT version 6.07/03:**
1184
1185A second rendering technique is also available with the COL2 and COLZ2 options.
1186
1187These options provide potential performance improvements compared to the standard
1188COL option. The performance comparison of the COL2 to the COL option depends on
1189the histogram and the size of the rendering region in the current pad. In general,
1190a small (approx. less than 100 bins per axis), sparsely populated TH2 will render
1191faster with the COL option.
1192
1193However, for larger histograms (approx. more than 100 bins per axis)
1194that are not sparse, the COL2 option will provide up to 20 times performance improvements.
1195For example, a 1000x1000 bin TH2 that is not sparse will render an order of magnitude
1196faster with the COL2 option.
1197
1198The COL2 option will also scale its performance based on the size of the
1199pixmap the histogram image is being rendered into. It also is much better optimized for
1200sessions where the user is forwarding X11 windows through an `ssh` connection.
1201
1202For the most part, the COL2 and COLZ2 options are a drop in replacement to the COL
1203and COLZ options. There is one major difference and that concerns the treatment of
1204bins with zero content. The COL2 and COLZ2 options color these bins the color of zero.
1205
1206COL2 option renders the histogram as a bitmap. Therefore it cannot be saved in vector
1207graphics file format like PostScript or PDF (an empty image will be generated). It can
1208be saved only in bitmap files like PNG format for instance.
1209
1210
1211\anchor HP140
1212### The CANDLE and VIOLIN options
1213
1214The mechanism behind Candle plots and Violin plots is very similar. Because of this they are
1215implemented in the same class TCandle. The keywords CANDLE or VIOLIN will initiate the drawing of
1216the corresponding plots. Followed by the keyword the user can select a plot direction (X or V for
1217vertical projections, or Y or H for horizontal projections) and/or predefined definitions
1218(1-6 for candles, 1-2 for violins). The order doesn't matter. Default is X and 1.
1219
1220Instead of using the predefined representations, the candle and violin parameters can be
1221changed individually. In that case the option have the following form:
1222
1223 CANDLEX(<option-string>)
1224 CANDLEY(<option-string>)
1225 VIOLINX(<option-string>)
1226 VIOLINY(<option-string>).
1227
1228All zeros at the beginning of `option-string` can be omitted.
1229
1230`option-string` consists eight values, defined as follow:
1231
1232 "CANDLEX(zhpawMmb)"
1233
1234Where:
1235
1236 - `b = 0`; no box drawn
1237 - `b = 1`; the box is drawn. As the candle-plot is also called a box-plot it
1238 makes sense in the very most cases to always draw the box
1239 - `b = 2`; draw a filled box with border
1240
1241 - `m = 0`; no median drawn
1242 - `m = 1`; median is drawn as a line
1243 - `m = 2`; median is drawn with errors (notches)
1244 - `m = 3`; median is drawn as a circle
1245
1246 - `M = 0`; no mean drawn
1247 - `M = 1`; mean is drawn as a dashed line
1248 - `M = 3`; mean is drawn as a circle
1249
1250 - `w = 0`; no whisker drawn
1251 - `w = 1`; whisker is drawn to end of distribution.
1252 - `w = 2`; whisker is drawn to max 1.5*iqr
1253
1254 - `a = 0`; no anchor drawn
1255 - `a = 1`; the anchors are drawn
1256
1257 - `p = 0`; no points drawn
1258 - `p = 1`; only outliers are drawn
1259 - `p = 2`; all datapoints are drawn
1260 - `p = 3`: all datapoints are drawn scattered
1261
1262 - `h = 0`; no histogram is drawn
1263 - `h = 1`; histogram at the left or bottom side is drawn
1264 - `h = 2`; histogram at the right or top side is drawn
1265 - `h = 3`; histogram at left and right or top and bottom (violin-style) is drawn
1266
1267 - `z = 0`; no zero indicator line is drawn
1268 - `z = 1`; zero indicator line is drawn.
1269
1270As one can see all individual options for both candle and violin plots can be accessed by this
1271mechanism. In deed the keywords CANDLE(<option-string>) and VIOLIN(<option-string>) have the same
1272meaning. So you can parametrise an option-string for a candle plot and use the keywords VIOLIN and
1273vice versa, if you wish.
1274
1275Using a logarithmic x- or y-axis is possible for candle and violin charts.
1276
1277\since **ROOT version 6.11/01**
1278
1279a logarithmic z-axis is possible, too but will only affect violin charts of course.
1280
1281\anchor HP140a
1282#### The CANDLE option
1283
1284<a href="http://en.wikipedia.org/wiki/Box_plot">A Candle plot</a> (also known as
1285a "box plot" or "whisker plot") was invented in 1977 by John Tukey. It is a convenient
1286way to describe graphically a data distribution (D) with only five numbers:
1287
1288 1. The minimum value of the distribution D (bottom or left whisker).
1289 2. The lower quartile (Q1): 25% of the data points in D are less than Q1 (bottom of the box).
1290 3. The median (M): 50% of the data points in D are less than M.
1291 4. The upper quartile (Q3): 75% of the data points in D are less than Q3 (top of the box).
1292 5. The maximum value of the distribution D (top or right whisker).
1293
1294In this implementation a TH2 is considered as a collection of TH1 along
1295X (option `CANDLE` or `CANDLEX`) or Y (option `CANDLEY`).
1296Each TH1 is represented as one candle.
1297
1298Begin_Macro(source)
1299../../../tutorials/hist/hist052_Graphics_candle_plot_whiskers.C
1300End_Macro
1301
1302The candle reduces the information coming from a whole distribution into few values.
1303Independently from the number of entries or the significance of the underlying distribution
1304a candle will always look like a candle. So candle plots should be used carefully in
1305particular with unknown distributions. The definition of a candle is based on
1306__unbinned data__. Here, candles are created from binned data. Because of this, the
1307deviation is connected to the bin width used. The calculation of the quantiles
1308normally done on unbinned data also. Because data are binned, this will
1309only work the best possible way within the resolution of one bin
1310
1311Because of all these facts one should take care that:
1312
1313 - there are enough points per candle
1314 - the bin width is small enough (more bins will increase the maximum
1315 available resolution of the quantiles although there will be some
1316 bins with no entries)
1317 - never make a candle-plot if the underlying distribution is double-distributed
1318 - only create candles of distributions that are more-or-less gaussian (the
1319 MPV should be not too far away from the mean).
1320
1321#### What a candle is made of
1322
1323\since **ROOT version 6.07/05**
1324
1325##### The box
1326The box displays the position of the inter-quantile-range of the underlying
1327distribution. The box contains 25% of the distribution below the median
1328and 25% of the distribution above the median. If the underlying distribution is large
1329enough and gaussian shaped the end-points of the box represent \f$ 0.6745\times\sigma \f$
1330(Where \f$ \sigma \f$ is the standard deviation of the gaussian). The width and
1331the position of the box can be modified by SetBarWidth() and SetBarOffset().
1332The +-25% quantiles are calculated by the GetQuantiles() methods.
1333
1334\since **ROOT version 6.11/01**
1335
1336Using the static function TCandle::SetBoxRange(double) the box definition will be
1337overwritten. E.g. using a box range of 0.68 will redefine the area of the lower box edge
1338to the upper box edge in order to cover 68% of the distribution illustrated by that candle.
1339The static function will affect all candle-charts in the running program.
1340Default is 0.5.
1341
1342Using the static function TCandle::SetScaledCandle(bool) the width of the box (and the
1343whole candle) can be influenced. Deactivated, the width is constant (to be set by
1344SetBarWidth() ). Activated, the width of the boxes will be scaled to each other based on the
1345amount of data in the corresponding candle, the maximum width can be influenced by
1346SetBarWidth(). The static function will affect all candle-charts in the running program.
1347Default is false. Scaling between multiple candle-charts (using "same" or THStack) is not
1348supported, yet
1349
1350##### The Median
1351For a sorted list of numbers, the median is the value in the middle of the list.
1352E.g. if a sorted list is made of five numbers "1,2,3,6,7" 3 will be the median
1353because it is in the middle of the list. If the number of entries is even the
1354average of the two values in the middle will be used. As histograms are binned
1355data, the situation is a bit more complex. The following example shows this:
1356
1357~~~ {.cpp}
1358void quantiles() {
1359 auto h = new TH1I("h","h",10,0,10);
1360 //h->Fill(3);
1361 //h->Fill(3);
1362 h->Fill(4);
1363 h->Draw();
1364 double p = 0.;
1365 double q = 0.;
1366 h->GetQuantiles(1,&q,&p);
1367
1368 cout << "Median is: " << q << std::endl;
1369}
1370~~~
1371
1372Here the bin-width is 1.0. If the two Fill(3) are commented out, as there are currently,
1373the example will return a calculated median of 4.5, because that's the bin center
1374of the bin in which the value 4.0 has been dropped. If the two Fill(3) are not
1375commented out, it will return 3.75, because the algorithm tries to evenly distribute
1376the individual values of a bin with bin content > 0. It means the sorted list
1377would be "3.25, 3.75, 4.5".
1378
1379The consequence is a median of 3.75. This shows how important it is to use a
1380small enough bin-width when using candle-plots on binned data.
1381If the distribution is large enough and gaussian shaped the median will be exactly
1382equal to the mean.
1383The median can be shown as a line or as a circle or not shown at all.
1384
1385In order to show the significance of the median notched candle plots apply a "notch" or
1386narrowing of the box around the median. The significance is defined by
1387\f$ 1.57\times\frac{iqr}{N} \f$ and will be represented as the size of the notch
1388(where iqr is the size of the box and N is the number of entries of the whole
1389distribution). Candle plots like these are usually called "notched candle plots".
1390
1391In case the significance of the median is greater that the size of the box, the
1392box will have an unnatural shape. Usually it means the chart has not enough data,
1393or that representing this uncertainty is not useful
1394
1395##### The Mean
1396The mean can be drawn as a dashed line or as a circle or not drawn at all.
1397The mean is the arithmetic average of the values in the distribution.
1398It is calculated using GetMean(). Because histograms are
1399binned data, the mean value can differ from a calculation on the raw-data.
1400If the distribution is large enough and gaussian shaped the mean will be
1401exactly the median.
1402
1403##### The Whiskers
1404The whiskers represent the part of the distribution not covered by the box.
1405The upper 25% and the lower 25% of the distribution are located within the whiskers.
1406Two representations are available.
1407
1408 - A simple one (using w=1) defining the lower whisker from the lowest data value
1409 to the bottom of the box, and the upper whisker from the top of the box to the
1410 highest data value. In this representation the whisker-lines are dashed.
1411 - A more complex one having a further restriction. The whiskers are still connected
1412 to the box but their length cannot exceed \f$ 1.5\times iqr \f$. So it might
1413 be that the outermost part of the underlying distribution will not be covered
1414 by the whiskers. Usually these missing parts will be represented by the outliers
1415 (see points). Of course the upper and the lower whisker may differ in length.
1416 In this representation the whiskers are drawn as solid lines.
1417
1418\since **ROOT version 6.11/01**
1419
1420Using the static function TCandle::SetWhiskerRange(double) the whisker definition w=1
1421will be overwritten. E.g. using a whisker-range of 0.95 and w=1 will redefine the area of
1422the lower whisker to the upper whisker in order to cover 95% of the distribution inside
1423that candle. The static function will affect all candle-charts in the running program.
1424Default is 1.
1425
1426If the distribution is large enough and gaussian shaped, the maximum length of
1427the whisker will be located at \f$ \pm 2.698 \sigma \f$ (when using the
14281.5*iqr-definition (w=2), where \f$ \sigma \f$ is the standard deviation
1429(see picture above). In that case 99.3% of the total distribution will be covered
1430by the box and the whiskers, whereas 0.7% are represented by the outliers.
1431
1432##### The Anchors
1433The anchors have no special meaning in terms of statistical calculation. They mark
1434the end of the whiskers and they have the width of the box. Both representation
1435with and without anchors are common.
1436
1437##### The Points
1438Depending on the configuration the points can have different meanings:
1439 - If p=1 the points represent the outliers. If they are shown, it means
1440 some parts of the underlying distribution are not covered by the whiskers.
1441 This can only occur when the whiskers are set to option w=2. Here the whiskers
1442 can have a maximum length of \f$ 1.5 \times iqr \f$. So any points outside the
1443 whiskers will be drawn as outliers. The outliers will be represented by crosses.
1444 - If p=2 all points in the distribution will be painted as crosses. This is
1445 useful for small datasets only (up to 10 or 20 points per candle).
1446 The outliers are shown along the candle. Because the underlying distribution
1447 is binned, is frequently occurs that a bin contains more than one value.
1448 Because of this the points will be randomly scattered within their bin along
1449 the candle axis. If the bin content for a bin is exactly 1 (usually
1450 this happens for the outliers) if will be drawn in the middle of the bin along
1451 the candle axis. As the maximum number of points per candle is limited by kNMax/2
1452 on very large datasets scaling will be performed automatically. In that case one
1453 would loose all outliers because they have usually a bin content of 1 (and a
1454 bin content between 0 and 1 after the scaling). Because of this all bin contents
1455 between 0 and 1 - after the scaling - will be forced to be 1.
1456 - As the drawing of all values on large datasets can lead to big amounts of crosses,
1457 one can show all values as a scatter plot instead by choosing p=3. The points will be
1458 drawn as dots and will be scattered within the width of the candle. The color
1459 of the points will be the color of the candle-chart.
1460
1461##### Other Options
1462Is is possible to combine all options of candle and violin plots with each other. E.g. a box-plot
1463with a histogram.
1464
1465#### How to use the candle-plots drawing option
1466
1467There are six predefined candle-plot representations:
1468
1469 - "CANDLEX1": Standard candle (whiskers cover the whole distribution)
1470 - "CANDLEX2": Standard candle with better whisker definition + outliers.
1471 It is a good compromise
1472 - "CANDLEX3": Like candle2 but with a mean as a circle.
1473 It is easier to distinguish mean and median
1474 - "CANDLEX4": Like candle3 but showing the uncertainty of the median as well
1475 (notched candle plots).
1476 For bigger datasets per candle
1477 - "CANDLEX5": Like candle2 but showing all data points.
1478 For very small datasets
1479 - "CANDLEX6": Like candle2 but showing all datapoints scattered.
1480 For huge datasets
1481
1482
1483The following picture shows how the six predefined representations look.
1484
1485Begin_Macro
1486{
1487 auto c1 = new TCanvas("c1","c1",700,800);
1488 c1->Divide(2,3);
1489 gStyle->SetOptStat(kFALSE);
1490
1491 auto hcandle = new TH2F("hcandle"," ",10,-4,4,40,-20,20);
1492 float px, py;
1493 for (Int_t i = 0; i < 15000; i++) {
1494 gRandom->Rannor(px,py);
1495 hcandle->Fill(px,5*py);
1496 }
1497 hcandle->SetMarkerSize(0.5);
1498
1499 TH2F *h2;
1500 for (Int_t i=1; i<7; i++) {
1501 c1->cd(i);
1502 h2 = (TH2F*)hcandle->DrawClone(Form("CANDLE%d",i));
1503 h2->SetTitle(Form("CANDLE%d",i));
1504 }
1505}
1506End_Macro
1507
1508
1509#### Example 1
1510Box and improved whisker, no mean, no median, no anchor no outliers
1511
1512 h1->Draw("CANDLEX(2001)");
1513
1514#### Example 2
1515A Candle-definition like "CANDLEX2" (New standard candle with better whisker definition + outliers)
1516
1517 h1->Draw("CANDLEX(112111)");
1518
1519#### Example 3
1520The following example shows how several candle plots can be super-imposed using
1521the option SAME. Note that the bar-width and bar-offset are active on candle plots.
1522Also the color, the line width, the size of the points and so on can be changed by the
1523standard attribute setting methods such as SetLineColor() SetLineWidth().
1524
1525Begin_Macro(source)
1526../../../tutorials/hist/hist049_Graphics_candle_plot.C
1527End_Macro
1528
1529\anchor HP140b
1530#### The VIOLIN option
1531
1532<a href="http://en.wikipedia.org/wiki/Violin_plot">A violin plot</a> is a candle plot
1533that also encodes the pdf information at each point.
1534
1535
1536Quartiles and mean are also represented at each point, with a marker
1537and two lines.
1538
1539In this implementation a TH2 is considered as a collection of TH1 along
1540X (option `VIOLIN` or `VIOLINX`) or Y (option `VIOLINY`).
1541
1542#### What a violin is made of
1543
1544\since **ROOT version 6.09/02**
1545
1546##### The histogram
1547The histogram is typically drawn to both directions with respect to the middle-line of the
1548corresponding bin. This can be achieved by using h=3. It is possible to draw a histogram only to
1549one side (h=1, or h=2).
1550The maximum number of bins in the histogram is limited to 500, if the number of bins in the used
1551histogram is higher it will be rebinned automatically. The maximum height of the histogram can
1552be modified by using SetBarWidth() and the position can be changed with SetBarOffset().
1553A solid fill style is recommended.
1554
1555\since **ROOT version 6.11/01**
1556
1557Using the static function TCandle::SetScaledViolin(bool) the height of the histogram or the
1558violin can be influenced. Activated, the height of the bins of the individual violins will be
1559scaled with respect to each other, the maximum height can be influenced by SetBarWidth().
1560Deactivated, the height of the bin with the maximum content of each individual violin is
1561set to a constant value using SetBarWidth(). The static function will affect all violin-charts
1562in the running program. Default is true. Scaling between multiple violin-charts
1563(using "same" or THStack) is not supported, yet.
1564
1565##### The zero indicator line
1566Typical for violin charts is a line in the background over the whole histogram indicating
1567the bins with zero entries. The zero indicator line can be activated with z=1. The line color
1568will always be the same as the fill-color of the histogram.
1569
1570##### The Mean
1571The Mean is illustrated with the same mechanism as used for candle plots. Usually a circle is used.
1572
1573##### Whiskers
1574The whiskers are illustrated by the same mechanism as used for candle plots. There is only one
1575difference. When using the simple whisker definition (w=1) and the zero indicator line (z=1), then
1576the whiskers will be forced to be solid (usually hashed)
1577
1578##### Points
1579The points are illustrated by the same mechanism as used for candle plots. E.g. VIOLIN2 uses
1580better whisker definition (w=2) and outliers (p=1).
1581
1582##### Other options
1583It is possible to combine all options of candle or violin plots with each other. E.g. a violin plot
1584including a box-plot.
1585
1586#### How to use the violin-plots drawing option
1587
1588There are two predefined violin-plot representations:
1589 - "VIOLINX1": Standard violin (histogram, mean, whisker over full distribution,
1590 zero indicator line)
1591 - "VIOLINX2": Line VIOLINX1 both with better whisker definition + outliers.
1592
1593A solid fill style is recommended for this plot (as opposed to a hollow or
1594hashed style).
1595
1596Begin_Macro(source)
1597{
1598 auto c1 = new TCanvas("c1","c1",600,400);
1599 Int_t nx(6), ny(40);
1600 double xmin(0.0), xmax(+6.0), ymin(0.0), ymax(+4.0);
1601 auto hviolin = new TH2F("hviolin", "Option VIOLIN example", nx, xmin, xmax, ny, ymin, ymax);
1602 TF1 f1("f1", "gaus", +0,0 +4.0);
1603 double x,y;
1604 for (Int_t iBin=1; iBin<hviolin->GetNbinsX(); ++iBin) {
1605 double xc = hviolin->GetXaxis()->GetBinCenter(iBin);
1606 f1.SetParameters(1, 2.0+TMath::Sin(1.0+xc), 0.2+0.1*(xc-xmin)/xmax);
1607 for(Int_t i=0; i<10000; ++i){
1608 x = xc;
1609 y = f1.GetRandom();
1610 hviolin->Fill(x, y);
1611 }
1612 }
1613 hviolin->SetFillColor(kGray);
1614 hviolin->SetMarkerStyle(20);
1615 hviolin->SetMarkerSize(0.5);
1616 hviolin->Draw("VIOLIN");
1617 c1->Update();
1618}
1619End_Macro
1620
1621The next example illustrates a time development of a certain value:
1622
1623Begin_Macro(source)
1624../../../tutorials/hist/hist047_Graphics_candle_decay.C
1625End_Macro
1626
1627
1628\anchor HP15
1629### The TEXT and TEXTnn Option
1630
1631
1632For each bin the content is printed. The text attributes are:
1633
1634- text font = current TStyle font (`gStyle->SetTextFont()`).
1635- text size = 0.02*padheight*markersize (if `h` is the histogram drawn
1636 with the option `TEXT` the marker size can be changed with
1637 `h->SetMarkerSize(markersize)`).
1638- text color = marker color.
1639
1640By default the format `g` is used. This format can be redefined
1641by calling `gStyle->SetPaintTextFormat()`.
1642
1643It is also possible to use `TEXTnn` in order to draw the text with
1644the angle `nn` (`0 < nn <= 90`).
1645
1646For 2D histograms the text is plotted in the center of each non empty cells.
1647It is possible to plot empty cells by calling `gStyle->SetHistMinimumZero()`
1648or providing MIN0 draw option. For 1D histogram the text is plotted at a y
1649position equal to the bin content.
1650
1651For 2D histograms when the option "E" (errors) is combined with the option
1652text ("TEXTE"), the error for each bin is also printed.
1653
1654Begin_Macro(source)
1655{
1656 auto c01 = new TCanvas("c01","c01",700,400);
1657 c01->Divide(2,1);
1658 auto htext1 = new TH1F("htext1","Option TEXT on 1D histograms ",10,-4,4);
1659 auto htext2 = new TH2F("htext2","Option TEXT on 2D histograms ",10,-4,4,10,-20,20);
1660 float px, py;
1661 for (Int_t i = 0; i < 25000; i++) {
1662 gRandom->Rannor(px,py);
1663 htext1->Fill(px,0.1);
1664 htext2->Fill(px,5*py,0.1);
1665 }
1666 gStyle->SetPaintTextFormat("4.1f m");
1667 htext2->SetMarkerSize(1.8);
1668 c01->cd(1);
1669 htext2->Draw("TEXT45");
1670 c01->cd(2);
1671 htext1->Draw();
1672 htext1->Draw("HIST TEXT0 SAME");
1673}
1674End_Macro
1675
1676\since **ROOT version 6.07/07:**
1677
1678In case several histograms are drawn on top ot each other (using option `SAME`),
1679the text can be shifted using `SetBarOffset()`. It specifies an offset for the
1680text position in each cell, in percentage of the bin width.
1681
1682Begin_Macro(source)
1683{
1684 auto c03 = new TCanvas("c03","c03",700,400);
1685 gStyle->SetOptStat(0);
1686 auto htext3 = new TH2F("htext3","Several 2D histograms drawn with option TEXT",10,-4,4,10,-20,20);
1687 auto htext4 = new TH2F("htext4","htext4",10,-4,4,10,-20,20);
1688 auto htext5 = new TH2F("htext5","htext5",10,-4,4,10,-20,20);
1689 float px, py;
1690 for (Int_t i = 0; i < 25000; i++) {
1691 gRandom->Rannor(px,py);
1692 htext3->Fill(4*px,20*py,0.1);
1693 htext4->Fill(4*px,20*py,0.5);
1694 htext5->Fill(4*px,20*py,1.0);
1695 }
1696 htext4->SetMarkerSize(1.8);
1697 htext5->SetMarkerSize(1.8);
1698 htext5->SetMarkerColor(kRed);
1699 htext4->SetBarOffset(0.2);
1700 htext5->SetBarOffset(-0.2);
1701 htext3->Draw("COL");
1702 htext4->Draw("TEXT SAME");
1703 htext5->Draw("TEXT SAME");
1704}
1705End_Macro
1706
1707In the case of profile histograms it is possible to print the number
1708of entries instead of the bin content. It is enough to combine the
1709option "E" (for entries) with the option "TEXT".
1710
1711Begin_Macro(source)
1712{
1713 auto c02 = new TCanvas("c02","c02",700,400);
1714 c02->Divide(2,1);
1715 gStyle->SetPaintTextFormat("g");
1716
1717 auto profile = new TProfile("profile","profile",10,0,10);
1718 profile->SetMarkerSize(2.2);
1719 profile->Fill(0.5,1);
1720 profile->Fill(1.5,2);
1721 profile->Fill(2.5,3);
1722 profile->Fill(3.5,4);
1723 profile->Fill(4.5,5);
1724 profile->Fill(5.5,5);
1725 profile->Fill(6.5,4);
1726 profile->Fill(7.5,3);
1727 profile->Fill(8.5,2);
1728 profile->Fill(9.5,1);
1729 c02->cd(1); profile->Draw("HIST TEXT0");
1730 c02->cd(2); profile->Draw("HIST TEXT0E");
1731}
1732End_Macro
1733
1734\anchor HP16
1735### The CONTour options
1736
1737
1738The following contour options are supported:
1739
1740| Option | Description |
1741|----------|-----------------------------------------------------------------------------|
1742| "CONT" | Draw a contour plot (same as CONT0). |
1743| "CONT0" | Draw a contour plot using surface colors to distinguish contours. |
1744| "CONT1" | Draw a contour plot using the line colors to distinguish contours. |
1745| "CONT2" | Draw a contour plot using the line styles (1 to 5) to distinguish contours. |
1746| "CONT3" | Draw a contour plot using the same line style for all contours. |
1747| "CONT4" | Draw a contour plot using surface colors (`SURF` option at theta = 0). |
1748
1749
1750The following example shows a 2D histogram plotted with the option
1751`CONTZ`. The option `CONT` draws a contour plot using surface
1752colors to distinguish contours. Combined with the option `CONT` (or
1753`CONT0`), the option `Z` allows to display the color palette
1754defined by `gStyle->SetPalette()`.
1755
1756Begin_Macro(source)
1757{
1758 auto c1 = new TCanvas("c1","c1",600,400);
1759 auto hcontz = new TH2F("hcontz","Option CONTZ example ",40,-4,4,40,-20,20);
1760 float px, py;
1761 for (Int_t i = 0; i < 25000; i++) {
1762 gRandom->Rannor(px,py);
1763 hcontz->Fill(px-1,5*py);
1764 hcontz->Fill(2+0.5*px,2*py-10.,0.1);
1765 }
1766 hcontz->Draw("CONTZ");
1767}
1768End_Macro
1769
1770The following example shows a 2D histogram plotted with the option
1771`CONT1Z`. The option `CONT1` draws a contour plot using the
1772line colors to distinguish contours. Combined with the option `CONT1`,
1773the option `Z` allows to display the color palette defined by
1774`gStyle->SetPalette()`.
1775
1776Begin_Macro(source)
1777{
1778 auto c1 = new TCanvas("c1","c1",600,400);
1779 auto hcont1 = new TH2F("hcont1","Option CONT1Z example ",40,-4,4,40,-20,20);
1780 float px, py;
1781 for (Int_t i = 0; i < 25000; i++) {
1782 gRandom->Rannor(px,py);
1783 hcont1->Fill(px-1,5*py);
1784 hcont1->Fill(2+0.5*px,2*py-10.,0.1);
1785 }
1786 hcont1->Draw("CONT1Z");
1787}
1788End_Macro
1789
1790The following example shows a 2D histogram plotted with the option
1791`CONT2`. The option `CONT2` draws a contour plot using the
1792line styles (1 to 5) to distinguish contours.
1793
1794Begin_Macro(source)
1795{
1796 auto c1 = new TCanvas("c1","c1",600,400);
1797 auto hcont2 = new TH2F("hcont2","Option CONT2 example ",40,-4,4,40,-20,20);
1798 float px, py;
1799 for (Int_t i = 0; i < 25000; i++) {
1800 gRandom->Rannor(px,py);
1801 hcont2->Fill(px-1,5*py);
1802 hcont2->Fill(2+0.5*px,2*py-10.,0.1);
1803 }
1804 hcont2->Draw("CONT2");
1805}
1806End_Macro
1807
1808The following example shows a 2D histogram plotted with the option
1809`CONT3`. The option `CONT3` draws contour plot using the same line style for
1810all contours.
1811
1812Begin_Macro(source)
1813{
1814 auto c1 = new TCanvas("c1","c1",600,400);
1815 auto hcont3 = new TH2F("hcont3","Option CONT3 example ",40,-4,4,40,-20,20);
1816 float px, py;
1817 for (Int_t i = 0; i < 25000; i++) {
1818 gRandom->Rannor(px,py);
1819 hcont3->Fill(px-1,5*py);
1820 hcont3->Fill(2+0.5*px,2*py-10.,0.1);
1821 }
1822 hcont3->SetLineStyle(kDotted);
1823 hcont3->Draw("CONT3");
1824}
1825End_Macro
1826
1827The following example shows a 2D histogram plotted with the option
1828`CONT4`. The option `CONT4` draws a contour plot using surface
1829colors to distinguish contours (`SURF` option at theta = 0). Combined
1830with the option `CONT` (or `CONT0`), the option `Z`
1831allows to display the color palette defined by `gStyle->SetPalette()`.
1832
1833Begin_Macro(source)
1834{
1835 auto c1 = new TCanvas("c1","c1",600,400);
1836 auto hcont4 = new TH2F("hcont4","Option CONT4Z example ",40,-4,4,40,-20,20);
1837 float px, py;
1838 for (Int_t i = 0; i < 25000; i++) {
1839 gRandom->Rannor(px,py);
1840 hcont4->Fill(px-1,5*py);
1841 hcont4->Fill(2+0.5*px,2*py-10.,0.1);
1842 }
1843 hcont4->Draw("CONT4Z");
1844}
1845End_Macro
1846
1847The default number of contour levels is 20 equidistant levels and can be changed
1848with `TH1::SetContour()` or `TStyle::SetNumberContours()`.
1849
1850\anchor HP16a
1851#### The LIST option
1852
1853When option `LIST` is specified together with option
1854`CONT`, the points used to draw the contours are saved in
1855`TGraph` objects:
1856
1857 h->Draw("CONT LIST");
1858 gPad->Update();
1859
1860The contour are saved in `TGraph` objects once the pad is painted.
1861Therefore to use this functionality in a macro, `gPad->Update()`
1862should be performed after the histogram drawing. Once the list is
1863built, the contours are accessible in the following way:
1864
1865 TObjArray *contours = (TObjArray*)gROOT->GetListOfSpecials()->FindObject("contours");
1866 Int_t ncontours = contours->GetSize();
1867 TList *list = (TList*)contours->At(i);
1868
1869Where `i` is a contour number, and list contains a list of
1870`TGraph` objects.
1871For one given contour, more than one disjoint polyline may be generated.
1872The number of TGraphs per contour is given by:
1873
1874 list->GetSize();
1875
1876To access the first graph in the list one should do:
1877
1878 TGraph *gr1 = (TGraph*)list->First();
1879
1880
1881The following example (hist102_TH2_contour_list.C) shows how to use this functionality.
1882
1883Begin_Macro(source)
1884../../../tutorials/hist/hist102_TH2_contour_list.C
1885End_Macro
1886
1887\anchor HP16b
1888#### The AITOFF, MERCATOR, SINUSOIDAL and PARABOLIC options
1889
1890The following options select the `CONT4` option and are useful for
1891sky maps or exposure maps (earth.C).
1892
1893| Option | Description |
1894|--------------|---------------------------------------------------------------|
1895| "AITOFF" | Draw a contour via an AITOFF projection.|
1896| "MERCATOR" | Draw a contour via an Mercator projection.|
1897| "SINUSOIDAL" | Draw a contour via an Sinusoidal projection.|
1898| "PARABOLIC" | Draw a contour via an Parabolic projection.|
1899
1900Begin_Macro(source)
1901../../../tutorials/visualisation/graphics/earth.C
1902End_Macro
1903
1904
1905\anchor HP17
1906### The LEGO options
1907
1908
1909In a lego plot the cell contents are drawn as 3-d boxes. The height of each box
1910is proportional to the cell content. The lego aspect is control with the
1911following options:
1912
1913| Option | Description |
1914|----------|-------------------------------------------------------------------|
1915| "LEGO" | Draw a lego plot using the hidden lines removal technique.|
1916| "LEGO1" | Draw a lego plot using the hidden surface removal technique.|
1917| "LEGO2" | Draw a lego plot using colors to show the cell contents.|
1918| "LEGO3" | Draw a lego plot with hidden surface removal, like LEGO1 but the border lines of each lego-bar are not drawn.|
1919| "LEGO4" | Draw a lego plot with hidden surface removal, like LEGO1 but without the shadow effect on each lego-bar.|
1920| "0" | When used with any LEGO option, the empty bins are not drawn.|
1921
1922
1923See the limitations with [the option "SAME"](\ref HP060a).
1924
1925Line attributes can be used in lego plots to change the edges' style.
1926
1927The following example shows a 2D histogram plotted with the option
1928`LEGO`. The option `LEGO` draws a lego plot using the hidden
1929lines removal technique.
1930
1931Begin_Macro(source)
1932{
1933 auto c2 = new TCanvas("c2","c2",600,400);
1934 auto hlego = new TH2F("hlego","Option LEGO example ",40,-4,4,40,-20,20);
1935 float px, py;
1936 for (Int_t i = 0; i < 25000; i++) {
1937 gRandom->Rannor(px,py);
1938 hlego->Fill(px-1,5*py);
1939 hlego->Fill(2+0.5*px,2*py-10.,0.1);
1940 }
1941 hlego->Draw("LEGO");
1942}
1943End_Macro
1944
1945The following example shows a 2D histogram plotted with the option
1946`LEGO1`. The option `LEGO1` draws a lego plot using the
1947hidden surface removal technique. Combined with any `LEGOn` option, the
1948option `0` allows to not drawn the empty bins.
1949
1950Begin_Macro(source)
1951{
1952 auto c2 = new TCanvas("c2","c2",600,400);
1953 auto hlego1 = new TH2F("hlego1","Option LEGO1 example (with option 0) ",40,-4,4,40,-20,20);
1954 float px, py;
1955 for (Int_t i = 0; i < 25000; i++) {
1956 gRandom->Rannor(px,py);
1957 hlego1->Fill(px-1,5*py);
1958 hlego1->Fill(2+0.5*px,2*py-10.,0.1);
1959 }
1960 hlego1->SetFillColor(kYellow);
1961 hlego1->Draw("LEGO1 0");
1962}
1963End_Macro
1964
1965The following example shows a 2D histogram plotted with the option
1966`LEGO3`. Like the option `LEGO1`, the option `LEGO3`
1967draws a lego plot using the hidden surface removal technique but doesn't draw
1968the border lines of each individual lego-bar. This is very useful for histograms
1969having many bins. With such histograms the option `LEGO1` gives a black
1970image because of the border lines. This option also works with stacked legos.
1971
1972Begin_Macro(source)
1973{
1974 auto c2 = new TCanvas("c2","c2",600,400);
1975 auto hlego3 = new TH2F("hlego3","Option LEGO3 example",40,-4,4,40,-20,20);
1976 float px, py;
1977 for (Int_t i = 0; i < 25000; i++) {
1978 gRandom->Rannor(px,py);
1979 hlego3->Fill(px-1,5*py);
1980 hlego3->Fill(2+0.5*px,2*py-10.,0.1);
1981 }
1982 hlego3->SetFillColor(kRed);
1983 hlego3->Draw("LEGO3");
1984}
1985End_Macro
1986
1987The following example shows a 2D histogram plotted with the option
1988`LEGO2`. The option `LEGO2` draws a lego plot using colors to
1989show the cell contents. Combined with the option `LEGO2`, the option
1990`Z` allows to display the color palette defined by
1991`gStyle->SetPalette()`.
1992
1993Begin_Macro(source)
1994{
1995 auto c2 = new TCanvas("c2","c2",600,400);
1996 auto hlego2 = new TH2F("hlego2","Option LEGO2Z example ",40,-4,4,40,-20,20);
1997 float px, py;
1998 for (Int_t i = 0; i < 25000; i++) {
1999 gRandom->Rannor(px,py);
2000 hlego2->Fill(px-1,5*py);
2001 hlego2->Fill(2+0.5*px,2*py-10.,0.1);
2002 }
2003 hlego2->Draw("LEGO2Z");
2004}
2005End_Macro
2006
2007
2008
2009\anchor HP18
2010### The "SURFace" options
2011
2012
2013In a surface plot, cell contents are represented as a mesh.
2014The height of the mesh is proportional to the cell content.
2015
2016| Option | Description |
2017|----------|-------------------------------------------------------------------|
2018| "SURF" | Draw a surface plot using the hidden line removal technique.|
2019| "SURF1" | Draw a surface plot using the hidden surface removal technique.|
2020| "SURF2" | Draw a surface plot using colors to show the cell contents.|
2021| "SURF3" | Same as `SURF` with an additional filled contour plot on top.|
2022| "SURF4" | Draw a surface using the Gouraud shading technique.|
2023| "SURF5" | Used with one of the options CYL, PSR and CYL this option allows to draw a filled contour plot.|
2024| "SURF6" | This option should not be used directly. It is used internally when the CONT is used with option the option SAME on a 3D plot.|
2025| "SURF7" | Same as `SURF2` with an additional line contour plot on top.|
2026
2027
2028
2029See the limitations with [the option "SAME"](\ref HP060a).
2030
2031The following example shows a 2D histogram plotted with the option
2032`SURF`. The option `SURF` draws a lego plot using the hidden
2033lines removal technique.
2034
2035Begin_Macro(source)
2036{
2037 auto c2 = new TCanvas("c2","c2",600,400);
2038 auto hsurf = new TH2F("hsurf","Option SURF example ",30,-4,4,30,-20,20);
2039 float px, py;
2040 for (Int_t i = 0; i < 25000; i++) {
2041 gRandom->Rannor(px,py);
2042 hsurf->Fill(px-1,5*py);
2043 hsurf->Fill(2+0.5*px,2*py-10.,0.1);
2044 }
2045 hsurf->Draw("SURF");
2046}
2047End_Macro
2048
2049The following example shows a 2D histogram plotted with the option
2050`SURF1`. The option `SURF1` draws a surface plot using the
2051hidden surface removal technique. Combined with the option `SURF1`,
2052the option `Z` allows to display the color palette defined by
2053`gStyle->SetPalette()`.
2054
2055Begin_Macro(source)
2056{
2057 auto c2 = new TCanvas("c2","c2",600,400);
2058 auto hsurf1 = new TH2F("hsurf1","Option SURF1 example ",30,-4,4,30,-20,20);
2059 float px, py;
2060 for (Int_t i = 0; i < 25000; i++) {
2061 gRandom->Rannor(px,py);
2062 hsurf1->Fill(px-1,5*py);
2063 hsurf1->Fill(2+0.5*px,2*py-10.,0.1);
2064 }
2065 hsurf1->Draw("SURF1");
2066}
2067End_Macro
2068
2069The following example shows a 2D histogram plotted with the option
2070`SURF2`. The option `SURF2` draws a surface plot using colors
2071to show the cell contents. Combined with the option `SURF2`, the option
2072`Z` allows to display the color palette defined by
2073`gStyle->SetPalette()`.
2074
2075Begin_Macro(source)
2076{
2077 auto c2 = new TCanvas("c2","c2",600,400);
2078 auto hsurf2 = new TH2F("hsurf2","Option SURF2 example ",30,-4,4,30,-20,20);
2079 float px, py;
2080 for (Int_t i = 0; i < 25000; i++) {
2081 gRandom->Rannor(px,py);
2082 hsurf2->Fill(px-1,5*py);
2083 hsurf2->Fill(2+0.5*px,2*py-10.,0.1);
2084 }
2085 hsurf2->Draw("SURF2");
2086}
2087End_Macro
2088
2089The following example shows a 2D histogram plotted with the option
2090`SURF3`. The option `SURF3` draws a surface plot using the
2091hidden line removal technique with, in addition, a filled contour view drawn on the
2092top. Combined with the option `SURF3`, the option `Z` allows
2093to display the color palette defined by `gStyle->SetPalette()`.
2094
2095Begin_Macro(source)
2096{
2097 auto c2 = new TCanvas("c2","c2",600,400);
2098 auto hsurf3 = new TH2F("hsurf3","Option SURF3 example ",30,-4,4,30,-20,20);
2099 float px, py;
2100 for (Int_t i = 0; i < 25000; i++) {
2101 gRandom->Rannor(px,py);
2102 hsurf3->Fill(px-1,5*py);
2103 hsurf3->Fill(2+0.5*px,2*py-10.,0.1);
2104 }
2105 hsurf3->Draw("SURF3");
2106}
2107End_Macro
2108
2109The following example shows a 2D histogram plotted with the option
2110`SURF4`. The option `SURF4` draws a surface using the Gouraud
2111shading technique.
2112
2113Begin_Macro(source)
2114{
2115 auto c2 = new TCanvas("c2","c2",600,400);
2116 auto hsurf4 = new TH2F("hsurf4","Option SURF4 example ",30,-4,4,30,-20,20);
2117 float px, py;
2118 for (Int_t i = 0; i < 25000; i++) {
2119 gRandom->Rannor(px,py);
2120 hsurf4->Fill(px-1,5*py);
2121 hsurf4->Fill(2+0.5*px,2*py-10.,0.1);
2122 }
2123 hsurf4->SetFillColor(kOrange);
2124 hsurf4->Draw("SURF4");
2125}
2126End_Macro
2127
2128The following example shows a 2D histogram plotted with the option
2129`SURF5 CYL`. Combined with the option `SURF5`, the option
2130`Z` allows to display the color palette defined by `gStyle->SetPalette()`.
2131
2132Begin_Macro(source)
2133{
2134 auto c2 = new TCanvas("c2","c2",600,400);
2135 auto hsurf5 = new TH2F("hsurf4","Option SURF5 example ",30,-4,4,30,-20,20);
2136 float px, py;
2137 for (Int_t i = 0; i < 25000; i++) {
2138 gRandom->Rannor(px,py);
2139 hsurf5->Fill(px-1,5*py);
2140 hsurf5->Fill(2+0.5*px,2*py-10.,0.1);
2141 }
2142 hsurf5->Draw("SURF5 CYL");
2143}
2144End_Macro
2145
2146The following example shows a 2D histogram plotted with the option
2147`SURF7`. The option `SURF7` draws a surface plot using the
2148hidden surfaces removal technique with, in addition, a line contour view drawn on the
2149top. Combined with the option `SURF7`, the option `Z` allows
2150to display the color palette defined by `gStyle->SetPalette()`.
2151
2152Begin_Macro(source)
2153{
2154 auto c2 = new TCanvas("c2","c2",600,400);
2155 auto hsurf7 = new TH2F("hsurf3","Option SURF7 example ",30,-4,4,30,-20,20);
2156 float px, py;
2157 for (Int_t i = 0; i < 25000; i++) {
2158 gRandom->Rannor(px,py);
2159 hsurf7->Fill(px-1,5*py);
2160 hsurf7->Fill(2+0.5*px,2*py-10.,0.1);
2161 }
2162 hsurf7->Draw("SURF7");
2163}
2164End_Macro
2165
2166As shown in the following example, when a contour plot is painted on top of a
2167surface plot using the option `SAME`, the contours appear in 3D on the
2168surface.
2169
2170Begin_Macro(source)
2171{
2172 auto c20=new TCanvas("c20","c20",600,400);
2173 int NBins = 50;
2174 double d = 2;
2175 auto hsc = new TH2F("hsc", "Surface and contour with option SAME ", NBins, -d, d, NBins, -d, d);
2176 for (int bx = 1; bx <= NBins; ++bx) {
2177 for (int by = 1; by <= NBins; ++by) {
2178 double x = hsc->GetXaxis()->GetBinCenter(bx);
2179 double y = hsc->GetYaxis()->GetBinCenter(by);
2180 hsc->SetBinContent(bx, by, exp(-x*x)*exp(-y*y));
2181 }
2182 }
2183 hsc->Draw("surf2");
2184 hsc->Draw("CONT1 SAME");
2185}
2186End_Macro
2187
2188
2189\anchor HP19
2190### Cylindrical, Polar, Spherical and PseudoRapidity/Phi options
2191
2192
2193Legos and surfaces plots are represented by default in Cartesian coordinates.
2194Combined with any `LEGOn` or `SURFn` options the following
2195options allow to draw a lego or a surface in other coordinates systems.
2196
2197| Option | Description |
2198|----------|-------------------------------------------------------------------|
2199| "CYL" | Use Cylindrical coordinates. The X coordinate is mapped on the angle and the Y coordinate on the cylinder length.|
2200| "POL" | Use Polar coordinates. The X coordinate is mapped on the angle and the Y coordinate on the radius.|
2201| "SPH" | Use Spherical coordinates. The X coordinate is mapped on the latitude and the Y coordinate on the longitude.|
2202| "PSR" | Use PseudoRapidity/Phi coordinates. The X coordinate is mapped on Phi.|
2203
2204
2205
2206<b>WARNING:</b> Axis are not drawn with these options.
2207
2208The following example shows the same histogram as a lego plot is the four
2209different coordinates systems.
2210
2211Begin_Macro(source)
2212{
2213 auto c3 = new TCanvas("c3","c3",600,400);
2214 c3->Divide(2,2);
2215 auto hlcc = new TH2F("hlcc","Cylindrical coordinates",20,-4,4,20,-20,20);
2216 float px, py;
2217 for (Int_t i = 0; i < 25000; i++) {
2218 gRandom->Rannor(px,py);
2219 hlcc->Fill(px-1,5*py);
2220 hlcc->Fill(2+0.5*px,2*py-10.,0.1);
2221 }
2222 hlcc->SetFillColor(kYellow);
2223 c3->cd(1); hlcc->Draw("LEGO1 CYL");
2224 c3->cd(2); auto hlpc = (TH2F*) hlcc->DrawClone("LEGO1 POL");
2225 hlpc->SetTitle("Polar coordinates");
2226 c3->cd(3); auto hlsc = (TH2F*) hlcc->DrawClone("LEGO1 SPH");
2227 hlsc->SetTitle("Spherical coordinates");
2228 c3->cd(4); auto hlprpc = (TH2F*) hlcc->DrawClone("LEGO1 PSR");
2229 hlprpc->SetTitle("PseudoRapidity/Phi coordinates");
2230}
2231End_Macro
2232
2233The following example shows the same histogram as a surface plot is the four different coordinates systems.
2234
2235Begin_Macro(source)
2236{
2237 auto c4 = new TCanvas("c4","c4",600,400);
2238 c4->Divide(2,2);
2239 auto hscc = new TH2F("hscc","Cylindrical coordinates",20,-4,4,20,-20,20);
2240 float px, py;
2241 for (Int_t i = 0; i < 25000; i++) {
2242 gRandom->Rannor(px,py);
2243 hscc->Fill(px-1,5*py);
2244 hscc->Fill(2+0.5*px,2*py-10.,0.1);
2245 }
2246 c4->cd(1); hscc->Draw("SURF1 CYL");
2247 c4->cd(2); auto hspc = (TH2F*) hscc->DrawClone("SURF1 POL");
2248 hspc->SetTitle("Polar coordinates");
2249 c4->cd(3); auto hssc = (TH2F*) hscc->DrawClone("SURF1 SPH");
2250 hssc->SetTitle("Spherical coordinates");
2251 c4->cd(4); auto hsprpc = (TH2F*) hscc->DrawClone("SURF1 PSR");
2252 hsprpc->SetTitle("PseudoRapidity/Phi coordinates");
2253}
2254End_Macro
2255
2256
2257\anchor HP20
2258### Base line for bar-charts and lego plots
2259
2260
2261By default the base line used to draw the boxes for bar-charts and lego plots is
2262the histogram minimum. It is possible to force this base line to be 0, using MIN0 draw
2263option or with the command:
2264
2265 gStyle->SetHistMinimumZero();
2266
2267Begin_Macro(source)
2268{
2269 auto c5 = new TCanvas("c5","c5",700,400);
2270 c5->Divide(2,1);
2271 auto hz1 = new TH1F("hz1","Bar-chart drawn from 0",20,-3,3);
2272 auto hz2 = new TH2F("hz2","Lego plot drawn from 0",20,-3,3,20,-3,3);
2273 Int_t i;
2274 double x,y;
2275 hz1->SetFillColor(kBlue);
2276 hz2->SetFillColor(kBlue);
2277 for (i=0;i<10000;i++) {
2278 x = gRandom->Gaus(0,1);
2279 y = gRandom->Gaus(0,1);
2280 if (x>0) {
2281 hz1->Fill(x,1);
2282 hz2->Fill(x,y,1);
2283 } else {
2284 hz1->Fill(x,-1);
2285 hz2->Fill(x,y,-2);
2286 }
2287 }
2288 c5->cd(1); hz1->Draw("bar2 min0");
2289 c5->cd(2); hz2->Draw("lego1 min0");
2290}
2291End_Macro
2292
2293This option also works for horizontal plots. The example given in the section
2294["The bar chart option"](\ref HP100) appears as follow:
2295
2296Begin_Macro(source)
2297{
2298 int i;
2299 const Int_t nx = 8;
2300 string os_X[nx] = {"8","32","128","512","2048","8192","32768","131072"};
2301 float d_35_0[nx] = {0.75, -3.30, -0.92, 0.10, 0.08, -1.69, -1.29, -2.37};
2302 float d_35_1[nx] = {1.01, -3.02, -0.65, 0.37, 0.34, -1.42, -1.02, -2.10};
2303
2304 auto cbh = new TCanvas("cbh","cbh",400,600);
2305 cbh->SetGrid();
2306
2307 auto h1bh = new TH1F("h1bh","Option HBAR centered on 0",nx,0,nx);
2308 h1bh->SetFillColor(4);
2309 h1bh->SetBarWidth(0.4);
2310 h1bh->SetBarOffset(0.1);
2311 h1bh->SetStats(0);
2312 h1bh->SetMinimum(-5);
2313 h1bh->SetMaximum(5);
2314
2315 for (i=1; i<=nx; i++) {
2316 h1bh->Fill(os_X[i-1].c_str(), d_35_0[i-1]);
2317 h1bh->GetXaxis()->SetBinLabel(i,os_X[i-1].c_str());
2318 }
2319
2320 h1bh->Draw("hbar min0");
2321
2322 auto h2bh = new TH1F("h2bh","h2bh",nx,0,nx);
2323 h2bh->SetFillColor(38);
2324 h2bh->SetBarWidth(0.4);
2325 h2bh->SetBarOffset(0.5);
2326 h2bh->SetStats(0);
2327 for (i=1;i<=nx;i++) h2bh->Fill(os_X[i-1].c_str(), d_35_1[i-1]);
2328
2329 h2bh->Draw("hbar min0 same");
2330}
2331End_Macro
2332
2333
2334\anchor HP20a
2335### TH2Poly Drawing
2336
2337
2338The following options are supported:
2339
2340| Option | Description |
2341|----------|-------------------------------------------------------------------|
2342| "SCAT" | Draw a scatter plot (legacy draw option).|
2343| "COL" | Draw a color plot. All the bins are painted even the empty bins (default).|
2344| "COLZ" | Same as "COL". In addition the color palette is also drawn.|
2345| "0" | When used with any COL options, the empty bins are not drawn.|
2346| "TEXT" | Draw bin contents as text (format set via `gStyle->SetPaintTextFormat`).|
2347| "TEXTN" | Draw bin names as text.|
2348| "TEXTnn" | Draw bin contents as text at angle nn (0 < nn <= 90).|
2349| "L" | Draw the bins boundaries as lines. The lines attributes are the TGraphs ones.|
2350| "P" | Draw the bins boundaries as markers. The markers attributes are the TGraphs ones.|
2351| "F" | Draw the bins boundaries as filled polygons. The filled polygons attributes are the TGraphs ones.|
2352
2353
2354
2355`TH2Poly` can be drawn as a color plot (option COL). `TH2Poly` bins can have any
2356shapes. The bins are defined as graphs. The following macro is a very simple
2357example showing how to book a TH2Poly and draw it.
2358
2359Begin_Macro(source)
2360{
2361 auto ch2p1 = new TCanvas("ch2p1","ch2p1",600,400);
2362 auto h2p = new TH2Poly();
2363 h2p->SetName("h2poly_name");
2364 h2p->SetTitle("h2poly_title");
2365 double px1[] = {0, 5, 6};
2366 double py1[] = {0, 0, 5};
2367 double px2[] = {0, -1, -1, 0};
2368 double py2[] = {0, 0, -1, 3};
2369 double px3[] = {4, 3, 0, 1, 2.4};
2370 double py3[] = {4, 3.7, 1, 3.7, 2.5};
2371 h2p->AddBin(3, px1, py1);
2372 h2p->AddBin(4, px2, py2);
2373 h2p->AddBin(5, px3, py3);
2374 h2p->Fill(0.1, 0.01, 3);
2375 h2p->Fill(-0.5, -0.5, 7);
2376 h2p->Fill(-0.7, -0.5, 1);
2377 h2p->Fill(1, 3, 1.5);
2378 double fx[] = {0.1, -0.5, -0.7, 1};
2379 double fy[] = {0.01, -0.5, -0.5, 3};
2380 double fw[] = {3, 1, 1, 1.5};
2381 h2p->FillN(4, fx, fy, fw);
2382 h2p->Draw("col");
2383}
2384End_Macro
2385
2386Rectangular bins are a frequent case. The special version of
2387the `AddBin` method allows to define them more easily like
2388shown in the following example (hist037_TH2Poly_boxes.C).
2389
2390Begin_Macro(source)
2391../../../tutorials/hist/hist037_TH2Poly_boxes.C
2392End_Macro
2393
2394One `TH2Poly` bin can be a list of polygons. Such bins are defined
2395by calling `AddBin` with a `TMultiGraph`. The following example
2396shows a such case:
2397
2398Begin_Macro(source)
2399{
2400 auto ch2p2 = new TCanvas("ch2p2","ch2p2",600,400);
2401
2402 Int_t i, bin;
2403 const Int_t nx = 48;
2404 const char *states [nx] = {
2405 "alabama", "arizona", "arkansas", "california",
2406 "colorado", "connecticut", "delaware", "florida",
2407 "georgia", "idaho", "illinois", "indiana",
2408 "iowa", "kansas", "kentucky", "louisiana",
2409 "maine", "maryland", "massachusetts", "michigan",
2410 "minnesota", "mississippi", "missouri", "montana",
2411 "nebraska", "nevada", "new_hampshire", "new_jersey",
2412 "new_mexico", "new_york", "north_carolina", "north_dakota",
2413 "ohio", "oklahoma", "oregon", "pennsylvania",
2414 "rhode_island", "south_carolina", "south_dakota", "tennessee",
2415 "texas", "utah", "vermont", "virginia",
2416 "washington", "west_virginia", "wisconsin", "wyoming"
2417 };
2418 Double_t pop[nx] = {
2419 4708708, 6595778, 2889450, 36961664, 5024748, 3518288, 885122, 18537969,
2420 9829211, 1545801, 12910409, 6423113, 3007856, 2818747, 4314113, 4492076,
2421 1318301, 5699478, 6593587, 9969727, 5266214, 2951996, 5987580, 974989,
2422 1796619, 2643085, 1324575, 8707739, 2009671, 19541453, 9380884, 646844,
2423 11542645, 3687050, 3825657, 12604767, 1053209, 4561242, 812383, 6296254,
2424 24782302, 2784572, 621760, 7882590, 6664195, 1819777, 5654774, 544270
2425 };
2426
2427 Double_t lon1 = -130;
2428 Double_t lon2 = -65;
2429 Double_t lat1 = 24;
2430 Double_t lat2 = 50;
2431 auto p = new TH2Poly("USA","USA Population",lon1,lon2,lat1,lat2);
2432
2433 TFile::SetCacheFileDir(".");
2434 auto f = TFile::Open("http://root.cern/files/usa.root", "CACHEREAD");
2435
2436 TMultiGraph *mg;
2437 TKey *key;
2438 TIter nextkey(gDirectory->GetListOfKeys());
2439 while ((key = (TKey*)nextkey())) {
2440 TObject *obj = key->ReadObj();
2441 if (obj->InheritsFrom("TMultiGraph")) {
2442 mg = (TMultiGraph*)obj;
2443 bin = p->AddBin(mg);
2444 }
2445 }
2446
2447 for (i=0; i<nx; i++) p->Fill(states[i], pop[i]);
2448
2449 gStyle->SetOptStat(11);
2450 p->Draw("COLZ L");
2451}
2452End_Macro
2453
2454`TH2Poly` histograms can also be plotted using the GL interface using
2455the option "GLLEGO".
2456
2457\since **ROOT version 6.09/01**
2458
2459In some cases it can be useful to not draw the empty bins. the option "0"
2460combined with the option "COL" et COLZ allows to do that.
2461
2462Begin_Macro(source)
2463{
2464 auto chc = new TCanvas("chc","chc",600,400);
2465
2466 auto hc = new TH2Poly();
2467 hc->Honeycomb(0,0,.1,25,25);
2468 hc->SetName("hc");
2469 hc->SetTitle("Option COLZ 0");
2470 TRandom ran;
2471 for (int i = 0; i<300; i++) hc->Fill(ran.Gaus(2.,1), ran.Gaus(2.,1));
2472 hc->Draw("colz 0");
2473}
2474End_Macro
2475
2476\anchor HP21
2477### The SPEC option
2478
2479
2480This option allows to use the `TSpectrum2Painter` tools. See the full
2481documentation in `TSpectrum2Painter::PaintSpectrum`.
2482
2483
2484\anchor HP22
2485### Option "Z" : Adding the color palette on the right side of the pad
2486
2487
2488When this option is specified, a color palette with an axis indicating the value
2489of the corresponding color is drawn on the right side of the picture. In case,
2490not enough space is left, one can increase the size of the right margin by
2491calling `TPad::SetRightMargin()`. The attributes used to display the
2492palette axis values are taken from the Z axis of the object. For example, to
2493set the labels size on the palette axis do:
2494
2495 hist->GetZaxis()->SetLabelSize().
2496
2497<b>WARNING:</b> The palette axis is always drawn vertically.
2498
2499
2500\anchor HP23
2501### Setting the color palette
2502
2503
2504To change the color palette `TStyle::SetPalette` should be used, eg:
2505
2506 gStyle->SetPalette(ncolors,colors);
2507
2508For example the option `COL` draws a 2D histogram with cells
2509represented by a box filled with a color index which is a function
2510of the cell content.
2511If the cell content is N, the color index used will be the color number
2512in `colors[N]`, etc. If the maximum cell content is greater than
2513`ncolors`, all cell contents are scaled to `ncolors`.
2514
2515If ` ncolors <= 0`, a default palette (see below) of 50 colors is
2516defined. This palette is recommended for pads, labels ...
2517
2518`if ncolors == 1 && colors == 0`, then a Pretty Palette with a
2519Spectrum Violet->Red is created with 50 colors. That's the default rain bow
2520palette.
2521
2522Other pre-defined palettes with 255 colors are available when `colors == 0`.
2523The following value of `ncolors` give access to:
2524
2525
2526 if ncolors = 51 and colors=0, a Deep Sea palette is used.
2527 if ncolors = 52 and colors=0, a Grey Scale palette is used.
2528 if ncolors = 53 and colors=0, a Dark Body Radiator palette is used.
2529 if ncolors = 54 and colors=0, a two-color hue palette palette is used.(dark blue through neutral gray to bright
2530yellow) if ncolors = 55 and colors=0, a Rain Bow palette is used. if ncolors = 56 and colors=0, an inverted Dark Body
2531Radiator palette is used.
2532
2533
2534If `ncolors > 0 && colors == 0`, the default palette is used with a maximum of ncolors.
2535
2536The default palette defines:
2537
2538- index 0 to 9 : shades of grey
2539- index 10 to 19 : shades of brown
2540- index 20 to 29 : shades of blue
2541- index 30 to 39 : shades of red
2542- index 40 to 49 : basic colors
2543
2544The color numbers specified in the palette can be viewed by selecting
2545the item `colors` in the `VIEW` menu of the canvas tool bar.
2546The red, green, and blue components of a color can be changed thanks to
2547`TColor::SetRGB()`.
2548
2549\since **ROOT version 6.19/01**
2550
2551As default labels and ticks are drawn by `TGAxis` at equidistant (lin or log)
2552points as controlled by SetNdivisions.
2553If option "CJUST" is given labels and ticks are justified at the
2554color boundaries defined by the contour levels.
2555For more details see `TPaletteAxis`
2556
2557\anchor HP24
2558### Drawing a sub-range of a 2D histogram; the [cutg] option
2559
2560
2561Using a `TCutG` object, it is possible to draw a sub-range of a 2D
2562histogram. One must create a graphical cut (mouse or C++) and specify the name
2563of the cut between `[]` in the `Draw()` option.
2564For example (fit2a.C), with a `TCutG` named `cutg`, one can call:
2565
2566 myhist->Draw("surf1 [cutg]");
2567
2568To invert the cut, it is enough to put a `-` in front of its name:
2569
2570 myhist->Draw("surf1 [-cutg]");
2571
2572It is possible to apply several cuts (`,` means logical AND):
2573
2574 myhist->Draw("surf1 [cutg1,cutg2]");
2575
2576Begin_Macro(source)
2577../../../tutorials/fit/fit2a.C
2578End_Macro
2579
2580\anchor HP25
2581### Drawing options for 3D histograms
2582
2583
2584| Option | Description |
2585|----------|-------------------------------------------------------------------|
2586| "SCAT" | Draw a scatter plot (legacy draw option).|
2587| "ISO" | Draw a Gouraud shaded 3d iso surface through a 3d histogram. It paints one surface at the value computed as follow: `SumOfWeights/(NbinsX*NbinsY*NbinsZ)`|
2588| "BOX" | Draw a for each cell with volume proportional to the content's absolute value. An hidden line removal algorithm is used|
2589| "BOX1" | Same as BOX but an hidden surface removal algorithm is used|
2590| "BOX2" | Same as "COL". The boxes' colors are picked in the current palette according to the bins' contents (default)|
2591| "BOX2Z" | Same as "BOX2". In addition the color palette is also drawn.|
2592| "BOX3" | Same as BOX1, but the border lines of each lego-bar are not drawn.|
2593
2594Note that instead of `BOX` one can also use `LEGO`.
2595
2596By default, 3D histograms are drawn as a colored box plots.
2597
2598The following example shows a 3D histogram plotted as a scatter plot.
2599
2600Begin_Macro(source)
2601{
2602 auto c06 = new TCanvas("c06","c06",600,400);
2603 gStyle->SetOptStat(kFALSE);
2604 auto h3scat = new TH3F("h3scat","Option SCAT",15,-2,2,15,-2,2,15,0,4);
2605 double x, y, z;
2606 for (Int_t i=0;i<10000;i++) {
2607 gRandom->Rannor(x, y);
2608 z = x*x + y*y;
2609 h3scat->Fill(x,y,z);
2610 }
2611 h3scat->Draw("SCAT"); // This a legacy draw option
2612}
2613End_Macro
2614
2615The following example shows a 3D histogram plotted with the option `BOX`.
2616
2617Begin_Macro(source)
2618{
2619 auto c16 = new TCanvas("c16","c16",600,400);
2620 gStyle->SetOptStat(kFALSE);
2621 auto h3box = new TH3F("h3box","Option BOX",15,-2,2,15,-2,2,15,0,4);
2622 double x, y, z;
2623 for (Int_t i=0;i<10000;i++) {
2624 gRandom->Rannor(x, y);
2625 z = x*x + y*y;
2626 h3box->Fill(x,y,z);
2627 }
2628 h3box->Draw("BOX");
2629}
2630End_Macro
2631
2632The following example shows a 3D histogram plotted with the option `BOX1`.
2633
2634Begin_Macro(source)
2635{
2636 auto c36 = new TCanvas("c36","c36",600,400);
2637 gStyle->SetOptStat(kFALSE);
2638 auto h3box = new TH3F("h3box","Option BOX1",10,-2.,2.,10,-2.,2.,10,-0.5,2.);
2639 double x, y, z;
2640 for (Int_t i=0;i<10000;i++) {
2641 gRandom->Rannor(x, y);
2642 z = abs(sin(x)/x + cos(y)*y);
2643 h3box->Fill(x,y,z);
2644 }
2645 h3box->SetFillColor(9);
2646 h3box->Draw("BOX1");
2647}
2648End_Macro
2649
2650The following example shows a 3D histogram plotted with the option `BOX2`.
2651
2652Begin_Macro(source)
2653{
2654 auto c56 = new TCanvas("c56","c56",600,400);
2655 gStyle->SetOptStat(kFALSE);
2656 auto h3box = new TH3F("h3box","Option BOX2 (default)",10,-2.,2.,10,-2.,2.,10,-0.5,2.);
2657 double x, y, z;
2658 for (Int_t i=0;i<10000;i++) {
2659 gRandom->Rannor(x, y);
2660 z = abs(sin(x)/x + cos(y)*y);
2661 h3box->Fill(x,y,z);
2662 }
2663 h3box->Draw("BOX2 Z");
2664}
2665End_Macro
2666
2667The following example shows a 3D histogram plotted with the option `BOX3`.
2668
2669Begin_Macro(source)
2670{
2671 auto c46 = new TCanvas("c46","c46",600,400);
2672 c46->SetFillColor(38);
2673 gStyle->SetOptStat(kFALSE);
2674 auto h3box = new TH3F("h3box","Option BOX3",15,-2,2,15,-2,2,15,0,4);
2675 double x, y, z;
2676 for (Int_t i=0;i<10000;i++) {
2677 gRandom->Rannor(x, y);
2678 z = x*x + y*y;
2679 h3box->Fill(x,y,z);
2680 }
2681 h3box->Draw("BOX3");
2682}
2683End_Macro
2684
2685For all the `BOX` options each bin is drawn as a 3D box with a volume proportional
2686to the absolute value of the bin content. The bins with a negative content are
2687drawn with a X on each face of the box as shown in the following example:
2688
2689Begin_Macro(source)
2690{
2691 auto c = new TCanvas("c","c",600,400);
2692 gStyle->SetOptStat(kFALSE);
2693 auto h3box = new TH3F("h3box","Option BOX1 with negative bins",3, 0., 4., 3, 0.,4., 3, 0., 4.);
2694 h3box->Fill(0., 2., 2., 10.);
2695 h3box->Fill(2., 2., 2., 5.);
2696 h3box->Fill(2., 2., .5, 2.);
2697 h3box->Fill(2., 2., 3., -1.);
2698 h3box->Fill(3., 2., 2., -10.);
2699 h3box->SetFillColor(8);
2700 h3box->Draw("box1");
2701}
2702End_Macro
2703
2704The following example shows a 3D histogram plotted with the option `ISO`.
2705
2706Begin_Macro(source)
2707{
2708 auto c26 = new TCanvas("c26","c26",600,400);
2709 gStyle->SetOptStat(kFALSE);
2710 auto h3iso = new TH3F("h3iso","Option ISO",15,-2,2,15,-2,2,15,0,4);
2711 double x, y, z;
2712 for (Int_t i=0;i<10000;i++) {
2713 gRandom->Rannor(x, y);
2714 z = x*x + y*y;
2715 h3iso->Fill(x,y,z);
2716 }
2717 h3iso->SetFillColor(kCyan);
2718 h3iso->Draw("ISO");
2719}
2720End_Macro
2721
2722
2723\anchor HP26
2724### Drawing option for histograms' stacks
2725
2726
2727Stacks of histograms are managed with the `THStack`. A `THStack`
2728is a collection of `TH1` (or derived) objects. For painting only the
2729`THStack` containing `TH1` only or
2730`THStack` containing `TH2` only will be considered.
2731
2732By default, histograms are shown stacked:
2733
27341. The first histogram is paint.
27352. The sum of the first and second, etc...
2736
2737If the option `NOSTACK` is specified, the histograms are all paint in
2738the same pad as if the option `SAME` had been specified. This allows to
2739compute X and Y scales common to all the histograms, like
2740`TMultiGraph` does for graphs.
2741
2742If the option `PADS` is specified, the current pad/canvas is
2743subdivided into a number of pads equal to the number of histograms and each
2744histogram is paint into a separate pad.
2745
2746The following example shows various types of stacks (hist023_THStack_simple.C).
2747
2748Begin_Macro(source)
2749../../../tutorials/hist/hist023_THStack_simple.C
2750End_Macro
2751
2752The option `nostackb` allows to draw the histograms next to each
2753other as bar charts:
2754
2755Begin_Macro(source)
2756{
2757 auto cst0 = new TCanvas("cst0","cst0",600,400);
2758 auto hs = new THStack("hs","Stacked 1D histograms: option #font[82]{\"nostackb\"}");
2759
2760 auto h1 = new TH1F("h1","h1",10,-4,4);
2761 h1->FillRandom("gaus",20000);
2762 h1->SetFillColor(kRed);
2763 hs->Add(h1);
2764
2765 auto h2 = new TH1F("h2","h2",10,-4,4);
2766 h2->FillRandom("gaus",15000);
2767 h2->SetFillColor(kBlue);
2768 hs->Add(h2);
2769
2770 auto h3 = new TH1F("h3","h3",10,-4,4);
2771 h3->FillRandom("gaus",10000);
2772 h3->SetFillColor(kGreen);
2773 hs->Add(h3);
2774
2775 hs->Draw("nostackb");
2776 hs->GetXaxis()->SetNdivisions(-10);
2777 cst0->SetGridx();
2778}
2779End_Macro
2780
2781If at least one of the histograms in the stack has errors, the whole stack is
2782visualized by default with error bars. To visualize it without errors the
2783option `HIST` should be used.
2784
2785Begin_Macro(source)
2786{
2787 auto cst1 = new TCanvas("cst1","cst1",700,400);
2788 cst1->Divide(2,1);
2789
2790 auto hst11 = new TH1F("hst11", "", 20, -10, 10);
2791 hst11->Sumw2();
2792 hst11->FillRandom("gaus", 1000);
2793 hst11->SetFillColor(kViolet);
2794 hst11->SetLineColor(kViolet);
2795
2796 auto hst12 = new TH1F("hst12", "", 20, -10, 10);
2797 hst12->FillRandom("gaus", 500);
2798 hst12->SetFillColor(kBlue);
2799 hst12->SetLineColor(kBlue);
2800
2801 THStack st1("st1", "st1");
2802 st1.Add(hst11);
2803 st1.Add(hst12);
2804
2805 cst1->cd(1); st1.Draw();
2806 cst1->cd(2); st1.Draw("hist");
2807}
2808End_Macro
2809
2810\anchor HP27
2811### Drawing of 3D implicit functions
2812
2813
28143D implicit functions (`TF3`) can be drawn as iso-surfaces.
2815The implicit function f(x,y,z) = 0 is drawn in cartesian coordinates.
2816In the following example the options "FB" and "BB" suppress the
2817"Front Box" and "Back Box" around the plot.
2818
2819Begin_Macro(source)
2820{
2821 auto c2 = new TCanvas("c2","c2",600,400);
2822 auto f3 = new TF3("f3","sin(x*x+y*y+z*z-36)",-2,2,-2,2,-2,2);
2823 f3->SetClippingBoxOn(0,0,0);
2824 f3->SetFillColor(30);
2825 f3->SetLineColor(15);
2826 f3->Draw("FBBB");
2827}
2828End_Macro
2829
2830
2831\anchor HP28
2832### Associated functions drawing
2833
2834
2835An associated function is created by `TH1::Fit`. More than on fitted
2836function can be associated with one histogram (see `TH1::Fit`).
2837
2838A `TF1` object `f1` can be added to the list of associated
2839functions of an histogram `h` without calling `TH1::Fit`
2840simply doing:
2841
2842 h->GetListOfFunctions()->Add(f1);
2843
2844or
2845
2846 h->GetListOfFunctions()->Add(f1,someoption);
2847
2848To retrieve a function by name from this list, do:
2849
2850 TF1 *f1 = (TF1*)h->GetListOfFunctions()->FindObject(name);
2851
2852or
2853
2854 TF1 *f1 = h->GetFunction(name);
2855
2856Associated functions are automatically painted when an histogram is drawn.
2857To avoid the painting of the associated functions the option `HIST`
2858should be added to the list of the options used to paint the histogram.
2859
2860
2861\anchor HP29
2862### Drawing using OpenGL
2863
2864
2865The class `TGLHistPainter` allows to paint data set using the OpenGL 3D
2866graphics library. The plotting options start with `GL` keyword.
2867In addition, in order to inform canvases that OpenGL should be used to render
28683D representations, the following option should be set:
2869
2870 gStyle->SetCanvasPreferGL(true);
2871
2872
2873\anchor HP29a
2874#### General information: plot types and supported options
2875
2876The following types of plots are provided:
2877
2878For lego plots the supported options are:
2879
2880| Option | Description |
2881|----------|-------------------------------------------------------------------|
2882| "GLLEGO" | Draw a lego plot. It works also for `TH2Poly`.|
2883| "GLLEGO2"| Bins with color levels.|
2884| "GLLEGO3"| Cylindrical bars.|
2885
2886
2887
2888Lego painter in cartesian supports logarithmic scales for X, Y, Z.
2889In polar only Z axis can be logarithmic, in cylindrical only Y.
2890
2891For surface plots (`TF2` and `TH2`) the supported options are:
2892
2893| Option | Description |
2894|-----------|------------------------------------------------------------------|
2895| "GLSURF" | Draw a surface.|
2896| "GLSURF1" | Surface with color levels|
2897| "GLSURF2" | The same as "GLSURF1" but without polygon outlines.|
2898| "GLSURF3" | Color level projection on top of plot (works only in cartesian coordinate system).|
2899| "GLSURF4" | Same as "GLSURF" but without polygon outlines.|
2900
2901
2902
2903The surface painting in cartesian coordinates supports logarithmic scales along
2904X, Y, Z axis. In polar coordinates only the Z axis can be logarithmic,
2905in cylindrical coordinates only the Y axis.
2906
2907Additional options to SURF and LEGO - Coordinate systems:
2908
2909| Option | Description |
2910|----------|-------------------------------------------------------------------|
2911| " " | Default, cartesian coordinates system.|
2912| "POL" | Polar coordinates system.|
2913| "CYL" | Cylindrical coordinates system.|
2914| "SPH" | Spherical coordinates system.|
2915
2916
2917
2918\anchor HP290
2919#### TH3 as color boxes
2920
2921The supported option is:
2922
2923| Option | Description |
2924|----------|-------------------------------------------------------------------|
2925| "GLCOL" | H3 is drawn using semi-transparent colored boxes. See `$ROOTSYS/tutorials/visualisation/gl/glvox1.C`.|
2926
2927
2928
2929\anchor HP29b
2930#### TH3 as boxes (spheres)
2931
2932The supported options are:
2933
2934| Option | Description |
2935|----------|-------------------------------------------------------------------|
2936| "GLBOX" | TH3 as a set of boxes, size of box is proportional to bin content.|
2937| "GLBOX1" | The same as "glbox", but spheres are drawn instead of boxes.|
2938
2939
2940
2941\anchor HP29c
2942#### TH3 as iso-surface(s)
2943
2944The supported option is:
2945
2946| Option | Description |
2947|----------|-------------------------------------------------------------------|
2948| "GLISO" | TH3 is drawn using iso-surfaces.|
2949
2950
2951
2952\anchor HP29d
2953#### TF3 (implicit function)
2954
2955The supported option is:
2956
2957| Option | Description |
2958|----------|-------------------------------------------------------------------|
2959| "GL" | Draw a TF3.|
2960
2961
2962
2963\anchor HP29e
2964#### Parametric surfaces
2965
2966`$ROOTSYS/tutorials/visualisation/gl/glparametric.C` shows how to create parametric
2967equations and visualize the surface.
2968
2969\anchor HP29f
2970#### Interaction with the plots
2971
2972All the interactions are implemented via standard methods
2973`DistancetoPrimitive()` and `ExecuteEvent()`. That's why all the
2974interactions with the OpenGL plots are possible only when the mouse cursor is
2975in the plot's area (the plot's area is the part of a the pad occupied by
2976gl-produced picture). If the mouse cursor is not above gl-picture, the standard
2977pad interaction is performed.
2978
2979\anchor HP29g
2980#### Selectable parts
2981
2982Different parts of the plot can be selected:
2983
2984- xoz, yoz, xoy back planes: When such a plane selected, it's highlighted in green
2985 if the dynamic slicing by this plane is supported, and it's highlighted in red,
2986 if the dynamic slicing is not supported.
2987- The plot itself:
2988 On surfaces, the selected surface is outlined in red. (TF3 and
2989 ISO are not outlined). On lego plots, the selected bin is
2990 highlighted. The bin number and content are displayed in pad's
2991 status bar. In box plots, the box or sphere is highlighted and
2992 the bin info is displayed in pad's status bar.
2993
2994
2995\anchor HP29h
2996#### Rotation and zooming
2997
2998
2999- Rotation:
3000 When the plot is selected, it can be rotated by pressing and
3001 holding the left mouse button and move the cursor.
3002- Zoom/Unzoom:
3003 Mouse wheel or 'j', 'J', 'k', 'K' keys.
3004
3005
3006\anchor HP29i
3007#### Panning
3008
3009The selected plot can be moved in a pad's area by pressing and
3010holding the left mouse button and the shift key.
3011
3012\anchor HP29j
3013#### Box cut
3014
3015Surface, iso, box, TF3 and parametric painters support box cut by
3016pressing the 'c' or 'C' key when the mouse cursor is in a plot's
3017area. That will display a transparent box, cutting away part of the
3018surface (or boxes) in order to show internal part of plot. This box
3019can be moved inside the plot's area (the full size of the box is
3020equal to the plot's surrounding box) by selecting one of the box
3021cut axes and pressing the left mouse button to move it.
3022
3023\anchor HP29k
3024#### Plot specific interactions (dynamic slicing etc.)
3025
3026Currently, all gl-plots support some form of slicing. When back plane
3027is selected (and if it's highlighted in green) you can press and hold
3028left mouse button and shift key and move this back plane inside
3029plot's area, creating the slice. During this "slicing" plot becomes
3030semi-transparent. To remove all slices (and projected curves for
3031surfaces) double click with left mouse button in a plot's area.
3032
3033\anchor HP29l
3034#### Surface with option "GLSURF"
3035
3036The surface profile is displayed on the slicing plane.
3037The profile projection is drawn on the back plane
3038by pressing `'p'` or `'P'` key.
3039
3040\anchor HP29m
3041#### TF3
3042
3043The contour plot is drawn on the slicing plane. For TF3 the color
3044scheme can be changed by pressing 's' or 'S'.
3045
3046\anchor HP29n
3047#### Box
3048
3049The contour plot corresponding to slice plane position is drawn in real time.
3050
3051\anchor HP29o
3052#### Iso
3053
3054Slicing is similar to "GLBOX" option.
3055
3056\anchor HP29p
3057#### Parametric plot
3058
3059No slicing. Additional keys: 's' or 'S' to change color scheme -
3060about 20 color schemes supported ('s' for "scheme"); 'l' or 'L' to
3061increase number of polygons ('l' for "level" of details), 'w' or 'W'
3062to show outlines ('w' for "wireframe").
3063
3064\anchor HP30
3065#### Highlight mode for histogram
3066
3067\since **ROOT version 6.15/01**
3068
3069\image html hlHisto3_top.gif "Highlight mode"
3070
3071Highlight mode is implemented for `TH1` (and for `TGraph`) class. When
3072highlight mode is on, mouse movement over the bin will be represented
3073graphically. Bin will be highlighted as "bin box" (presented by box
3074object). Moreover, any highlight (change of bin) emits signal
3075`TCanvas::Highlighted()` which allows the user to react and call their own
3076function. For a better understanding see also the tutorial `hist043` to `hist046`
3077lacated in `$ROOTSYS/tutorials/hist/`.
3078
3079Highlight mode is switched on/off by `TH1::SetHighlight()` function
3080or interactively from `TH1` context menu. `TH1::IsHighlight()` to verify
3081whether the highlight mode enabled or disabled, default it is disabled.
3082
3083~~~ {.cpp}
3084 root [0] .x $ROOTSYS/tutorials/hsimple.C
3085 root [1] hpx->SetHighlight(kTRUE) // or interactively from TH1 context menu
3086 root [2] hpx->IsHighlight()
3087 (bool) true
3088~~~
3089
3090\image html hlsimple_nofun.gif "Highlight mode for histogram"
3091
3092\anchor HP30a
3093#### Highlight mode and user function
3094
3095The user can use (connect) `TCanvas::Highlighted()` signal, which is always
3096emitted if there is a highlight bin and call user function via signal
3097and slot communication mechanism. `TCanvas::Highlighted()` is similar
3098`TCanvas::Picked()`
3099
3100- when selected object (histogram as a whole) is different from previous
3101then emit `Picked()` signal
3102- when selected (highlighted) bin from histogram is different from previous
3103then emit `Highlighted()` signal
3104
3105Any user function (or functions) has to be defined
3106`UserFunction(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)`.
3107In example (see below) has name `PrintInfo()`. All parameters of user
3108function are taken from
3109
3110 void TCanvas::Highlighted(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)
3111
3112- `pad` is pointer to pad with highlighted histogram
3113- `obj` is pointer to highlighted histogram
3114- `x` is highlighted x bin for 1D histogram
3115- `y` is highlighted y bin for 2D histogram (for 1D histogram not in use)
3116
3117Example how to create a connection from any `TCanvas` object to a user
3118`UserFunction()` slot (see also `TQObject::Connect()` for additional info)
3119
3120 TQObject::Connect("TCanvas", "Highlighted(TVirtualPad*,TObject*,Int_t,Int_t)",
3121 0, 0, "UserFunction(TVirtualPad*,TObject*,Int_t,Int_t)");
3122
3123or use non-static "simplified" function
3124`TCanvas::HighlightConnect(const char *slot)`
3125
3126 c1->HighlightConnect("UserFunction(TVirtualPad*,TObject*,Int_t,Int_t)");
3127
3128NOTE the signal and slot string must have a form
3129"(TVirtualPad*,TObject*,Int_t,Int_t)"
3130
3131 root [0] .x $ROOTSYS/tutorials/hsimple.C
3132 root [1] hpx->SetHighlight(kTRUE)
3133 root [2] .x hlprint.C
3134
3135file `hlprint.C`
3136~~~ {.cpp}
3137void PrintInfo(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)
3138{
3139 auto h = (TH1F *)obj;
3140 if (!h->IsHighlight()) // after highlight disabled
3141 h->SetTitle("highlight disable");
3142 else
3143 h->SetTitle(TString::Format("bin[%03d] (%5.2f) content %g", x,
3144 h->GetBinCenter(x), h->GetBinContent(x)));
3145 pad->Update();
3146}
3147
3148void hlprint()
3149{
3150 if (!gPad) return;
3151 gPad->GetCanvas()->HighlightConnect("PrintInfo(TVirtualPad*,TObject*,Int_t,Int_t)");
3152}
3153~~~
3154
3155\image html hlsimple.gif "Highlight mode and simple user function"
3156
3157For more complex demo please see for example `$ROOTSYS/tutorials/io/tree/tree200_temperature.C` file.
3158
3159*/
3160
3162
3165
3166const Int_t kNMAX = 2000;
3167
3168const Int_t kMAXCONTOUR = 104;
3170
3171static std::unique_ptr<TBox> gXHighlightBox, gYHighlightBox; // highlight X and Y box
3172
3194
3196
3197////////////////////////////////////////////////////////////////////////////////
3198/// Default constructor.
3199
3201{
3202 fH = nullptr;
3203 fXaxis = nullptr;
3204 fYaxis = nullptr;
3205 fZaxis = nullptr;
3206 fFunctions = nullptr;
3207 fNcuts = 0;
3208 fStack = nullptr;
3209 fShowProjection = 0;
3210 fShowProjection2 = 0;
3211 fShowOption = "";
3212 for (int i=0; i<kMaxCuts; i++) {
3213 fCuts[i] = nullptr;
3214 fCutsOpt[i] = 0;
3215 }
3216 fXHighlightBin = -1;
3217 fYHighlightBin = -1;
3218 fCurrentF3 = nullptr;
3219
3220 gStringEntries = gEnv->GetValue("Hist.Stats.Entries", "Entries");
3221 gStringMean = gEnv->GetValue("Hist.Stats.Mean", "Mean");
3222 gStringMeanX = gEnv->GetValue("Hist.Stats.MeanX", "Mean x");
3223 gStringMeanY = gEnv->GetValue("Hist.Stats.MeanY", "Mean y");
3224 gStringMeanZ = gEnv->GetValue("Hist.Stats.MeanZ", "Mean z");
3225 gStringStdDev = gEnv->GetValue("Hist.Stats.StdDev", "Std Dev");
3226 gStringStdDevX = gEnv->GetValue("Hist.Stats.StdDevX", "Std Dev x");
3227 gStringStdDevY = gEnv->GetValue("Hist.Stats.StdDevY", "Std Dev y");
3228 gStringStdDevZ = gEnv->GetValue("Hist.Stats.StdDevZ", "Std Dev z");
3229 gStringUnderflow = gEnv->GetValue("Hist.Stats.Underflow", "Underflow");
3230 gStringOverflow = gEnv->GetValue("Hist.Stats.Overflow", "Overflow");
3231 gStringIntegral = gEnv->GetValue("Hist.Stats.Integral", "Integral");
3232 gStringIntegralBinWidth = gEnv->GetValue("Hist.Stats.IntegralBinWidth", "Integral(w)");
3233 gStringSkewness = gEnv->GetValue("Hist.Stats.Skewness", "Skewness");
3234 gStringSkewnessX = gEnv->GetValue("Hist.Stats.SkewnessX", "Skewness x");
3235 gStringSkewnessY = gEnv->GetValue("Hist.Stats.SkewnessY", "Skewness y");
3236 gStringSkewnessZ = gEnv->GetValue("Hist.Stats.SkewnessZ", "Skewness z");
3237 gStringKurtosis = gEnv->GetValue("Hist.Stats.Kurtosis", "Kurtosis");
3238 gStringKurtosisX = gEnv->GetValue("Hist.Stats.KurtosisX", "Kurtosis x");
3239 gStringKurtosisY = gEnv->GetValue("Hist.Stats.KurtosisY", "Kurtosis y");
3240 gStringKurtosisZ = gEnv->GetValue("Hist.Stats.KurtosisZ", "Kurtosis z");
3241}
3242
3243////////////////////////////////////////////////////////////////////////////////
3244/// destructor.
3245
3249
3250////////////////////////////////////////////////////////////////////////////////
3251/// Compute the distance from the point px,py to a line.
3252///
3253/// Compute the closest distance of approach from point px,py to elements of
3254/// an histogram. The distance is computed in pixels units.
3255///
3256/// Algorithm: Currently, this simple model computes the distance from the mouse
3257/// to the histogram contour only.
3258
3260{
3261
3262 Double_t defaultLabelSize = 0.04; // See TAttAxis.h for source of this value
3263
3264 const Int_t big = 9999;
3265 const Int_t kMaxDiff = 7;
3266
3267 if (fPie)
3268 return fPie->DistancetoPrimitive(px, py);
3269
3270 Double_t x = gPad->AbsPixeltoX(px);
3271 Double_t x1 = gPad->AbsPixeltoX(px+1);
3272
3273 Int_t puxmin = gPad->XtoAbsPixel(gPad->GetUxmin());
3274 Int_t puymin = gPad->YtoAbsPixel(gPad->GetUymin());
3275 Int_t puxmax = gPad->XtoAbsPixel(gPad->GetUxmax());
3276 Int_t puymax = gPad->YtoAbsPixel(gPad->GetUymax());
3277 Int_t curdist = big;
3279 Bool_t dsame;
3280 TObject *PadPointer = gPad->GetPadPointer();
3281 if (!PadPointer) return 0;
3282 TString doption = PadPointer->GetDrawOption();
3283 Double_t factor = 1;
3284 if (fH->GetNormFactor() != 0) {
3285 factor = fH->GetNormFactor()/fH->GetSumOfWeights();
3286 }
3287 // return if point is not in the histogram area
3288
3289 // If a 3D view exists, check distance to axis
3290 TView *view = gPad->GetView();
3291 Int_t d1,d2,d3;
3292 if (view && Hoption.Contour != 14) {
3293 Double_t ratio;
3294 d3 = view->GetDistancetoAxis(3, px, py, ratio);
3295 if (d3 <= kMaxDiff) {gPad->SetSelected(fZaxis); return 0;}
3296 d1 = view->GetDistancetoAxis(1, px, py, ratio);
3297 if (d1 <= kMaxDiff) {gPad->SetSelected(fXaxis); return 0;}
3298 d2 = view->GetDistancetoAxis(2, px, py, ratio);
3299 if (d2 <= kMaxDiff) {gPad->SetSelected(fYaxis); return 0;}
3300 if ( px > puxmin && px < puxmax && py > puymax && py < puymin) curdist = 1;
3301 goto FUNCTIONS;
3302 }
3303 // check if point is close to an axis
3304 doption.ToLower();
3305 dsame = kFALSE;
3306 if (doption.Contains("same")) dsame = kTRUE;
3307
3309 if (doption.Contains("y+")) {
3311 if (px <= xyaxis+dyaxis && px >= xyaxis && py >puymax && py < puymin) {
3312 if (!dsame) {
3313 if (gPad->IsVertical()) gPad->SetSelected(fYaxis);
3314 else gPad->SetSelected(fXaxis);
3315 return 0;
3316 }
3317 }
3318 } else {
3320 if (px >= xyaxis-dyaxis && px <= xyaxis && py >puymax && py < puymin) {
3321 if (!dsame) {
3322 if (gPad->IsVertical()) gPad->SetSelected(fYaxis);
3323 else gPad->SetSelected(fXaxis);
3324 return 0;
3325 }
3326 }
3327 }
3328
3330 if (doption.Contains("x+")) {
3332 if (py >= yxaxis-dxaxis && py <= yxaxis && px <puxmax && px > puxmin) {
3333 if (!dsame) {
3334 if (gPad->IsVertical()) gPad->SetSelected(fXaxis);
3335 else gPad->SetSelected(fYaxis);
3336 return 0;
3337 }
3338 }
3339 } else {
3341 if (yxaxis < puymin) yxaxis = puymin;
3343 if (!dsame) {
3344 if (gPad->IsVertical()) gPad->SetSelected(fXaxis);
3345 else gPad->SetSelected(fYaxis);
3346 return 0;
3347 }
3348 }
3349 }
3350
3351 if (fH->IsHighlight()) { // only if highlight is enable
3352 if ((px > puxmin) && (py < puymin) && (px < puxmax) && (py > puymax))
3353 HighlightBin(px, py);
3354 }
3355
3356 // if object is 2D or 3D return this object
3357 if (fH->GetDimension() == 2) {
3358 if (fH->InheritsFrom(TH2Poly::Class())) {
3359 TH2Poly *th2 = (TH2Poly*)fH;
3361 gPad->GetRangeAxis(xmin, ymin, xmax, ymax);
3362 Double_t pxu = gPad->AbsPixeltoX(px);
3363 Double_t pyu = gPad->AbsPixeltoY(py);
3364 if ((pxu>xmax) || (pxu < xmin) || (pyu>ymax) || (pyu < ymin)) {
3365 curdist = big;
3366 goto FUNCTIONS;
3367 } else {
3368 Int_t bin = th2->FindBin(pxu, pyu);
3369 if (bin>0) curdist = 1;
3370 else curdist = big;
3371 goto FUNCTIONS;
3372 }
3373 }
3374 Int_t delta2 = 5; //Give a margin of delta2 pixels to be in the 2-d area
3375 if ( px > puxmin + delta2
3376 && px < puxmax - delta2
3377 && py > puymax + delta2
3378 && py < puymin - delta2) {curdist =1; goto FUNCTIONS;}
3379 }
3380
3381 // point is inside histogram area. Find channel number
3382 if (gPad->IsVertical()) {
3383 Int_t bin = fXaxis->FindFixBin(gPad->PadtoX(x));
3384 Int_t binsup = fXaxis->FindFixBin(gPad->PadtoX(x1));
3385 Double_t binval = factor*fH->GetBinContent(bin);
3386 Int_t pybin = gPad->YtoAbsPixel(gPad->YtoPad(binval));
3387 if (binval == 0 && pybin < puymin) pybin = 10000;
3388 // special case if more than one bin for the pixel
3389 if (binsup-bin>1) {
3393 for (Int_t ibin=bin+1; ibin<binsup; ibin++) {
3397 }
3398 Int_t pybinmin = gPad->YtoAbsPixel(gPad->YtoPad(binvalmax));
3399 Int_t pybinmax = gPad->YtoAbsPixel(gPad->YtoPad(binvalmin));
3401 }
3402 if (bin != binsup) { // Mouse on bin border
3404 Int_t pybinsub = gPad->YtoAbsPixel(gPad->YtoPad(binsupval));
3405 if (py <= TMath::Max(pybinsub,pybin) && py >= TMath::Min(pybinsub,pybin) && pybin != 10000) return 0;
3406 }
3407 if (TMath::Abs(py - pybin) <= kMaxDiff) return TMath::Abs(py - pybin);
3408 } else {
3409 Double_t y = gPad->AbsPixeltoY(py);
3410 Double_t y1 = gPad->AbsPixeltoY(py+1);
3411 Int_t bin = fXaxis->FindFixBin(gPad->PadtoY(y));
3412 Int_t binsup = fXaxis->FindFixBin(gPad->PadtoY(y1));
3413 Double_t binval = factor*fH->GetBinContent(bin);
3414 Int_t pxbin = gPad->XtoAbsPixel(gPad->XtoPad(binval));
3415 if (binval == 0 && pxbin > puxmin) pxbin = 10000;
3416 // special case if more than one bin for the pixel
3417 if (binsup-bin>1) {
3421 for (Int_t ibin=bin+1; ibin<binsup; ibin++) {
3425 }
3426 Int_t pxbinmin = gPad->XtoAbsPixel(gPad->XtoPad(binvalmax));
3427 Int_t pxbinmax = gPad->XtoAbsPixel(gPad->XtoPad(binvalmin));
3429 }
3430 if (TMath::Abs(px - pxbin) <= kMaxDiff) return TMath::Abs(px - pxbin);
3431 }
3432 // Loop on the list of associated functions and user objects
3433FUNCTIONS:
3434 TObject *f;
3435 TIter next(fFunctions);
3436 while ((f = (TObject*) next())) {
3437 Int_t dist;
3438 if (f->InheritsFrom(TF1::Class())) dist = f->DistancetoPrimitive(-px,py);
3439 else dist = f->DistancetoPrimitive(px,py);
3440 if (dist < kMaxDiff) {gPad->SetSelected(f); return dist;}
3441 }
3442 return curdist;
3443}
3444
3445////////////////////////////////////////////////////////////////////////////////
3446/// Display a panel with all histogram drawing options.
3447
3449{
3450
3451 gCurrentHist = fH;
3452 if (!gPad) {
3453 Error("DrawPanel", "need to draw histogram first");
3454 return;
3455 }
3457 editor->Show();
3458 gROOT->ProcessLine(TString::Format("((TCanvas*)0x%zx)->Selected((TVirtualPad*)0x%zx,(TObject*)0x%zx,1)",
3459 (size_t)gPad->GetCanvas(), (size_t)gPad, (size_t)fH).Data());
3460}
3461
3462////////////////////////////////////////////////////////////////////////////////
3463/// Execute the actions corresponding to `event`.
3464///
3465/// This function is called when a histogram is clicked with the locator at
3466/// the pixel position px,py.
3467
3469{
3470
3471 if (!gPad) return;
3472
3473 static Int_t bin, px1, py1, px2, py2, pyold;
3474 static std::unique_ptr<TBox> zoombox;
3476
3477 Int_t bin1, bin2;
3478 Double_t xlow, xup, ylow, binval, x, baroffset, barwidth, binwidth;
3479 Bool_t opaque = gPad->OpaqueMoving();
3480
3481 if (!gPad->IsEditable()) return;
3482
3483 if (fPie) {
3484 fPie->ExecuteEvent(event, px, py);
3485 return;
3486 }
3487 // come here if we have a lego/surface in the pad
3488 TView *view = gPad->GetView();
3489
3490 if (!fShowProjection && view && !view->TestBit(kCannotRotate)) {
3491 view->ExecuteRotateView(event, px, py);
3492 return;
3493 }
3494
3495 TAxis *xaxis = fH->GetXaxis();
3496 TAxis *yaxis = fH->GetYaxis();
3497 Int_t dimension = fH->GetDimension();
3498
3499 // In case of option SAME the axis must be the ones of the first drawn histogram
3500 TString IsSame = fH->GetDrawOption();
3501 IsSame.ToLower();
3502 if (IsSame.Index("same")>=0) {
3503 TH1 *h1;
3504 TIter next(gPad->GetListOfPrimitives());
3505 while ((h1 = (TH1 *)next())) {
3506 if (!h1->InheritsFrom(TH1::Class())) continue;
3507 xaxis = h1->GetXaxis();
3508 yaxis = h1->GetYaxis();
3509 break;
3510 }
3511 }
3512
3513 Double_t factor = 1;
3514 if (fH->GetNormFactor() != 0) {
3515 factor = fH->GetNormFactor()/fH->GetSumOfWeights();
3516 }
3517
3518 switch (event) {
3519
3520 case kButton1Down:
3521
3522 if (!opaque) gVirtualX->SetLineColor(-1);
3523 fH->TAttLine::Modify();
3524
3525 if (opaque && dimension ==2) {
3526 zbx1 = gPad->AbsPixeltoX(px);
3527 zbx2 = gPad->AbsPixeltoX(px);
3528 zby1 = gPad->AbsPixeltoY(py);
3529 zby2 = gPad->AbsPixeltoY(py);
3530 px1 = px;
3531 py1 = py;
3532 if (gPad->GetLogx()) {
3533 zbx1 = TMath::Power(10,zbx1);
3534 zbx2 = TMath::Power(10,zbx2);
3535 }
3536 if (gPad->GetLogy()) {
3537 zby1 = TMath::Power(10,zby1);
3538 zby2 = TMath::Power(10,zby2);
3539 }
3540 if (zoombox) Error("ExecuteEvent", "Last zoom box was not deleted");
3541 zoombox = std::make_unique<TBox>(zbx1, zby1, zbx2, zby2);
3542 Int_t ci = TColor::GetColor("#7d7dff");
3543 TColor *zoomcolor = gROOT->GetColor(ci);
3544 if (!TCanvas::SupportAlpha() || !zoomcolor) zoombox->SetFillStyle(3002);
3545 else zoomcolor->SetAlpha(0.5);
3546 zoombox->SetFillColor(ci);
3547 zoombox->Draw();
3548 gPad->Modified();
3549 gPad->Update();
3550 }
3551 // No break !!!
3552
3553 case kMouseMotion:
3554
3555 if (fShowProjection) {ShowProjection3(px,py); break;}
3556
3557 gPad->SetCursor(kPointer);
3558 if (dimension ==1) {
3559 if (Hoption.Bar) {
3560 baroffset = fH->GetBarOffset();
3561 barwidth = fH->GetBarWidth();
3562 } else {
3563 baroffset = 0;
3564 barwidth = 1;
3565 }
3566 x = gPad->AbsPixeltoX(px);
3567 bin = fXaxis->FindFixBin(gPad->PadtoX(x));
3568 binwidth = fXaxis->GetBinWidth(bin);
3569 xlow = gPad->XtoPad(fXaxis->GetBinLowEdge(bin) + baroffset*binwidth);
3570 xup = gPad->XtoPad(xlow + barwidth*binwidth);
3571 ylow = gPad->GetUymin();
3572 px1 = gPad->XtoAbsPixel(xlow);
3573 px2 = gPad->XtoAbsPixel(xup);
3574 py1 = gPad->YtoAbsPixel(ylow);
3575 py2 = py;
3576 pyold = py;
3577 if (gROOT->GetEditHistograms()) gPad->SetCursor(kArrowVer);
3578 }
3579
3580 break;
3581
3582 case kButton1Motion:
3583
3584 if (dimension ==1) {
3585 if (gROOT->GetEditHistograms()) {
3586 if (!opaque) {
3587 gVirtualX->DrawBox(px1, py1, px2, py2,TVirtualX::kHollow); // Draw the old box
3588 py2 += py - pyold;
3589 gVirtualX->DrawBox(px1, py1, px2, py2,TVirtualX::kHollow); // Draw the new box
3590 pyold = py;
3591 } else {
3592 py2 += py - pyold;
3593 pyold = py;
3594 binval = gPad->PadtoY(gPad->AbsPixeltoY(py2))/factor;
3595 fH->SetBinContent(bin,binval);
3596 gPad->Modified(kTRUE);
3597 }
3598 }
3599 }
3600
3601 if (opaque && dimension ==2) {
3602 if (TMath::Abs(px1-px)>5 && TMath::Abs(py1-py)>5) {
3603 zbx2 = gPad->AbsPixeltoX(px);
3604 zby2 = gPad->AbsPixeltoY(py);
3605 if (gPad->GetLogx()) zbx2 = TMath::Power(10,zbx2);
3606 if (gPad->GetLogy()) zby2 = TMath::Power(10,zby2);
3607 if (zoombox) {
3608 zoombox->SetX2(zbx2);
3609 zoombox->SetY2(zby2);
3610 }
3611 gPad->Modified();
3612 gPad->Update();
3613 }
3614 }
3615
3616 break;
3617
3618 case kWheelUp:
3619
3620 if (dimension ==2) {
3621 bin1 = xaxis->GetFirst()+1;
3622 bin2 = xaxis->GetLast()-1;
3623 bin1 = TMath::Max(bin1, 1);
3624 bin2 = TMath::Min(bin2, xaxis->GetNbins());
3625 if (bin2>bin1) xaxis->SetRange(bin1,bin2);
3626 bin1 = yaxis->GetFirst()+1;
3627 bin2 = yaxis->GetLast()-1;
3628 bin1 = TMath::Max(bin1, 1);
3629 bin2 = TMath::Min(bin2, yaxis->GetNbins());
3630 if (bin2>bin1) yaxis->SetRange(bin1,bin2);
3631 }
3632 gPad->Modified();
3633 gPad->Update();
3634
3635 break;
3636
3637 case kWheelDown:
3638
3639 if (dimension == 2) {
3640 bin1 = xaxis->GetFirst()-1;
3641 bin2 = xaxis->GetLast()+1;
3642 bin1 = TMath::Max(bin1, 1);
3643 bin2 = TMath::Min(bin2, xaxis->GetNbins());
3644 const bool resetXaxisRange = bin1 == 1 && xaxis->GetFirst() == 1 && bin2 == xaxis->GetNbins() && xaxis->GetLast() == xaxis->GetNbins();
3645 if (bin2>bin1) xaxis->SetRange(bin1,bin2);
3646 if (resetXaxisRange) xaxis->ResetBit(TAxis::kAxisRange);
3647 bin1 = yaxis->GetFirst()-1;
3648 bin2 = yaxis->GetLast()+1;
3649 bin1 = TMath::Max(bin1, 1);
3650 bin2 = TMath::Min(bin2, yaxis->GetNbins());
3651 const bool resetYaxisRange = bin1 == 1 && yaxis->GetFirst() == 1 && bin2 == yaxis->GetNbins() && yaxis->GetLast() == yaxis->GetNbins();
3652 if (bin2>bin1) yaxis->SetRange(bin1,bin2);
3653 if (resetYaxisRange) yaxis->ResetBit(TAxis::kAxisRange);
3654 }
3655 gPad->Modified();
3656 gPad->Update();
3657
3658 break;
3659
3660 case kButton1Up:
3661 if (dimension ==1) {
3662 if (gROOT->GetEditHistograms()) {
3663 binval = gPad->PadtoY(gPad->AbsPixeltoY(py2))/factor;
3664 fH->SetBinContent(bin,binval);
3665 PaintInit(); // recalculate Hparam structure and recalculate range
3666 }
3667
3668 // might resize pad pixmap so should be called before any paint routine
3670 }
3671 if (opaque && dimension ==2) {
3672 if (zoombox) {
3673 Double_t x1 = TMath::Min(zoombox->GetX1(), zoombox->GetX2());
3674 Double_t x2 = TMath::Max(zoombox->GetX1(), zoombox->GetX2());
3675 Double_t y1 = TMath::Min(zoombox->GetY1(), zoombox->GetY2());
3676 Double_t y2 = TMath::Max(zoombox->GetY1(), zoombox->GetY2());
3677 x1 = TMath::Max(x1,xaxis->GetXmin());
3678 x2 = TMath::Min(x2,xaxis->GetXmax());
3679 y1 = TMath::Max(y1,yaxis->GetXmin());
3680 y2 = TMath::Min(y2,yaxis->GetXmax());
3681 if (x1<x2 && y1<y2) {
3682 xaxis->SetRangeUser(x1, x2);
3683 yaxis->SetRangeUser(y1, y2);
3684 }
3685 zoombox.reset();
3686 }
3687 }
3688 gPad->Modified(kTRUE);
3689 if (opaque) gVirtualX->SetLineColor(-1);
3690
3691 break;
3692
3693 case kButton1Locate:
3694
3695 ExecuteEvent(kButton1Down, px, py);
3696
3697 while (true) {
3698 px = py = 0;
3699 event = gVirtualX->RequestLocator(1, 1, px, py);
3700
3702
3703 if (event != -1) { // button is released
3704 ExecuteEvent(kButton1Up, px, py);
3705 return;
3706 }
3707 }
3708 }
3709}
3710
3711////////////////////////////////////////////////////////////////////////////////
3712/// Get a contour (as a list of TGraphs) using the Delaunay triangulation.
3713
3715{
3716 // Check if fH contains a TGraphDelaunay2D
3718 TGraphDelaunay2D *dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
3719 // try with the old painter
3720 TGraphDelaunay *dtOld = nullptr;
3721 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
3722
3723 if (!dt && !dtOld) return nullptr;
3724
3725 gCurrentHist = fH;
3726
3727 if (!fGraph2DPainter)
3728 ((THistPainter*)this)->fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
3729
3730 return fGraph2DPainter->GetContourList(contour);
3731}
3732
3733////////////////////////////////////////////////////////////////////////////////
3734/// Display the histogram info (bin number, contents, integral up to bin
3735/// corresponding to cursor position px,py.
3736
3738{
3739
3740 if (!gPad) return (char*)"";
3741
3742 Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
3743 Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
3744 Double_t x1 = gPad->PadtoX(gPad->AbsPixeltoX(px+1));
3746 drawOption.ToLower();
3749 if (fH->GetDimension() == 2) {
3750 if (gPad->GetView() || drawOption.Index("cont") >= 0) {
3751 uxmin=gPad->GetUxmin();
3752 uxmax=gPad->GetUxmax();
3755 x = xmin +(xmax-xmin)*(x-uxmin)/(uxmax-uxmin);
3756 uymin=gPad->GetUymin();
3757 uymax=gPad->GetUymax();
3760 y = ymin +(ymax-ymin)*(y-uymin)/(uymax-uymin);
3761 }
3762 }
3764 if (gPad->IsVertical()) {
3765 binx = fXaxis->FindFixBin(x);
3766 if (drawOption.Index("same") >= 0) {
3767 TH1 *h1;
3768 TIter next(gPad->GetListOfPrimitives());
3769 while ((h1 = (TH1 *)next())) {
3770 if (!h1->InheritsFrom(TH1::Class())) continue;
3771 binmin = h1->GetXaxis()->GetFirst();
3772 break;
3773 }
3774 } else {
3775 binmin = fXaxis->GetFirst();
3776 }
3778 // special case if more than 1 bin in x per pixel
3779 if (binx1-binx>1 && fH->GetDimension() == 1) {
3782 for (Int_t ibin=binx+1; ibin<binx1; ibin++) {
3786 binnear=ibin;
3787 }
3788 }
3789 binx = binnear;
3790 }
3791 } else {
3792 x1 = gPad->PadtoY(gPad->AbsPixeltoY(py+1));
3793 binx = fXaxis->FindFixBin(y);
3794 if (drawOption.Index("same") >= 0) {
3795 TH1 *h1;
3796 TIter next(gPad->GetListOfPrimitives());
3797 while ((h1 = (TH1 *)next())) {
3798 if (!h1->InheritsFrom(TH1::Class())) continue;
3799 binmin = h1->GetXaxis()->GetFirst();
3800 break;
3801 }
3802 } else {
3803 binmin = fXaxis->GetFirst();
3804 }
3806 // special case if more than 1 bin in x per pixel
3807 if (binx1-binx>1 && fH->GetDimension() == 1) {
3810 for (Int_t ibin=binx+1; ibin<binx1; ibin++) {
3814 binnear=ibin;
3815 }
3816 }
3817 binx = binnear;
3818 }
3819 }
3820 if (fH->GetDimension() == 1) {
3822 TProfile *tp = (TProfile*)fH;
3823 fObjectInfo.Form("(x=%g, y=%g, binx=%d, binc=%g, bine=%g, binn=%d)",
3825 (Int_t) tp->GetBinEntries(binx));
3826 }
3827 else {
3828 Double_t integ = 0;
3829 for (Int_t bin=binmin;bin<=binx;bin++) {integ += fH->GetBinContent(bin);}
3830 fObjectInfo.Form("(x=%g, y=%g, binx=%d, binc=%g, Sum=%g)",
3832 }
3833 } else if (fH->GetDimension() == 2) {
3834 if (fH->InheritsFrom(TH2Poly::Class())) {
3835 TH2Poly *th2 = (TH2Poly*)fH;
3836 biny = th2->FindBin(x,y);
3837 fObjectInfo.Form("%s (x=%g, y=%g, bin=%d, binc=%g)",
3838 th2->GetBinTitle(biny),x,y,biny,th2->GetBinContent(biny));
3839 }
3840 else if (fH->InheritsFrom(TProfile2D::Class())) {
3842 biny = fYaxis->FindFixBin(y);
3843 Int_t bin = fH->GetBin(binx,biny);
3844 fObjectInfo.Form("(x=%g, y=%g, binx=%d, biny=%d, binc=%g, bine=%g, binn=%d)",
3845 x, y, binx, biny, fH->GetBinContent(bin),
3846 fH->GetBinError(bin), (Int_t) tp->GetBinEntries(bin));
3847 } else {
3848 biny = fYaxis->FindFixBin(y);
3849 fObjectInfo.Form("(x=%g, y=%g, binx=%d, biny=%d, binc=%g bine=%g)",
3852 }
3853 } else {
3854 // 3d case: retrieving the x,y,z bin is not yet implemented
3855 // print just the x,y info
3856 fObjectInfo.Form("(x=%g, y=%g)",x,y);
3857 }
3858
3859 return (char *)fObjectInfo.Data();
3860}
3861
3862////////////////////////////////////////////////////////////////////////////////
3863/// Set highlight (enable/disable) mode for fH
3864
3866{
3867 if (fH->IsHighlight()) return;
3868
3869 fXHighlightBin = -1;
3870 fYHighlightBin = -1;
3871 // delete previous highlight box
3872 if (gXHighlightBox) gXHighlightBox.reset();
3873 if (gYHighlightBox) gYHighlightBox.reset();
3874 // emit Highlighted() signal (user can check on disabled)
3875 if (gPad->GetCanvas()) gPad->GetCanvas()->Highlighted(gPad, fH, fXHighlightBin, fYHighlightBin);
3876}
3877
3878////////////////////////////////////////////////////////////////////////////////
3879/// Check on highlight bin
3880
3882{
3883 // call from DistancetoPrimitive (only if highlight is enable)
3884
3885 Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
3886 Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
3889 if (!gPad->IsVertical()) binx = fXaxis->FindFixBin(y);
3890
3892 if (binx != fXHighlightBin) {
3894 changedBin = kTRUE;
3895 } else if (fH->GetDimension() == 1) return;
3896 if (biny != fYHighlightBin) {
3898 changedBin = kTRUE;
3899 }
3900 if (!changedBin) return;
3901
3902 // Info("HighlightBin", "histo: %p '%s'\txbin: %d, ybin: %d",
3903 // (void *)fH, fH->GetName(), fXHighlightBin, fYHighlightBin);
3904
3905 // paint highlight bin as box (recursive calls PaintHighlightBin)
3906 gPad->Modified(kTRUE);
3907 gPad->Update();
3908
3909 // emit Highlighted() signal
3910 if (gPad->GetCanvas()) gPad->GetCanvas()->Highlighted(gPad, fH, fXHighlightBin, fYHighlightBin);
3911}
3912
3913////////////////////////////////////////////////////////////////////////////////
3914/// Paint highlight bin as TBox object
3915
3917{
3918 // call from PaintTitle
3919
3920 if (!fH->IsHighlight()) return;
3921
3922 Double_t uxmin = gPad->GetUxmin();
3923 Double_t uxmax = gPad->GetUxmax();
3924 Double_t uymin = gPad->GetUymin();
3925 Double_t uymax = gPad->GetUymax();
3926 if (gPad->GetLogx()) {
3927 uxmin = TMath::Power(10.0, uxmin);
3928 uxmax = TMath::Power(10.0, uxmax);
3929 }
3930 if (gPad->GetLogy()) {
3931 uymin = TMath::Power(10.0, uymin);
3932 uymax = TMath::Power(10.0, uymax);
3933 }
3934
3935 // testing specific possibility (after zoom, draw with "same", log, etc.)
3937 if (gPad->IsVertical()) {
3939 if ((hcenter < uxmin) || (hcenter > uxmax)) return;
3940 } else {
3942 if ((hcenter < uymin) || (hcenter > uymax)) return;
3943 }
3944 if (fH->GetDimension() == 2) {
3946 if ((hcenter < uymin) || (hcenter > uymax)) return;
3947 }
3948
3949 // paint X highlight bin (for 1D or 2D)
3951 if (gPad->IsVertical()) {
3954 hby1 = uymin;
3955 hby2 = uymax;
3956 } else {
3957 hbx1 = uxmin;
3958 hbx2 = uxmax;
3961 }
3962
3963 if (!gXHighlightBox) {
3964 gXHighlightBox = std::make_unique<TBox>(hbx1, hby1, hbx2, hby2);
3965 gXHighlightBox->SetBit(kCannotPick);
3966 gXHighlightBox->SetFillColor(TColor::GetColor("#9797ff"));
3967 if (!TCanvas::SupportAlpha()) gXHighlightBox->SetFillStyle(3001);
3968 else gROOT->GetColor(gXHighlightBox->GetFillColor())->SetAlpha(0.5);
3969 }
3970 gXHighlightBox->SetX1(hbx1);
3971 gXHighlightBox->SetX2(hbx2);
3972 gXHighlightBox->SetY1(hby1);
3973 gXHighlightBox->SetY2(hby2);
3974 gXHighlightBox->Paint();
3975
3976 // Info("PaintHighlightBin", "histo: %p '%s'\txbin: %d, ybin: %d",
3977 // (void *)fH, fH->GetName(), fXHighlightBin, fYHighlightBin);
3978
3979 // paint Y highlight bin (only for 2D)
3980 if (fH->GetDimension() != 2) return;
3981 hbx1 = uxmin;
3982 hbx2 = uxmax;
3985
3986 if (!gYHighlightBox) {
3987 gYHighlightBox = std::make_unique<TBox>(hbx1, hby1, hbx2, hby2);
3988 gYHighlightBox->SetBit(kCannotPick);
3989 gYHighlightBox->SetFillColor(gXHighlightBox->GetFillColor());
3990 gYHighlightBox->SetFillStyle(gXHighlightBox->GetFillStyle());
3991 }
3992 gYHighlightBox->SetX1(hbx1);
3993 gYHighlightBox->SetX2(hbx2);
3994 gYHighlightBox->SetY1(hby1);
3995 gYHighlightBox->SetY2(hby2);
3996 gYHighlightBox->Paint();
3997}
3998
3999////////////////////////////////////////////////////////////////////////////////
4000/// Return `kTRUE` if the cell `ix`, `iy` is inside one of the graphical cuts.
4001
4003{
4004
4005 for (Int_t i=0;i<fNcuts;i++) {
4008 if (fCutsOpt[i] > 0) {
4009 if (!fCuts[i]->IsInside(x,y)) return kFALSE;
4010 } else {
4011 if (fCuts[i]->IsInside(x,y)) return kFALSE;
4012 }
4013 }
4014 return kTRUE;
4015}
4016
4017////////////////////////////////////////////////////////////////////////////////
4018/// Return `kTRUE` if the point `x`, `y` is inside one of the graphical cuts.
4019
4021{
4022
4023 for (Int_t i=0;i<fNcuts;i++) {
4024 if (fCutsOpt[i] > 0) {
4025 if (!fCuts[i]->IsInside(x,y)) return kFALSE;
4026 } else {
4027 if (fCuts[i]->IsInside(x,y)) return kFALSE;
4028 }
4029 }
4030 return kTRUE;
4031}
4032
4033////////////////////////////////////////////////////////////////////////////////
4034/// Decode string `choptin` and fill Hoption structure.
4035
4037{
4038
4039 char *l;
4040 char chopt[128];
4042 strlcpy(chopt,choptin,128);
4045
4053 Hoption.Candle = 0;
4054
4055 // special 2D options
4056 Hoption.List = 0;
4057 Hoption.Zscale = 0;
4058 Hoption.FrontBox = 1;
4059 Hoption.BackBox = 1;
4061
4062 Hoption.Zero = 0;
4063
4065
4066 //check for graphical cuts
4067 MakeCuts(chopt);
4068
4069 for (Int_t i=0;i<nch;i++) chopt[i] = toupper(chopt[i]);
4070 if (hdim > 1) Hoption.Color = 1; // Default drawing option for 2D and 3D histograms
4071 if (!nch) Hoption.Hist = 1;
4072 if (fFunctions->First()) Hoption.Func = 1;
4073 if (fH->GetSumw2N() && hdim == 1) Hoption.Error = 2;
4074
4075 char *l1 = strstr(chopt,"PFC"); // Automatic Fill Color
4076 char *l2 = strstr(chopt,"PLC"); // Automatic Line Color
4077 char *l3 = strstr(chopt,"PMC"); // Automatic Marker Color
4078 if (l1 || l2 || l3) {
4079 Int_t i = gPad->NextPaletteColor();
4080 if (l1) {memcpy(l1," ",3); fH->SetFillColor(i);}
4081 if (l2) {memcpy(l2," ",3); fH->SetLineColor(i);}
4082 if (l3) {memcpy(l3," ",3); fH->SetMarkerColor(i);}
4083 Hoption.Hist = 1; // Make sure something is drawn in case there is no drawing option specified.
4084 }
4085
4086 l = strstr(chopt,"MIN0");
4087 if (l) {
4088 Hoption.MinimumZero = 1;
4089 memcpy(l," ",4);
4090 }
4091
4092 l = strstr(chopt,"SPEC");
4093 if (l) {
4094 Hoption.Color = 0;
4095 memcpy(l," ",4);
4096 Int_t bs=0;
4097 l = strstr(chopt,"BF(");
4098 if (l) {
4099 if (sscanf(&l[3],"%d",&bs) > 0) {
4100 Int_t i=0;
4101 while (l[i]!=')') {
4102 l[i] = ' ';
4103 i++;
4104 }
4105 l[i] = ' ';
4106 }
4107 }
4108 Hoption.Spec = TMath::Max(1600,bs);
4109 return 1;
4110 }
4111
4112 l = strstr(chopt,"GL");
4113 if (l) {
4114 memcpy(l," ",2);
4115 }
4116 l = strstr(chopt,"X+");
4117 if (l) {
4118 Hoption.AxisPos = 10;
4119 memcpy(l," ",2);
4120 }
4121 l = strstr(chopt,"Y+");
4122 if (l) {
4123 Hoption.AxisPos += 1;
4124 memcpy(l," ",2);
4125 }
4126 if ((Hoption.AxisPos == 10 || Hoption.AxisPos == 1) && (nch == 2)) Hoption.Hist = 1;
4127 if (Hoption.AxisPos == 11 && nch == 4) Hoption.Hist = 1;
4128
4129 l = strstr(chopt,"SAMES");
4130 if (l) {
4131 if (nch == 5) Hoption.Hist = 1;
4132 Hoption.Same = 2;
4133 memcpy(l," ",5);
4134 if (l[5] == '0') { Hoption.Same += 10; l[5] = ' '; }
4135 }
4136 l = strstr(chopt,"SAME");
4137 if (l) {
4138 if (nch == 4) Hoption.Hist = 1;
4139 Hoption.Same = 1;
4140 memcpy(l," ",4);
4141 if (l[4] == '0') { Hoption.Same += 10; l[4] = ' '; }
4142 }
4143
4144 l = strstr(chopt,"SCAT");
4145 if (l) {
4146 Warning("MakeChopt","option SCAT is deprecated.");
4147 Hoption.Scat = 1;
4148 memcpy(l," ",4);
4149 Hoption.Color = 0;
4150 }
4151
4152 l = strstr(chopt,"PIE");
4153 if (l) {
4154 Hoption.Pie = 1;
4155 memcpy(l," ",3);
4156 }
4157
4158
4159 l = strstr(chopt,"CANDLE");
4160 if (l) {
4162 Hoption.Candle = candle.ParseOption(l);
4163 Hoption.Color = 0;
4164 }
4165
4166 l = strstr(chopt,"VIOLIN");
4167 if (l) {
4169 Hoption.Candle = candle.ParseOption(l);
4170 Hoption.Color = 0;
4171 }
4172
4173 l = strstr(chopt,"LEGO");
4174 if (l) {
4175 Hoption.Color = 0;
4176 Hoption.Lego = 1; memcpy(l," ",4);
4177 if (l[4] == '1') { Hoption.Lego = 11; l[4] = ' '; }
4178 if (l[4] == '2') { Hoption.Lego = 12; l[4] = ' '; }
4179 if (l[4] == '3') { Hoption.Lego = 13; l[4] = ' '; }
4180 if (l[4] == '4') { Hoption.Lego = 14; l[4] = ' '; }
4181 if (l[4] == '9') { Hoption.Lego = 19; l[4] = ' '; }
4182 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4183 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4184 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4185 }
4186
4187 l = strstr(chopt,"SURF");
4188 if (l) {
4189 Hoption.Color = 0;
4190 Hoption.Surf = 1; memcpy(l," ",4);
4191 if (l[4] == '1') { Hoption.Surf = 11; l[4] = ' '; }
4192 if (l[4] == '2') { Hoption.Surf = 12; l[4] = ' '; }
4193 if (l[4] == '3') { Hoption.Surf = 13; l[4] = ' '; }
4194 if (l[4] == '4') { Hoption.Surf = 14; l[4] = ' '; }
4195 if (l[4] == '5') { Hoption.Surf = 15; l[4] = ' '; }
4196 if (l[4] == '6') { Hoption.Surf = 16; l[4] = ' '; }
4197 if (l[4] == '7') { Hoption.Surf = 17; l[4] = ' '; }
4198 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4199 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4200 }
4201
4202 l = strstr(chopt,"TF3");
4203 if (l) {
4204 memcpy(l," ",3);
4205 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4206 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4207 }
4208
4209 l = strstr(chopt,"ISO");
4210 if (l) {
4211 memcpy(l," ",3);
4212 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4213 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4214 Hoption.Color = 0;
4215 }
4216
4217 l = strstr(chopt,"LIST"); if (l) { Hoption.List = 1; memcpy(l," ",4);}
4218
4219 l = strstr(chopt,"CONT");
4220 if (l) {
4221 memcpy(l," ",4);
4222 if (hdim>1) {
4223 Hoption.Color = 0;
4224 Hoption.Contour = 1;
4225 if (l[4] == '1') { Hoption.Contour = 11; l[4] = ' '; }
4226 if (l[4] == '2') { Hoption.Contour = 12; l[4] = ' '; }
4227 if (l[4] == '3') { Hoption.Contour = 13; l[4] = ' '; }
4228 if (l[4] == '4') { Hoption.Contour = 14; l[4] = ' '; }
4229 if (l[4] == '5') { Hoption.Contour = 15; l[4] = ' '; }
4230 } else {
4231 Hoption.Hist = 1;
4232 }
4233 }
4234 l = strstr(chopt,"HBAR");
4235 if (l) {
4236 Hoption.Hist = 0;
4237 Hoption.Bar = 20; memcpy(l," ",4);
4238 if (l[4] == '1') { Hoption.Bar = 21; l[4] = ' '; }
4239 if (l[4] == '2') { Hoption.Bar = 22; l[4] = ' '; }
4240 if (l[4] == '3') { Hoption.Bar = 23; l[4] = ' '; }
4241 if (l[4] == '4') { Hoption.Bar = 24; l[4] = ' '; }
4242 }
4243 l = strstr(chopt,"BAR");
4244 if (l) {
4245 Hoption.Hist = 0;
4246 Hoption.Bar = 10; memcpy(l," ",3);
4247 if (l[3] == '1') { Hoption.Bar = 11; l[3] = ' '; }
4248 if (l[3] == '2') { Hoption.Bar = 12; l[3] = ' '; }
4249 if (l[3] == '3') { Hoption.Bar = 13; l[3] = ' '; }
4250 if (l[3] == '4') { Hoption.Bar = 14; l[3] = ' '; }
4251 }
4252
4253 l = strstr(chopt,"ARR" );
4254 if (l) {
4255 memcpy(l," ", 3);
4256 if (hdim>1) {
4257 Hoption.Arrow = 1;
4258 Hoption.Color = 0;
4259 l = strstr(chopt,"COL"); if (l) { Hoption.Arrow = 2; memcpy(l," ",3); }
4260 l = strstr(chopt,"Z"); if (l) { Hoption.Zscale = 1; memcpy(l," ",1); }
4261 } else {
4262 Hoption.Hist = 1;
4263 }
4264 }
4265 l = strstr(chopt,"BOX" );
4266 if (l) {
4267 memcpy(l," ", 3);
4268 if (hdim>1) {
4269 Hoption.Color = 0;
4270 Hoption.Box = 1;
4271 if (l[3] == '1') { Hoption.Box = 11; l[3] = ' '; }
4272 if (l[3] == '2') { Hoption.Box = 12; l[3] = ' '; }
4273 if (l[3] == '3') { Hoption.Box = 13; l[3] = ' '; }
4274 } else {
4275 Hoption.Hist = 1;
4276 }
4277 }
4278 l = strstr(chopt,"TEXT");
4279 if (l) {
4280 Int_t angle;
4281 if (sscanf(&l[4],"%d",&angle) > 0) {
4282 if (angle < 0) angle=0;
4283 if (angle > 90) angle=90;
4284 Hoption.Text = 1000+angle;
4285 } else {
4286 Hoption.Text = 1;
4287 }
4288 memcpy(l," ", 4);
4289 l = strstr(chopt,"N");
4290 if (l && fH->InheritsFrom(TH2Poly::Class())) Hoption.Text = 3000 + (Hoption.Text != 1 ? Hoption.Text : 0);
4291 Hoption.Color = 0;
4292 }
4293 l = strstr(chopt,"COLZ");
4294 if (l) {
4295 memcpy(l," ",4);
4296 if (hdim > 1) {
4298 Hoption.Color = 1;
4299 Hoption.Zscale = 1;
4300 if (l[4] == '2') { Hoption.Color = 3; l[4] = ' '; }
4301 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4302 l = strstr(chopt,"1"); if (l) { Hoption.Color = 2; memcpy(l," ",1); }
4303 } else {
4304 Hoption.Hist = 1;
4305 }
4306 }
4307 l = strstr(chopt,"COL" );
4308 if (l) {
4309 memcpy(l," ", 3);
4310 if (hdim > 1) {
4312 Hoption.Color = 1;
4313 if (l[3] == '2') { Hoption.Color = 3; l[3] = ' '; }
4314 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4315 l = strstr(chopt,"1"); if (l) { Hoption.Color = 2; memcpy(l," ",1); }
4316 } else {
4317 Hoption.Hist = 1;
4318 }
4319 }
4320 l = strstr(chopt,"FUNC"); if (l) { Hoption.Func = 2; memcpy(l," ",4); Hoption.Hist = 0; }
4321 l = strstr(chopt,"HIST"); if (l) { Hoption.Hist = 2; memcpy(l," ",4); Hoption.Func = 0; Hoption.Error = 0;}
4322 l = strstr(chopt,"AXIS"); if (l) { Hoption.Axis = 1; memcpy(l," ",4); }
4323 l = strstr(chopt,"AXIG"); if (l) { Hoption.Axis = 2; memcpy(l," ",4); }
4324 l = strstr(chopt,"SCAT"); if (l) { Hoption.Scat = 1; memcpy(l," ",4); }
4325 l = strstr(chopt,"POL"); if (l) { Hoption.System = kPOLAR; memcpy(l," ",3); }
4326 l = strstr(chopt,"CYL"); if (l) { Hoption.System = kCYLINDRICAL; memcpy(l," ",3); }
4327 l = strstr(chopt,"SPH"); if (l) { Hoption.System = kSPHERICAL; memcpy(l," ",3); }
4328 l = strstr(chopt,"PSR"); if (l) { Hoption.System = kRAPIDITY; memcpy(l," ",3); }
4329
4330 l = strstr(chopt,"TRI");
4331 if (l) {
4332 if (!explicitColor) Hoption.Color = 0;
4333 Hoption.Tri = 1; memcpy(l," ",3);
4334 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4335 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4336 l = strstr(chopt,"ERR"); if (l) memcpy(l," ",3);
4337 }
4338
4339 l = strstr(chopt,"AITOFF");
4340 if (l) {
4341 Hoption.Proj = 1; memcpy(l," ",6); //Aitoff projection
4342 }
4343 l = strstr(chopt,"MERCATOR");
4344 if (l) {
4345 Hoption.Proj = 2; memcpy(l," ",8); //Mercator projection
4346 }
4347 l = strstr(chopt,"SINUSOIDAL");
4348 if (l) {
4349 Hoption.Proj = 3; memcpy(l," ",10); //Sinusoidal projection
4350 }
4351 l = strstr(chopt,"PARABOLIC");
4352 if (l) {
4353 Hoption.Proj = 4; memcpy(l," ",9); //Parabolic projection
4354 }
4355 l = strstr(chopt,"MOLLWEIDE");
4356 if (l) {
4357 Hoption.Proj = 5; memcpy(l," ",9); //Mollweide projection
4358 }
4359 if (Hoption.Proj > 0) {
4360 if (!explicitColor) Hoption.Color = 0;
4361 Hoption.Contour = 14;
4362 }
4363
4364 if (strstr(chopt,"A")) Hoption.Axis = -1;
4365 if (strstr(chopt,"B")) Hoption.Bar = 1;
4366 if (strstr(chopt,"C") && !strstr(chopt,"CJUST")) { Hoption.Curve =1; Hoption.Hist = -1;}
4367 if (strstr(chopt,"F")) Hoption.Fill =1;
4368 if (strstr(chopt,"][")) {Hoption.Off =1; Hoption.Hist =1;}
4369 if (strstr(chopt,"F2")) Hoption.Fill =2;
4370 if (strstr(chopt,"L")) { Hoption.Line =1; Hoption.Hist = -1;}
4371 if (strstr(chopt,"P")) { Hoption.Mark =1; Hoption.Hist = -1;}
4372 if (strstr(chopt,"Z")) Hoption.Zscale =1;
4373 if (strstr(chopt,"*")) Hoption.Star =1;
4374 if (strstr(chopt,"H")) Hoption.Hist =2;
4375 if (strstr(chopt,"P0")) Hoption.Mark =10;
4376
4377 if (fH->InheritsFrom(TH2Poly::Class())) {
4379 }
4380
4381 if (strstr(chopt,"E")) {
4382 if (hdim == 1) {
4383 Hoption.Error = 1;
4384 if (strstr(chopt,"E1")) Hoption.Error = 11;
4385 if (strstr(chopt,"E2")) Hoption.Error = 12;
4386 if (strstr(chopt,"E3")) Hoption.Error = 13;
4387 if (strstr(chopt,"E4")) Hoption.Error = 14;
4388 if (strstr(chopt,"E5")) Hoption.Error = 15;
4389 if (strstr(chopt,"E6")) Hoption.Error = 16;
4390 if (strstr(chopt,"E0")) Hoption.Error += 40;
4391 if (strstr(chopt,"X0")) {
4392 if (Hoption.Error == 1) Hoption.Error += 20;
4393 Hoption.Error += 10;
4394 }
4396 Hoption.Text += 2000;
4397 Hoption.Error = 0;
4398 }
4399 } else {
4400 if (Hoption.Error == 0) {
4401 Hoption.Error = 100;
4402 if (!explicitColor) Hoption.Color = 0;
4403 }
4404 if (Hoption.Text) {
4405 Hoption.Text += 2000;
4406 Hoption.Error = 0;
4407 }
4408 }
4409 }
4410
4411 if (Hoption.Surf == 15) {
4413 Hoption.Surf = 13;
4414 Warning("MakeChopt","option SURF5 is not supported in Cartesian and Polar modes");
4415 }
4416 }
4417
4418 // Copy options from current style
4419 Hoption.Logx = gPad->GetLogx();
4420 Hoption.Logy = gPad->GetLogy();
4421 Hoption.Logz = gPad->GetLogz();
4422
4423 // Check options incompatibilities
4424 if (Hoption.Bar == 1) Hoption.Hist = -1;
4425 return 1;
4426}
4427
4428////////////////////////////////////////////////////////////////////////////////
4429/// Decode string `choptin` and fill Graphical cuts structure.
4430
4432{
4433
4434 fNcuts = 0;
4435 char *left = (char*)strchr(choptin,'[');
4436 if (!left) return 0;
4437 char *right = (char*)strchr(choptin,']');
4438 if (!right) return 0;
4439 Int_t nch = right-left;
4440 if (nch < 2) return 0;
4441 char *cuts = left+1;
4442 *right = 0;
4443 char *comma, *minus;
4444 Int_t i;
4445 while (true) {
4446 comma = strchr(cuts,',');
4447 if (comma) *comma = 0;
4448 minus = strchr(cuts,'-');
4449 if (minus) cuts = minus+1;
4450 while (*cuts == ' ') cuts++;
4451 Int_t nc = strlen(cuts);
4452 while (cuts[nc-1] == ' ') {cuts[nc-1] = 0; nc--;}
4453 TIter next(gROOT->GetListOfSpecials());
4454 TCutG *cut=nullptr;
4455 TObject *obj;
4456 while ((obj = next())) {
4457 if (!obj->InheritsFrom(TCutG::Class())) continue;
4458 if (strcmp(obj->GetName(),cuts)) continue;
4459 cut = (TCutG*)obj;
4460 break;
4461 }
4462 if (cut) {
4463 fCuts[fNcuts] = cut;
4464 fCutsOpt[fNcuts] = 1;
4465 if (minus) fCutsOpt[fNcuts] = -1;
4466 fNcuts++;
4467 }
4468 if (!comma) break;
4469 cuts = comma+1;
4470 }
4471 for (i=0;i<=nch;i++) left[i] = ' ';
4472 return fNcuts;
4473}
4474
4475////////////////////////////////////////////////////////////////////////////////
4476/// [Control routine to paint any kind of histograms](\ref HP00)
4477
4479{
4480
4481 if (fH->GetBuffer()) fH->BufferEmpty(-1);
4482
4483 //For iOS: put the histogram on the top of stack of pickable objects.
4485
4486 gPad->SetVertical(kTRUE);
4487
4489 gCurrentHist = fH;
4490 TH1 *hsave = fH;
4492
4493 if (!MakeChopt(option)) return; //check options and fill Hoption structure
4494
4495 // Paint using TSpectrum2Painter
4496 if (Hoption.Spec) {
4497 if (!TableInit()) return;
4498 if (!TClass::GetClass("TSpectrum2Painter")) gSystem->Load("libSpectrumPainter");
4499 gROOT->ProcessLineFast(TString::Format("TSpectrum2Painter::PaintSpectrum((TH2F*)0x%zx,\"%s\",%d)",
4500 (size_t)fH, option, Hoption.Spec).Data());
4501 return;
4502 }
4503
4504 // Deflate the labels in case of alphanumeric labels
4508
4509 if (Hoption.Pie) {
4510 if (fH->GetDimension() == 1) {
4511 if (!fPie)
4512 fPie = std::make_unique<TPie>(fH);
4513 fPie->Paint(option);
4514 } else {
4515 Error("Paint", "Option PIE is for 1D histograms only");
4516 }
4517 return;
4518 } else {
4519 fPie.reset();
4520 }
4521
4522 fXbuf.resize(kNMAX);
4523 fYbuf.resize(kNMAX);
4524 if (fH->GetDimension() > 2) {
4525 PaintH3(option);
4527 if (Hoption.Func) {
4532 Hoption = hoptsave;
4533 Hparam = hparsave;
4534 }
4536 fXbuf.clear();
4537 fYbuf.clear();
4538 return;
4539 }
4540 TView *view = gPad->GetView();
4541 if (view) {
4542 if (!Hoption.Lego && !Hoption.Surf && !Hoption.Tri) {
4543 delete view;
4544 gPad->SetView(nullptr);
4545 }
4546 }
4547 if (fH->GetDimension() > 1 || Hoption.Lego || Hoption.Surf) {
4548 // In case of 1D histogram, Z axis becomes Y axis.
4549 Int_t logysav=0, logzsav=0;
4550 if (fH->GetDimension() == 1) {
4553 Hoption.Logz = 0;
4554 if (Hoption.Logy) {
4555 Hoption.Logz = 1;
4556 Hoption.Logy = 0;
4557 }
4558 }
4560 if (Hoption.Func) {
4565 Hoption = hoptsave;
4566 Hparam = hparsave;
4567 }
4570 fXbuf.clear();
4571 fYbuf.clear();
4572 if (fH->GetDimension() == 1) {
4575 }
4576 return;
4577 }
4578
4579 if (Hoption.Bar >= 20) {
4581 fXbuf.clear();
4582 fYbuf.clear();
4583 return;
4584 }
4585
4586 gPad->RangeAxisChanged(); //emit RangeAxisChanged() signal to sync axes
4587 // fill Hparam structure with histo parameters
4588 if (!PaintInit()) {
4589 fXbuf.clear();
4590 fYbuf.clear();
4591 return;
4592 }
4593
4594 // Picture surround (if new page) and page number (if requested).
4595 // Histogram surround (if not option "Same").
4596 PaintFrame();
4597
4598 // Paint histogram axis only
4599 Bool_t gridx = gPad->GetGridx();
4600 Bool_t gridy = gPad->GetGridy();
4601 if (Hoption.Axis > 0) {
4602 if (Hoption.Axis > 1) PaintAxis(kTRUE); //axis with grid
4603 else {
4604 if (gridx) gPad->SetGridx(0);
4605 if (gridy) gPad->SetGridy(0);
4607 if (gridx) gPad->SetGridx(1);
4608 if (gridy) gPad->SetGridy(1);
4609 }
4610 if ((Hoption.Same%10) ==1) Hoption.Same += 1;
4611 goto paintstat;
4612 }
4613 if (gridx || gridy) PaintAxis(kTRUE); // Draw the grid only
4614
4615 // test for options BAR or HBAR
4616 if (Hoption.Bar >= 10) {
4618 }
4619
4620 // do not draw histogram if error bars required
4621 if (!Hoption.Error) {
4622 if (Hoption.Hist && Hoption.Bar<10) PaintHist(option);
4623 }
4624
4625 // test for error bars or option E
4626 if (Hoption.Error) {
4628 if (Hoption.Hist == 2) PaintHist(option);
4629 }
4630
4632
4633 // test for associated function
4634 if (Hoption.Func) {
4639 Hoption = hoptsave;
4640 Hparam = hparsave;
4641 }
4642
4643 if (gridx) gPad->SetGridx(0);
4644 if (gridy) gPad->SetGridy(0);
4646 if (gridx) gPad->SetGridx(1);
4647 if (gridy) gPad->SetGridy(1);
4648
4649 PaintTitle(); // Draw histogram title
4650
4651 // Draw box with histogram statistics and/or fit parameters
4652paintstat:
4653 if ((Hoption.Same%10) != 1 && !fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
4654 TIter next(fFunctions);
4655 TObject *obj = nullptr;
4656 while ((obj = next())) {
4657 if (obj->InheritsFrom(TF1::Class())) break;
4658 obj = nullptr;
4659 }
4660
4661 //Stat is painted twice (first, it will be in canvas' list of primitives),
4662 //second, it will be here, this is not required on iOS.
4663 //Condition is ALWAYS true on a platform different from iOS.
4664 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode())
4665 PaintStat(gStyle->GetOptStat(),(TF1*)obj);
4666 }
4669 fXbuf.clear();
4670 fYbuf.clear();
4671}
4672
4673////////////////////////////////////////////////////////////////////////////////
4674/// [Control function to draw a table as an arrow plot](\ref HP12)
4675
4677{
4679 Double_t dx, dy, x1, x2, y1, y2, xc, yc, dxn, dyn;
4682 Double_t xrg = gPad->GetUxmin();
4683 Double_t yrg = gPad->GetUymin();
4684 Double_t xln = gPad->GetUxmax() - xrg;
4685 Double_t yln = gPad->GetUymax() - yrg;
4686 Double_t cx = (xln/Double_t(ncx))/2.;
4687 Double_t cy = (yln/Double_t(ncy))/2.;
4688 Double_t dn = 1.E-30;
4689
4690 auto arrow = new TArrow();
4691 arrow->SetAngle(30);
4692 arrow->SetFillStyle(1001);
4693 arrow->SetFillColor(fH->GetLineColor());
4694 arrow->SetLineColor(fH->GetLineColor());
4695 arrow->SetLineWidth(fH->GetLineWidth());
4696
4697 // Initialize the levels on the Z axis
4698 Int_t ncolors=0, ndivz=0;
4699 Double_t scale=0.;
4700 if (Hoption.Arrow>1) {
4701 ncolors = gStyle->GetNumberOfColors();
4702 Int_t ndiv = fH->GetContour();
4703 if (ndiv == 0 ) {
4704 ndiv = gStyle->GetNumberContours();
4705 fH->SetContour(ndiv);
4706 }
4707 ndivz = TMath::Abs(ndiv);
4708 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
4710 }
4711
4712 for (Int_t id=1;id<=2;id++) {
4713 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
4716 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
4717 xk = fXaxis->GetBinLowEdge(i);
4718 xstep = fXaxis->GetBinWidth(i);
4719 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
4720 if (i == Hparam.xfirst) {
4721 dx = fH->GetBinContent(i+1, j) - fH->GetBinContent(i, j);
4722 } else if (i == Hparam.xlast) {
4723 dx = fH->GetBinContent(i, j) - fH->GetBinContent(i-1, j);
4724 } else {
4725 dx = 0.5*(fH->GetBinContent(i+1, j) - fH->GetBinContent(i-1, j));
4726 }
4727 if (j == Hparam.yfirst) {
4728 dy = fH->GetBinContent(i, j+1) - fH->GetBinContent(i, j);
4729 } else if (j == Hparam.ylast) {
4730 dy = fH->GetBinContent(i, j) - fH->GetBinContent(i, j-1);
4731 } else {
4732 dy = 0.5*(fH->GetBinContent(i, j+1) - fH->GetBinContent(i, j-1));
4733 }
4734 if (id == 1) {
4737 } else if (id == 2) {
4738 xc = xrg + xln*(Double_t(i - Hparam.xfirst+1)-0.5)/Double_t(ncx);
4739 dxn = cx*dx/dn;
4740 x1 = xc - dxn;
4741 x2 = xc + dxn;
4742 yc = yrg + yln*(Double_t(j - Hparam.yfirst+1)-0.5)/Double_t(ncy);
4743 dyn = cy*dy/dn;
4744 y1 = yc - dyn;
4745 y2 = yc + dyn;
4746 if (Hoption.Arrow>1) {
4747 int color = Int_t(0.01+(fH->GetBinContent(i, j)-fH->GetMinimum())*scale);
4748 Int_t theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
4749 if (theColor > ncolors-1) theColor = ncolors-1;
4750 arrow->SetFillColor(gStyle->GetColorPalette(theColor));
4751 arrow->SetLineColor(gStyle->GetColorPalette(theColor));
4752 }
4753 if (TMath::Abs(x2-x1) > 0. || TMath::Abs(y2-y1) > 0.) {
4754 arrow->PaintArrow(x1, y1, x2, y2, 0.015, "|>");
4755 } else {
4756 arrow->PaintArrow(x1, y1, x2, y2, 0.005, "|>");
4757 }
4758 }
4759 }
4760 }
4761 }
4762
4764}
4765
4766////////////////////////////////////////////////////////////////////////////////
4767/// Draw axis (2D case) of an histogram.
4768///
4769/// If `drawGridOnly` is `TRUE`, only the grid is painted (if needed). This allows
4770/// to draw the grid and the axis separately. In `THistPainter::Paint` this
4771/// feature is used to make sure that the grid is drawn in the background and
4772/// the axis tick marks in the foreground of the pad.
4773
4775{
4776
4777 //On iOS, grid should not be pickable and can not be highlighted.
4778 //Condition is never true on a platform different from iOS.
4779 if (drawGridOnly && (gPad->PadInHighlightMode() || gPad->PadInSelectionMode()))
4780 return;
4781
4782 if (Hoption.Axis == -1) return;
4783 if (Hoption.Same && Hoption.Axis <= 0) return;
4784
4785 // Repainting alphanumeric labels axis on a plot done with
4786 // the option HBAR (horizontal) needs some adjustments.
4787 TAxis *xaxis = nullptr;
4788 TAxis *yaxis = nullptr;
4789 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4790 if (fXaxis->GetLabels() || fYaxis->GetLabels()) { // One axis has alphanumeric labels
4791 TIter next(gPad->GetListOfPrimitives());
4792 TObject *obj;
4793 // Check if the first TH1 of THStack in the pad is drawn with the option HBAR
4794 while ((obj = next())) {
4795 if (!obj->InheritsFrom(TH1::Class()) &&
4796 !obj->InheritsFrom(THStack::Class())) continue;
4797 TString opt = obj->GetDrawOption();
4798 opt.ToLower();
4799 // if drawn with HBAR, the axis should be inverted and the pad set to horizontal
4800 if (strstr(opt,"hbar")) {
4801 gPad->SetVertical(kFALSE);
4802 xaxis = fXaxis;
4803 yaxis = fYaxis;
4804 if (!strcmp(xaxis->GetName(),"xaxis")) {
4805 fXaxis = yaxis;
4806 fYaxis = xaxis;
4807 }
4808 }
4809 break;
4810 }
4811 }
4812 }
4813
4814 static char chopt[10] = "";
4815 Double_t gridl = 0;
4816 Int_t ndiv, ndivx, ndivy, nx1, nx2, ndivsave;
4817 Int_t useHparam = 0;
4821
4822 Double_t axmin = gPad->GetUxmin();
4823 Double_t axmax = gPad->GetUxmax();
4824 Double_t aymin = gPad->GetUymin();
4825 Double_t aymax = gPad->GetUymax();
4826 char *cw = nullptr;
4827 TGaxis axis;
4828
4829 // In case of option 'cont4' or in case of option 'same' over a 'cont4 plot'
4830 // Hparam must be use for the axis limits.
4831 if (Hoption.Contour == 14) useHparam = 1;
4832 if (Hoption.Same) {
4833 TObject *obj;
4834 TIter next(gPad->GetListOfPrimitives());
4835 while ((obj=next())) {
4836 if (strstr(obj->GetDrawOption(),"cont4")) {
4837 useHparam = 1;
4838 break;
4839 }
4840 }
4841 }
4842
4843 // Paint X axis
4844
4845 //To make X-axis selectable on iOS device.
4846 if (gPad->PadInSelectionMode())
4847 gPad->PushSelectableObject(fXaxis);
4848
4849 //This condition is ALWAYS true, unless it works on iOS (can be false on iOS).
4850 if (gPad->PadInSelectionMode() || !gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && gPad->GetSelected() == fXaxis)) {
4852 if (ndivx > 1000) {
4853 nx2 = ndivx/100;
4854 nx1 = TMath::Max(1, ndivx%100);
4855 ndivx = 100*nx2 + Int_t(Float_t(nx1)*gPad->GetAbsWNDC());
4856 }
4857 axis.SetTextAngle(0);
4859
4860 chopt[0] = 0;
4861 strlcat(chopt, "SDH",10);
4862 if (ndivx < 0) strlcat(chopt, "N",10);
4863 if (gPad->GetGridx()) {
4864 gridl = (aymax-aymin)/(gPad->GetY2() - gPad->GetY1());
4865 strlcat(chopt, "W",10);
4866 }
4867
4868 // Define X-Axis limits
4869 if (Hoption.Logx) {
4870 strlcat(chopt, "G",10);
4871 ndiv = TMath::Abs(ndivx);
4872 if (useHparam) {
4875 } else {
4876 umin = TMath::Power(10,axmin);
4877 umax = TMath::Power(10,axmax);
4878 }
4879 } else {
4880 ndiv = TMath::Abs(ndivx);
4881 if (useHparam) {
4882 umin = Hparam.xmin;
4883 umax = Hparam.xmax;
4884 } else {
4885 umin = axmin;
4886 umax = axmax;
4887 }
4888 }
4889
4890 // Display axis as time
4891 if (fXaxis->GetTimeDisplay()) {
4892 strlcat(chopt,"t",10);
4893 if (strlen(fXaxis->GetTimeFormatOnly()) == 0) {
4895 }
4896 }
4897
4898 // The main X axis can be on the bottom or on the top of the pad
4900 if (xAxisPos == 1) {
4901 // Main X axis top
4902 xAxisYPos1 = aymax;
4903 xAxisYPos2 = aymin;
4904 } else {
4905 // Main X axis bottom
4906 xAxisYPos1 = aymin;
4907 xAxisYPos2 = aymax;
4908 }
4909
4910 // Paint the main X axis (always)
4911 uminsave = umin;
4912 umaxsave = umax;
4913 ndivsave = ndiv;
4914 axis.SetOption(chopt);
4915 if (xAxisPos) {
4916 strlcat(chopt, "-",10);
4917 gridl = -gridl;
4918 }
4919 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4920 axis.SetLabelSize(0.);
4921 axis.SetTitle("");
4922 }
4925 umin, umax, ndiv, chopt, gridl, drawGridOnly);
4926
4927 // Paint additional X axis (if needed)
4928 // On iOS, this additional X axis is neither pickable, nor highlighted.
4929 // Additional checks PadInSelectionMode etc. does not effect non-iOS platform.
4930 if (gPad->GetTickx() && !gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
4931 if (xAxisPos) {
4932 cw=strstr(chopt,"-");
4933 *cw='z';
4934 } else {
4935 strlcat(chopt, "-",10);
4936 }
4937 if (gPad->GetTickx() < 2) strlcat(chopt, "U",10);
4938 if ((cw=strstr(chopt,"W"))) *cw='z';
4939 axis.SetTitle("");
4943 }
4944 }//End of "if pad in selection mode etc".
4945
4946 // Paint Y axis
4947 //On iOS, Y axis must pushed into the stack of selectable objects.
4948 if (gPad->PadInSelectionMode())
4949 gPad->PushSelectableObject(fYaxis);
4950
4951 //This conditions is ALWAYS true on a platform, different from iOS (on iOS can be true, can be false).
4952 if (gPad->PadInSelectionMode() || !gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && gPad->GetSelected() == fYaxis)) {
4955
4956 chopt[0] = 0;
4957 strlcat(chopt, "SDH",10);
4958 if (ndivy < 0) strlcat(chopt, "N",10);
4959 if (gPad->GetGridy()) {
4960 gridl = (axmax-axmin)/(gPad->GetX2() - gPad->GetX1());
4961 strlcat(chopt, "W",10);
4962 }
4963
4964 // Define Y-Axis limits
4965 if (Hoption.Logy) {
4966 strlcat(chopt, "G",10);
4967 ndiv = TMath::Abs(ndivy);
4968 if (useHparam) {
4971 } else {
4972 umin = TMath::Power(10,aymin);
4973 umax = TMath::Power(10,aymax);
4974 }
4975 } else {
4976 ndiv = TMath::Abs(ndivy);
4977 if (useHparam) {
4978 umin = Hparam.ymin;
4979 umax = Hparam.ymax;
4980 } else {
4981 umin = aymin;
4982 umax = aymax;
4983 }
4984 }
4985
4986 // Display axis as time
4987 if (fYaxis->GetTimeDisplay()) {
4988 strlcat(chopt,"t",10);
4989 if (strlen(fYaxis->GetTimeFormatOnly()) == 0) {
4991 }
4992 }
4993
4994 // The main Y axis can be on the left or on the right of the pad
4996 if (yAxisPos == 1) {
4997 // Main Y axis left
4998 yAxisXPos1 = axmax;
4999 yAxisXPos2 = axmin;
5000 } else {
5001 // Main Y axis right
5002 yAxisXPos1 = axmin;
5003 yAxisXPos2 = axmax;
5004 }
5005
5006 // Paint the main Y axis (always)
5007 uminsave = umin;
5008 umaxsave = umax;
5009 ndivsave = ndiv;
5010 axis.SetOption(chopt);
5011 if (yAxisPos) {
5012 strlcat(chopt, "+L",10);
5013 gridl = -gridl;
5014 }
5015 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
5016 axis.SetLabelSize(0.);
5017 axis.SetTitle("");
5018 }
5021 umin, umax, ndiv, chopt, gridl, drawGridOnly);
5022
5023 // Paint the additional Y axis (if needed)
5024 // Additional checks for pad mode are required on iOS: this "second" axis is
5025 // neither pickable, nor highlighted. Additional checks have no effect on non-iOS platform.
5026 if (gPad->GetTicky() && !gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
5027 if (gPad->GetTicky() < 2) {
5028 strlcat(chopt, "U",10);
5030 } else {
5031 strlcat(chopt, "+L",10);
5032 }
5033 if ((cw=strstr(chopt,"W"))) *cw='z';
5034 axis.SetTitle("");
5038 }
5039 }//End of "if pad is in selection mode etc."
5040
5041 // Reset the axis if they have been inverted in case of option HBAR
5042 if (xaxis) {
5043 fXaxis = xaxis;
5044 fYaxis = yaxis;
5045 }
5046}
5047
5048////////////////////////////////////////////////////////////////////////////////
5049/// [Draw a bar-chart in a normal pad.](\ref HP10)
5050
5052{
5053
5054 Int_t bar = Hoption.Bar - 10;
5058 TBox box;
5060 if (hcolor == gPad->GetFrameFillColor()) ++hcolor;
5062 box.SetFillColor(hcolor);
5063 box.SetFillStyle(hstyle);
5064 box.SetLineStyle(fH->GetLineStyle());
5065 box.SetLineColor(fH->GetLineColor());
5066 box.SetLineWidth(fH->GetLineWidth());
5067 for (Int_t bin=fXaxis->GetFirst();bin<=fXaxis->GetLast();bin++) {
5068 y = fH->GetBinContent(bin);
5069 xmin = gPad->XtoPad(fXaxis->GetBinLowEdge(bin));
5070 xmax = gPad->XtoPad(fXaxis->GetBinUpEdge(bin));
5071 ymin = gPad->GetUymin();
5072 ymax = gPad->YtoPad(y);
5073 if (ymax < gPad->GetUymin()) continue;
5074 if (ymax > gPad->GetUymax()) ymax = gPad->GetUymax();
5075 if (ymin < gPad->GetUymin()) ymin = gPad->GetUymin();
5076 if (Hoption.MinimumZero && ymin < 0)
5077 ymin=TMath::Min(0.,gPad->GetUymax());
5078 w = (xmax-xmin)*width;
5079 xmin += offset*(xmax-xmin);
5080 xmax = xmin + w;
5081 if (bar < 1) {
5082 box.PaintBox(xmin,ymin,xmax,ymax);
5083 } else {
5084 umin = xmin + bar*(xmax-xmin)/10.;
5085 umax = xmax - bar*(xmax-xmin)/10.;
5086 box.SetFillColor(TColor::GetColorBright(hcolor)); //bright
5087 box.PaintBox(xmin,ymin,umin,ymax);
5088 box.SetFillColor(hcolor);
5089 box.PaintBox(umin,ymin,umax,ymax);
5090 box.SetFillColor(TColor::GetColorDark(hcolor)); //dark
5091 box.PaintBox(umax,ymin,xmax,ymax);
5092 }
5093 }
5094}
5095
5096////////////////////////////////////////////////////////////////////////////////
5097/// [Draw a bar char in a rotated pad (X vertical, Y horizontal)](\ref HP10)
5098
5100{
5101
5102 gPad->SetVertical(kFALSE);
5103
5104 PaintInitH();
5105
5106 TAxis *xaxis = fXaxis;
5107 TAxis *yaxis = fYaxis;
5108 if (!strcmp(xaxis->GetName(),"xaxis")) {
5109 fXaxis = yaxis;
5110 fYaxis = xaxis;
5111 }
5112
5113 PaintFrame();
5115
5116 Int_t bar = Hoption.Bar - 20;
5120 TBox box;
5122 if (hcolor == gPad->GetFrameFillColor()) ++hcolor;
5124 box.SetFillColor(hcolor);
5125 box.SetFillStyle(hstyle);
5126 box.SetLineStyle(fH->GetLineStyle());
5127 box.SetLineColor(fH->GetLineColor());
5128 box.SetLineWidth(fH->GetLineWidth());
5129 for (Int_t bin=fYaxis->GetFirst();bin<=fYaxis->GetLast();bin++) {
5130 ymin = gPad->YtoPad(fYaxis->GetBinLowEdge(bin));
5131 ymax = gPad->YtoPad(fYaxis->GetBinUpEdge(bin));
5132 xmin = gPad->GetUxmin();
5133 xmax = gPad->XtoPad(fH->GetBinContent(bin));
5134 if (xmax < gPad->GetUxmin()) continue;
5135 if (xmax > gPad->GetUxmax()) xmax = gPad->GetUxmax();
5136 if (xmin < gPad->GetUxmin()) xmin = gPad->GetUxmin();
5137 if (Hoption.MinimumZero && xmin < 0)
5138 xmin=TMath::Min(0.,gPad->GetUxmax());
5139 w = (ymax-ymin)*width;
5140 ymin += offset*(ymax-ymin);
5141 ymax = ymin + w;
5142 if (bar < 1) {
5143 box.PaintBox(xmin,ymin,xmax,ymax);
5144 } else {
5145 umin = ymin + bar*(ymax-ymin)/10.;
5146 umax = ymax - bar*(ymax-ymin)/10.;
5147 box.SetFillColor(TColor::GetColorDark(hcolor)); //dark
5148 box.PaintBox(xmin,ymin,xmax,umin);
5149 box.SetFillColor(hcolor);
5150 box.PaintBox(xmin,umin,xmax,umax);
5151 box.SetFillColor(TColor::GetColorBright(hcolor)); //bright
5152 box.PaintBox(xmin,umax,xmax,ymax);
5153 }
5154 }
5155
5156 PaintTitle();
5157
5158 // Draw box with histogram statistics and/or fit parameters
5159 if ((Hoption.Same%10) != 1 && !fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
5160 TIter next(fFunctions);
5161 TObject *obj = nullptr;
5162 while ((obj = next())) {
5163 if (obj->InheritsFrom(TF1::Class())) break;
5164 obj = nullptr;
5165 }
5166 PaintStat(gStyle->GetOptStat(),(TF1*)obj);
5167 }
5168
5169 fXaxis = xaxis;
5170 fYaxis = yaxis;
5171}
5172
5173////////////////////////////////////////////////////////////////////////////////
5174/// [Control function to draw a 2D histogram as a box plot](\ref HP13)
5175
5177{
5178
5181 if (fH->GetFillColor() == 0) fH->SetFillStyle(0);
5182 if (Hoption.Box == 11) fH->SetFillStyle(1001);
5183 fH->TAttLine::Modify();
5184 fH->TAttFill::Modify();
5185
5186 Double_t z, xk,xstep, yk, ystep, xcent, ycent, xlow, xup, ylow, yup;
5187 Double_t ux1 = gPad->PixeltoX(1);
5188 Double_t ux0 = gPad->PixeltoX(0);
5189 Double_t uy1 = gPad->PixeltoY(1);
5190 Double_t uy0 = gPad->PixeltoY(0);
5191 Double_t dxmin = 0.51*(gPad->PadtoX(ux1)-gPad->PadtoX(ux0));
5192 Double_t dymin = 0.51*(gPad->PadtoY(uy0)-gPad->PadtoY(uy1));
5193
5194 Double_t zmin = TMath::Max(fH->GetMinimum(),0.);
5197 Double_t zminlin = zmin, zmaxlin = zmax;
5198
5199 // In case of option SAME, zmin and zmax values are taken from the
5200 // first plotted 2D histogram.
5201 if (Hoption.Same > 0 && Hoption.Same < 10) {
5202 TH2 *h2;
5203 TIter next(gPad->GetListOfPrimitives());
5204 while ((h2 = (TH2 *)next())) {
5205 if (!h2->InheritsFrom(TH2::Class())) continue;
5206 zmin = TMath::Max(h2->GetMinimum(), 0.);
5207 zmax = TMath::Max(TMath::Abs(h2->GetMaximum()),
5208 TMath::Abs(h2->GetMinimum()));
5209 zminlin = zmin;
5210 zmaxlin = zmax;
5211 if (Hoption.Logz) {
5212 if (zmin <= 0) {
5213 zmin = TMath::Log10(zmax*0.001);
5214 } else {
5215 zmin = TMath::Log10(zmin);
5216 }
5217 zmax = TMath::Log10(zmax);
5218 }
5219 break;
5220 }
5221 } else {
5222 if (Hoption.Logz) {
5223 if (zmin > 0) {
5224 zmin = TMath::Log10(zmin);
5225 zmax = TMath::Log10(zmax);
5226 } else {
5227 return;
5228 }
5229 }
5230 }
5231
5232 Double_t zratio, dz = zmax - zmin;
5234 if (fH->GetMinimum()<0) kZminNeg = kTRUE;
5236
5237 // Define the dark and light colors the "button style" boxes.
5238 Color_t color = fH->GetFillColor();
5239 Color_t light=0, dark=0;
5240 if (Hoption.Box == 11) {
5242 dark = TColor::GetColorDark(color);
5243 }
5244
5245 // Loop over all the bins and draw the boxes
5246 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
5249 ycent = 0.5*ystep;
5250 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
5251 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
5252 xk = fXaxis->GetBinLowEdge(i);
5253 xstep = fXaxis->GetBinWidth(i);
5254 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
5255 xcent = 0.5*xstep;
5256 z = Hparam.factor*fH->GetBinContent(bin);
5257 kZNeg = kFALSE;
5258
5259 if (TMath::Abs(z) < zminlin) continue; // Can be the case with ...
5260 if (TMath::Abs(z) > zmaxlin) z = zmaxlin; // ... option Same
5261 if (kZminNeg && z==0) continue; // Do not draw empty bins if case of histo with negative bins.
5262
5263 if (z < 0) {
5264 if (Hoption.Logz) continue;
5265 z = -z;
5266 kZNeg = kTRUE;
5267 }
5268 if (Hoption.Logz) {
5269 if (z != 0) z = TMath::Log10(z);
5270 else z = zmin;
5271 }
5272
5273 if (dz == 0) continue;
5274 zratio = TMath::Sqrt((z-zmin)/dz);
5275 if (zratio == 0) continue;
5276
5277 xup = xcent*zratio + xk + xcent;
5278 xlow = 2*(xk + xcent) - xup;
5279 if (xup-xlow < dxmin) xup = xlow+dxmin;
5280 if (Hoption.Logx) {
5281 if (xup > 0) xup = TMath::Log10(xup);
5282 else continue;
5283 if (xlow > 0) xlow = TMath::Log10(xlow);
5284 else continue;
5285 }
5286
5287 yup = ycent*zratio + yk + ycent;
5288 ylow = 2*(yk + ycent) - yup;
5289 if (yup-ylow < dymin) yup = ylow+dymin;
5290 if (Hoption.Logy) {
5291 if (yup > 0) yup = TMath::Log10(yup);
5292 else continue;
5293 if (ylow > 0) ylow = TMath::Log10(ylow);
5294 else continue;
5295 }
5296
5297 xlow = TMath::Max(xlow, gPad->GetUxmin());
5298 ylow = TMath::Max(ylow, gPad->GetUymin());
5299 xup = TMath::Min(xup , gPad->GetUxmax());
5300 yup = TMath::Min(yup , gPad->GetUymax());
5301
5302 if (xlow >= xup) continue;
5303 if (ylow >= yup) continue;
5304
5305 if (Hoption.Box == 1) {
5306 fH->SetFillColor(color);
5307 fH->TAttFill::Modify();
5308 gPad->PaintBox(xlow, ylow, xup, yup);
5309 if (kZNeg) {
5310 gPad->PaintLine(xlow, ylow, xup, yup);
5311 gPad->PaintLine(xlow, yup, xup, ylow);
5312 }
5313 } else if (Hoption.Box == 11) {
5314 // Draw the center of the box
5315 fH->SetFillColor(color);
5316 fH->TAttFill::Modify();
5317 gPad->PaintBox(xlow, ylow, xup, yup);
5318
5319 // Draw top&left part of the box
5320 Double_t x[7], y[7];
5321 Double_t bwidth = 0.1;
5322 x[0] = xlow; y[0] = ylow;
5323 x[1] = xlow + bwidth*(xup-xlow); y[1] = ylow + bwidth*(yup-ylow);
5324 x[2] = x[1]; y[2] = yup - bwidth*(yup-ylow);
5325 x[3] = xup - bwidth*(xup-xlow); y[3] = y[2];
5326 x[4] = xup; y[4] = yup;
5327 x[5] = xlow; y[5] = yup;
5328 x[6] = xlow; y[6] = ylow;
5329 if (kZNeg) fH->SetFillColor(dark);
5330 else fH->SetFillColor(light);
5331 fH->TAttFill::Modify();
5332 gPad->PaintFillArea(7, x, y);
5333
5334 // Draw bottom&right part of the box
5335 x[0] = xlow; y[0] = ylow;
5336 x[1] = xlow + bwidth*(xup-xlow); y[1] = ylow + bwidth*(yup-ylow);
5337 x[2] = xup - bwidth*(xup-xlow); y[2] = y[1];
5338 x[3] = x[2]; y[3] = yup - bwidth*(yup-ylow);
5339 x[4] = xup; y[4] = yup;
5340 x[5] = xup; y[5] = ylow;
5341 x[6] = xlow; y[6] = ylow;
5342 if (kZNeg) fH->SetFillColor(light);
5343 else fH->SetFillColor(dark);
5344 fH->TAttFill::Modify();
5345 gPad->PaintFillArea(7, x, y);
5346 }
5347 }
5348 }
5349
5353 fH->TAttFill::Modify();
5354}
5355
5356
5357
5358////////////////////////////////////////////////////////////////////////////////
5359/// [Control function to draw a 2D histogram as a candle (box) plot or violin plot](\ref HP14)
5360
5362{
5363 TH1D *hproj = nullptr;
5364 TH2D *h2 = (TH2D*)fH;
5365
5368 myCandle.SetMarkerColor(fH->GetLineColor());
5369 myCandle.SetLineColor(fH->GetLineColor());
5370 myCandle.SetLineWidth(fH->GetLineWidth());
5371 myCandle.SetFillColor(fH->GetFillColor());
5372 myCandle.SetFillStyle(fH->GetFillStyle());
5373 myCandle.SetMarkerSize(fH->GetMarkerSize());
5374 myCandle.SetMarkerStyle(fH->GetMarkerStyle());
5376
5377 Bool_t swapXY = myCandle.IsHorizontal();
5378 const Double_t standardCandleWidth = 0.66;
5379 const Double_t standardHistoWidth = 0.8;
5380
5381 double allMaxContent = 0, allMaxIntegral = 0;
5382 if (myCandle.IsViolinScaled())
5383 allMaxContent = h2->GetBinContent(h2->GetMaximumBin());
5384
5385 if (!swapXY) { // Vertical candle
5386 //Determining the slice with the maximum integral - if necessary
5387 if (myCandle.IsCandleScaled())
5388 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast; i++) {
5389 hproj = h2->ProjectionY("_px", i, i);
5390 if (hproj->Integral() > allMaxIntegral) allMaxIntegral = hproj->Integral();
5391 }
5392 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast; i++) {
5394 Double_t binWidth = fXaxis->GetBinWidth(i);
5395 hproj = h2->ProjectionY("_px", i, i);
5396 if (hproj->GetEntries() != 0) {
5398 Double_t offset = fH->GetBarOffset()*binWidth;
5399 double myMaxContent = hproj->GetBinContent(hproj->GetMaximumBin());
5400 double myIntegral = hproj->Integral();
5402 if (candleWidth > 0.999 && candleWidth < 1.001) {
5405 }
5406 if (Hoption.Logz && myMaxContent > 0) {
5408 if (myCandle.IsViolinScaled() && myMaxContent > 0 && allMaxContent > 0)
5410 } else if (myCandle.IsViolinScaled() && (allMaxContent > 0))
5412 if (myCandle.IsCandleScaled() && (allMaxIntegral > 0))
5414
5415 myCandle.SetAxisPosition(binPosX+binWidth/2. + offset);
5416 myCandle.SetCandleWidth(candleWidth*binWidth);
5417 myCandle.SetHistoWidth(histoWidth*binWidth);
5418 myCandle.SetHistogram(hproj);
5419 myCandle.Paint();
5420 }
5421 }
5422 } else { // Horizontal candle
5423 //Determining the slice with the maximum integral - if necessary
5424 if (myCandle.IsCandleScaled())
5425 for (Int_t i=Hparam.yfirst; i<=Hparam.ylast; i++) {
5426 hproj = h2->ProjectionX("_py", i, i);
5427 if (hproj->Integral() > allMaxIntegral) allMaxIntegral = hproj->Integral();
5428 }
5429 for (Int_t i=Hparam.yfirst; i<=Hparam.ylast; i++) {
5431 Double_t binWidth = fYaxis->GetBinWidth(i);
5432 hproj = h2->ProjectionX("_py", i, i);
5433 if (hproj->GetEntries() != 0) {
5435 Double_t offset = fH->GetBarOffset()*binWidth;
5436 double myMaxContent = hproj->GetBinContent(hproj->GetMaximumBin());
5437 double myIntegral = hproj->Integral();
5439 if (candleWidth > 0.999 && candleWidth < 1.001) {
5442 }
5443 if (Hoption.Logz && myMaxContent > 0) {
5445 if (myCandle.IsViolinScaled() && myMaxContent > 0 && allMaxContent > 0)
5447 } else if (myCandle.IsViolinScaled() && (allMaxContent > 0))
5449 if (myCandle.IsCandleScaled() && (allMaxIntegral > 0))
5451
5452 myCandle.SetAxisPosition(binPosY+binWidth/2. + offset);
5453 myCandle.SetCandleWidth(candleWidth*binWidth);
5454 myCandle.SetHistoWidth(histoWidth*binWidth);
5455 myCandle.SetHistogram(hproj);
5456 myCandle.Paint();
5457 }
5458 }
5459 }
5460 delete hproj;
5461}
5462
5463
5464
5465////////////////////////////////////////////////////////////////////////////////
5466/// Returns the rendering regions for an axis to use in the COL2 option
5467///
5468/// The algorithm analyses the size of the axis compared to the size of
5469/// the rendering region. It figures out the boundaries to use for each color
5470/// of the rendering region. Only one axis is computed here.
5471///
5472/// This allows for a single computation of the boundaries before iterating
5473/// through all of the bins.
5474///
5475/// \param pAxis the axis to consider
5476/// \param nPixels the number of pixels to render axis into
5477/// \param isLog whether the axis is log scale
5478
5479std::vector<THistRenderingRegion>
5481{
5482 std::vector<THistRenderingRegion> regions;
5483
5484 enum STRATEGY { Bins, Pixels } strategy;
5485
5486 Int_t nBins = (pAxis->GetLast() - pAxis->GetFirst() + 1);
5487
5488 if (nBins >= nPixels) {
5489 // more bins than pixels... we should loop over pixels and sample
5490 strategy = Pixels;
5491 } else {
5492 // fewer bins than pixels... we should loop over bins
5493 strategy = Bins;
5494 }
5495
5496 if (isLog) {
5497
5498 Double_t xMin = pAxis->GetBinLowEdge(pAxis->GetFirst());
5499 Int_t binOffset=0;
5500 while (xMin <= 0 && ((pAxis->GetFirst()+binOffset) != pAxis->GetLast()) ) {
5501 binOffset++;
5502 xMin = pAxis->GetBinLowEdge(pAxis->GetFirst()+binOffset);
5503 }
5504 if (xMin <= 0) {
5505 // this should cause an error if we have
5506 return regions;
5507 }
5508 Double_t xMax = pAxis->GetBinUpEdge(pAxis->GetLast());
5509
5510 if (strategy == Bins) {
5511 // logarithmic plot. we find the pixel for the bin
5512 // pixel = eta * log10(V) - alpha
5513 // where eta = nPixels/(log10(Vmax)-log10(Vmin))
5514 // and alpha = nPixels*log10(Vmin)/(log10(Vmax)-log10(Vmin))
5515 // and V is axis value
5517 Double_t offset = -1.0 * eta * TMath::Log10(xMin);
5518
5519 for (Int_t bin=pAxis->GetFirst()+binOffset; bin<=pAxis->GetLast(); bin++) {
5520
5521 // linear plot. we simply need to find the appropriate bin
5522 // for the
5523 Double_t xLowValue = pAxis->GetBinLowEdge(bin);
5524 Double_t xUpValue = pAxis->GetBinUpEdge(bin);
5527 THistRenderingRegion region = {std::make_pair(xPx0, xPx1),
5528 std::make_pair(bin, bin+1)};
5529 regions.push_back(region);
5530 }
5531
5532 } else {
5533
5534 // loop over pixels
5535
5537
5538 for (Int_t pixelIndex=0; pixelIndex<(nPixels-1); pixelIndex++) {
5539 // linear plot
5540 Int_t binLow = pAxis->FindBin(xMin*TMath::Power(10.0, beta*pixelIndex));
5541 Int_t binHigh = pAxis->FindBin(xMin*TMath::Power(10.0, beta*(pixelIndex+1)));
5542 THistRenderingRegion region = { std::make_pair(pixelIndex, pixelIndex+1),
5543 std::make_pair(binLow, binHigh)};
5544 regions.push_back(region);
5545 }
5546 }
5547 } else {
5548 // standard linear plot
5549
5550 if (strategy == Bins) {
5551 // loop over bins
5552 for (Int_t bin=pAxis->GetFirst(); bin<=pAxis->GetLast(); bin++) {
5553
5554 // linear plot. we simply need to find the appropriate bin
5555 // for the
5556 Int_t xPx0 = ((bin - pAxis->GetFirst()) * nPixels)/nBins;
5557 Int_t xPx1 = xPx0 + nPixels/nBins;
5558
5559 // make sure we don't compute beyond our bounds
5560 if (xPx1>= nPixels) xPx1 = nPixels-1;
5561
5562 THistRenderingRegion region = {std::make_pair(xPx0, xPx1),
5563 std::make_pair(bin, bin+1)};
5564 regions.push_back(region);
5565 }
5566 } else {
5567 // loop over pixels
5569 // linear plot
5570 Int_t binLow = (nBins*pixelIndex)/nPixels + pAxis->GetFirst();
5571 Int_t binHigh = binLow + nBins/nPixels;
5572 THistRenderingRegion region = { std::make_pair(pixelIndex, pixelIndex+1),
5573 std::make_pair(binLow, binHigh)};
5574 regions.push_back(region);
5575 }
5576 }
5577 }
5578
5579 return regions;
5580}
5581
5582////////////////////////////////////////////////////////////////////////////////
5583/// [Rendering scheme for the COL2 and COLZ2 options] (\ref HP14)
5584
5586{
5587
5588 if (Hoption.System != kCARTESIAN) {
5589 Error("THistPainter::PaintColorLevelsFast(Option_t*)",
5590 "Only cartesian coordinates supported by 'COL2' option. Using 'COL' option instead.");
5591 PaintColorLevels(nullptr);
5592 return;
5593 }
5594
5595 Double_t z;
5596
5597 // Use existing max or min values. If either is already set
5598 // the appropriate value to use.
5599 Double_t zmin = fH->GetMinimumStored();
5600 Double_t zmax = fH->GetMaximumStored();
5601 Double_t originalZMin = zmin;
5602 Double_t originalZMax = zmax;
5603 if ((zmin == -1111) && (zmax == -1111)) {
5604 fH->GetMinimumAndMaximum(zmin, zmax);
5605 fH->SetMinimum(zmin);
5606 fH->SetMaximum(zmax);
5607 } else if (zmin == -1111) {
5608 zmin = fH->GetMinimum();
5609 fH->SetMinimum(zmin);
5610 } else if (zmax == -1111) {
5611 zmax = fH->GetMaximum();
5612 fH->SetMaximum(zmax);
5613 }
5614
5615 Double_t dz = zmax - zmin;
5616 if (dz <= 0) { // Histogram filled with a constant value
5617 zmax += 0.1*TMath::Abs(zmax);
5618 zmin -= 0.1*TMath::Abs(zmin);
5619 dz = zmax - zmin;
5620 }
5621
5622 if (Hoption.Logz) {
5623 if (zmin > 0) {
5624 zmin = TMath::Log10(zmin);
5625 zmax = TMath::Log10(zmax);
5626 dz = zmax - zmin;
5627 } else {
5628 Error("THistPainter::PaintColorLevelsFast(Option_t*)",
5629 "Cannot plot logz because bin content is less than 0.");
5630 return;
5631 }
5632 }
5633
5634 // Initialize the levels on the Z axis
5635 Int_t ndiv = fH->GetContour();
5636 if (ndiv == 0 ) {
5637 ndiv = gStyle->GetNumberContours();
5638 fH->SetContour(ndiv);
5639 }
5640 std::vector<Double_t> colorBounds(ndiv);
5641 std::vector<Double_t> contours(ndiv, 0);
5642 if (!fH->TestBit(TH1::kUserContour)) {
5643 fH->SetContour(ndiv);
5644 } else {
5645 fH->GetContour(contours.data());
5646 }
5647
5648 Double_t step = 1.0/ndiv;
5649 for (Int_t i=0; i<ndiv; ++i) {
5650 colorBounds[i] = step*i;
5651 }
5652
5653 auto pFrame = gPad->GetFrame();
5654 Int_t px0 = gPad->XtoPixel(pFrame->GetX1());
5655 Int_t px1 = gPad->XtoPixel(pFrame->GetX2());
5656 Int_t py0 = gPad->YtoPixel(pFrame->GetY1());
5657 Int_t py1 = gPad->YtoPixel(pFrame->GetY2());
5658 Int_t nXPixels = px1-px0;
5659 Int_t nYPixels = py0-py1; // y=0 is at the top of the screen
5660
5661 std::vector<Double_t> buffer(nXPixels*nYPixels, 0);
5662
5665 if (xRegions.empty() || yRegions.empty()) {
5666 Error("THistPainter::PaintColorLevelFast(Option_t*)",
5667 "Encountered error while computing rendering regions.");
5668 return;
5669 }
5670
5673 Double_t minValue = 1.;
5674 Double_t maxValue = 0.;
5675 for (auto& yRegion : yRegions) {
5676 for (auto& xRegion : xRegions ) {
5677
5678 const auto& xBinRange = xRegion.fBinRange;
5679 const auto& yBinRange = yRegion.fBinRange;
5680
5681 // sample the range
5682 z = fH->GetBinContent(xBinRange.second-1, yBinRange.second-1);
5683
5684 if (Hoption.Logz) {
5685 if (z > 0) z = TMath::Log10(z);
5686 else z = zmin;
5687 }
5688
5689 // obey the user's max and min values if they were set
5690 if (z > zmax) z = zmax;
5691 if (z < zmin) z = zmin;
5692
5694 // contours are absolute values
5695 auto index = TMath::BinarySearch(contours.size(), contours.data(), z);
5696 z = colorBounds[index];
5697 } else {
5698 Int_t index = 0;
5699 if (dz != 0) {
5700 index = 0.001 + ((z - zmin)/dz)*ndiv;
5701 }
5702
5703 if (index == static_cast<Int_t>(colorBounds.size())) {
5704 index--;
5705 }
5706
5707 // Do a little bookkeeping to use later for getting libAfterImage to produce
5708 // the correct colors
5709 if (index == 0) {
5710 minExists = kTRUE;
5711 } else if (index == static_cast<Int_t>(colorBounds.size()-1)) {
5712 maxExists = kTRUE;
5713 }
5714
5715 z = colorBounds[index];
5716
5717 if (z < minValue) {
5718 minValue = z;
5719 }
5720 if (z > maxValue) {
5721 maxValue = z;
5722 }
5723 }
5724
5725 // fill in the actual pixels
5726 const auto& xPixelRange = xRegion.fPixelRange;
5727 const auto& yPixelRange = yRegion.fPixelRange;
5728 for (Int_t xPx = xPixelRange.first; xPx <= xPixelRange.second; ++xPx) {
5729 for (Int_t yPx = yPixelRange.first; yPx <= yPixelRange.second; ++yPx) {
5731 buffer[pixel] = z;
5732 }
5733 }
5734 } // end px loop
5735 } // end py loop
5736
5737 // This is a bit of a hack to ensure that we span the entire color range and
5738 // don't screw up the colors for a sparse histogram. No one will notice that I set a
5739 // single pixel on the edge of the image to a different color. This is even more
5740 // true because the chosen pixels will be covered by the axis.
5741 if (minValue != maxValue) {
5742 if ( !minExists) {
5743 buffer.front() = 0;
5744 }
5745
5746 if ( !maxExists) {
5747 buffer[buffer.size()-nXPixels] = 0.95;
5748 }
5749 }
5750
5751 // Generate the TImage
5754 pImage->SetImageQuality(TAttImage::kImgBest);
5755 pImage->SetImage(buffer.data(), nXPixels, nYPixels, pPalette);
5756 delete pPalette;
5757
5758 Window_t wid = static_cast<Window_t>(gVirtualX->GetWindowID(gPad->GetPixmapID()));
5759 pImage->PaintImage(wid, px0, py1, 0, 0, nXPixels, nYPixels);
5760 delete pImage;
5761
5763
5764 // Reset the maximum and minimum values to their original values
5765 // when this function was called. If we don't do this, an initial
5766 // value of -1111 will be replaced with the true max or min values.
5769}
5770
5771////////////////////////////////////////////////////////////////////////////////
5772/// [Control function to draw a 2D histogram as a color plot.](\ref HP14)
5773
5775{
5776 Double_t z, e, zc, xk, xstep, yk, ystep, xlow, xup, ylow, yup;
5777
5778 Double_t zmin = fH->GetMinimum();
5779 Double_t zmax = fH->GetMaximum();
5780
5781 Double_t dz = zmax - zmin;
5782 if (dz <= 0) { // Histogram filled with a constant value
5783 zmax += 0.1*TMath::Abs(zmax);
5784 zmin -= 0.1*TMath::Abs(zmin);
5785 dz = zmax - zmin;
5786 }
5787
5788 // In case of option SAME, zmin and zmax values are taken from the
5789 // first plotted 2D histogram.
5790 if (Hoption.Same > 0 && Hoption.Same < 10) {
5791 TH2 *h2;
5792 TIter next(gPad->GetListOfPrimitives());
5793 while ((h2 = (TH2 *)next())) {
5794 if (!h2->InheritsFrom(TH2::Class())) continue;
5795 zmin = h2->GetMinimum();
5796 zmax = h2->GetMaximum();
5797 fH->SetMinimum(zmin);
5798 fH->SetMaximum(zmax);
5799 if (Hoption.Logz) {
5800 if (zmin <= 0) {
5801 zmin = TMath::Log10(zmax*0.001);
5802 } else {
5803 zmin = TMath::Log10(zmin);
5804 }
5805 zmax = TMath::Log10(zmax);
5806 }
5807 dz = zmax - zmin;
5808 break;
5809 }
5810 } else {
5811 if (Hoption.Logz) {
5812 if (zmin > 0) {
5813 zmin = TMath::Log10(zmin);
5814 zmax = TMath::Log10(zmax);
5815 dz = zmax - zmin;
5816 } else {
5817 return;
5818 }
5819 }
5820 }
5821
5824 fH->SetFillStyle(1001);
5825 fH->TAttFill::Modify();
5826
5827 // Initialize the levels on the Z axis
5828 Int_t ncolors = gStyle->GetNumberOfColors();
5829 Int_t ndiv = fH->GetContour();
5830 if (ndiv == 0 ) {
5831 ndiv = gStyle->GetNumberContours();
5832 fH->SetContour(ndiv);
5833 }
5834 Int_t ndivz = TMath::Abs(ndiv);
5835 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
5836 Double_t scale = (dz ? ndivz / dz : 1.0);
5837
5838 Int_t color;
5839 TProfile2D* prof2d = dynamic_cast<TProfile2D*>(fH);
5840 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
5843 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
5844 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
5845 xk = fXaxis->GetBinLowEdge(i);
5846 xstep = fXaxis->GetBinWidth(i);
5847 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
5848 z = fH->GetBinContent(bin);
5849 e = fH->GetBinError(bin);
5850 // if fH is a profile histogram do not draw empty bins
5851 if (prof2d) {
5852 const Double_t binEntries = prof2d->GetBinEntries(bin);
5853 if (binEntries == 0)
5854 continue;
5855 } else {
5856 // don't draw the empty bins for non-profile histograms
5857 // with positive content
5858 if (z == 0 && e == 0) {
5859 if (zmin >= 0 || Hoption.Logz) continue;
5860 if (Hoption.Color == 2) continue;
5861 }
5862 }
5863
5864 if (Hoption.Logz) {
5865 if (z > 0) z = TMath::Log10(z);
5866 else z = zmin;
5867 }
5868 if (z < zmin && !Hoption.Zero) continue;
5869 xup = xk + xstep;
5870 xlow = xk;
5871 if (Hoption.Logx) {
5872 if (xup > 0) xup = TMath::Log10(xup);
5873 else continue;
5874 if (xlow > 0) xlow = TMath::Log10(xlow);
5875 else continue;
5876 }
5877 yup = yk + ystep;
5878 ylow = yk;
5879 if (Hoption.Logy) {
5880 if (yup > 0) yup = TMath::Log10(yup);
5881 else continue;
5882 if (ylow > 0) ylow = TMath::Log10(ylow);
5883 else continue;
5884 }
5885 if (xup < gPad->GetUxmin()) continue;
5886 if (yup < gPad->GetUymin()) continue;
5887 if (xlow > gPad->GetUxmax()) continue;
5888 if (ylow > gPad->GetUymax()) continue;
5889 if (xlow < gPad->GetUxmin()) xlow = gPad->GetUxmin();
5890 if (ylow < gPad->GetUymin()) ylow = gPad->GetUymin();
5891 if (xup > gPad->GetUxmax()) xup = gPad->GetUxmax();
5892 if (yup > gPad->GetUymax()) yup = gPad->GetUymax();
5893
5895 zc = fH->GetContourLevelPad(0);
5896 if (z < zc) continue;
5897 color = -1;
5898 for (Int_t k=0; k<ndiv; k++) {
5899 zc = fH->GetContourLevelPad(k);
5900 if (z < zc) {
5901 continue;
5902 } else {
5903 color++;
5904 }
5905 }
5906 } else {
5907 color = Int_t(0.01+(z-zmin)*scale);
5908 }
5909
5910 Int_t theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
5911 if (theColor > ncolors-1) theColor = ncolors-1;
5913 if (Hoption.System != kPOLAR) {
5915 fH->TAttFill::Modify();
5916 gPad->PaintBox(xlow, ylow, xup, yup);
5917 } else {
5918 Double_t midx = (gPad->GetUxmin() + gPad->GetUxmax()) / 2,
5919 midy = (gPad->GetUymin() + gPad->GetUymax()) / 2,
5920 a1 = (xlow - gPad->GetUxmin()) / (gPad->GetUxmax() - gPad->GetUxmin()) * 360,
5921 a2 = (xup - gPad->GetUxmin()) / (gPad->GetUxmax() - gPad->GetUxmin()) * 360,
5922 rx = gPad->GetUxmax() - gPad->GetUxmin(),
5923 ry = gPad->GetUymax() - gPad->GetUymin(),
5924 r1 = (ylow - gPad->GetUymin()) / (gPad->GetUymax() - gPad->GetUymin()) * rx / 2,
5925 r2 = (yup - gPad->GetUymin()) / (gPad->GetUymax() - gPad->GetUymin()) * rx / 2;
5926
5927 TCrown crown(midx, midy, r1, r2, a1, a2);
5928 crown.SetYXRatio(rx > 0 ? ry / rx : 1);
5929 crown.SetFillColor(fillColor);
5930 crown.SetLineColor(fH->GetLineColor());
5931 crown.SetLineWidth(fH->GetLineWidth());
5932 crown.SetLineStyle(fH->GetLineStyle());
5933 crown.Paint();
5934 }
5935 }
5936 }
5937
5939
5942 fH->TAttFill::Modify();
5943
5944}
5945
5946////////////////////////////////////////////////////////////////////////////////
5947/// [Control function to draw a 2D histogram as a contour plot.](\ref HP16)
5948
5950{
5951
5952 Int_t i, j, count, ncontour, icol, n, lj, m, ix, jx, ljfill;
5953 Int_t itars, mode, ir[4];
5954 Double_t xsave, ysave, thesave,phisave,x[4], y[4], zc[4];
5955
5956 if (Hoption.Contour == 14) {
5957 Hoption.Surf = 12;
5958 Hoption.Axis = 1;
5959 thesave = gPad->GetTheta();
5960 phisave = gPad->GetPhi();
5961 gPad->SetPhi(0.);
5962 gPad->SetTheta(90.);
5964 gPad->SetPhi(phisave);
5965 gPad->SetTheta(thesave);
5966 TView *view = gPad->GetView();
5967 if (view) view->SetBit(kCannotRotate); //tested in ExecuteEvent
5968 PaintAxis();
5969 return;
5970 }
5971
5972 if (Hoption.Same) {
5973 // If the contour is painted on a 3d plot, the contour lines are
5974 // paint in 3d too.
5975 TObject *obj;
5976 TIter next(gPad->GetListOfPrimitives());
5977 while ((obj=next())) {
5978 if (strstr(obj->GetDrawOption(),"surf") ||
5979 strstr(obj->GetDrawOption(),"lego") ||
5980 strstr(obj->GetDrawOption(),"tri")) {
5981 Hoption.Surf = 16;
5983 return;
5984 }
5985 }
5986 }
5987
5988 if (Hoption.Contour == 15) {
5989 TGraphDelaunay2D *dt = nullptr;
5990 TGraphDelaunay *dtOld = nullptr;
5992 dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
5993 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
5994 if (!dt && !dtOld) return;
5995 if (!fGraph2DPainter)
5996 fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
5997 fGraph2DPainter->Paint(option);
5998 return;
5999 }
6000
6001 gPad->SetBit(TGraph::kClipFrame);
6002
6003 std::vector<Double_t> levels(2*kMAXCONTOUR);
6004 std::vector<Double_t> xarr(2*kMAXCONTOUR);
6005 std::vector<Double_t> yarr(2*kMAXCONTOUR);
6006 std::vector<Int_t> itarr(2*kMAXCONTOUR);
6007
6008 Int_t npmax = 0;
6009 for (i=0;i<2*kMAXCONTOUR;i++) itarr[i] = 0;
6010
6011 ncontour = fH->GetContour();
6012 if (ncontour == 0) {
6015 }
6016 if (ncontour > kMAXCONTOUR) {
6017 Warning("PaintContour", "maximum number of contours is %d, asked for %d",
6020 }
6022
6023 for (i=0;i<ncontour;i++) levels[i] = fH->GetContourLevelPad(i);
6027 if (Hoption.Contour == 13) {
6028 fH->TAttLine::Modify();
6029 }
6030
6031 std::vector<std::unique_ptr<TPolyLine>> polys;
6032 TObjArray *contours = nullptr;
6033 TList *list = nullptr;
6034 TGraph *graph = nullptr;
6035 std::vector<Int_t> np;
6036 if (Hoption.Contour == 1) {
6037 np.resize(ncontour);
6038 for (i=0;i<ncontour;i++)
6039 np[i] = 0;
6040 for (i=0;i<ncontour;i++)
6041 polys.emplace_back(std::make_unique<TPolyLine>(100));
6042 if (Hoption.List == 1) {
6043 contours = (TObjArray*)gROOT->GetListOfSpecials()->FindObject("contours");
6044 if (contours) {
6045 gROOT->GetListOfSpecials()->Remove(contours);
6046 count = contours->GetSize();
6047 for (i=0;i<count;i++) {
6048 list = (TList*)contours->At(i);
6049 if (list) list->Delete();
6050 }
6051 contours->Delete();
6052 delete contours;
6053 }
6055 contours->SetName("contours");
6056 gROOT->GetListOfSpecials()->Add(contours);
6057 for (i=0;i<ncontour;i++) {
6058 list = new TList();
6059 contours->Add(list);
6060 }
6061 }
6062 }
6064 Int_t ncolors = gStyle->GetNumberOfColors();
6066
6067 Int_t k,ipoly;
6068 for (j=Hparam.yfirst; j<Hparam.ylast; j++) {
6069 y[0] = fYaxis->GetBinCenter(j);
6070 y[1] = y[0];
6071 y[2] = fYaxis->GetBinCenter(j+1);
6072 y[3] = y[2];
6073 for (i=Hparam.xfirst; i<Hparam.xlast; i++) {
6074 zc[0] = fH->GetBinContent(i, j);
6075 zc[1] = fH->GetBinContent(i+1, j);
6076 zc[2] = fH->GetBinContent(i+1, j+1);
6077 zc[3] = fH->GetBinContent(i, j+1);
6078 if (!IsInside(fXaxis->GetBinCenter(i),fYaxis->GetBinCenter(j))) continue;
6079 if (Hoption.Logz) {
6080 if (zc[0] > 0) zc[0] = TMath::Log10(zc[0]);
6081 else zc[0] = Hparam.zmin;
6082 if (zc[1] > 0) zc[1] = TMath::Log10(zc[1]);
6083 else zc[1] = Hparam.zmin;
6084 if (zc[2] > 0) zc[2] = TMath::Log10(zc[2]);
6085 else zc[2] = Hparam.zmin;
6086 if (zc[3] > 0) zc[3] = TMath::Log10(zc[3]);
6087 else zc[3] = Hparam.zmin;
6088 }
6089 for (k=0;k<4;k++) {
6090 ir[k] = TMath::BinarySearch(ncontour, levels.data(), zc[k]);
6091 }
6092 if (ir[0] != ir[1] || ir[1] != ir[2] || ir[2] != ir[3] || ir[3] != ir[0]) {
6093 x[0] = fXaxis->GetBinCenter(i);
6094 x[3] = x[0];
6095 x[1] = fXaxis->GetBinCenter(i+1);
6096 x[2] = x[1];
6097 if (zc[0] <= zc[1]) n = 0; else n = 1;
6098 if (zc[2] <= zc[3]) m = 2; else m = 3;
6099 if (zc[n] > zc[m]) n = m;
6100 n++;
6101 lj=1;
6102 for (ix=1;ix<=4;ix++) {
6103 m = n%4 + 1;
6104 ljfill = PaintContourLine(zc[n-1],ir[n-1],x[n-1],y[n-1],zc[m-1],
6105 ir[m-1],x[m-1],y[m-1], xarr.data()+lj-1,yarr.data()+lj-1,itarr.data()+lj-1, levels.data());
6106 lj += 2*ljfill;
6107 n = m;
6108 }
6109
6110 if (zc[0] <= zc[1]) n = 0; else n = 1;
6111 if (zc[2] <= zc[3]) m = 2; else m = 3;
6112 if (zc[n] > zc[m]) n = m;
6113 n++;
6114 lj=2;
6115 for (ix=1;ix<=4;ix++) {
6116 if (n == 1) m = 4;
6117 else m = n-1;
6118 ljfill = PaintContourLine(zc[n-1],ir[n-1],x[n-1],y[n-1],zc[m-1],
6119 ir[m-1],x[m-1],y[m-1],xarr.data()+lj-1,yarr.data()+lj-1,itarr.data()+lj-1, levels.data());
6120 lj += 2*ljfill;
6121 n = m;
6122 }
6123
6124 // Re-order endpoints
6125
6126 count = 0;
6127 for (ix=1; ix<=lj-5; ix +=2) {
6128 //count = 0;
6129 while (itarr[ix-1] != itarr[ix]) {
6130 xsave = xarr[ix];
6131 ysave = yarr[ix];
6132 itars = itarr[ix];
6133 for (jx=ix; jx<=lj-5; jx +=2) {
6134 xarr[jx] = xarr[jx+2];
6135 yarr[jx] = yarr[jx+2];
6136 itarr[jx] = itarr[jx+2];
6137 }
6138 xarr[lj-3] = xsave;
6139 yarr[lj-3] = ysave;
6140 itarr[lj-3] = itars;
6141 if (count > 100) break;
6142 count++;
6143 }
6144 }
6145
6146 if (count > 100) continue;
6147 for (ix=1; ix<=lj-2; ix +=2) {
6148 theColor = Int_t((itarr[ix-1]+0.99)*Float_t(ncolors)/Float_t(ndivz));
6150 if (Hoption.Contour == 11) {
6152 }
6153 if (Hoption.Contour == 12) {
6154 mode = icol%5;
6155 if (mode == 0) mode = 5;
6157 }
6158 if (Hoption.Contour != 1) {
6159 fH->TAttLine::Modify();
6160 gPad->PaintPolyLine(2,xarr.data()+ix-1,yarr.data()+ix-1);
6161 continue;
6162 }
6163
6164 ipoly = itarr[ix-1];
6165 if (ipoly >=0 && ipoly <ncontour) {
6166 polys[ipoly]->SetPoint(np[ipoly] ,xarr[ix-1],yarr[ix-1]);
6167 polys[ipoly]->SetPoint(np[ipoly]+1,xarr[ix], yarr[ix]);
6168 np[ipoly] += 2;
6169 if (npmax < np[ipoly]) npmax = np[ipoly];
6170 }
6171 }
6172 } // end of if (ir[0]
6173 } //end of for (i
6174 } //end of for (j
6175
6177 std::vector<Double_t> xp, yp;
6179 Int_t istart;
6180 Int_t first = ncontour;
6181 std::vector<Int_t> polysort;
6183 if (Hoption.Contour != 1) goto theEND;
6184
6185 //The 2 points line generated above are now sorted/merged to generate
6186 //a list of consecutive points.
6187 // If the option "List" has been specified, the list of points is saved
6188 // in the form of TGraph objects in the ROOT list of special objects.
6189 xmin = gPad->GetUxmin();
6190 ymin = gPad->GetUymin();
6191 xp.resize(2*npmax);
6192 yp.resize(2*npmax);
6193 polysort.resize(ncontour);
6194 //find first positive contour
6195 for (ipoly=0;ipoly<ncontour;ipoly++) {
6196 if (levels[ipoly] >= 0) {first = ipoly; break;}
6197 }
6198 //store negative contours from 0 to minimum, then all positive contours
6199 k = 0;
6200 for (ipoly=first-1;ipoly>=0;ipoly--) {polysort[k] = ipoly; k++;}
6201 for (ipoly=first;ipoly<ncontour;ipoly++) {polysort[k] = ipoly; k++;}
6202 // we can now draw sorted contours
6203 contListNb = 0;
6204 fH->SetFillStyle(1001);
6205 for (k=0;k<ncontour;k++) {
6206 ipoly = polysort[k];
6207 if (np[ipoly] == 0) continue;
6208 if (Hoption.List) list = (TList*)contours->At(contListNb);
6209 contListNb++;
6210 Double_t *xx = polys[ipoly]->GetX();
6211 Double_t *yy = polys[ipoly]->GetY();
6212 istart = 0;
6213 while (true) {
6214 iminus = npmax;
6215 iplus = iminus+1;
6216 xp[iminus]= xx[istart]; yp[iminus] = yy[istart];
6217 xp[iplus] = xx[istart+1]; yp[iplus] = yy[istart+1];
6218 xx[istart] = xmin; yy[istart] = ymin;
6219 xx[istart+1] = xmin; yy[istart+1] = ymin;
6220 while (true) {
6221 nadd = 0;
6222 for (i=2;i<np[ipoly];i+=2) {
6223 if ((iplus < 2*npmax-1) && (xx[i] == xp[iplus]) && (yy[i] == yp[iplus])) {
6224 iplus++;
6225 xp[iplus] = xx[i+1]; yp[iplus] = yy[i+1];
6226 xx[i] = xmin; yy[i] = ymin;
6227 xx[i+1] = xmin; yy[i+1] = ymin;
6228 nadd++;
6229 }
6230 if ((iminus > 0) && (xx[i+1] == xp[iminus]) && (yy[i+1] == yp[iminus])) {
6231 iminus--;
6232 xp[iminus] = xx[i]; yp[iminus] = yy[i];
6233 xx[i] = xmin; yy[i] = ymin;
6234 xx[i+1] = xmin; yy[i+1] = ymin;
6235 nadd++;
6236 }
6237 }
6238 if (nadd == 0) break;
6239 }
6240 theColor = Int_t((ipoly+0.99)*Float_t(ncolors)/Float_t(ndivz));
6242 if (ndivz > 1) fH->SetFillColor(icol);
6243 fH->TAttFill::Modify();
6244 gPad->PaintFillArea(iplus-iminus+1,xp.data()+iminus,yp.data()+iminus);
6245 if (Hoption.List) {
6246 graph = new TGraph(iplus-iminus+1,xp.data()+iminus,yp.data()+iminus);
6247 graph->SetFillColor(icol);
6248 graph->SetLineWidth(fH->GetLineWidth());
6249 list->Add(graph);
6250 }
6251 //check if more points are left
6252 istart = 0;
6253 for (i=2;i<np[ipoly];i+=2) {
6254 if (xx[i] != xmin && yy[i] != ymin) {
6255 istart = i;
6256 break;
6257 }
6258 }
6259 if (istart == 0) break;
6260 }
6261 }
6262
6263theEND:
6264 gPad->ResetBit(TGraph::kClipFrame);
6269}
6270
6271////////////////////////////////////////////////////////////////////////////////
6272/// Fill the matrix `xarr` and `yarr` for Contour Plot.
6273
6277{
6278
6279 Bool_t vert;
6281 Int_t n, i, icount;
6282
6283 if (x1 == x2) {
6284 vert = kTRUE;
6285 tlen = y2 - y1;
6286 } else {
6287 vert = kFALSE;
6288 tlen = x2 - x1;
6289 }
6290
6291 n = icont1 +1;
6292 tdif = elev2 - elev1;
6293 i = 0;
6294 icount = 0;
6295 while (n <= icont2 && i <= kMAXCONTOUR/2 -3) {
6296 //elev = fH->GetContourLevel(n);
6297 elev = levels[n];
6298 diff = elev - elev1;
6299 pdif = diff/tdif;
6300 xlen = tlen*pdif;
6301 if (vert) {
6302 if (Hoption.Logx)
6303 xarr[i] = TMath::Log10(x1);
6304 else
6305 xarr[i] = x1;
6306 if (Hoption.Logy)
6307 yarr[i] = TMath::Log10(y1 + xlen);
6308 else
6309 yarr[i] = y1 + xlen;
6310 } else {
6311 if (Hoption.Logx)
6312 xarr[i] = TMath::Log10(x1 + xlen);
6313 else
6314 xarr[i] = x1 + xlen;
6315 if (Hoption.Logy)
6316 yarr[i] = TMath::Log10(y1);
6317 else
6318 yarr[i] = y1;
6319 }
6320 itarr[i] = n;
6321 icount++;
6322 i +=2;
6323 n++;
6324 }
6325 return icount;
6326}
6327
6328////////////////////////////////////////////////////////////////////////////////
6329/// [Draw 1D histograms error bars.](\ref HP09)
6330
6332{
6333
6334 // On iOS, we do not highlight histogram, if it's not picked at the moment
6335 // (but part of histogram (axis or pavestat) was picked, that's why this code
6336 // is called at all. This conditional statement never executes on non-iOS platform.
6337 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH) return;
6338
6339 const Int_t kBASEMARKER=8;
6340 Double_t xp, yp, ex1, ex2, ey1, ey2;
6341 Double_t delta;
6343 Double_t xi1, xi2, xi3, xi4, yi1, yi2, yi3, yi4;
6345 Double_t logxmin = 0;
6346 Double_t logymin = 0;
6347 Double_t offset = 0.;
6348 Double_t width = 0.;
6349 Int_t i, k, npoints, first, last, fixbin;
6350 Int_t if1 = 0;
6351 Int_t if2 = 0;
6354 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};
6355 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};
6356
6357 std::vector<Double_t> xline, yline;
6359 if (Hoption.Error >= 40) {Hoption.Error -=40; option0 = 1;}
6360 if (Int_t(Hoption.Error/10) == 2) {optionEX0 = 1; Hoption.Error -= 10;}
6361 if (Hoption.Error == 31) {optionEX0 = 1; Hoption.Error = 1;}
6362 if (Hoption.Error == 11) option1 = 1;
6363 if (Hoption.Error == 12) option2 = 1;
6364 if (Hoption.Error == 13) option3 = 1;
6365 if (Hoption.Error == 14) {option4 = 1; option3 = 1;}
6366 if (Hoption.Error == 15) {optionI0 = 1; option3 = 1;}
6367 if (Hoption.Error == 16) {optionI0 = 1; option4 = 1; option3 = 1;}
6368 if (option2+option3 == 0) optionE = 1;
6369 if (Hoption.Error == 0) optionE = 0;
6370 if (fXaxis->GetXbins()->fN) fixbin = 0;
6371 else fixbin = 1;
6372
6373 offset = fH->GetBarOffset();
6374 width = fH->GetBarWidth();
6375
6377 if (optionEX0) {
6378 xerror = 0;
6379 } else {
6380 xerror = gStyle->GetErrorX();
6381 }
6383 if (errormarker == 1) symbolsize = 0.01;
6385 if (errormarker >= 20 && errormarker <= 49) {
6386 sbasex *= cxx[errormarker-20];
6387 sbasey *= cyy[errormarker-20];
6388 }
6389 // set the graphics attributes
6390
6391 fH->TAttLine::Modify();
6392 fH->TAttFill::Modify();
6393 fH->TAttMarker::Modify();
6394
6395 // set the first and last bin
6396
6397 Double_t factor = Hparam.factor;
6398 first = Hparam.xfirst;
6399 last = Hparam.xlast;
6400 npoints = last - first +1;
6401 xmin = gPad->GetUxmin();
6402 xmax = gPad->GetUxmax();
6403 ymin = gPad->GetUymin();
6404 ymax = gPad->GetUymax();
6405
6406
6407 if (option3) {
6408 xline.resize(2*npoints);
6409 yline.resize(2*npoints);
6410 if ((npoints > 0) && (xline.empty() || yline.empty())) {
6411 Error("PaintErrors", "too many points, out of memory");
6412 return;
6413 }
6414 if1 = 1;
6415 if2 = 2*npoints;
6416 }
6417
6418 // compute the offset of the error bars due to the symbol size
6419 s2x = gPad->PixeltoX(Int_t(0.5*sbasex)) - gPad->PixeltoX(0);
6420 s2y =-gPad->PixeltoY(Int_t(0.5*sbasey)) + gPad->PixeltoY(0);
6421
6422 // compute size of the lines at the end of the error bars
6424 bxsize = gPad->PixeltoX(dxend) - gPad->PixeltoX(0);
6425 bysize =-gPad->PixeltoY(dxend) + gPad->PixeltoY(0);
6426
6427
6428 if (fixbin) {
6430 else xp = Hparam.xmin + 0.5*Hparam.xbinsize;
6431 } else {
6432 delta = fH->GetBinWidth(first);
6433 xp = fH->GetBinLowEdge(first) + 0.5*delta;
6434 }
6435
6436 // if errormarker = 0 or symbolsize = 0. no symbol is drawn
6439
6440 // ---------------------- Loop over the points---------------------
6441 for (k=first; k<=last; k++) {
6442
6443 // get the data
6444 // xp = X position of the current point
6445 // yp = Y position of the current point
6446 // ex1 = Low X error
6447 // ex2 = Up X error
6448 // ey1 = Low Y error
6449 // ey2 = Up Y error
6450 // (xi,yi) = Error bars coordinates
6451
6452 // apply offset on errors for bar histograms
6453 Double_t xminTmp = gPad->XtoPad(fXaxis->GetBinLowEdge(k));
6454 Double_t xmaxTmp = gPad->XtoPad(fXaxis->GetBinUpEdge(k));
6455 if (Hoption.Logx) {
6458 }
6461 xmaxTmp = xminTmp + w;
6462 xp = (xminTmp+xmaxTmp)/2.;
6463
6464 if (Hoption.Logx) {
6465 if (xp <= 0) goto L30;
6466 if (xp < logxmin) goto L30;
6467 if (xp > TMath::Power(10,xmax)) break;
6468 } else {
6469 if (xp < xmin) goto L30;
6470 if (xp > xmax) break;
6471 }
6472 yp = factor*fH->GetBinContent(k);
6473 if (optionI0 && yp==0) goto L30;
6474 if (fixbin) {
6476 } else {
6477 delta = fH->GetBinWidth(k);
6478 ex1 = xerror*delta;
6479 }
6480 if (fH->GetBinErrorOption() == TH1::kNormal) {
6481 ey1 = factor*fH->GetBinError(k);
6482 ey2 = ey1;
6483 } else {
6484 ey1 = factor*fH->GetBinErrorLow(k);
6485 ey2 = factor*fH->GetBinErrorUp(k);
6486 }
6487 ex2 = ex1;
6488
6489 xi4 = xp;
6490 xi3 = xp;
6491 xi2 = xp + ex2;
6492 xi1 = xp - ex1;
6493
6494 yi1 = yp;
6495 yi2 = yp;
6496 yi3 = yp - ey1;
6497 yi4 = yp + ey2;
6498
6499 // take the LOG if necessary
6500 if (Hoption.Logx) {
6505 }
6506 if (Hoption.Logy) {
6511 }
6512
6513 // test if error bars are not outside the limits
6514 // otherwise they are truncated
6515
6520
6521 // test if the marker is on the frame limits. If "Yes", the
6522 // marker will not be drawn and the error bars will be readjusted.
6523
6524 drawmarker = kTRUE;
6525 if (!option0 && !option3) {
6526 if (Hoption.Logy && yp < logymin) goto L30;
6527 if (yi1 < ymin || yi1 > ymax) goto L30;
6528 if (Hoption.Error != 0 && yp == 0 && ey1 <= 0) drawmarker = kFALSE;
6529 }
6531
6532 // draw the error rectangles
6533 if (option2) {
6534 if (yi3 >= ymax) goto L30;
6535 if (yi4 <= ymin) goto L30;
6536 gPad->PaintBox(xi1,yi3,xi2,yi4);
6537 }
6538
6539 // keep points for fill area drawing
6540 if (option3) {
6541 xline[if1-1] = xi3;
6542 xline[if2-1] = xi3;
6543 yline[if1-1] = yi4;
6544 yline[if2-1] = yi3;
6545 if1++;
6546 if2--;
6547 }
6548
6549 // draw the error bars
6550 if (Hoption.Logy && yp < logymin) drawmarker = kFALSE;
6551 if (optionE && drawmarker) {
6552 if ((yi3 < yi1 - s2y) && (yi3 < ymax)) gPad->PaintLine(xi3,yi3,xi4,TMath::Min(yi1 - s2y,ymax));
6553 if ((yi1 + s2y < yi4) && (yi4 > ymin)) gPad->PaintLine(xi3,TMath::Max(yi1 + s2y, ymin),xi4,yi4);
6554 // don't duplicate the horizontal line
6555 if (Hoption.Hist != 2) {
6557 if (xi1 < xi3 - s2x) gPad->PaintLine(xi1,yi1,xi3 - s2x,yi2);
6558 if (xi3 + s2x < xi2) gPad->PaintLine(xi3 + s2x,yi1,xi2,yi2);
6559 }
6560 }
6561 }
6562 if (optionE && !drawmarker && (ey1 != 0 || ey2 !=0)) {
6563 if ((yi3 < yi1) && (yi3 < ymax)) gPad->PaintLine(xi3,yi3,xi4,TMath::Min(yi1,ymax));
6564 if ((yi1 < yi4) && (yi4 > ymin)) gPad->PaintLine(xi3,TMath::Max(yi1,ymin),xi4,yi4);
6565 // don't duplicate the horizontal line
6566 if (Hoption.Hist != 2) {
6568 if (xi1 < xi3) gPad->PaintLine(xi1,yi1,xi3,yi2);
6569 if (xi3 < xi2) gPad->PaintLine(xi3,yi1,xi2,yi2);
6570 }
6571 }
6572 }
6573
6574 // draw line at the end of the error bars
6575
6576 if (option1 && drawmarker) {
6577
6578 if (yi3 < yi1-s2y && yi3 < ymax && yi3 > ymin) gPad->PaintLine(xi3 - bxsize, yi3 , xi3 + bxsize, yi3);
6579 if (yi4 > yi1+s2y && yi4 < ymax && yi4 > ymin) gPad->PaintLine(xi3 - bxsize, yi4 , xi3 + bxsize, yi4);
6581 if (xi1 < xi3-s2x) gPad->PaintLine(xi1 , yi1 - bysize, xi1 , yi1 + bysize);
6582 if (xi2 > xi3+s2x) gPad->PaintLine(xi2 , yi1 - bysize, xi2 , yi1 + bysize);
6583 }
6584 }
6585
6586 // draw the marker
6587
6588 if (drawmarker) gPad->PaintPolyMarker(1, &xi3, &yi1);
6589
6590L30:
6591 if (fixbin) xp += Hparam.xbinsize;
6592 else {
6593 if (k < last) {
6594 delta = fH->GetBinWidth(k+1);
6595 xp = fH->GetBinLowEdge(k+1) + 0.5*delta;
6596 }
6597 }
6598 } //end of for loop
6599
6600 // draw the filled area
6601
6602 if (option3) {
6603 TGraph graph;
6604 graph.SetLineStyle(fH->GetLineStyle());
6605 graph.SetLineColor(fH->GetLineColor());
6606 graph.SetLineWidth(fH->GetLineWidth());
6607 graph.SetFillStyle(fH->GetFillStyle());
6608 graph.SetFillColor(fH->GetFillColor());
6609 Int_t logx = gPad->GetLogx();
6610 Int_t logy = gPad->GetLogy();
6611 gPad->SetLogx(0);
6612 gPad->SetLogy(0);
6613
6614 // In some cases the number of points in the fill area is smaller than
6615 // 2*npoints. In such cases the array xline and yline must be arranged
6616 // before being plotted. The next loop does that.
6617 if (if2 > npoints) {
6618 for (i=1; i<if1; i++) {
6619 xline[if1-2+i] = xline[if2-1+i];
6620 yline[if1-2+i] = yline[if2-1+i];
6621 }
6622 npoints = if1-1;
6623 }
6624 if (option4) graph.PaintGraph(2*npoints,xline.data(),yline.data(),"FC");
6625 else graph.PaintGraph(2*npoints,xline.data(),yline.data(),"F");
6626 gPad->SetLogx(logx);
6627 gPad->SetLogy(logy);
6628 }
6629}
6630
6631////////////////////////////////////////////////////////////////////////////////
6632/// Draw 2D histograms errors.
6633
6635{
6636
6637 fH->TAttMarker::Modify();
6638 fH->TAttLine::Modify();
6639
6640 // Define the 3D view
6641 fXbuf[0] = Hparam.xmin;
6642 fYbuf[0] = Hparam.xmax;
6643 fXbuf[1] = Hparam.ymin;
6644 fYbuf[1] = Hparam.ymax;
6645 fXbuf[2] = Hparam.zmin;
6646 fYbuf[2] = Hparam.zmax*(1. + gStyle->GetHistTopMargin());
6647 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
6648 TView *view = gPad ? gPad->GetView() : nullptr;
6649 if (!view) {
6650 Error("Paint2DErrors", "no TView in current pad");
6651 return;
6652 }
6653 Double_t thedeg = 90 - gPad->GetTheta();
6654 Double_t phideg = -90 - gPad->GetPhi();
6655 Double_t psideg = view->GetPsi();
6656 Int_t irep;
6657 view->SetView(phideg, thedeg, psideg, irep);
6658
6659 // Set color/style for back box
6660 fLego->SetFillStyle(gPad->GetFrameFillStyle());
6661 fLego->SetFillColor(gPad->GetFrameFillColor());
6662 fLego->TAttFill::Modify();
6663 Int_t backcolor = gPad->GetFrameFillColor();
6664 if (Hoption.System != kCARTESIAN) backcolor = 0;
6665 view->PadRange(backcolor);
6666 fLego->SetFillStyle(fH->GetFillStyle());
6667 fLego->SetFillColor(fH->GetFillColor());
6668 fLego->TAttFill::Modify();
6669
6670 // Paint the Back Box if needed
6671 if (Hoption.BackBox && !Hoption.Same && !Hoption.Lego && !Hoption.Surf) {
6672 fLego->InitMoveScreen(-1.1,1.1);
6673 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
6675 fLego->BackBox(90);
6676 }
6677
6678 // Paint the Errors
6679 Double_t x, ex, x1, x2;
6680 Double_t y, ey, y1, y2;
6681 Double_t z, ez1, ez2, z1, z2;
6682 Double_t temp1[3],temp2[3];
6684 if (Hoption.Error == 110) {
6685 xyerror = 0;
6686 } else {
6688 }
6689
6691 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
6692 y = fYaxis->GetBinCenter(j);
6694 y1 = y-ey;
6695 y2 = y+ey;
6696 if (Hoption.Logy) {
6697 if (y > 0) y = TMath::Log10(y);
6698 else continue;
6699 if (y1 > 0) y1 = TMath::Log10(y1);
6700 else y1 = Hparam.ymin;
6701 if (y2 > 0) y2 = TMath::Log10(y2);
6702 else y2 = Hparam.ymin;
6703 }
6706 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
6707 xk = fXaxis->GetBinLowEdge(i);
6708 xstep = fXaxis->GetBinWidth(i);
6709 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
6710 Int_t bin = fH->GetBin(i,j);
6711 x = fXaxis->GetBinCenter(i);
6713 x1 = x-ex;
6714 x2 = x+ex;
6715 if (Hoption.Logx) {
6716 if (x > 0) x = TMath::Log10(x);
6717 else continue;
6718 if (x1 > 0) x1 = TMath::Log10(x1);
6719 else x1 = Hparam.xmin;
6720 if (x2 > 0) x2 = TMath::Log10(x2);
6721 else x2 = Hparam.xmin;
6722 }
6723 z = fH->GetBinContent(bin);
6724 if (fH->GetBinErrorOption() == TH1::kNormal) {
6725 ez1 = fH->GetBinError(bin);
6726 ez2 = ez1;
6727 }
6728 else {
6729 ez1 = fH->GetBinErrorLow(bin);
6730 ez2 = fH->GetBinErrorUp(bin);
6731 }
6732 z1 = z - ez1;
6733 z2 = z + ez2;
6734 if (Hoption.Logz) {
6735 if (z > 0) z = TMath::Log10(z);
6736 else z = Hparam.zmin;
6737 if (z1 > 0) z1 = TMath::Log10(z1);
6738 else z1 = Hparam.zmin;
6739 if (z2 > 0) z2 = TMath::Log10(z2);
6740 else z2 = Hparam.zmin;
6741
6742 }
6743 if (z <= Hparam.zmin) continue;
6744 if (z > Hparam.zmax) z = Hparam.zmax;
6745
6746 temp1[0] = x1;
6747 temp1[1] = y;
6748 temp1[2] = z;
6749 temp2[0] = x2;
6750 temp2[1] = y;
6751 temp2[2] = z;
6752 gPad->PaintLine3D(temp1, temp2);
6753 temp1[0] = x;
6754 temp1[1] = y1;
6755 temp1[2] = z;
6756 temp2[0] = x;
6757 temp2[1] = y2;
6758 temp2[2] = z;
6759 gPad->PaintLine3D(temp1, temp2);
6760 temp1[0] = x;
6761 temp1[1] = y;
6762 temp1[2] = z1;
6763 temp2[0] = x;
6764 temp2[1] = y;
6765 temp2[2] = z2;
6766 gPad->PaintLine3D(temp1, temp2);
6767 temp1[0] = x;
6768 temp1[1] = y;
6769 temp1[2] = z;
6770 view->WCtoNDC(temp1, &temp2[0]);
6771 gPad->PaintPolyMarker(1, &temp2[0], &temp2[1]);
6772 }
6773 }
6774
6775 // Paint the Front Box if needed
6776 if (Hoption.FrontBox) {
6777 fLego->InitMoveScreen(-1.1,1.1);
6779 fLego->FrontBox(90);
6780 }
6781
6782 // Paint the Axis if needed
6783 if (!Hoption.Axis && !Hoption.Same && !Hoption.Lego && !Hoption.Surf) {
6784 TGaxis axis;
6785 PaintLegoAxis(&axis, 90);
6786 }
6787
6788 fLego.reset();
6789}
6790
6791////////////////////////////////////////////////////////////////////////////////
6792/// Calculate range and clear pad (canvas).
6793
6795{
6796
6797 if (Hoption.Same) return;
6798
6800
6801 if (Hoption.Lego || Hoption.Surf || Hoption.Tri ||
6802 Hoption.Contour == 14 || Hoption.Error >= 100) {
6803 TObject *frame = gPad->FindObject("TFrame");
6804 if (frame) gPad->Remove(frame);
6805 return;
6806 }
6807
6808 //The next statement is always executed on non-iOS platform,
6809 //on iOS depends on pad mode.
6810 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode())
6811 gPad->PaintPadFrame(Hparam.xmin,Hparam.ymin,Hparam.xmax,Hparam.ymax);
6812}
6813
6814////////////////////////////////////////////////////////////////////////////////
6815/// [Paint functions associated to an histogram.](\ref HP28")
6816
6818{
6819 auto lnk = fFunctions->FirstLink();
6820
6821 while (lnk) {
6822 auto obj = lnk->GetObject();
6824 if (obj->InheritsFrom(TF2::Class())) {
6825 if (!obj->TestBit(TF2::kNotDraw)) {
6826 if (Hoption.Lego || Hoption.Surf || Hoption.Error >= 100) {
6827 TF2 *f2 = (TF2*)obj;
6828 f2->SetMinimum(fH->GetMinimum());
6829 f2->SetMaximum(fH->GetMaximum());
6830 f2->SetRange(fH->GetXaxis()->GetXmin(), fH->GetYaxis()->GetXmin(), fH->GetXaxis()->GetXmax(), fH->GetYaxis()->GetXmax() );
6831 f2->Paint("surf same");
6832 } else {
6833 obj->Paint("cont3 same");
6834 }
6835 }
6836 } else if (obj->InheritsFrom(TF1::Class())) {
6837 if (!obj->TestBit(TF1::kNotDraw)) obj->Paint("lsame");
6838 } else {
6839 //Let's make this 'function' selectable on iOS device (for example, it can be TPaveStat).
6840 gPad->PushSelectableObject(obj);
6841
6842 //The next statement is ALWAYS executed on non-iOS platform, on iOS it depends on pad's mode
6843 //and picked object.
6844 if (!gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && obj == gPad->GetSelected()))
6845 obj->Paint(lnk->GetOption());
6846 }
6847 lnk = lnk->Next();
6848 }
6849}
6850
6851////////////////////////////////////////////////////////////////////////////////
6852/// [Control routine to draw 1D histograms](\ref HP01b)
6853
6855{
6856
6857 //On iOS: do not highlight hist, if part of it was selected.
6858 //Never executes on non-iOS platform.
6859 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
6860 return;
6861
6862 static char chopth[17];
6863
6865 Int_t i, j, first, last, nbins, fixbin;
6866 Double_t c1, yb;
6867 yb = 0;
6868
6869 strlcpy(chopth, " ",17);
6870
6873 Double_t baroffset = fH->GetBarOffset();
6874 Double_t barwidth = fH->GetBarWidth();
6877 gStyle->SetBarOffset(baroffset);
6878 gStyle->SetBarWidth(barwidth);
6879
6880 // Create "LIFE" structure to keep current histogram status
6881
6882 first = Hparam.xfirst;
6883 last = Hparam.xlast;
6884 nbins = last - first + 1;
6885
6886 std::vector<Double_t> keepx, keepy;
6887 if (fXaxis->GetXbins()->fN) fixbin = 0;
6888 else fixbin = 1;
6889 if (fixbin) keepx.resize(2);
6890 else keepx.resize(nbins+1);
6891 keepy.resize(nbins);
6892 Double_t logymin = 0;
6894
6895 // Loop on histogram bins
6896
6897 for (j=first; j<=last;j++) {
6899 if (TMath::Abs(ymax-ymin) > 0) {
6901 else yb = c1;
6902 }
6903 if (!Hoption.Line) {
6904 yb = TMath::Max(yb, ymin);
6905 yb = TMath::Min(yb, ymax);
6906 }
6907 keepy[j-first] = yb;
6908 }
6909
6910 // Draw histogram according to value of FillStyle and FillColor
6911
6912 if (fixbin) { keepx[0] = Hparam.xmin; keepx[1] = Hparam.xmax; }
6913 else {
6914 for (i=0; i<nbins; i++) keepx[i] = fXaxis->GetBinLowEdge(i+first);
6915 keepx[nbins] = fXaxis->GetBinUpEdge(nbins-1+first);
6916 }
6917
6918 // Prepare Fill area (systematic with option "Bar").
6919
6921 htype = oldhtype;
6922 if (Hoption.Bar) {
6923 if (htype == 0 || htype == 1000) htype = 1001;
6924 }
6925
6927
6928 // Code option for GrapHist
6929
6930 if (Hoption.Line) chopth[0] = 'L';
6931 if (Hoption.Star) chopth[1] = '*';
6932 if (Hoption.Mark) chopth[2] = 'P';
6933 if (Hoption.Mark == 10) chopth[3] = '0';
6935 if (Hoption.Curve) chopth[3] = 'C';
6936 if (Hoption.Hist > 0) chopth[4] = 'H';
6937 else if (Hoption.Bar) chopth[5] = 'B';
6938 if (Hoption.Logy) chopth[6] = '1';
6939 if (fH->GetFillColor() && htype) {
6940 if (Hoption.Hist > 0 || Hoption.Curve || Hoption.Line) {
6941 chopth[7] = 'F';
6942 }
6943 }
6944 }
6945 if (!fixbin && strlen(chopth)) {
6946 chopth[8] = 'N';
6947 }
6948
6949 if (Hoption.Fill == 2) chopth[13] = '2';
6950
6951 // Option LOGX
6952
6953 if (Hoption.Logx) {
6954 chopth[9] = 'G';
6955 chopth[10] = 'X';
6956 if (fixbin) {
6957 keepx[0] = TMath::Power(10,keepx[0]);
6958 keepx[1] = TMath::Power(10,keepx[1]);
6959 }
6960 }
6961
6962 if (Hoption.Off) {
6963 chopth[11] = ']';
6964 chopth[12] = '[';
6965 }
6966
6967 // Draw the histogram
6968
6969 TGraph graph;
6970 graph.SetLineWidth(lw);
6971 graph.SetLineStyle(fH->GetLineStyle());
6972 graph.SetLineColor(fH->GetLineColor());
6973 graph.SetFillStyle(htype);
6974 graph.SetFillColor(fH->GetFillColor());
6976 graph.SetMarkerSize(fH->GetMarkerSize());
6979
6980 graph.PaintGrapHist(nbins, keepx.data(), keepy.data() ,chopth);
6981
6984
6986}
6987
6988////////////////////////////////////////////////////////////////////////////////
6989/// [Control function to draw a 3D histograms.](\ref HP01d)
6990
6992{
6993
6994 TString cmd;
6995 TString opt = option;
6996 opt.ToLower();
6997 Int_t irep;
6998 Float_t NEntries = fH->GetEntries();
6999
7000 if (fCurrentF3 || strstr(opt,"tf3")) {
7001 PaintTF3();
7002 return;
7003 }
7004
7005 if (NEntries > 0) {
7006 if (Hoption.Box || Hoption.Lego || Hoption.Color) {
7007 if (Hoption.Box == 11 || Hoption.Lego == 11) {
7008 PaintH3Box(1);
7009 } else if (Hoption.Box == 12 || Hoption.Lego == 12 || Hoption.Color == 1) {
7010 PaintH3Box(2);
7011 } else if (Hoption.Box == 13 || Hoption.Lego == 13) {
7012 PaintH3Box(3);
7013 } else {
7015 }
7016 return;
7017 }
7018
7019 if (strstr(opt,"iso")) {
7020 PaintH3Iso();
7021 return;
7022 }
7023 }
7024
7025 TView *view = gPad ? gPad->GetView() : nullptr;
7026 if (!view) return;
7027
7028 if (strstr(opt,"fb")) Hoption.FrontBox = 0;
7029 if (strstr(opt,"bb")) Hoption.BackBox = 0;
7030
7031 Double_t thedeg = 90 - gPad->GetTheta();
7032 Double_t phideg = -90 - gPad->GetPhi();
7033 Double_t psideg = view->GetPsi();
7034 view->SetView(phideg, thedeg, psideg, irep);
7035
7036 if(NEntries > 0) { // Paint as 3D scatter plot
7037 cmd.Form("TPolyMarker3D::PaintH3((TH1 *)0x%zx,\"%s\");",(size_t)fH,option);
7038 gROOT->ProcessLine(cmd.Data());
7039 } else {
7040 TAxis* xAxis = fH->GetXaxis();
7041 TAxis* yAxis = fH->GetYaxis();
7042 TAxis* zAxis = fH->GetZaxis();
7043 Double_t xmin = xAxis->GetXmin();
7044 Double_t xmax = xAxis->GetXmax();
7045 Double_t ymin = yAxis->GetXmin();
7046 Double_t ymax = yAxis->GetXmax();
7047 Double_t zmin = zAxis->GetXmin();
7048 Double_t zmax = zAxis->GetXmax();
7049 view->SetRange(xmin, ymin, zmin, xmax, ymax, zmax); // Set the axis limits (Xmin, Ymin, Zmin, Xmax, Ymax, Zmax)
7050 }
7051
7052 if (Hoption.Same) return;
7053
7054 // Draw axis
7055 view->SetOutlineToCube();
7056 TSeqCollection *ol = view->GetOutline();
7057 if (ol && Hoption.BackBox && Hoption.FrontBox) ol->Paint(option);
7059
7060 if (!Hoption.Axis && !Hoption.Same) {
7061 TGaxis axis;
7062 PaintLegoAxis(&axis, 90);
7063 }
7064
7065 // Draw palette. In case of 4D plot with TTree::Draw() the palette should
7066 // be painted with the option colz.
7067 if (fH->GetDrawOption() && strstr(opt,"colz")) {
7068 Int_t ndiv = fH->GetContour();
7069 if (ndiv == 0 ) {
7070 ndiv = gStyle->GetNumberContours();
7071 fH->SetContour(ndiv);
7072 }
7073 PaintPalette();
7074 }
7075
7076 // Draw title
7077 PaintTitle();
7078
7079 //Draw stats and fit results
7080 TF1 *fit = nullptr;
7081 TIter next(fFunctions);
7082 while (auto obj = next()) {
7083 if (obj->InheritsFrom(TF1::Class())) {
7084 fit = (TF1*)obj;
7085 break;
7086 }
7087 }
7088 if ((Hoption.Same%10) != 1) {
7089 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7091 }
7092 }
7093
7094}
7095
7096////////////////////////////////////////////////////////////////////////////////
7097/// Compute histogram parameters used by the drawing routines.
7098
7100{
7101
7102 if (fH->GetDimension() > 1 || Hoption.Lego || Hoption.Surf) return 1;
7103
7104 Int_t i;
7105 static const char *where = "PaintInit";
7107 Int_t maximum = 0;
7108 Int_t minimum = 0;
7109 if (fH->GetMaximumStored() != -1111) maximum = 1;
7110 if (fH->GetMinimumStored() != -1111) minimum = 1;
7111
7112 // Compute X axis parameters
7113
7114 Int_t last = fXaxis->GetLast();
7115 Int_t first = fXaxis->GetFirst();
7118 Hparam.xlast = last;
7119 Hparam.xfirst = first;
7122
7123 // if log scale in X, replace xmin,max by the log
7124 if (Hoption.Logx) {
7125 if (Hparam.xmax<=0) {
7126 Error(where, "cannot set X axis to log scale");
7127 return 0;
7128 }
7129 if (Hparam.xlowedge <=0 ) {
7130 if (Hoption.Same) {
7131 TH1* h1 = nullptr;
7132 TObject *obj;
7133 TIter next(gPad->GetListOfPrimitives());
7134 while ((obj = (TObject *)next())) {
7135 if (obj->InheritsFrom(TH1::Class())) { h1 = (TH1*)(obj) ; break; }
7136 if (obj->InheritsFrom(THStack::Class())) { h1 = ((THStack*)(obj))->GetHistogram() ; break; }
7137 if (obj->InheritsFrom(TGraph::Class())) { h1 = ((TGraph*)(obj))->GetHistogram() ; break; }
7138 if (obj->InheritsFrom(TMultiGraph::Class())) { h1 = ((TMultiGraph*)(obj))->GetHistogram(); break; }
7139 if (obj->InheritsFrom(TGraph2D::Class())) { h1 = ((TGraph2D*)(obj))->GetHistogram(); break; }
7140 if (obj->InheritsFrom(TF1::Class())) { h1 = ((TF1*)(obj))->GetHistogram(); break; }
7141 }
7142 if (h1) {
7144 } else {
7145 Error(where, "undefined user's coordinates. Cannot use option SAME");
7146 return 0;
7147 }
7148 } else {
7149 for (i=first; i<=last; i++) {
7150 Double_t binLow = fXaxis->GetBinLowEdge(i);
7151 if (binLow>0) {
7152 Hparam.xlowedge = binLow;
7153 break;
7154 }
7155 if (binLow == 0 && fH->GetBinContent(i) !=0) {
7156 Hparam.xlowedge = fXaxis->GetBinUpEdge(i)*0.001;
7157 break;
7158 }
7159 }
7160 if (Hparam.xlowedge<=0) {
7161 Error(where, "cannot set X axis to log scale");
7162 return 0;
7163 }
7164 }
7166 }
7171 if (Hparam.xlast > last) Hparam.xlast = last;
7172 if (Hparam.xfirst < first) Hparam.xfirst = first;
7173 }
7174
7175 // Compute Y axis parameters
7176 Double_t bigp = TMath::Power(10,32);
7177 Double_t ymax = -bigp;
7178 Double_t ymin = bigp;
7179 Double_t c1, e1;
7180 Double_t xv[1];
7181 Double_t fval;
7182 TObject *f;
7183 TF1 *f1;
7184 Double_t allchan = 0;
7185 Int_t nonNullErrors = 0;
7186 TIter next(fFunctions);
7187 for (i=first; i<=last;i++) {
7188 c1 = fH->GetBinContent(i);
7190 if (Hoption.Logy) {
7191 if (c1 > 0) ymin = TMath::Min(ymin,c1);
7192 } else {
7194 }
7195 if (Hoption.Error) {
7197 e1 = fH->GetBinError(i);
7198 else
7199 e1 = fH->GetBinErrorUp(i);
7200 if (e1 > 0) nonNullErrors++;
7203 e1 = fH->GetBinErrorLow(i);
7204
7205 if (Hoption.Logy) {
7206 if (c1-e1>0.01*TMath::Abs(c1)) ymin = TMath::Min(ymin,c1-e1);
7207 } else {
7209 }
7210 }
7211 if (Hoption.Func) {
7212 xv[0] = fXaxis->GetBinCenter(i);
7213 while ((f = (TObject*) next())) {
7214 if (f->IsA() == TF1::Class()) {
7215 f1 = (TF1*)f;
7216 if (xv[0] < f1->GetXmin() || xv[0] > f1->GetXmax()) continue;
7217 fval = f1->Eval(xv[0],0,0);
7218 if (f1->GetMaximumStored() != -1111) fval = TMath::Min(f1->GetMaximumStored(), fval);
7220 if (Hoption.Logy) {
7221 if (c1 > 0 && fval > 0.3*c1) ymin = TMath::Min(ymin,fval);
7222 }
7223 }
7224 }
7225 next.Reset();
7226 }
7227 allchan += c1;
7228 }
7229 if (!nonNullErrors) {
7230 if (Hoption.Error) {
7231 if (!Hoption.Mark && !Hoption.Line && !Hoption.Star && !Hoption.Curve) Hoption.Hist = 2;
7232 Hoption.Error=0;
7233 }
7234 }
7235
7236
7237 // Take into account maximum , minimum
7238
7239 if (Hoption.Logy && ymin <= 0) {
7240 if (ymax >= 1) ymin = TMath::Max(.005,ymax*1e-10);
7241 else ymin = 0.001*ymax;
7242 }
7243
7244 Double_t xm = ymin;
7245 if (maximum) ymax = fH->GetMaximumStored();
7246 if (minimum) xm = fH->GetMinimumStored();
7247 if (Hoption.Logy && xm < 0) {
7248 Error(where, "log scale requested with a negative argument (%f)", xm);
7249 return 0;
7250 } else if (Hoption.Logy && xm>=0 && ymax==0) { // empty histogram in log scale
7251 ymin = 0.01;
7252 ymax = 10.;
7253 } else {
7254 ymin = xm;
7255 }
7256
7257 if (ymin >= ymax) {
7258 if (Hoption.Logy) {
7259 if (ymax > 0) ymin = 0.001*ymax;
7260 else {
7261 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", ymax);
7262 return 0;
7263 }
7264 }
7265 else {
7266 if (ymin > 0) {
7267 ymin = 0;
7268 ymax *= 2;
7269 } else if (ymin < 0) {
7270 ymax = 0;
7271 ymin *= 2;
7272 } else {
7273 ymin = 0;
7274 ymax = 1;
7275 }
7276 }
7277 }
7278
7279 // In some cases, mainly because of precision issues, ymin and ymax could almost equal.
7280 if (TMath::AreEqualRel(ymin,ymax,1E-15)) {
7281 ymin = ymin*(1-1E-14);
7282 ymax = ymax*(1+1E-14);
7283 }
7284
7285 // take into account normalization factor
7286 Hparam.allchan = allchan;
7287 Double_t factor = allchan;
7288 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
7289 if (allchan) factor /= allchan;
7290 if (factor == 0) factor = 1;
7291 Hparam.factor = factor;
7292 ymax = factor*ymax;
7293 ymin = factor*ymin;
7294 //just in case the norm factor is negative
7295 // this may happen with a positive norm factor and a negative integral !
7296 if (ymax < ymin) {
7297 Double_t temp = ymax;
7298 ymax = ymin;
7299 ymin = temp;
7300 }
7301
7302 // For log scales, histogram coordinates are LOG10(ymin) and
7303 // LOG10(ymax). Final adjustment (if not option "Same"
7304 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
7305 // Maximum and Minimum are not defined.
7306 if (Hoption.Logy) {
7307 if (ymin <=0 || ymax <=0) {
7308 Error(where, "Cannot set Y axis to log scale");
7309 return 0;
7310 }
7312 if (!minimum) ymin += TMath::Log10(0.5);
7314 if (!maximum) ymax += TMath::Log10(2*(0.9/0.95));
7315 if (!Hoption.Same) {
7316 Hparam.ymin = ymin;
7317 Hparam.ymax = ymax;
7318 }
7319 return 1;
7320 }
7321
7322 // final adjustment of ymin for linear scale.
7323 // if minimum is not set , then ymin is set to zero if >0
7324 // or to ymin - margin if <0.
7325 if (!minimum) {
7326 if (Hoption.MinimumZero) {
7327 if (ymin >= 0) ymin = 0;
7328 else ymin -= yMARGIN*(ymax-ymin);
7329 } else {
7331 if (ymin >= 0 && (ymin-dymin <= 0)) ymin = 0;
7332 else ymin -= dymin;
7333 }
7334 }
7335
7336 // final adjustment of YMAXI for linear scale (if not option "Same"):
7337 // decrease histogram height to MAX% of allowed height if HMAXIM
7338 // has not been called.
7339 if (!maximum) {
7340 ymax += yMARGIN*(ymax-ymin);
7341 }
7342
7343 Hparam.ymin = ymin;
7344 Hparam.ymax = ymax;
7345 return 1;
7346}
7347
7348////////////////////////////////////////////////////////////////////////////////
7349/// Compute histogram parameters used by the drawing routines for a rotated pad.
7350
7352{
7353
7354 static const char *where = "PaintInitH";
7356 Int_t maximum = 0;
7357 Int_t minimum = 0;
7358 if (fH->GetMaximumStored() != -1111) maximum = 1;
7359 if (fH->GetMinimumStored() != -1111) minimum = 1;
7360
7361 // Compute X axis parameters
7362
7363 Int_t last = fXaxis->GetLast();
7364 Int_t first = fXaxis->GetFirst();
7367 Hparam.xlast = last;
7368 Hparam.xfirst = first;
7371
7372 // if log scale in Y, replace ymin,max by the log
7373 if (Hoption.Logy) {
7374 if (Hparam.xlowedge <=0 ) {
7377 }
7378 if (Hparam.ymin <=0 || Hparam.ymax <=0) {
7379 Error(where, "cannot set Y axis to log scale");
7380 return 0;
7381 }
7386 if (Hparam.xlast > last) Hparam.xlast = last;
7387 }
7388
7389 // Compute Y axis parameters
7390 Double_t bigp = TMath::Power(10,32);
7391 Double_t xmax = -bigp;
7392 Double_t xmin = bigp;
7393 Double_t c1, e1;
7394 Double_t xv[1];
7395 Double_t fval;
7396 Int_t i;
7397 TObject *f;
7398 TF1 *f1;
7399 Double_t allchan = 0;
7400 TIter next(fFunctions);
7401 for (i=first; i<=last;i++) {
7402 c1 = fH->GetBinContent(i);
7405 if (Hoption.Error) {
7406 e1 = fH->GetBinError(i);
7409 }
7410 if (Hoption.Func) {
7411 xv[0] = fXaxis->GetBinCenter(i);
7412 while ((f = (TObject*) next())) {
7413 if (f->IsA() == TF1::Class()) {
7414 f1 = (TF1*)f;
7415 if (xv[0] < f1->GetXmin() || xv[0] > f1->GetXmax()) continue;
7416 fval = f1->Eval(xv[0],0,0);
7418 if (Hoption.Logy) {
7419 if (fval > 0.3*c1) xmin = TMath::Min(xmin,fval);
7420 }
7421 }
7422 }
7423 next.Reset();
7424 }
7425 allchan += c1;
7426 }
7427
7428 // Take into account maximum , minimum
7429
7430 if (Hoption.Logx && xmin <= 0) {
7431 if (xmax >= 1) xmin = TMath::Max(.5,xmax*1e-10);
7432 else xmin = 0.001*xmax;
7433 }
7434 Double_t xm = xmin;
7435 if (maximum) xmax = fH->GetMaximumStored();
7436 if (minimum) xm = fH->GetMinimumStored();
7437 if (Hoption.Logx && xm <= 0) {
7438 Error(where, "log scale requested with zero or negative argument (%f)", xm);
7439 return 0;
7440 }
7441 else xmin = xm;
7442 if (xmin >= xmax) {
7443 if (Hoption.Logx) {
7444 if (xmax > 0) xmin = 0.001*xmax;
7445 else {
7446 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", xmax);
7447 return 0;
7448 }
7449 }
7450 else {
7451 if (xmin > 0) {
7452 xmin = 0;
7453 xmax *= 2;
7454 } else if (xmin < 0) {
7455 xmax = 0;
7456 xmin *= 2;
7457 } else {
7458 xmin = 0;
7459 xmax = 1;
7460 }
7461 }
7462 }
7463
7464 // take into account normalization factor
7465 Hparam.allchan = allchan;
7466 Double_t factor = allchan;
7467 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
7468 if (allchan) factor /= allchan;
7469 if (factor == 0) factor = 1;
7470 Hparam.factor = factor;
7471 xmax = factor*xmax;
7472 xmin = factor*xmin;
7473
7474 // For log scales, histogram coordinates are LOG10(ymin) and
7475 // LOG10(ymax). Final adjustment (if not option "Same"
7476 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
7477 // Maximum and Minimum are not defined.
7478 if (Hoption.Logx) {
7479 if (xmin <=0 || xmax <=0) {
7480 Error(where, "Cannot set Y axis to log scale");
7481 return 0;
7482 }
7484 if (!minimum) xmin += TMath::Log10(0.5);
7486 if (!maximum) xmax += TMath::Log10(2*(0.9/0.95));
7487 if (!Hoption.Same) {
7488 Hparam.xmin = xmin;
7489 Hparam.xmax = xmax;
7490 }
7491 return 1;
7492 }
7493
7494 // final adjustment of ymin for linear scale.
7495 // if minimum is not set , then ymin is set to zero if >0
7496 // or to ymin - margin if <0.
7497 if (!minimum) {
7498 if (xmin >= 0) xmin = 0;
7499 else xmin -= yMARGIN*(xmax-xmin);
7500 }
7501
7502 // final adjustment of YMAXI for linear scale (if not option "Same"):
7503 // decrease histogram height to MAX% of allowed height if HMAXIM
7504 // has not been called.
7505 if (!maximum) {
7506 xmax += yMARGIN*(xmax-xmin);
7507 }
7508 Hparam.xmin = xmin;
7509 Hparam.xmax = xmax;
7510 return 1;
7511}
7512
7513////////////////////////////////////////////////////////////////////////////////
7514/// [Control function to draw a 3D histogram with boxes.](\ref HP25)
7515
7517{
7518 // Predefined box structure
7519 Double_t wxyz[8][3] = { {-1,-1,-1}, {1,-1,-1}, {1,1,-1}, {-1,1,-1},
7520 {-1,-1, 1}, {1,-1, 1}, {1,1, 1}, {-1,1, 1} };
7521 Int_t iface[6][4] = { {0,3,2,1}, {4,5,6,7},
7522 {0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7} };
7523
7524 // Define dimensions of world space
7525 TAxis *xaxis = fH->GetXaxis();
7526 TAxis *yaxis = fH->GetYaxis();
7527 TAxis *zaxis = fH->GetZaxis();
7528
7529 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7530 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7531 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7532 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7533 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7534 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7535
7536 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7537
7538 // Set view
7539 TView *view = gPad ? gPad->GetView() : nullptr;
7540 if (!view) {
7541 Error("PaintH3", "no TView in current pad");
7542 return;
7543 }
7544 Double_t thedeg = 90 - gPad->GetTheta();
7545 Double_t phideg = -90 - gPad->GetPhi();
7546 Double_t psideg = view->GetPsi();
7547 Int_t irep;
7548 view->SetView(phideg, thedeg, psideg, irep);
7549
7550 Int_t backcolor = gPad->GetFrameFillColor();
7551 view->PadRange(backcolor);
7552
7553 // Draw back surfaces of frame box
7554 fLego->InitMoveScreen(-1.1,1.1);
7555 if (Hoption.BackBox) {
7556 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
7558 fLego->BackBox(90);
7559 }
7560
7562
7563 // Define order of drawing
7564 Double_t *tnorm = view->GetTnorm();
7565 if (!tnorm) return;
7566 Int_t incrx = (tnorm[ 8] < 0.) ? -1 : +1;
7567 Int_t incry = (tnorm[ 9] < 0.) ? -1 : +1;
7568 Int_t incrz = (tnorm[10] < 0.) ? -1 : +1;
7569 Int_t ix1 = (incrx == +1) ? xaxis->GetFirst() : xaxis->GetLast();
7570 Int_t iy1 = (incry == +1) ? yaxis->GetFirst() : yaxis->GetLast();
7571 Int_t iz1 = (incrz == +1) ? zaxis->GetFirst() : zaxis->GetLast();
7572 Int_t ix2 = (incrx == +1) ? xaxis->GetLast() : xaxis->GetFirst();
7573 Int_t iy2 = (incry == +1) ? yaxis->GetLast() : yaxis->GetFirst();
7574 Int_t iz2 = (incrz == +1) ? zaxis->GetLast() : zaxis->GetFirst();
7575
7576 // Set graphic attributes (colour, style, etc.)
7581
7582 fH->SetFillStyle(1001);
7583 fH->TAttFill::Modify();
7584 fH->TAttLine::Modify();
7585 Int_t ncolors = gStyle->GetNumberOfColors();
7587
7588 // Create bin boxes and draw
7592
7593 Double_t pmin[3], pmax[3], sxyz[8][3];
7594 for (Int_t ix = ix1; ix !=ix2+incrx; ix += incrx) {
7595 pmin[0] = xaxis->GetBinLowEdge(ix);
7596 pmax[0] = xaxis->GetBinUpEdge(ix);
7597 for (Int_t iy = iy1; iy != iy2+incry; iy += incry) {
7598 pmin[1] = yaxis->GetBinLowEdge(iy);
7599 pmax[1] = yaxis->GetBinUpEdge(iy);
7600 for (Int_t iz = iz1; iz != iz2+incrz; iz += incrz) {
7601 pmin[2] = zaxis->GetBinLowEdge(iz);
7602 pmax[2] = zaxis->GetBinUpEdge(iz);
7603 Double_t w = fH->GetBinContent(fH->GetBin(ix,iy,iz));
7604 Bool_t neg = kFALSE;
7605 Int_t n = 5;
7606 if (w<0) {
7607 w = -w;
7608 neg = kTRUE;
7609 }
7610 if (w < wmin) continue;
7611 if (w > wmax) w = wmax;
7612 Double_t scale = (TMath::Power((w-wmin)/(wmax-wmin),1./3.))/2.;
7613 if (scale == 0) continue;
7614 for (Int_t i=0; i<3; ++i) {
7615 Double_t c = (pmax[i] + pmin[i])*0.5;
7616 Double_t d = (pmax[i] - pmin[i])*scale;
7617 for (Int_t k=0; k<8; ++k) { // set bin box vertices
7618 sxyz[k][i] = wxyz[k][i]*d + c;
7619 }
7620 }
7621 for (Int_t k=0; k<8; ++k) { // transform to normalized space
7622 view->WCtoNDC(&sxyz[k][0],&sxyz[k][0]);
7623 }
7624 Double_t x[8], y[8]; // draw bin box faces
7625 for (Int_t k=0; k<6; ++k) {
7626 for (Int_t i=0; i<4; ++i) {
7627 Int_t iv = iface[k][i];
7628 x[i] = sxyz[iv][0];
7629 y[i] = sxyz[iv][1];
7630 }
7631 x[4] = x[0] ; y[4] = y[0];
7632 if (neg) {
7633 x[5] = x[2] ; y[5] = y[2];
7634 x[6] = x[3] ; y[6] = y[3];
7635 x[7] = x[1] ; y[7] = y[1];
7636 n = 8;
7637 } else {
7638 n = 5;
7639 }
7640 Double_t z = (x[2]-x[0])*(y[3]-y[1]) - (y[2]-y[0])*(x[3]-x[1]);
7641 if (z <= 0.) continue;
7642 if (iopt == 2) {
7643 theColor = ncolors*((w-wmin)/(wmax-wmin)) -1;
7645 } else {
7646 if (k == 3 || k == 5) {
7648 } else if (k == 0 || k == 1) {
7650 } else {
7652 }
7653 }
7654 fH->TAttFill::Modify();
7655 gPad->PaintFillArea(4, x, y);
7656 if (iopt != 3)gPad->PaintPolyLine(n, x, y);
7657 }
7658 }
7659 }
7660 }
7661
7662 // Draw front surfaces of frame box
7663 if (Hoption.FrontBox) fLego->FrontBox(90);
7664
7665 // Draw axis and title
7666 if (!Hoption.Axis && !Hoption.Same) {
7667 TGaxis axis;
7668 PaintLegoAxis(&axis, 90);
7669 }
7670 PaintTitle();
7671
7672 // Draw palette. if needed.
7673 if (Hoption.Zscale) {
7674 Int_t ndiv = fH->GetContour();
7675 if (ndiv == 0 ) {
7676 ndiv = gStyle->GetNumberContours();
7677 fH->SetContour(ndiv);
7678 }
7679 PaintPalette();
7680 }
7681
7682 //Draw stats and fit results
7683 TF1 *fit = nullptr;
7684 TIter next(fFunctions);
7685 while (auto obj = next()) {
7686 if (obj->InheritsFrom(TF1::Class())) {
7687 fit = (TF1*)obj;
7688 break;
7689 }
7690 }
7691 if ((Hoption.Same%10) != 1) {
7692 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7694 }
7695 }
7696
7697 fLego.reset();
7698
7701 fH->TAttFill::Modify();
7702}
7703
7704////////////////////////////////////////////////////////////////////////////////
7705/// [Control function to draw a 3D histogram with boxes.](\ref HP25)
7706
7708{
7709 // Predefined box structure
7710 Double_t wxyz[8][3] = {
7711 {-1,-1,-1}, {1,-1,-1}, {1,1,-1}, {-1,1,-1}, // bottom vertices
7712 {-1,-1, 1}, {1,-1, 1}, {1,1, 1}, {-1,1, 1} // top vertices
7713 };
7714 Int_t iface[6][4] = {
7715 {0,3,2,1}, {4,5,6,7}, // bottom and top faces
7716 {0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7} // side faces
7717 };
7718 Double_t normal[6][3] = {
7719 {0,0,-1}, {0,0,1}, // Z-, Z+
7720 {0,-1,0}, {1,0,0}, {0,1,0}, {-1,0,0} // Y-, X+, Y+, X-
7721 };
7722
7723 // Define dimensions of world space
7724 TAxis *xaxis = fH->GetXaxis();
7725 TAxis *yaxis = fH->GetYaxis();
7726 TAxis *zaxis = fH->GetZaxis();
7727
7728 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7729 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7730 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7731 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7732 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7733 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7734
7735 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7736
7737 // Set view
7738 TView *view = gPad ? gPad->GetView() : nullptr;
7739 if (!view) {
7740 Error("PaintH3", "no TView in current pad");
7741 return;
7742 }
7743 Double_t thedeg = 90 - gPad->GetTheta();
7744 Double_t phideg = -90 - gPad->GetPhi();
7745 Double_t psideg = view->GetPsi();
7746 Int_t irep;
7747 view->SetView(phideg, thedeg, psideg, irep);
7748
7749 Int_t backcolor = gPad->GetFrameFillColor();
7750 view->PadRange(backcolor);
7751
7752 // Draw front surfaces of frame box
7753 if (Hoption.FrontBox) {
7754 fLego->InitMoveScreen(-1.1,1.1);
7756 }
7757
7758 // Initialize hidden line removal algorithm "raster screen"
7759 fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
7760
7761 // Define order of drawing
7762 Double_t *tnorm = view->GetTnorm();
7763 if (!tnorm) return;
7764 Int_t incrx = (tnorm[ 8] < 0.) ? +1 : -1;
7765 Int_t incry = (tnorm[ 9] < 0.) ? +1 : -1;
7766 Int_t incrz = (tnorm[10] < 0.) ? +1 : -1;
7767 Int_t ix1 = (incrx == +1) ? xaxis->GetFirst() : xaxis->GetLast();
7768 Int_t iy1 = (incry == +1) ? yaxis->GetFirst() : yaxis->GetLast();
7769 Int_t iz1 = (incrz == +1) ? zaxis->GetFirst() : zaxis->GetLast();
7770 Int_t ix2 = (incrx == +1) ? xaxis->GetLast() : xaxis->GetFirst();
7771 Int_t iy2 = (incry == +1) ? yaxis->GetLast() : yaxis->GetFirst();
7772 Int_t iz2 = (incrz == +1) ? zaxis->GetLast() : zaxis->GetFirst();
7773
7774 // Set line attributes (colour, style, etc.)
7775 fH->TAttLine::Modify();
7776
7777 // Create bin boxes and draw
7778 const Int_t NTMAX = 100;
7779 Double_t tt[NTMAX][2];
7783 Double_t pmin[3], pmax[3], sxyz[8][3], pp[4][2];
7784 for (Int_t ix = ix1; ix !=ix2+incrx; ix += incrx) {
7785 pmin[0] = xaxis->GetBinLowEdge(ix);
7786 pmax[0] = xaxis->GetBinUpEdge(ix);
7787 for (Int_t iy = iy1; iy != iy2+incry; iy += incry) {
7788 pmin[1] = yaxis->GetBinLowEdge(iy);
7789 pmax[1] = yaxis->GetBinUpEdge(iy);
7790 for (Int_t iz = iz1; iz != iz2+incrz; iz += incrz) {
7791 pmin[2] = zaxis->GetBinLowEdge(iz);
7792 pmax[2] = zaxis->GetBinUpEdge(iz);
7793 Double_t w = fH->GetBinContent(fH->GetBin(ix,iy,iz));
7794 Bool_t neg = kFALSE;
7795 if (w<0) {
7796 w = -w;
7797 neg = kTRUE;
7798 }
7799 if (w < wmin) continue;
7800 if (w > wmax) w = wmax;
7801 Double_t scale = (TMath::Power((w-wmin)/(wmax-wmin),1./3.))/2.;
7802 if (scale == 0) continue;
7803 for (Int_t i=0; i<3; ++i) {
7804 Double_t c = (pmax[i] + pmin[i])*0.5;
7805 Double_t d = (pmax[i] - pmin[i])*scale;
7806 for (Int_t k=0; k<8; ++k) { // set bin box vertices
7807 sxyz[k][i] = wxyz[k][i]*d + c;
7808 }
7809 }
7810 for (Int_t k=0; k<8; ++k) { // transform to normalized space
7811 view->WCtoNDC(&sxyz[k][0],&sxyz[k][0]);
7812 }
7813 for (Int_t k=0; k<6; ++k) { // draw box faces
7814 Double_t zn;
7815 view->FindNormal(normal[k][0], normal[k][1], normal[k][2], zn);
7816 if (zn <= 0) continue;
7817 for (Int_t i=0; i<4; ++i) {
7818 Int_t ip = iface[k][i];
7819 pp[i][0] = sxyz[ip][0];
7820 pp[i][1] = sxyz[ip][1];
7821 }
7822 for (Int_t i=0; i<4; ++i) {
7823 Int_t i1 = i;
7824 Int_t i2 = (i == 3) ? 0 : i + 1;
7825 Int_t nt;
7826 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7827 Double_t xdel = pp[i2][0] - pp[i1][0];
7828 Double_t ydel = pp[i2][1] - pp[i1][1];
7829 Double_t x[2], y[2];
7830 for (Int_t it = 0; it < nt; ++it) {
7831 x[0] = pp[i1][0] + xdel*tt[it][0];
7832 y[0] = pp[i1][1] + ydel*tt[it][0];
7833 x[1] = pp[i1][0] + xdel*tt[it][1];
7834 y[1] = pp[i1][1] + ydel*tt[it][1];
7835 gPad->PaintPolyLine(2, x, y);
7836 }
7837 }
7838 if (neg) {
7839 Int_t i1 = 0;
7840 Int_t i2 = 2;
7841 Int_t nt;
7842 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7843 Double_t xdel = pp[i2][0] - pp[i1][0];
7844 Double_t ydel = pp[i2][1] - pp[i1][1];
7845 Double_t x[2], y[2];
7846 for (Int_t it = 0; it < nt; ++it) {
7847 x[0] = pp[i1][0] + xdel*tt[it][0];
7848 y[0] = pp[i1][1] + ydel*tt[it][0];
7849 x[1] = pp[i1][0] + xdel*tt[it][1];
7850 y[1] = pp[i1][1] + ydel*tt[it][1];
7851 gPad->PaintPolyLine(2, x, y);
7852 }
7853 i1 = 1;
7854 i2 = 3;
7855 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7856 xdel = pp[i2][0] - pp[i1][0];
7857 ydel = pp[i2][1] - pp[i1][1];
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 }
7866 fLego->FillPolygonBorder(4, &pp[0][0]); // update raster screen
7867 }
7868 }
7869 }
7870 }
7871
7872 // Draw frame box
7873 if (Hoption.BackBox) {
7874 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
7876 fLego->BackBox(90);
7877 }
7878
7879 if (Hoption.FrontBox) fLego->FrontBox(90);
7880
7881 // Draw axis and title
7882 if (!Hoption.Axis && !Hoption.Same) {
7883 TGaxis axis;
7884 PaintLegoAxis(&axis, 90);
7885 }
7886 PaintTitle();
7887
7888 //Draw stats and fit results
7889 TF1 *fit = nullptr;
7890 TIter next(fFunctions);
7891 while (auto obj = next()) {
7892 if (obj->InheritsFrom(TF1::Class())) {
7893 fit = (TF1*)obj;
7894 break;
7895 }
7896 }
7897 if ((Hoption.Same%10) != 1) {
7898 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7900 }
7901 }
7902
7903 fLego.reset();
7904}
7905
7906////////////////////////////////////////////////////////////////////////////////
7907/// [Control function to draw a 3D histogram with Iso Surfaces.](\ref HP25)
7908
7910{
7911
7912 const Double_t ydiff = 1;
7913 const Double_t yligh1 = 10;
7914 const Double_t qa = 0.15;
7915 const Double_t qd = 0.15;
7916 const Double_t qs = 0.8;
7918 Int_t i, irep;
7919 Int_t nbcol = 28;
7920 Int_t icol1 = 201;
7921 Int_t ic1 = icol1;
7922 Int_t ic2 = ic1+nbcol;
7923 Int_t ic3 = ic2+nbcol;
7924
7925 TAxis *xaxis = fH->GetXaxis();
7926 TAxis *yaxis = fH->GetYaxis();
7927 TAxis *zaxis = fH->GetZaxis();
7928
7929 Int_t nx = fH->GetNbinsX();
7930 Int_t ny = fH->GetNbinsY();
7931 Int_t nz = fH->GetNbinsZ();
7932
7933 std::vector<Double_t> x(nx);
7934 std::vector<Double_t> y(ny);
7935 std::vector<Double_t> z(nz);
7936
7937 for (i=0; i<nx; i++) x[i] = xaxis->GetBinCenter(i+1);
7938 for (i=0; i<ny; i++) y[i] = yaxis->GetBinCenter(i+1);
7939 for (i=0; i<nz; i++) z[i] = zaxis->GetBinCenter(i+1);
7940
7941 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7942 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7943 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7944 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7945 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7946 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7947
7948 Double_t s[3];
7949 s[0] = fH->GetSumOfWeights()/(fH->GetNbinsX()*fH->GetNbinsY()*fH->GetNbinsZ());
7950 s[1] = 0.5*s[0];
7951 s[2] = 1.5*s[0];
7952
7953 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7954
7955 TView *view = gPad ? gPad->GetView() : nullptr;
7956 if (!view) {
7957 Error("PaintH3Iso", "no TView in current pad");
7958 return;
7959 }
7960 Double_t thedeg = 90 - gPad->GetTheta();
7961 Double_t phideg = -90 - gPad->GetPhi();
7962 Double_t psideg = view->GetPsi();
7963 view->SetView(phideg, thedeg, psideg, irep);
7964
7965 Int_t backcolor = gPad->GetFrameFillColor();
7966 if (Hoption.System != kCARTESIAN) backcolor = 0;
7967 view->PadRange(backcolor);
7968
7969 Double_t dcol = 0.5/Double_t(nbcol);
7970 TColor *colref = gROOT->GetColor(fH->GetFillColor());
7971 if (!colref) {
7972 return;
7973 }
7974 Float_t r, g, b, hue, light, satur;
7975 colref->GetRGB(r,g,b);
7977 TColor *acol;
7978 for (Int_t col=0;col<nbcol;col++) {
7979 acol = gROOT->GetColor(col+icol1);
7980 TColor::HLStoRGB(hue, .4+col*dcol, satur, r, g, b);
7981 if (acol) acol->SetRGB(r, g, b);
7982 }
7983
7984 fLego->InitMoveScreen(-1.1,1.1);
7985
7986 if (Hoption.BackBox) {
7987 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
7989 fLego->BackBox(90);
7990 }
7991
7992 fLego->LightSource(0, ydiff, 0, 0, 0, irep);
7993 fLego->LightSource(1, yligh1, 1, 1, 1, irep);
7994 fLego->SurfaceProperty(qa, qd, qs, 1, irep);
7995 fmin = ydiff*qa;
7996 fmax = ydiff*qa + (yligh1+0.1)*(qd+qs);
7997 fLego->SetIsoSurfaceParameters(fmin, fmax, nbcol, ic1, ic2, ic3);
7998
7999 fLego->IsoSurface(1, s, nx, ny, nz, x.data(), y.data(), z.data(), "BF");
8000
8001 if (Hoption.FrontBox) {
8002 fLego->InitMoveScreen(-1.1,1.1);
8004 fLego->FrontBox(90);
8005 }
8006 if (!Hoption.Axis && !Hoption.Same) {
8007 TGaxis axis;
8008 PaintLegoAxis(&axis, 90);
8009 }
8010
8011 PaintTitle();
8012
8013 //Draw stats and fit results
8014 TF1 *fit = nullptr;
8015 TIter next(fFunctions);
8016 while (auto obj = next()) {
8017 if (obj->InheritsFrom(TF1::Class())) {
8018 fit = (TF1*)obj;
8019 break;
8020 }
8021 }
8022 if ((Hoption.Same%10) != 1) {
8023 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
8025 }
8026 }
8027
8028 fLego.reset();
8029}
8030
8031////////////////////////////////////////////////////////////////////////////////
8032/// [Control function to draw a 2D histogram as a lego plot.](\ref HP17)
8033
8035{
8036
8037 Int_t raster = 1;
8038 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
8039 Int_t nx = Hparam.xlast - Hparam.xfirst + 1;
8040 Int_t ny = Hparam.ylast - Hparam.yfirst + 1;
8041 Double_t zmin = Hparam.zmin;
8042 Double_t zmax = Hparam.zmax;
8047 Double_t dangle = 10*3.141592/180; //Delta angle for Rapidity option
8048 Double_t deltaz = TMath::Abs(zmin);
8049 if (deltaz == 0) deltaz = 1;
8050 if (zmin >= zmax) {
8051 zmin -= 0.5*deltaz;
8052 zmax += 0.5*deltaz;
8053 }
8054 Double_t z1c = zmin;
8055 Double_t z2c = zmin + (zmax-zmin)*(1+gStyle->GetHistTopMargin());
8056
8057 // Compute the lego limits and instantiate a lego object
8058 fXbuf[0] = -1;
8059 fYbuf[0] = 1;
8060 fXbuf[1] = -1;
8061 fYbuf[1] = 1;
8062 if (Hoption.System == kPOLAR) {
8063 fXbuf[2] = z1c;
8064 fYbuf[2] = z2c;
8065 } else if (Hoption.System == kCYLINDRICAL) {
8066 if (Hoption.Logy) {
8067 if (ylab1 > 0) fXbuf[2] = TMath::Log10(ylab1);
8068 else fXbuf[2] = 0;
8069 if (ylab2 > 0) fYbuf[2] = TMath::Log10(ylab2);
8070 else fYbuf[2] = 0;
8071 } else {
8072 fXbuf[2] = ylab1;
8073 fYbuf[2] = ylab2;
8074 }
8075 z1c = 0; z2c = 1;
8076 } else if (Hoption.System == kSPHERICAL) {
8077 fXbuf[2] = -1;
8078 fYbuf[2] = 1;
8079 z1c = 0; z2c = 1;
8080 } else if (Hoption.System == kRAPIDITY) {
8081 fXbuf[2] = -1/TMath::Tan(dangle);
8082 fYbuf[2] = 1/TMath::Tan(dangle);
8083 } else {
8084 fXbuf[0] = xlab1;
8085 fYbuf[0] = xlab2;
8086 fXbuf[1] = ylab1;
8087 fYbuf[1] = ylab2;
8088 fXbuf[2] = z1c;
8089 fYbuf[2] = z2c;
8090 raster = 0;
8091 }
8092
8093 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data(), Hoption.System);
8094
8095 Int_t nids = -1;
8096 TH1 * hid = nullptr;
8097 Color_t colormain = -1, colordark = -1;
8099
8100 // LEGO3 is like LEGO1 except that the black lines around each lego are not drawn.
8101 if (Hoption.Lego == 13) {
8102 Hoption.Lego = 11;
8103 fLego->SetMesh(0);
8104 }
8105 // LEGO4 is like LEGO1 except no shadows are drawn.
8106 if (Hoption.Lego == 14) {
8107 Hoption.Lego = 11;
8109 }
8110
8111 // Initialize the levels on the Z axis
8112 Int_t ndiv = fH->GetContour();
8113 if (ndiv == 0 ) {
8114 ndiv = gStyle->GetNumberContours();
8115 fH->SetContour(ndiv);
8116 }
8117 Int_t ndivz = TMath::Abs(ndiv);
8118 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
8119
8120 // Initialize colors
8121 if (!fStack) {
8122 fLego->SetEdgeAtt(fH->GetLineColor(),fH->GetLineStyle(),fH->GetLineWidth(),0);
8123 } else {
8124 for (Int_t id=0;id<=fStack->GetSize();id++) {
8125 hid = (TH1*)fStack->At((id==0)?id:id-1);
8126 fLego->SetEdgeAtt(hid->GetLineColor(),hid->GetLineStyle(),hid->GetLineWidth(),id);
8127 }
8128 }
8129
8130 if (Hoption.Lego == 11) {
8131 nids = 1;
8132 if (fStack) nids = fStack->GetSize();
8133 hid = fH;
8134 for (Int_t id=0;id<=nids;id++) {
8135 if (id > 0 && fStack) hid = (TH1*)fStack->At(id-1);
8136 colormain = hid->GetFillColor();
8137 if (colormain == 1) colormain = 17; //avoid drawing with black
8139 else colordark = colormain;
8140 fLego->SetColorMain(colormain,id);
8141 fLego->SetColorDark(colordark,id);
8142 if (id <= 1) fLego->SetColorMain(colormain,-1); // Set Bottom color
8143 if (id == nids) fLego->SetColorMain(colormain,99); // Set Top color
8144 }
8145 }
8146
8147 // Now ready to draw the lego plot
8148 Int_t irep = 0;
8149
8150 TView *view = gPad ? gPad->GetView() : nullptr;
8151 if (!view) {
8152 Error("PaintLego", "no TView in current pad");
8153 return;
8154 }
8155
8156 Double_t thedeg = 90 - gPad->GetTheta();
8157 Double_t phideg = -90 - gPad->GetPhi();
8158 Double_t psideg = view->GetPsi();
8159 view->SetView(phideg, thedeg, psideg, irep);
8160
8161 fLego->SetLineColor(kBlack); // zgrid color for lego1 & lego2
8162 fLego->SetFillStyle(fH->GetFillStyle());
8163
8164 // Set color/style for back box
8165 fLego->SetFillStyle(gPad->GetFrameFillStyle());
8166 fLego->SetFillColor(gPad->GetFrameFillColor());
8167 fLego->TAttFill::Modify();
8168
8169 Int_t backcolor = gPad->GetFrameFillColor();
8170 if (Hoption.System != kCARTESIAN) backcolor = 0;
8171 view->PadRange(backcolor);
8172
8173 fLego->SetFillStyle(fH->GetFillStyle());
8174 fLego->SetFillColor(fH->GetFillColor());
8175 fLego->TAttFill::Modify();
8176
8177 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
8178
8179 if (raster) fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
8180 else fLego->InitMoveScreen(-1.1,1.1);
8181
8182 if (Hoption.Lego == 19) {
8184 if (Hoption.BackBox) fLego->BackBox(90);
8185 if (Hoption.FrontBox) fLego->FrontBox(90);
8186 if (!Hoption.Axis) { TGaxis axis; PaintLegoAxis(&axis, 90); }
8187 return;
8188 }
8189
8190 if (Hoption.Lego == 11 || Hoption.Lego == 12) {
8193 fLego->BackBox(90);
8194 }
8195 }
8196
8197 if (Hoption.Lego == 12) DefineColorLevels(ndivz);
8198
8199 fLego->SetLegoFunction(&TPainter3dAlgorithms::LegoFunction);
8201 if (Hoption.Lego == 11) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode3);
8202 if (Hoption.Lego == 12) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode2);
8203 if (Hoption.System == kPOLAR) {
8204 if (Hoption.Lego == 1) fLego->LegoPolar(1,nx,ny,"FB");
8205 if (Hoption.Lego == 11) fLego->LegoPolar(1,nx,ny,"BF");
8206 if (Hoption.Lego == 12) fLego->LegoPolar(1,nx,ny,"BF");
8207 } else if (Hoption.System == kCYLINDRICAL) {
8208 if (Hoption.Lego == 1) fLego->LegoCylindrical(1,nx,ny,"FB");
8209 if (Hoption.Lego == 11) fLego->LegoCylindrical(1,nx,ny,"BF");
8210 if (Hoption.Lego == 12) fLego->LegoCylindrical(1,nx,ny,"BF");
8211 } else if (Hoption.System == kSPHERICAL) {
8212 if (Hoption.Lego == 1) fLego->LegoSpherical(0,1,nx,ny,"FB");
8213 if (Hoption.Lego == 11) fLego->LegoSpherical(0,1,nx,ny,"BF");
8214 if (Hoption.Lego == 12) fLego->LegoSpherical(0,1,nx,ny,"BF");
8215 } else if (Hoption.System == kRAPIDITY) {
8216 if (Hoption.Lego == 1) fLego->LegoSpherical(1,1,nx,ny,"FB");
8217 if (Hoption.Lego == 11) fLego->LegoSpherical(1,1,nx,ny,"BF");
8218 if (Hoption.Lego == 12) fLego->LegoSpherical(1,1,nx,ny,"BF");
8219 } else {
8220 if (Hoption.Lego == 1) {
8222 fLego->LegoCartesian(90,nx,ny,"FB");}
8223 if (Hoption.Lego == 11) fLego->LegoCartesian(90,nx,ny,"BF");
8224 if (Hoption.Lego == 12) fLego->LegoCartesian(90,nx,ny,"BF");
8225 }
8226
8227 if (Hoption.Lego == 1 || Hoption.Lego == 11) {
8230 fLego->BackBox(90);
8231 }
8232 }
8233 if (Hoption.System == kCARTESIAN) {
8234 fLego->InitMoveScreen(-1.1,1.1);
8236 if (Hoption.FrontBox) fLego->FrontBox(90);
8237 }
8238 if (!Hoption.Axis && !Hoption.Same) {
8239 TGaxis axis;
8240 PaintLegoAxis(&axis, 90);
8241 }
8243 fLego.reset();
8244}
8245
8246////////////////////////////////////////////////////////////////////////////////
8247/// Draw the axis for legos and surface plots.
8248
8250{
8251
8252 static Double_t epsil = 0.001;
8253
8256 Double_t r[24] /* was [3][8] */;
8257 Int_t ndivx, ndivy, ndivz, i;
8258 Double_t x1[3], x2[3], y1[3], y2[3], z1[3], z2[3], av[24] /* was [3][8] */;
8259 static char chopax[8], chopay[8], chopaz[8];
8260 Int_t ix1, ix2, iy1, iy2, iz1, iz2;
8261 Double_t rad;
8262
8263 TView *view = gPad ? gPad->GetView() : nullptr;
8264 if (!view) {
8265 Error("PaintLegoAxis", "no TView in current pad");
8266 return;
8267 }
8268
8269 // In polar coordinates, draw a short line going from the external circle
8270 // corresponding to r = 1 up to r = 1.1
8271 if (Hoption.System == kPOLAR) {
8272 r[0] = 1;
8273 r[1] = 0;
8274 r[2] = 0;
8275 view->WCtoNDC(r, x1);
8276 r[0] = 1.1;
8277 r[1] = 0;
8278 r[2] = 0;
8279 view->WCtoNDC(r, x2);
8280 gPad->PaintLine(x1[0],x1[1],x2[0],x2[1]);
8281 return;
8282 }
8283
8284 if (Hoption.System != kCARTESIAN) return;
8285
8286 rad = TMath::ATan(1.) * 4. /180.;
8287 cosa = TMath::Cos(ang*rad);
8288 sina = TMath::Sin(ang*rad);
8289
8290 view->AxisVertex(ang, av, ix1, ix2, iy1, iy2, iz1, iz2);
8291 for (i = 1; i <= 8; ++i) {
8292 r[i*3 - 3] = av[i*3 - 3] + av[i*3 - 2]*cosa;
8293 r[i*3 - 2] = av[i*3 - 2]*sina;
8294 r[i*3 - 1] = av[i*3 - 1];
8295 }
8296
8297 view->WCtoNDC(&r[ix1*3 - 3], x1);
8298 view->WCtoNDC(&r[ix2*3 - 3], x2);
8299 view->WCtoNDC(&r[iy1*3 - 3], y1);
8300 view->WCtoNDC(&r[iy2*3 - 3], y2);
8301 view->WCtoNDC(&r[iz1*3 - 3], z1);
8302 view->WCtoNDC(&r[iz2*3 - 3], z2);
8303
8304 view->SetAxisNDC(x1, x2, y1, y2, z1, z2);
8305
8306 Double_t *rmin = view->GetRmin();
8307 Double_t *rmax = view->GetRmax();
8308 if (!rmin || !rmax) return;
8309
8310 // Initialize the axis options
8311 if (x1[0] > x2[0]) strlcpy(chopax, "SDH=+",8);
8312 else strlcpy(chopax, "SDH=-",8);
8313 if (y1[0] > y2[0]) strlcpy(chopay, "SDH=+",8);
8314 else strlcpy(chopay, "SDH=-",8);
8315 if (z2[1] > z1[1]) strlcpy(chopaz, "SDH=+",8);
8316 else strlcpy(chopaz, "SDH=-",8);
8317
8318 // Option LOG is required ?
8319 if (Hoption.Logx) strlcat(chopax,"G",8);
8320 if (Hoption.Logy) strlcat(chopay,"G",8);
8321 if (Hoption.Logz) strlcat(chopaz,"G",8);
8322
8323 // Initialize the number of divisions. If the
8324 // number of divisions is negative, option 'N' is required.
8328 if (ndivx < 0) {
8330 strlcat(chopax, "N",8);
8331 }
8332 if (ndivy < 0) {
8334 strlcat(chopay, "N",8);
8335 }
8336 if (ndivz < 0) {
8338 strlcat(chopaz, "N",8);
8339 }
8340
8341 // Set Axis attributes.
8342 // The variable SCALE rescales the VSIZ
8343 // in order to have the same label size for all angles.
8344
8345 axis->SetLineWidth(1);
8346
8347 // X axis drawing
8348 if (TMath::Abs(x1[0] - x2[0]) >= epsil || TMath::Abs(x1[1] - x2[1]) > epsil) {
8351 if (Hoption.Logx && !fH->InheritsFrom(TH3::Class())) {
8352 bmin = TMath::Power(10, rmin[0]);
8353 bmax = TMath::Power(10, rmax[0]);
8354 } else {
8355 bmin = rmin[0];
8356 bmax = rmax[0];
8357 }
8358 // Option time display is required ?
8359 if (fXaxis->GetTimeDisplay()) {
8360 strlcat(chopax,"t",8);
8361 if (strlen(fXaxis->GetTimeFormatOnly()) == 0) {
8363 } else {
8365 }
8366 }
8367 axis->SetOption(chopax);
8368 axis->PaintAxis(x1[0], x1[1], x2[0], x2[1], bmin, bmax, ndivx, chopax);
8369 }
8370
8371 // Y axis drawing
8372 if (TMath::Abs(y1[0] - y2[0]) >= epsil || TMath::Abs(y1[1] - y2[1]) > epsil) {
8375 if (fYaxis->GetTitleOffset() == 0) axis->SetTitleOffset(1.5);
8376
8377 if (fH->GetDimension() < 2) {
8378 strlcpy(chopay, "V=+UN",8);
8379 ndivy = 0;
8380 }
8381 if (TMath::Abs(y1[0] - y2[0]) < epsil) {
8382 y2[0] = y1[0];
8383 }
8384 if (Hoption.Logy && !fH->InheritsFrom(TH3::Class())) {
8385 bmin = TMath::Power(10, rmin[1]);
8386 bmax = TMath::Power(10, rmax[1]);
8387 } else {
8388 bmin = rmin[1];
8389 bmax = rmax[1];
8390 }
8391 // Option time display is required ?
8392 if (fYaxis->GetTimeDisplay()) {
8393 strlcat(chopay,"t",8);
8394 if (strlen(fYaxis->GetTimeFormatOnly()) == 0) {
8396 } else {
8398 }
8399 }
8400 axis->SetOption(chopay);
8401 axis->PaintAxis(y1[0], y1[1], y2[0], y2[1], bmin, bmax, ndivy, chopay);
8402 }
8403
8404 // Z axis drawing
8405 if (TMath::Abs(z1[0] - z2[0]) >= 100*epsil || TMath::Abs(z1[1] - z2[1]) > 100*epsil) {
8407 if (Hoption.Logz && !fH->InheritsFrom(TH3::Class())) {
8408 bmin = TMath::Power(10, rmin[2]);
8409 bmax = TMath::Power(10, rmax[2]);
8410 } else {
8411 bmin = rmin[2];
8412 bmax = rmax[2];
8413 }
8414 // Option time display is required ?
8415 if (fZaxis->GetTimeDisplay()) {
8416 strlcat(chopaz,"t",8);
8417 if (strlen(fZaxis->GetTimeFormatOnly()) == 0) {
8419 } else {
8421 }
8422 }
8423 axis->SetOption(chopaz);
8425 if (ztit.Index(";")>0) {
8426 ztit.Remove(ztit.Index(";"),ztit.Length());
8427 axis->SetTitle(ztit.Data());
8428 }
8429 axis->PaintAxis(z1[0], z1[1], z2[0], z2[1], bmin, bmax, ndivz, chopaz);
8430 }
8431
8432 //fH->SetLineStyle(1); /// otherwise fEdgeStyle[i] gets overwritten!
8433}
8434
8435////////////////////////////////////////////////////////////////////////////////
8436/// [Paint the color palette on the right side of the pad.](\ref HP22)
8437
8439{
8441 TView *view = gPad ? gPad->GetView() : nullptr;
8442 if (palette) {
8443 if (view) {
8444 if (!palette->TestBit(TPaletteAxis::kHasView)) {
8446 delete palette; palette = nullptr;
8447 }
8448 } else {
8449 if (palette->TestBit(TPaletteAxis::kHasView)) {
8451 delete palette; palette = nullptr;
8452 }
8453 }
8454 // make sure the histogram member of the palette is setup correctly. It may not be after a Clone()
8455 if (palette && !palette->GetHistogram()) palette->SetHistogram(fH);
8456 }
8457
8458 if (!palette) {
8459 Double_t xup = gPad->GetUxmax();
8460 Double_t x2 = gPad->PadtoX(gPad->GetX2());
8461 Double_t ymin = gPad->PadtoY(gPad->GetUymin());
8462 Double_t ymax = gPad->PadtoY(gPad->GetUymax());
8463 Double_t xr = 0.05*(gPad->GetX2() - gPad->GetX1());
8464 Double_t xmin = gPad->PadtoX(xup +0.1*xr);
8465 Double_t xmax = gPad->PadtoX(xup + xr);
8466 if (xmax > x2) xmax = gPad->PadtoX(gPad->GetX2()-0.01*xr);
8469 palette->Paint();
8470 }
8471}
8472
8473////////////////////////////////////////////////////////////////////////////////
8474/// [Control function to draw a 2D histogram as a scatter plot.](\ref HP11)
8475
8477{
8478
8479 fH->TAttMarker::Modify();
8480
8481 Int_t k, marker;
8482 Double_t dz, z, xk,xstep, yk, ystep;
8483 Double_t scale = 1;
8485 Double_t zmax = fH->GetMaximum();
8486 Double_t zmin = fH->GetMinimum();
8487 if (zmin == 0 && zmax == 0) return;
8488 if (zmin == zmax) {
8489 zmax += 0.1*TMath::Abs(zmax);
8490 zmin -= 0.1*TMath::Abs(zmin);
8491 }
8493 if (Hoption.Logz) {
8494 if (zmin > 0) zmin = TMath::Log10(zmin);
8495 else zmin = 0;
8496 if (zmax > 0) zmax = TMath::Log10(zmax);
8497 else zmax = 0;
8498 if (zmin == 0 && zmax == 0) return;
8499 dz = zmax - zmin;
8500 scale = 100/dz;
8501 if (ncells > 10000) scale /= 5;
8502 ltest = kTRUE;
8503 } else {
8504 dz = zmax - zmin;
8505 if (dz >= kNMAX || zmax < 1) {
8506 scale = (kNMAX-1)/dz;
8507 if (ncells > 10000) scale /= 5;
8508 ltest = kTRUE;
8509 }
8510 }
8511 if (fH->GetMinimumStored() == -1111) {
8513 if (Hoption.MinimumZero) {
8514 if (zmin >= 0) zmin = 0;
8515 else zmin -= yMARGIN*(zmax-zmin);
8516 } else {
8517 Double_t dzmin = yMARGIN*(zmax-zmin);
8518 if (zmin >= 0 && (zmin-dzmin <= 0)) zmin = 0;
8519 else zmin -= dzmin;
8520 }
8521 }
8522
8523 TString opt = option;
8524 opt.ToLower();
8525 if (opt.Contains("scat=")) {
8526 char optscat[100];
8527 strlcpy(optscat,opt.Data(),100);
8528 char *oscat = strstr(optscat,"scat=");
8529 char *blank = strstr(oscat," "); if (blank) *blank = 0;
8530 sscanf(oscat+5,"%lg",&scale);
8531 }
8532 // use an independent instance of a random generator
8533 // instead of gRandom to avoid conflicts and
8534 // to get same random numbers when drawing the same histogram
8536 marker=0;
8537 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
8540 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
8541 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
8542 xk = fXaxis->GetBinLowEdge(i);
8543 xstep = fXaxis->GetBinWidth(i);
8544 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
8545 z = fH->GetBinContent(bin);
8546 if (z < zmin) z = zmin;
8547 if (z > zmax) z = zmax;
8548 if (Hoption.Logz) {
8549 if (z > 0) z = TMath::Log10(z) - zmin;
8550 } else {
8551 z -= zmin;
8552 }
8553 if (z <= 0) continue;
8554 k = Int_t(z*scale);
8555 if (ltest) k++;
8556 if (k > 0) {
8557 for (Int_t loop=0; loop<k; loop++) {
8558 if (k+marker >= kNMAX) {
8559 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
8560 marker=0;
8561 }
8562 fXbuf[marker] = (random.Rndm()*xstep) + xk;
8563 fYbuf[marker] = (random.Rndm()*ystep) + yk;
8564 if (Hoption.Logx) {
8565 if (fXbuf[marker] > 0) fXbuf[marker] = TMath::Log10(fXbuf[marker]);
8566 else break;
8567 }
8568 if (Hoption.Logy) {
8569 if (fYbuf[marker] > 0) fYbuf[marker] = TMath::Log10(fYbuf[marker]);
8570 else break;
8571 }
8572 if (fXbuf[marker] < gPad->GetUxmin()) break;
8573 if (fYbuf[marker] < gPad->GetUymin()) break;
8574 if (fXbuf[marker] > gPad->GetUxmax()) break;
8575 if (fYbuf[marker] > gPad->GetUymax()) break;
8576 marker++;
8577 }
8578 }
8579 }
8580 }
8581 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
8582
8584}
8585
8586////////////////////////////////////////////////////////////////////////////////
8587/// Static function to paint special objects like vectors and matrices.
8588/// This function is called via `gROOT->ProcessLine` to paint these objects
8589/// without having a direct dependency of the graphics or histogramming
8590/// system.
8591
8593{
8594
8595 if (!obj) return;
8598
8599 if (obj->InheritsFrom(TMatrixFBase::Class())) {
8600 // case TMatrixF
8601 TH2F *R__TMatrixFBase = new TH2F((TMatrixFBase &)*obj);
8602 R__TMatrixFBase->SetBit(kCanDelete);
8603 R__TMatrixFBase->Draw(option);
8604
8605 } else if (obj->InheritsFrom(TMatrixDBase::Class())) {
8606 // case TMatrixD
8607 TH2D *R__TMatrixDBase = new TH2D((TMatrixDBase &)*obj);
8608 R__TMatrixDBase->SetBit(kCanDelete);
8609 R__TMatrixDBase->Draw(option);
8610
8611 } else if (obj->InheritsFrom(TVectorF::Class())) {
8612 //case TVectorF
8613 TH1F *R__TVectorF = new TH1F((TVectorF &)*obj);
8614 R__TVectorF->SetBit(kCanDelete);
8615 R__TVectorF->Draw(option);
8616
8617 } else if (obj->InheritsFrom(TVectorD::Class())) {
8618 //case TVectorD
8619 TH1D *R__TVectorD = new TH1D((TVectorD &)*obj);
8620 R__TVectorD->SetBit(kCanDelete);
8621 R__TVectorD->Draw(option);
8622 }
8623
8624 TH1::AddDirectory(status);
8625}
8626
8627////////////////////////////////////////////////////////////////////////////////
8628/// [Draw the statistics box for 1D and profile histograms.](\ref HP07)
8629
8631{
8632 TString tt, tf;
8633 Int_t dofit;
8634 TPaveStats *stats = nullptr;
8635 TIter next(fFunctions);
8636 while (auto obj = next()) {
8637 if (obj->InheritsFrom(TPaveStats::Class())) {
8638 stats = (TPaveStats*)obj;
8639 break;
8640 }
8641 }
8642
8643 if (stats && dostat) {
8644 dofit = stats->GetOptFit();
8645 dostat = stats->GetOptStat();
8646 } else {
8647 dofit = gStyle->GetOptFit();
8648 }
8649 if (!dofit) fit = nullptr;
8650 if (dofit == 1) dofit = 111;
8651 if (dostat == 1) dostat = 1111;
8652 Int_t print_name = dostat%10;
8653 Int_t print_entries = (dostat/10)%10;
8654 Int_t print_mean = (dostat/100)%10;
8655 Int_t print_stddev = (dostat/1000)%10;
8656 Int_t print_under = (dostat/10000)%10;
8657 Int_t print_over = (dostat/100000)%10;
8658 Int_t print_integral= (dostat/1000000)%10;
8659 Int_t print_skew = (dostat/10000000)%10;
8660 Int_t print_kurt = (dostat/100000000)%10;
8664 Int_t print_fval = dofit%10;
8665 Int_t print_ferrors = (dofit/10)%10;
8666 Int_t print_fchi2 = (dofit/100)%10;
8667 Int_t print_fprob = (dofit/1000)%10;
8669 if (fit) {
8670 if (print_fval < 2) nlinesf += fit->GetNumberFreeParameters();
8671 else nlinesf += fit->GetNpar();
8672 }
8674
8675 // Pavetext with statistics
8676 Bool_t done = kFALSE;
8677 if (!dostat && !fit) {
8678 if (stats) { fFunctions->Remove(stats); delete stats;}
8679 return;
8680 }
8682 if (fit) statw = 1.8*gStyle->GetStatW();
8684 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
8685 stath = 0.25*(nlines+nlinesf)*gStyle->GetStatH();
8686 }
8687 if (stats) {
8688 stats->Clear();
8689 done = kTRUE;
8690 } else {
8691 stats = new TPaveStats(
8694 gStyle->GetStatX(),
8695 gStyle->GetStatY(),"brNDC");
8696
8697 stats->SetParent(fH);
8698 stats->SetOptFit(dofit);
8699 stats->SetOptStat(dostat);
8700 stats->SetFillColor(gStyle->GetStatColor());
8701 stats->SetFillStyle(gStyle->GetStatStyle());
8702 stats->SetBorderSize(gStyle->GetStatBorderSize());
8703 stats->SetTextFont(gStyle->GetStatFont());
8704 if (gStyle->GetStatFont()%10 > 2)
8705 stats->SetTextSize(gStyle->GetStatFontSize());
8706 stats->SetFitFormat(gStyle->GetFitFormat());
8707 stats->SetStatFormat(gStyle->GetStatFormat());
8708 stats->SetName("stats");
8709
8710 stats->SetTextColor(gStyle->GetStatTextColor());
8711 stats->SetTextAlign(12);
8712 stats->SetBit(kCanDelete);
8713 stats->SetBit(kMustCleanup);
8714 }
8715 if (print_name) stats->AddText(fH->GetName());
8716 if (print_entries) {
8717 if (fH->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(fH->GetEntries()+0.5));
8718 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(fH->GetEntries()));
8719 stats->AddText(tt.Data());
8720 }
8721 if (print_mean) {
8722 if (print_mean == 1) {
8723 tf.Form("%s = %s%s",gStringMean.Data(),"%",stats->GetStatFormat());
8724 tt.Form(tf.Data(),fH->GetMean(1));
8725 } else {
8726 tf.Form("%s = %s%s #pm %s%s",gStringMean.Data(),"%",stats->GetStatFormat()
8727 ,"%",stats->GetStatFormat());
8728 tt.Form(tf.Data(),fH->GetMean(1),fH->GetMeanError(1));
8729 }
8730 stats->AddText(tt.Data());
8732 if (print_mean == 1) {
8733 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
8734 tt.Form(tf.Data(),fH->GetMean(2));
8735 } else {
8736 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
8737 ,"%",stats->GetStatFormat());
8738 tt.Form(tf.Data(),fH->GetMean(2),fH->GetMeanError(2));
8739 }
8740 stats->AddText(tt.Data());
8741 }
8742 }
8743 if (print_stddev) {
8744 if (print_stddev == 1) {
8745 tf.Form("%s = %s%s",gStringStdDev.Data(),"%",stats->GetStatFormat());
8746 tt.Form(tf.Data(),fH->GetStdDev(1));
8747 } else {
8748 tf.Form("%s = %s%s #pm %s%s",gStringStdDev.Data(),"%",stats->GetStatFormat()
8749 ,"%",stats->GetStatFormat());
8750 tt.Form(tf.Data(),fH->GetStdDev(1),fH->GetStdDevError(1));
8751 }
8752 stats->AddText(tt.Data());
8754 if (print_stddev == 1) {
8755 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
8756 tt.Form(tf.Data(),fH->GetStdDev(2));
8757 } else {
8758 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
8759 ,"%",stats->GetStatFormat());
8760 tt.Form(tf.Data(),fH->GetStdDev(2),fH->GetStdDevError(2));
8761 }
8762 stats->AddText(tt.Data());
8763 }
8764 }
8765 if (print_under) {
8766 tf.Form("%s = %s%s",gStringUnderflow.Data(),"%",stats->GetStatFormat());
8767 tt.Form(tf.Data(),fH->GetBinContent(0));
8768 stats->AddText(tt.Data());
8769 }
8770 if (print_over) {
8771 tf.Form("%s = %s%s",gStringOverflow.Data(),"%",stats->GetStatFormat());
8772 tt.Form(tf.Data(),fH->GetBinContent(fXaxis->GetNbins()+1));
8773 stats->AddText(tt.Data());
8774 }
8775 if (print_integral) {
8776 if (print_integral == 1) {
8777 tf.Form("%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
8778 tt.Form(tf.Data(),fH->Integral());
8779 } else {
8780 tf.Form("%s = %s%s",gStringIntegralBinWidth.Data(),"%",stats->GetStatFormat());
8781 tt.Form(tf.Data(),fH->Integral("width"));
8782 }
8783 stats->AddText(tt.Data());
8784 }
8785 if (print_skew) {
8786 if (print_skew == 1) {
8787 tf.Form("%s = %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat());
8788 tt.Form(tf.Data(),fH->GetSkewness(1));
8789 } else {
8790 tf.Form("%s = %s%s #pm %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat()
8791 ,"%",stats->GetStatFormat());
8792 tt.Form(tf.Data(),fH->GetSkewness(1),fH->GetSkewness(11));
8793 }
8794 stats->AddText(tt.Data());
8795 }
8796 if (print_kurt) {
8797 if (print_kurt == 1) {
8798 tf.Form("%s = %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat());
8799 tt.Form(tf.Data(),fH->GetKurtosis(1));
8800 } else {
8801 tf.Form("%s = %s%s #pm %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat()
8802 ,"%",stats->GetStatFormat());
8803 tt.Form(tf.Data(),fH->GetKurtosis(1),fH->GetKurtosis(11));
8804 }
8805 stats->AddText(tt.Data());
8806 }
8807
8808 // Draw Fit parameters
8809 if (fit) {
8810 Int_t ndf = fit->GetNDF();
8811 tf.Form("#chi^{2} / ndf = %s%s / %d","%",stats->GetFitFormat(),ndf);
8812 tt.Form(tf.Data(),fit->GetChisquare());
8813 if (print_fchi2) stats->AddText(tt.Data());
8814 if (print_fprob) {
8815 tf.Form("Prob = %s%s","%",stats->GetFitFormat());
8816 tt.Form(tf.Data(),TMath::Prob(fit->GetChisquare(),ndf));
8817 stats->AddText(tt.Data());
8818 }
8819 if (print_fval || print_ferrors) {
8821 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
8822 fit->GetParLimits(ipar,parmin,parmax);
8824 if (print_ferrors) {
8825 tf.Form("%-8s = %s%s #pm %s ", fit->GetParName(ipar), "%",stats->GetFitFormat(),
8826 GetBestFormat(fit->GetParameter(ipar), fit->GetParError(ipar), stats->GetFitFormat()));
8827 tt.Form(tf.Data(),fit->GetParameter(ipar)
8828 ,fit->GetParError(ipar));
8829 } else {
8830 tf.Form("%-8s = %s%s ",fit->GetParName(ipar), "%",stats->GetFitFormat());
8831 tt.Form(tf.Data(),fit->GetParameter(ipar));
8832 }
8833 stats->AddText(tt.Data());
8834 }
8835 }
8836 }
8837
8838 if (!done) fFunctions->Add(stats);
8839 stats->Paint(stats->GetOption());
8840}
8841
8842////////////////////////////////////////////////////////////////////////////////
8843/// [Draw the statistics box for 2D histograms.](\ref HP07)
8844
8846{
8847
8848 if (fH->GetDimension() != 2) return;
8849 TH2 *h2 = (TH2*)fH;
8850
8851 TString tt, tf;
8852 Int_t dofit;
8853 TPaveStats *stats = nullptr;
8854 TIter next(fFunctions);
8855 while (auto obj = next()) {
8856 if (obj->InheritsFrom(TPaveStats::Class())) {
8857 stats = (TPaveStats*)obj;
8858 break;
8859 }
8860 }
8861 if (stats && dostat) {
8862 dofit = stats->GetOptFit();
8863 dostat = stats->GetOptStat();
8864 } else {
8865 dofit = gStyle->GetOptFit();
8866 }
8867 if (dostat == 1) dostat = 1111;
8868 Int_t print_name = dostat%10;
8869 Int_t print_entries = (dostat/10)%10;
8870 Int_t print_mean = (dostat/100)%10;
8871 Int_t print_stddev = (dostat/1000)%10;
8872 Int_t print_under = (dostat/10000)%10;
8873 Int_t print_over = (dostat/100000)%10;
8874 Int_t print_integral= (dostat/1000000)%10;
8875 Int_t print_skew = (dostat/10000000)%10;
8876 Int_t print_kurt = (dostat/100000000)%10;
8878 if (print_under || print_over) nlines += 3;
8879
8880 // Pavetext with statistics
8881 if (!gStyle->GetOptFit()) fit = nullptr;
8882 Bool_t done = kFALSE;
8883 if (!dostat && !fit) {
8884 if (stats) { fFunctions->Remove(stats); delete stats;}
8885 return;
8886 }
8888 if (fit) statw = 1.8*gStyle->GetStatW();
8890 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
8891 stath = 0.25*nlines*gStyle->GetStatH();
8892 }
8893 if (fit) stath += gStyle->GetStatH();
8894 if (stats) {
8895 stats->Clear();
8896 done = kTRUE;
8897 } else {
8898 stats = new TPaveStats(
8901 gStyle->GetStatX(),
8902 gStyle->GetStatY(),"brNDC");
8903
8904 stats->SetParent(fH);
8905 stats->SetOptFit(dofit);
8906 stats->SetOptStat(dostat);
8907 stats->SetFillColor(gStyle->GetStatColor());
8908 stats->SetFillStyle(gStyle->GetStatStyle());
8909 stats->SetBorderSize(gStyle->GetStatBorderSize());
8910 stats->SetName("stats");
8911
8912 stats->SetTextColor(gStyle->GetStatTextColor());
8913 stats->SetTextAlign(12);
8914 stats->SetTextFont(gStyle->GetStatFont());
8915 if (gStyle->GetStatFont()%10 > 2)
8916 stats->SetTextSize(gStyle->GetStatFontSize());
8917 stats->SetFitFormat(gStyle->GetFitFormat());
8918 stats->SetStatFormat(gStyle->GetStatFormat());
8919 stats->SetBit(kCanDelete);
8920 stats->SetBit(kMustCleanup);
8921 }
8922 if (print_name) stats->AddText(h2->GetName());
8923 if (print_entries) {
8924 if (h2->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(h2->GetEntries()+0.5));
8925 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(h2->GetEntries()));
8926 stats->AddText(tt.Data());
8927 }
8928 if (print_mean) {
8929 if (print_mean == 1) {
8930 tf.Form("%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
8931 tt.Form(tf.Data(),h2->GetMean(1));
8932 stats->AddText(tt.Data());
8933 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
8934 tt.Form(tf.Data(),h2->GetMean(2));
8935 stats->AddText(tt.Data());
8936 } else {
8937 tf.Form("%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
8938 ,"%",stats->GetStatFormat());
8939 tt.Form(tf.Data(),h2->GetMean(1),h2->GetMeanError(1));
8940 stats->AddText(tt.Data());
8941 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
8942 ,"%",stats->GetStatFormat());
8943 tt.Form(tf.Data(),h2->GetMean(2),h2->GetMeanError(2));
8944 stats->AddText(tt.Data());
8945 }
8946 }
8947 if (print_stddev) {
8948 if (print_stddev == 1) {
8949 tf.Form("%s = %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat());
8950 tt.Form(tf.Data(),h2->GetStdDev(1));
8951 stats->AddText(tt.Data());
8952 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
8953 tt.Form(tf.Data(),h2->GetStdDev(2));
8954 stats->AddText(tt.Data());
8955 } else {
8956 tf.Form("%s = %s%s #pm %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat()
8957 ,"%",stats->GetStatFormat());
8958 tt.Form(tf.Data(),h2->GetStdDev(1),h2->GetStdDevError(1));
8959 stats->AddText(tt.Data());
8960 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
8961 ,"%",stats->GetStatFormat());
8962 tt.Form(tf.Data(),h2->GetStdDev(2),h2->GetStdDevError(2));
8963 stats->AddText(tt.Data());
8964 }
8965 }
8966 if (print_integral) {
8967 tf.Form("%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
8968 tt.Form(tf.Data(),fH->Integral());
8969 stats->AddText(tt.Data());
8970 }
8971 if (print_skew) {
8972 if (print_skew == 1) {
8973 tf.Form("%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
8974 tt.Form(tf.Data(),h2->GetSkewness(1));
8975 stats->AddText(tt.Data());
8976 tf.Form("%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
8977 tt.Form(tf.Data(),h2->GetSkewness(2));
8978 stats->AddText(tt.Data());
8979 } else {
8980 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
8981 ,"%",stats->GetStatFormat());
8982 tt.Form(tf.Data(),h2->GetSkewness(1),h2->GetSkewness(11));
8983 stats->AddText(tt.Data());
8984 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
8985 ,"%",stats->GetStatFormat());
8986 tt.Form(tf.Data(),h2->GetSkewness(2),h2->GetSkewness(12));
8987 stats->AddText(tt.Data());
8988 }
8989 }
8990 if (print_kurt) {
8991 if (print_kurt == 1) {
8992 tf.Form("%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
8993 tt.Form(tf.Data(),h2->GetKurtosis(1));
8994 stats->AddText(tt.Data());
8995 tf.Form("%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
8996 tt.Form(tf.Data(),h2->GetKurtosis(2));
8997 stats->AddText(tt.Data());
8998 } else {
8999 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
9000 ,"%",stats->GetStatFormat());
9001 tt.Form(tf.Data(),h2->GetKurtosis(1),h2->GetKurtosis(11));
9002 stats->AddText(tt.Data());
9003 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
9004 ,"%",stats->GetStatFormat());
9005 tt.Form(tf.Data(),h2->GetKurtosis(2),h2->GetKurtosis(12));
9006 stats->AddText(tt.Data());
9007 }
9008 }
9009 if (print_under || print_over) {
9010 //get 3*3 under/overflows for 2d hist
9011 Double_t unov[9];
9012
9013 Int_t cellsX = h2->GetXaxis()->GetNbins() + 1;
9014 Int_t cellsY = h2->GetYaxis()->GetNbins() + 1;
9015 Int_t firstX = std::max(1, h2->GetXaxis()->GetFirst());
9016 Int_t firstY = std::max(1, h2->GetYaxis()->GetFirst());
9017 Int_t lastX = std::min(h2->GetXaxis()->GetLast(), h2->GetXaxis()->GetNbins());
9018 Int_t lastY = std::min(h2->GetYaxis()->GetLast(), h2->GetYaxis()->GetNbins());
9019
9020 unov[0] = h2->Integral( 0, firstX-1, lastY+1, cellsY );
9021 unov[1] = h2->Integral(firstX , lastX , lastY+1, cellsY );
9022 unov[2] = h2->Integral(lastX+1, cellsX , lastY+1, cellsY );
9023 unov[3] = h2->Integral( 0, firstX-1, firstY , lastY );
9024 unov[4] = h2->Integral(firstX , lastX , firstY , lastY );
9025 unov[5] = h2->Integral(lastX+1, cellsX , firstY , lastY );
9026 unov[6] = h2->Integral( 0, firstX-1, 0, firstY-1);
9027 unov[7] = h2->Integral(firstX, lastX, 0, firstY-1);
9028 unov[8] = h2->Integral(lastX+1, cellsX , 0, firstY-1);
9029
9030 tt.Form("%g|%g|%g\n", unov[0], unov[1], unov[2]);
9031 stats->AddText(tt.Data());
9032 tt.Form("%g|%g|%g\n", unov[3], unov[4], unov[5]);
9033 stats->AddText(tt.Data());
9034 tt.Form("%g|%g|%g\n", unov[6], unov[7], unov[8]);
9035 stats->AddText(tt.Data());
9036 }
9037
9038 // Draw Fit parameters
9039 if (fit) {
9040 Int_t ndf = fit->GetNDF();
9041 tt.Form("#chi^{2} / ndf = %6.4g / %d",fit->GetChisquare(),ndf);
9042 stats->AddText(tt.Data());
9043 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
9044 tt.Form("%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
9045 ,fit->GetParameter(ipar)
9046 ,fit->GetParError(ipar));
9047 stats->AddText(tt.Data());
9048 }
9049 }
9050
9051 if (!done) fFunctions->Add(stats);
9052 stats->Paint(stats->GetOption());
9053}
9054
9055////////////////////////////////////////////////////////////////////////////////
9056/// [Draw the statistics box for 3D histograms.](\ref HP07)
9057
9059{
9060
9061 if (fH->GetDimension() != 3) return;
9062 TH3 *h3 = (TH3*)fH;
9063
9064 TString tt, tf;
9065 Int_t dofit;
9066 TPaveStats *stats = nullptr;
9067 TIter next(fFunctions);
9068 while (auto obj = next()) {
9069 if (obj->InheritsFrom(TPaveStats::Class())) {
9070 stats = (TPaveStats*)obj;
9071 break;
9072 }
9073 }
9074 if (stats && dostat) {
9075 dofit = stats->GetOptFit();
9076 dostat = stats->GetOptStat();
9077 } else {
9078 dofit = gStyle->GetOptFit();
9079 }
9080 if (dostat == 1) dostat = 1111;
9081 Int_t print_name = dostat%10;
9082 Int_t print_entries = (dostat/10)%10;
9083 Int_t print_mean = (dostat/100)%10;
9084 Int_t print_stddev = (dostat/1000)%10;
9085 Int_t print_under = (dostat/10000)%10;
9086 Int_t print_over = (dostat/100000)%10;
9087 Int_t print_integral= (dostat/1000000)%10;
9088 Int_t print_skew = (dostat/10000000)%10;
9089 Int_t print_kurt = (dostat/100000000)%10;
9091 if (print_under || print_over) nlines += 3;
9092
9093 // Pavetext with statistics
9094 if (!gStyle->GetOptFit()) fit = nullptr;
9095 Bool_t done = kFALSE;
9096 if (!dostat && !fit) {
9097 if (stats) { fFunctions->Remove(stats); delete stats;}
9098 return;
9099 }
9101 if (fit) statw = 1.8*gStyle->GetStatW();
9103 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
9104 stath = 0.25*nlines*gStyle->GetStatH();
9105 }
9106 if (fit) stath += gStyle->GetStatH();
9107 if (stats) {
9108 stats->Clear();
9109 done = kTRUE;
9110 } else {
9111 stats = new TPaveStats(
9114 gStyle->GetStatX(),
9115 gStyle->GetStatY(),"brNDC");
9116
9117 stats->SetParent(fH);
9118 stats->SetOptFit(dofit);
9119 stats->SetOptStat(dostat);
9120 stats->SetFillColor(gStyle->GetStatColor());
9121 stats->SetFillStyle(gStyle->GetStatStyle());
9122 stats->SetBorderSize(gStyle->GetStatBorderSize());
9123 stats->SetName("stats");
9124
9125 stats->SetTextColor(gStyle->GetStatTextColor());
9126 stats->SetTextAlign(12);
9127 stats->SetTextFont(gStyle->GetStatFont());
9128 stats->SetFitFormat(gStyle->GetFitFormat());
9129 stats->SetStatFormat(gStyle->GetStatFormat());
9130 stats->SetBit(kCanDelete);
9131 stats->SetBit(kMustCleanup);
9132 }
9133 if (print_name) stats->AddText(h3->GetName());
9134 if (print_entries) {
9135 if (h3->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(h3->GetEntries()+0.5));
9136 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(h3->GetEntries()+0.5));
9137 stats->AddText(tt.Data());
9138 }
9139 if (print_mean) {
9140 if (print_mean == 1) {
9141 tf.Form("%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
9142 tt.Form(tf.Data(),h3->GetMean(1));
9143 stats->AddText(tt.Data());
9144 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
9145 tt.Form(tf.Data(),h3->GetMean(2));
9146 stats->AddText(tt.Data());
9147 tf.Form("%s = %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat());
9148 tt.Form(tf.Data(),h3->GetMean(3));
9149 stats->AddText(tt.Data());
9150 } else {
9151 tf.Form("%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
9152 ,"%",stats->GetStatFormat());
9153 tt.Form(tf.Data(),h3->GetMean(1),h3->GetMeanError(1));
9154 stats->AddText(tt.Data());
9155 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
9156 ,"%",stats->GetStatFormat());
9157 tt.Form(tf.Data(),h3->GetMean(2),h3->GetMeanError(2));
9158 stats->AddText(tt.Data());
9159 tf.Form("%s = %s%s #pm %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat()
9160 ,"%",stats->GetStatFormat());
9161 tt.Form(tf.Data(),h3->GetMean(3),h3->GetMeanError(3));
9162 stats->AddText(tt.Data());
9163 }
9164 }
9165 if (print_stddev) {
9166 if (print_stddev == 1) {
9167 tf.Form("%s = %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat());
9168 tt.Form(tf.Data(),h3->GetStdDev(1));
9169 stats->AddText(tt.Data());
9170 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
9171 tt.Form(tf.Data(),h3->GetStdDev(2));
9172 stats->AddText(tt.Data());
9173 tf.Form("%s = %s%s",gStringStdDevZ.Data(),"%",stats->GetStatFormat());
9174 tt.Form(tf.Data(),h3->GetStdDev(3));
9175 stats->AddText(tt.Data());
9176 } else {
9177 tf.Form("%s = %s%s #pm %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat()
9178 ,"%",stats->GetStatFormat());
9179 tt.Form(tf.Data(),h3->GetStdDev(1),h3->GetStdDevError(1));
9180 stats->AddText(tt.Data());
9181 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
9182 ,"%",stats->GetStatFormat());
9183 tt.Form(tf.Data(),h3->GetStdDev(2),h3->GetStdDevError(2));
9184 stats->AddText(tt.Data());
9185 tf.Form("%s = %s%s #pm %s%s",gStringStdDevZ.Data(),"%",stats->GetStatFormat()
9186 ,"%",stats->GetStatFormat());
9187 tt.Form(tf.Data(),h3->GetStdDev(3),h3->GetStdDevError(3));
9188 stats->AddText(tt.Data());
9189 }
9190 }
9191 if (print_integral) {
9192 tt.Form("%s = %6.4g",gStringIntegral.Data(),h3->Integral());
9193 stats->AddText(tt.Data());
9194 }
9195 if (print_skew) {
9196 if (print_skew == 1) {
9197 tf.Form("%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
9198 tt.Form(tf.Data(),h3->GetSkewness(1));
9199 stats->AddText(tt.Data());
9200 tf.Form("%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
9201 tt.Form(tf.Data(),h3->GetSkewness(2));
9202 stats->AddText(tt.Data());
9203 tf.Form("%s = %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat());
9204 tt.Form(tf.Data(),h3->GetSkewness(3));
9205 stats->AddText(tt.Data());
9206 } else {
9207 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
9208 ,"%",stats->GetStatFormat());
9209 tt.Form(tf.Data(),h3->GetSkewness(1),h3->GetSkewness(11));
9210 stats->AddText(tt.Data());
9211 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
9212 ,"%",stats->GetStatFormat());
9213 tt.Form(tf.Data(),h3->GetSkewness(2),h3->GetSkewness(12));
9214 stats->AddText(tt.Data());
9215 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat()
9216 ,"%",stats->GetStatFormat());
9217 tt.Form(tf.Data(),h3->GetSkewness(3),h3->GetSkewness(13));
9218 stats->AddText(tt.Data());
9219 }
9220 }
9221 if (print_kurt) {
9222 if (print_kurt == 1) {
9223 tf.Form("%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
9224 tt.Form(tf.Data(),h3->GetKurtosis(1));
9225 stats->AddText(tt.Data());
9226 tf.Form("%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
9227 tt.Form(tf.Data(),h3->GetKurtosis(2));
9228 stats->AddText(tt.Data());
9229 tf.Form("%s = %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat());
9230 tt.Form(tf.Data(),h3->GetKurtosis(3));
9231 stats->AddText(tt.Data());
9232 } else {
9233 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
9234 ,"%",stats->GetStatFormat());
9235 tt.Form(tf.Data(),h3->GetKurtosis(1),h3->GetKurtosis(11));
9236 stats->AddText(tt.Data());
9237 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
9238 ,"%",stats->GetStatFormat());
9239 tt.Form(tf.Data(),h3->GetKurtosis(2),h3->GetKurtosis(12));
9240 stats->AddText(tt.Data());
9241 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat()
9242 ,"%",stats->GetStatFormat());
9243 tt.Form(tf.Data(),h3->GetKurtosis(3),h3->GetKurtosis(13));
9244 stats->AddText(tt.Data());
9245 }
9246 }
9247 if (print_under || print_over) {
9248 // no underflow - overflow printing for a 3D histogram
9249 // one would need a 3D table
9250 }
9251
9252 // Draw Fit parameters
9253 if (fit) {
9254 Int_t ndf = fit->GetNDF();
9255 tt.Form("#chi^{2} / ndf = %6.4g / %d",fit->GetChisquare(),ndf);
9256 stats->AddText(tt.Data());
9257 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
9258 tt.Form("%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
9259 ,fit->GetParameter(ipar)
9260 ,fit->GetParError(ipar));
9261 stats->AddText(tt.Data());
9262 }
9263 }
9264
9265 if (!done) fFunctions->Add(stats);
9266 stats->Paint(stats->GetOption());
9267}
9268
9269////////////////////////////////////////////////////////////////////////////////
9270/// [Control function to draw a 2D histogram as a surface plot.](\ref HP18)
9271
9273{
9274
9275 const Double_t ydiff = 1;
9276 const Double_t yligh1 = 10;
9277 const Double_t qa = 0.15;
9278 const Double_t qd = 0.15;
9279 const Double_t qs = 0.8;
9281 Int_t raster = 0;
9282 Int_t irep = 0;
9283
9284 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
9287 Double_t zmin = Hparam.zmin;
9288 Double_t zmax = Hparam.zmax;
9293 Double_t dangle = 10*3.141592/180; //Delta angle for Rapidity option
9294 Double_t deltaz = TMath::Abs(zmin);
9295 if (deltaz == 0) deltaz = 1;
9296 if (zmin >= zmax) {
9297 zmin -= 0.5*deltaz;
9298 zmax += 0.5*deltaz;
9299 }
9300 Double_t z1c = zmin;
9301 Double_t z2c = zmin + (zmax-zmin)*(1+gStyle->GetHistTopMargin());
9302 // Compute the lego limits and instantiate a lego object
9303 fXbuf[0] = -1;
9304 fYbuf[0] = 1;
9305 fXbuf[1] = -1;
9306 fYbuf[1] = 1;
9307 if (Hoption.System >= kPOLAR && (Hoption.Surf == 1 || Hoption.Surf == 13)) raster = 1;
9308 if (Hoption.System == kPOLAR) {
9309 fXbuf[2] = z1c;
9310 fYbuf[2] = z2c;
9311 } else if (Hoption.System == kCYLINDRICAL) {
9312 if (Hoption.Logy) {
9313 if (ylab1 > 0) fXbuf[2] = TMath::Log10(ylab1);
9314 else fXbuf[2] = 0;
9315 if (ylab2 > 0) fYbuf[2] = TMath::Log10(ylab2);
9316 else fYbuf[2] = 0;
9317 } else {
9318 fXbuf[2] = ylab1;
9319 fYbuf[2] = ylab2;
9320 }
9321 z1c = 0; z2c = 1;
9322 } else if (Hoption.System == kSPHERICAL) {
9323 fXbuf[2] = -1;
9324 fYbuf[2] = 1;
9325 z1c = 0; z2c = 1;
9326 } else if (Hoption.System == kRAPIDITY) {
9327 fXbuf[2] = -1/TMath::Tan(dangle);
9328 fYbuf[2] = 1/TMath::Tan(dangle);
9329 } else {
9330 fXbuf[0] = xlab1;
9331 fYbuf[0] = xlab2;
9332 fXbuf[1] = ylab1;
9333 fYbuf[1] = ylab2;
9334 fXbuf[2] = z1c;
9335 fYbuf[2] = z2c;
9336 }
9337
9338 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data(), Hoption.System);
9339 fLego->SetEdgeAtt(fH->GetLineColor(),fH->GetLineStyle(),fH->GetLineWidth(),0);
9340 fLego->SetFillColor(fH->GetFillColor());
9341
9342 // Initialize the levels on the Z axis
9343 Int_t ndiv = fH->GetContour();
9344 if (ndiv == 0 ) {
9345 ndiv = gStyle->GetNumberContours();
9346 fH->SetContour(ndiv);
9347 }
9348 Int_t ndivz = TMath::Abs(ndiv);
9349 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
9350
9351 if (Hoption.Surf == 13 || Hoption.Surf == 15) fLego->SetMesh(3);
9352 if (Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) fLego->SetMesh(0);
9353
9354 // Close the surface in case of non cartesian coordinates.
9355
9356 if (Hoption.System != kCARTESIAN) {nx++; ny++;}
9357
9358 // Now ready to draw the surface plot
9359
9360 TView *view = gPad ? gPad->GetView() : nullptr;
9361 if (!view) {
9362 Error("PaintSurface", "no TView in current pad");
9363 return;
9364 }
9365
9366 Double_t thedeg = 90 - gPad->GetTheta();
9367 Double_t phideg = -90 - gPad->GetPhi();
9368 Double_t psideg = view->GetPsi();
9369 view->SetView(phideg, thedeg, psideg, irep);
9370
9371 // Set color/style for back box
9372 if (Hoption.Same) {
9373 fLego->SetFillStyle(0);
9374 fLego->SetFillColor(1);
9375 } else {
9376 fLego->SetFillStyle(gPad->GetFrameFillStyle());
9377 fLego->SetFillColor(gPad->GetFrameFillColor());
9378 }
9379 fLego->TAttFill::Modify();
9380
9381 Int_t backcolor = gPad->GetFrameFillColor();
9382 if (Hoption.System != kCARTESIAN) backcolor = 0;
9383 view->PadRange(backcolor);
9384
9385 fLego->SetFillStyle(fH->GetFillStyle());
9386 fLego->SetFillColor(fH->GetFillColor());
9387 fLego->TAttFill::Modify();
9388
9389 // Draw the filled contour on top
9391
9393 if (Hoption.Surf == 13 || Hoption.Surf == 15) {
9395 Hoption.Surf = 23;
9396 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9398 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"BF");
9399 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9400 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9401 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9402 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"BF");
9404 fLego->SetMesh(1);
9405 }
9406
9407 if (raster) fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
9408 else fLego->InitMoveScreen(-1.1,1.1);
9409
9410 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) {
9411 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9414 fLego->BackBox(90);
9415 }
9416 }
9417
9418 // Gouraud Shading surface
9419 if (Hoption.Surf == 14) {
9420 // Set light sources
9421 fLego->LightSource(0, ydiff, 0,0,0,irep);
9422 fLego->LightSource(1, yligh1 ,1,1,1,irep);
9423 fLego->SurfaceProperty(qa, qd, qs, 1, irep);
9424 fmin = ydiff*qa;
9425 fmax = fmin + (yligh1+0.1)*(qd+qs);
9426 Int_t nbcol = 28;
9427 icol1 = 201;
9428 Double_t dcol = 0.5/Double_t(nbcol);
9429 TColor *colref = gROOT->GetColor(fH->GetFillColor());
9430 if (!colref) return;
9432 colref->GetRGB(r,g,b);
9434 TColor *acol;
9435 for (Int_t col=0;col<nbcol;col++) {
9436 acol = gROOT->GetColor(col+icol1);
9437 TColor::HLStoRGB(hue,.4+col*dcol,satur,r,g,b);
9438 if (acol) acol->SetRGB(r,g,b);
9439 }
9440 fLego->Spectrum(nbcol, fmin, fmax, icol1, 1, irep);
9441 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::GouraudFunction);
9443 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"BF");
9444 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9445 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9446 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9447 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"BF");
9448 } else if (Hoption.Surf == 15) {
9449 // The surface is not drawn in this case.
9450 } else {
9451 // Draw the surface
9452 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 16 || Hoption.Surf == 17) {
9454 } else {
9455 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9456 }
9457 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9458 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceRaster1);
9459 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode2);
9460 if (Hoption.System == kPOLAR) {
9461 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfacePolar(1,nx,ny,"FB");
9462 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfacePolar(1,nx,ny,"BF");
9463 } else if (Hoption.System == kCYLINDRICAL) {
9464 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceCylindrical(1,nx,ny,"FB");
9465 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9466 } else if (Hoption.System == kSPHERICAL) {
9467 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceSpherical(0,1,nx,ny,"FB");
9468 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9469 } else if (Hoption.System == kRAPIDITY) {
9470 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceSpherical(1,1,nx,ny,"FB");
9471 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9472 } else {
9473 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove1);
9474 if (Hoption.Surf == 16) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove3);
9475 if (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16) fLego->SurfaceCartesian(90,nx,ny,"FB");
9476 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCartesian(90,nx,ny,"BF");
9477 }
9478 }
9479
9480 // Paint the line contour on top for option SURF7
9481 if (Hoption.Surf == 17) {
9482 fLego->InitMoveScreen(-1.1,1.1);
9483 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9484 Hoption.Surf = 23;
9485 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9487 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"FB");
9488 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"FB");
9489 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"FB");
9490 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"FB");
9491 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"FB");
9492 }
9493
9494 if ((!Hoption.Same) &&
9495 (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16)) {
9498 fLego->BackBox(90);
9499 }
9500 }
9501 if (Hoption.System == kCARTESIAN) {
9502 fLego->InitMoveScreen(-1.1,1.1);
9504 if (Hoption.FrontBox) fLego->FrontBox(90);
9505 }
9506 if (!Hoption.Axis && !Hoption.Same) {
9507 TGaxis axis;
9508 PaintLegoAxis(&axis, 90);
9509 }
9510
9512
9513 fLego.reset();
9514}
9515
9516////////////////////////////////////////////////////////////////////////////////
9517/// Control function to draw a table using Delaunay triangles.
9518
9520{
9521
9522 TGraphDelaunay2D *dt = nullptr;
9523 TGraphDelaunay *dtOld = nullptr;
9524
9525 // Check if fH contains a TGraphDelaunay2D
9527 dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
9528 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
9529 if (!dt && !dtOld) return;
9530
9531 // If needed, create a TGraph2DPainter
9532 if (!fGraph2DPainter)
9533 fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
9534
9535 // Define the 3D view
9536 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
9537 if (Hoption.Same) {
9538 TView *viewsame = gPad ? gPad->GetView() : nullptr;
9539 if (!viewsame) {
9540 Error("PaintTriangles", "no TView in current pad, do not use option SAME");
9541 return;
9542 }
9543 Double_t *rmin = viewsame->GetRmin();
9544 Double_t *rmax = viewsame->GetRmax();
9545 if (!rmin || !rmax) return;
9546 fXbuf[0] = rmin[0];
9547 fYbuf[0] = rmax[0];
9548 fXbuf[1] = rmin[1];
9549 fYbuf[1] = rmax[1];
9550 fXbuf[2] = rmin[2];
9551 fYbuf[2] = rmax[2];
9552 fH->SetMaximum(rmax[2]);
9553 fH->SetMinimum(rmin[2]);
9554 fH->GetXaxis()->SetRangeUser(rmin[0],rmax[0]);
9555 fH->GetYaxis()->SetRangeUser(rmin[1],rmax[1]);
9556 } else {
9557 fXbuf[0] = Hparam.xmin;
9558 fYbuf[0] = Hparam.xmax;
9559 fXbuf[1] = Hparam.ymin;
9560 fYbuf[1] = Hparam.ymax;
9561 fXbuf[2] = Hparam.zmin;
9562 fYbuf[2] = Hparam.zmax;
9563 }
9564
9565 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
9566 TView *view = gPad ? gPad->GetView() : nullptr;
9567 if (!view) {
9568 Error("PaintTriangles", "no TView in current pad");
9569 return;
9570 }
9571 Double_t thedeg = 90 - gPad->GetTheta();
9572 Double_t phideg = -90 - gPad->GetPhi();
9573 Double_t psideg = view->GetPsi();
9574 Int_t irep;
9575 view->SetView(phideg, thedeg, psideg, irep);
9576
9577 // Set color/style for back box
9578 fLego->SetFillStyle(gPad->GetFrameFillStyle());
9579 fLego->SetFillColor(gPad->GetFrameFillColor());
9580 fLego->TAttFill::Modify();
9581 Int_t backcolor = gPad->GetFrameFillColor();
9582 if (Hoption.System != kCARTESIAN) backcolor = 0;
9583 view->PadRange(backcolor);
9584 fLego->SetFillStyle(fH->GetFillStyle());
9585 fLego->SetFillColor(fH->GetFillColor());
9586 fLego->TAttFill::Modify();
9587
9588 // Paint the Back Box if needed
9589 if (Hoption.BackBox && !Hoption.Same) {
9590 fLego->InitMoveScreen(-1.1,1.1);
9591 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9593 fLego->BackBox(90);
9594 }
9595
9596 // Paint the triangles
9597 fGraph2DPainter->Paint(option);
9598
9599 // Paint the Front Box if needed
9600 if (Hoption.FrontBox) {
9601 fLego->InitMoveScreen(-1.1,1.1);
9603 fLego->FrontBox(90);
9604 }
9605
9606 // Paint the Axis if needed
9607 if (!Hoption.Axis && !Hoption.Same) {
9608 TGaxis axis;
9609 PaintLegoAxis(&axis, 90);
9610 }
9611
9613
9614 fLego.reset();
9615}
9616
9617////////////////////////////////////////////////////////////////////////////////
9618/// Define the color levels used to paint legos, surfaces etc..
9619
9621{
9622
9623 Int_t i, irep;
9624
9625 // Initialize the color levels
9626 if (ndivz >= 100) {
9627 Warning("PaintSurface", "too many color levels, %d >= 100, reset to 99", ndivz);
9628 ndivz = 99;
9629 }
9630 std::vector<Double_t> funlevel(ndivz+1);
9631 std::vector<Int_t> colorlevel(ndivz+1);
9633 Int_t ncolors = gStyle->GetNumberOfColors();
9634 for (i = 0; i < ndivz; ++i) {
9636 theColor = Int_t((i+0.99)*Float_t(ncolors)/Float_t(ndivz));
9638 }
9639 colorlevel[ndivz] = gStyle->GetColorPalette(ncolors-1);
9640 fLego->ColorFunction(ndivz, funlevel.data(), colorlevel.data(), irep);
9641}
9642
9643////////////////////////////////////////////////////////////////////////////////
9644/// [Control function to draw 2D/3D histograms (tables).](\ref HP01c)
9645
9647{
9648
9649 // Fill Hparam structure with histo parameters
9650 if (!TableInit()) return;
9651
9652 // Draw histogram frame
9653 PaintFrame();
9654
9655 // If palette option not specified, delete a possible existing palette
9656 if (!Hoption.Zscale) {
9657 TObject *palette = fFunctions->FindObject("palette");
9658 if (palette) { fFunctions->Remove(palette); delete palette;}
9659 }
9660
9661 // Do not draw the histogram. Only the attached functions will be drawn.
9662 if (Hoption.Func == 2) {
9663 if (Hoption.Zscale) {
9664 Int_t ndiv = fH->GetContour();
9665 if (ndiv == 0 ) {
9666 ndiv = gStyle->GetNumberContours();
9667 fH->SetContour(ndiv);
9668 }
9669 PaintPalette();
9670 }
9671
9672 // Draw the histogram according to the option
9673 } else {
9674 if (fH->InheritsFrom(TH2Poly::Class()) && Hoption.Axis<=0) {
9675 if (Hoption.Fill) PaintTH2PolyBins("f");
9679 if (Hoption.Line) PaintTH2PolyBins("l");
9680 if (Hoption.Mark) PaintTH2PolyBins("P");
9681 } else if (Hoption.Axis<=0) {
9685 if (Hoption.Color) {
9688 }
9691 if (Hoption.Error >= 100) Paint2DErrors(option);
9693 }
9697 }
9698
9699 // Draw histogram title
9700 PaintTitle();
9701
9702 // Draw the axes
9703 if (!Hoption.Lego && !Hoption.Surf &&
9704 !Hoption.Tri && !(Hoption.Error >= 100)) PaintAxis(kFALSE);
9705
9706 TF1 *fit = nullptr;
9707 TIter next(fFunctions);
9708 while (auto obj = next()) {
9709 if (obj->InheritsFrom(TF1::Class())) {
9710 fit = (TF1*)obj;
9711 break;
9712 }
9713 }
9714 if ((Hoption.Same%10) != 1) {
9715 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
9716 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
9717 //ALWAYS executed on non-iOS platform.
9718 //On iOS, depends on mode.
9720 }
9721 }
9722 }
9723}
9724
9725////////////////////////////////////////////////////////////////////////////////
9726/// Control function to draw a TH2Poly bins' contours.
9727///
9728/// - option = "F" draw the bins as filled areas.
9729/// - option = "L" draw the bins as line.
9730/// - option = "P" draw the bins as markers.
9731
9733{
9734
9735 //Do not highlight the histogram, if its part was picked.
9736 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH) return;
9737
9738 TString opt = option;
9739 opt.ToLower();
9740 Bool_t line = kFALSE;
9741 Bool_t fill = kFALSE;
9742 Bool_t mark = kFALSE;
9743 if (opt.Contains("l")) line = kTRUE;
9744 if (opt.Contains("f")) fill = kTRUE;
9745 if (opt.Contains("p")) mark = kTRUE;
9746
9747 TH2PolyBin *b;
9748 Double_t z;
9749
9750 TIter next(((TH2Poly*)fH)->GetBins());
9751 TObject *obj, *poly;
9752
9753 while ((obj=next())) {
9754 b = (TH2PolyBin*)obj;
9755 z = b->GetContent();
9756 if (z==0 && Hoption.Zero) continue; // Do not draw empty bins in case of option "COL0 L"
9757 poly = b->GetPolygon();
9758
9759 // Paint the TGraph bins.
9760 if (poly->IsA() == TGraph::Class()) {
9761 TGraph *g = (TGraph*)poly;
9762 g->TAttLine::Modify();
9763 g->TAttMarker::Modify();
9764 g->TAttFill::Modify();
9765 if (line) {
9766 Int_t fs = g->GetFillStyle();
9768 g->SetFillStyle(0);
9770 g->Paint("F");
9772 g->SetFillStyle(fs);
9773 }
9774 if (fill) g->Paint("F");
9775 if (mark) g->Paint("P");
9776 }
9777
9778 // Paint the TMultiGraph bins.
9779 if (poly->IsA() == TMultiGraph::Class()) {
9781 TList *gl = mg->GetListOfGraphs();
9782 if (!gl) return;
9783 TGraph *g;
9784 TIter nextg(gl);
9785 while ((g = (TGraph*) nextg())) {
9786 g->TAttLine::Modify();
9787 g->TAttMarker::Modify();
9788 g->TAttFill::Modify();
9789 if (line) {
9790 Int_t fs = g->GetFillStyle();
9792 g->SetFillStyle(0);
9794 g->Paint("F");
9796 g->SetFillStyle(fs);
9797 }
9798 if (fill) g->Paint("F");
9799 if (mark) g->Paint("P");
9800 }
9801 }
9802 }
9803}
9804
9805////////////////////////////////////////////////////////////////////////////////
9806/// [Control function to draw a TH2Poly as a color plot.](\ref HP20a)
9807
9809{
9810
9811 //Do not highlight the histogram, if its part was picked.
9812 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
9813 return;
9814
9815 Int_t ncolors, color, theColor;
9816 Double_t z, zc;
9817 Double_t zmin = fH->GetMinimum();
9818 Double_t zmax = fH->GetMaximum();
9819 if (Hoption.Logz) {
9820 if (zmax > 0) {
9821 if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
9822 zmin = TMath::Log10(zmin);
9823 zmax = TMath::Log10(zmax);
9824 } else {
9825 return;
9826 }
9827 }
9828 Double_t dz = zmax - zmin;
9829
9830 // Initialize the levels on the Z axis
9831 ncolors = gStyle->GetNumberOfColors();
9832 Int_t ndiv = fH->GetContour();
9833 if (ndiv == 0 ) {
9834 ndiv = gStyle->GetNumberContours();
9835 fH->SetContour(ndiv);
9836 }
9837 Int_t ndivz = TMath::Abs(ndiv);
9838 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
9840
9841 TIter next(((TH2Poly*)fH)->GetBins());
9842
9843 while (auto obj = next()) {
9844 TH2PolyBin *b = (TH2PolyBin*)obj;
9845 TObject *poly = b->GetPolygon();
9846
9847 z = b->GetContent();
9848 if (z==0 && Hoption.Zero) continue;
9849 if (Hoption.Logz) {
9850 if (z > 0) z = TMath::Log10(z);
9851 else z = zmin;
9852 }
9853 if (z < zmin) continue;
9854
9855 // Define the bin color.
9857 zc = fH->GetContourLevelPad(0);
9858 if (z < zc) continue;
9859 color = -1;
9860 for (Int_t k=0; k<ndiv; k++) {
9861 zc = fH->GetContourLevelPad(k);
9862 if (z < zc) {
9863 continue;
9864 } else {
9865 color++;
9866 }
9867 }
9868 } else {
9869 color = Int_t(0.01+(z-zmin)*scale);
9870 }
9871 theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
9872 if (theColor > ncolors-1) theColor = ncolors-1;
9873
9874 // Paint the TGraph bins.
9875 if (poly->IsA() == TGraph::Class()) {
9876 TGraph *g = (TGraph*)poly;
9877 g->SetFillColor(gStyle->GetColorPalette(theColor));
9878 g->TAttFill::Modify();
9879 g->Paint("F");
9880 }
9881
9882 // Paint the TMultiGraph bins.
9883 if (poly->IsA() == TMultiGraph::Class()) {
9885 TList *gl = mg->GetListOfGraphs();
9886 if (!gl) return;
9887 TGraph *g;
9888 TIter nextg(gl);
9889 while ((g = (TGraph*) nextg())) {
9890 g->SetFillColor(gStyle->GetColorPalette(theColor));
9891 g->TAttFill::Modify();
9892 g->Paint("F");
9893 }
9894 }
9895 }
9897}
9898
9899////////////////////////////////////////////////////////////////////////////////
9900/// [Control function to draw a TH2Poly as a scatter plot.](\ref HP20a)
9901
9903{
9904
9905 //Do not highlight the histogram, if its part was selected.
9906 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
9907 return;
9908
9909 Int_t k, loop, marker=0;
9910 Double_t z, xk,xstep, yk, ystep, xp, yp;
9911 Double_t scale = 1;
9912 Double_t zmin = fH->GetMinimum();
9913 Double_t zmax = fH->GetMaximum();
9914 if (Hoption.Logz) {
9915 if (zmax > 0) {
9916 if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
9917 zmin = TMath::Log10(zmin);
9918 zmax = TMath::Log10(zmax);
9919 } else {
9920 return;
9921 }
9922 }
9923 Double_t dz = zmax - zmin;
9924 scale = (kNMAX-1)/dz;
9925
9926
9927 // use an independent instance of a random generator
9928 // instead of gRandom to avoid conflicts and
9929 // to get same random numbers when drawing the same histogram
9931
9932 TH2PolyBin *b;
9933
9934 TIter next(((TH2Poly*)fH)->GetBins());
9935 TObject *obj, *poly;
9936
9937 Double_t maxarea = 0, a;
9938 while ((obj=next())) {
9939 b = (TH2PolyBin*)obj;
9940 a = b->GetArea();
9941 if (a>maxarea) maxarea = a;
9942 }
9943
9944 next.Reset();
9945
9946 while ((obj=next())) {
9947 b = (TH2PolyBin*)obj;
9948 poly = b->GetPolygon();
9949 z = b->GetContent();
9950 if (z < zmin) z = zmin;
9951 if (z > zmax) z = zmax;
9952 if (Hoption.Logz) {
9953 if (z > 0) z = TMath::Log10(z) - zmin;
9954 } else {
9955 z -= zmin;
9956 }
9957 k = Int_t((z*scale)*(b->GetArea()/maxarea));
9958 xk = b->GetXMin();
9959 yk = b->GetYMin();
9960 xstep = b->GetXMax()-xk;
9961 ystep = b->GetYMax()-yk;
9962
9963 // Paint the TGraph bins.
9964 if (poly->IsA() == TGraph::Class()) {
9965 TGraph *g = (TGraph*)poly;
9966 if (k <= 0 || z <= 0) continue;
9967 loop = 0;
9968 while (loop<k) {
9969 if (k+marker >= kNMAX) {
9970 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
9971 marker=0;
9972 }
9973 xp = (random.Rndm()*xstep) + xk;
9974 yp = (random.Rndm()*ystep) + yk;
9975 if (g->IsInside(xp,yp)) {
9976 fXbuf[marker] = xp;
9977 fYbuf[marker] = yp;
9978 marker++;
9979 loop++;
9980 }
9981 }
9982 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
9983 }
9984
9985 // Paint the TMultiGraph bins.
9986 if (poly->IsA() == TMultiGraph::Class()) {
9988 TList *gl = mg->GetListOfGraphs();
9989 if (!gl) return;
9990 if (k <= 0 || z <= 0) continue;
9991 loop = 0;
9992 while (loop<k) {
9993 if (k+marker >= kNMAX) {
9994 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
9995 marker=0;
9996 }
9997 xp = (random.Rndm()*xstep) + xk;
9998 yp = (random.Rndm()*ystep) + yk;
9999 if (mg->IsInside(xp,yp)) {
10000 fXbuf[marker] = xp;
10001 fYbuf[marker] = yp;
10002 marker++;
10003 loop++;
10004 }
10005 }
10006 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10007 }
10008 }
10009 PaintTH2PolyBins("l");
10010}
10011
10012////////////////////////////////////////////////////////////////////////////////
10013/// [Control function to draw a TH2Poly as a text plot.](\ref HP20a)
10014
10016{
10017
10018 TLatex text;
10019 text.SetTextFont(gStyle->GetTextFont());
10020 text.SetTextColor(fH->GetMarkerColor());
10021 text.SetTextSize(0.02*fH->GetMarkerSize());
10022
10023 Double_t x, y, z, e, angle = 0;
10024 TString tt, tf;
10025 tf.Form("%s%s","%",gStyle->GetPaintTextFormat());
10026 if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
10027 Int_t opt = (Int_t)Hoption.Text/1000;
10028
10029 text.SetTextAlign(22);
10030 if (Hoption.Text == 1) angle = 0;
10031 text.SetTextAngle(angle);
10032 text.TAttText::Modify();
10033
10034 TH2PolyBin *b;
10035
10036 TIter next(((TH2Poly*)fH)->GetBins());
10037 TObject *obj, *p;
10038
10039 while ((obj=next())) {
10040 b = (TH2PolyBin*)obj;
10041 p = b->GetPolygon();
10042 x = (b->GetXMin()+b->GetXMax())/2;
10043 if (Hoption.Logx) {
10044 if (x > 0) x = TMath::Log10(x);
10045 else continue;
10046 }
10047 y = (b->GetYMin()+b->GetYMax())/2;
10048 if (Hoption.Logy) {
10049 if (y > 0) y = TMath::Log10(y);
10050 else continue;
10051 }
10052 z = b->GetContent();
10053 if (z < fH->GetMinimum() || (z == 0 && !Hoption.MinimumZero)) continue;
10054 if (opt==2) {
10055 e = fH->GetBinError(b->GetBinNumber());
10056 tf.Form("#splitline{%s%s}{#pm %s%s}",
10058 "%",gStyle->GetPaintTextFormat());
10059 tt.Form(tf.Data(),z,e);
10060 } else {
10061 tt.Form(tf.Data(),z);
10062 }
10063 if (opt==3) text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),p->GetName());
10064 else text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),tt.Data());
10065 }
10066
10067 PaintTH2PolyBins("l");
10068}
10069
10070////////////////////////////////////////////////////////////////////////////////
10071/// [Control function to draw a 1D/2D histograms with the bin values.](\ref HP15)
10072
10074{
10075
10076 TLatex text;
10077 text.SetTextFont(((int)gStyle->GetTextFont()/10)*10+2); // font precision must be 2
10078 text.SetTextColor(fH->GetMarkerColor());
10079 text.SetTextSize(0.02*fH->GetMarkerSize());
10080
10081 Double_t x, y, z, e, angle = 0;
10082 TString tt, tf;
10083 tf.Form("%s%s","%",gStyle->GetPaintTextFormat());
10084 if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
10085
10086 // 1D histograms
10087 if (fH->GetDimension() == 1) {
10089 Double_t yt;
10090 TProfile *hp = (TProfile*)fH;
10091 if (Hoption.Text>2000 && fH->InheritsFrom(TProfile::Class())) {
10092 Hoption.Text = Hoption.Text-2000;
10093 getentries = kTRUE;
10094 }
10095 if (Hoption.Text == 1) angle = 90;
10096 text.SetTextAlign(11);
10097 if (angle == 90) text.SetTextAlign(12);
10098 if (angle == 0) text.SetTextAlign(21);
10099 text.TAttText::Modify();
10100 Double_t dt = 0.02*(gPad->GetY2()-gPad->GetY1());
10101 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10102 if (Hoption.Bar) {
10103 x = fH->GetXaxis()->GetBinLowEdge(i)+
10104 fH->GetXaxis()->GetBinWidth(i)*
10105 (fH->GetBarOffset()+0.5*fH->GetBarWidth());
10106 } else {
10107 x = fH->GetXaxis()->GetBinCenter(i);
10108 }
10109 y = fH->GetBinContent(i);
10110 yt = y;
10111 if (Hoption.MinimumZero && y<0) y = 0;
10112 if (getentries) yt = hp->GetBinEntries(i);
10113 if (yt == 0.) continue;
10114 tt.Form(tf.Data(),yt);
10115 if (Hoption.Logx) {
10116 if (x > 0) x = TMath::Log10(x);
10117 else continue;
10118 }
10119 if (Hoption.Logy) {
10120 if (y > 0) y = TMath::Log10(y);
10121 else continue;
10122 }
10123 if (y >= gPad->GetY2()) continue;
10124 if (y <= gPad->GetY1()) continue;
10125 text.PaintLatex(x,y+0.2*dt,angle,0.02*fH->GetMarkerSize(),tt.Data());
10126 }
10127
10128 // 2D histograms
10129 } else {
10130 text.SetTextAlign(22);
10131 if (Hoption.Text == 1) angle = 0;
10132 text.SetTextAngle(angle);
10133 text.TAttText::Modify();
10134 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
10135 y = fYaxis->GetBinCenter(j);
10136 if (Hoption.Logy) {
10137 if (y > 0) y = TMath::Log10(y);
10138 else continue;
10139 }
10140 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10141 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
10142 x = fXaxis->GetBinCenter(i);
10143 if (Hoption.Logx) {
10144 if (x > 0) x = TMath::Log10(x);
10145 else continue;
10146 }
10147 if (!IsInside(x,y)) continue;
10148 z = fH->GetBinContent(bin);
10149 if (z < Hparam.zmin || (z == 0 && !Hoption.MinimumZero)) continue;
10150 if (Hoption.Text>2000) {
10151 e = fH->GetBinError(bin);
10152 tf.Form("#splitline{%s%s}{#pm %s%s}",
10154 "%",gStyle->GetPaintTextFormat());
10155 tt.Form(tf.Data(),z,e);
10156 } else {
10157 tt.Form(tf.Data(),z);
10158 }
10159 text.PaintLatex(x,y+fH->GetBarOffset()*fYaxis->GetBinWidth(j),
10160 angle,0.02*fH->GetMarkerSize(),tt.Data());
10161 }
10162 }
10163 }
10164}
10165
10166////////////////////////////////////////////////////////////////////////////////
10167/// [Control function to draw a 3D implicit functions.](\ref HP27)
10168
10170{
10171
10172 Int_t irep;
10173
10174 TAxis *xaxis = fH->GetXaxis();
10175 TAxis *yaxis = fH->GetYaxis();
10176 TAxis *zaxis = fH->GetZaxis();
10177
10178 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
10179 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
10180 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
10181 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
10182 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
10183 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
10184
10185 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
10186
10187 TView *view = gPad ? gPad->GetView() : nullptr;
10188 if (!view) {
10189 Error("PaintTF3", "no TView in current pad");
10190 return;
10191 }
10192 Double_t thedeg = 90 - gPad->GetTheta();
10193 Double_t phideg = -90 - gPad->GetPhi();
10194 Double_t psideg = view->GetPsi();
10195 view->SetView(phideg, thedeg, psideg, irep);
10196
10197 fLego->InitMoveScreen(-1.1,1.1);
10198
10199 if (Hoption.BackBox) {
10200 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
10202 fLego->BackBox(90);
10203 }
10204
10206
10207 fLego->ImplicitFunction(fCurrentF3, fXbuf.data(), fYbuf.data(), fH->GetNbinsX(),
10208 fH->GetNbinsY(),
10209 fH->GetNbinsZ(), "BF");
10210
10211 if (Hoption.FrontBox) {
10212 fLego->InitMoveScreen(-1.1,1.1);
10214 fLego->FrontBox(90);
10215 }
10216 if (!Hoption.Axis && !Hoption.Same) {
10217 TGaxis axis;
10218 PaintLegoAxis(&axis, 90);
10219 }
10220
10221 PaintTitle();
10222
10223 fLego.reset();
10224}
10225
10226/////////////////////////////////////////////////////////////new TGaxis///////////////////
10227/// Draw the histogram title
10228///
10229/// The title is drawn according to the title alignment returned by
10230/// `GetTitleAlign()`. It is a 2 digits integer): hv
10231///
10232/// where `h` is the horizontal alignment and `v` is the
10233/// vertical alignment.
10234///
10235/// - `h` can get the values 1 2 3 for left, center, and right
10236/// - `v` can get the values 1 2 3 for bottom, middle and top
10237///
10238/// for instance the default alignment is: 13 (left top)
10239
10241{
10242 // probably best place for calls PaintHighlightBin
10243 // calls after paint histo (1D or 2D) and before paint title and stats
10244 if (!gPad->GetView()) PaintHighlightBin();
10245
10246 if (Hoption.Same) return;
10247 if (fH->TestBit(TH1::kNoTitle)) return;
10248 Int_t nt = strlen(fH->GetTitle());
10249 TPaveText *title = nullptr;
10250 TObject *obj;
10251 TIter next(gPad->GetListOfPrimitives());
10252 while ((obj = next())) {
10253 if (!obj->InheritsFrom(TPaveText::Class())) continue;
10254 title = (TPaveText*)obj;
10255 if (strcmp(title->GetName(),"title")) {title = nullptr; continue;}
10256 break;
10257 }
10258 if (nt == 0 || gStyle->GetOptTitle() <= 0) {
10259 if (title) delete title;
10260 return;
10261 }
10264
10265 if (ht <= 0) {
10266 if (gStyle->GetTitleFont("")%10 == 3) {
10267 Double_t hw = TMath::Max((Double_t)gPad->XtoPixel(gPad->GetX2()),
10268 (Double_t)gPad->YtoPixel(gPad->GetY1()));
10269 ht = 1.1*(gStyle->GetTitleSize("")/hw);
10270 } else {
10271 ht = 1.1*gStyle->GetTitleFontSize();
10272 }
10273 }
10274 if (ht <= 0) ht = 0.05;
10275 if (wt <= 0) {
10276 TLatex l;
10277 l.SetTextSize(ht);
10278 l.SetTitle(fH->GetTitle());
10279 // adjustment in case the title has several lines (#splitline)
10280 ht = TMath::Max(ht, 1.2*l.GetYsize()/(gPad->GetY2() - gPad->GetY1()));
10281 Double_t wndc = l.GetXsize()/(gPad->GetX2() - gPad->GetX1());
10282 wt = TMath::Min(0.7, 0.02+wndc);
10283 }
10284 if (title) {
10285 TText *t0 = (TText*)title->GetLine(0);
10286 if (t0) {
10287 if (!strcmp(t0->GetTitle(),fH->GetTitle())) return;
10288 t0->SetTitle(fH->GetTitle());
10289 if (wt > 0) title->SetX2NDC(title->GetX1NDC()+wt);
10290 }
10291 return;
10292 }
10293
10295 if (talh < 1) talh = 1; else if (talh > 3) talh = 3;
10297 if (talv < 1) talv = 1; else if (talv > 3) talv = 3;
10299 xpos = gStyle->GetTitleX();
10300 ypos = gStyle->GetTitleY();
10301 if (talh == 2) xpos = xpos-wt/2.;
10302 if (talh == 3) xpos = xpos-wt;
10303 if (talv == 2) ypos = ypos+ht/2.;
10304 if (talv == 1) ypos = ypos+ht;
10305
10306 TPaveText *ptitle = new TPaveText(xpos, ypos-ht, xpos+wt, ypos,"blNDC");
10307
10308 // box with the histogram title
10309 ptitle->SetFillColor(gStyle->GetTitleFillColor());
10310 ptitle->SetFillStyle(gStyle->GetTitleStyle());
10311 ptitle->SetName("title");
10312 ptitle->SetBorderSize(gStyle->GetTitleBorderSize());
10313 ptitle->SetTextColor(gStyle->GetTitleTextColor());
10314 ptitle->SetTextFont(gStyle->GetTitleFont(""));
10315 if (gStyle->GetTitleFont("")%10 > 2)
10316 ptitle->SetTextSize(gStyle->GetTitleFontSize());
10317 ptitle->AddText(fH->GetTitle());
10318 ptitle->SetBit(kCanDelete);
10319 ptitle->Draw();
10320 ptitle->Paint("blNDC");
10321
10322 if(!gPad->IsEditable()) delete ptitle;
10323}
10324
10325////////////////////////////////////////////////////////////////////////////////
10326/// Process message `mess`.
10327
10328void THistPainter::ProcessMessage(const char *mess, const TObject *obj)
10329{
10330 if (!strcmp(mess,"SetF3")) {
10331 fCurrentF3 = (TF3 *)obj;
10332 }
10333}
10334
10335////////////////////////////////////////////////////////////////////////////////
10336/// Static function.
10337///
10338/// Convert Right Ascension, Declination to X,Y using an AITOFF projection.
10339/// This procedure can be used to create an all-sky map in Galactic
10340/// coordinates with an equal-area Aitoff projection. Output map
10341/// coordinates are zero longitude centered.
10342/// Also called Hammer-Aitoff projection (first presented by Ernst von Hammer in 1892)
10343///
10344/// source: GMT
10345///
10346/// code from Ernst-Jan Buis
10347
10349{
10350
10351 Double_t x, y;
10352
10354 Double_t delta = b*TMath::DegToRad();
10355 Double_t r2 = TMath::Sqrt(2.);
10356 Double_t f = 2*r2/TMath::Pi();
10357 Double_t cdec = TMath::Cos(delta);
10360 y = TMath::Sin(delta)*r2/denom;
10361 x *= TMath::RadToDeg()/f;
10362 y *= TMath::RadToDeg()/f;
10363 // x *= -1.; // for a skymap swap left<->right
10364 Al = x;
10365 Ab = y;
10366
10367 return 0;
10368}
10369
10370////////////////////////////////////////////////////////////////////////////////
10371/// Static function
10372///
10373/// Probably the most famous of the various map projections, the Mercator projection
10374/// takes its name from Mercator who presented it in 1569. It is a cylindrical, conformal projection
10375/// with no distortion along the equator.
10376/// The Mercator projection has been used extensively for world maps in which the distortion towards
10377/// the polar regions grows rather large, thus incorrectly giving the impression that, for example,
10378/// Greenland is larger than South America. In reality, the latter is about eight times the size of
10379/// Greenland. Also, the Former Soviet Union looks much bigger than Africa or South America. One may wonder
10380/// whether this illusion has had any influence on U.S. foreign policy.' (Source: GMT)
10381/// code from Ernst-Jan Buis
10382
10384{
10385
10386 Al = l;
10388 Ab = TMath::Log(aid);
10389 return 0;
10390}
10391
10392////////////////////////////////////////////////////////////////////////////////
10393/// Static function code for sinusoidal projection
10394/// from Ernst-Jan Buis
10395/// Source https://en.wikipedia.org/wiki/Sinusoidal_projection
10396
10398{
10399
10400 Al = l*cos(b*TMath::DegToRad());
10401 Ab = b;
10402 return 0;
10403}
10404
10405////////////////////////////////////////////////////////////////////////////////
10406/// Static function code for parabolic projection
10407/// from Ernst-Jan Buis
10408
10410{
10411
10412 Al = l*(2.*TMath::Cos(2*b*TMath::DegToRad()/3) - 1);
10413 Ab = 180*TMath::Sin(b*TMath::DegToRad()/3);
10414 return 0;
10415}
10416
10417////////////////////////////////////////////////////////////////////////////////
10418/// Static function.
10419///
10420/// Convert Right Ascension, Declination to X,Y using an MOLLWEIDE projection.
10421/// This procedure can be used to create an all-sky map in Galactic
10422/// coordinates with an equal-area Mollweide projection. Output map
10423/// coordinates are zero longitude centered.
10424/// It is also known as the Babinet projection, homalographic projection, homolographic projection, and elliptical projection.
10425/// Source: https://en.wikipedia.org/wiki/Mollweide_projection
10426///
10427/// code from Marco Meyer-Conde
10428
10430{
10431
10432 Double_t theta0 = b * TMath::DegToRad(), theta = theta0;
10433
10434 for (int i = 0; i < 100; i++) {
10435 Double_t num = 2 * theta + TMath::Sin(2 * theta) - TMath::Pi() * TMath::Sin(theta0);
10436 Double_t den = 4 * TMath::Power(TMath::Cos(theta), 2);
10437
10438 if (den < 1e-20) {
10439 theta = theta0;
10440 break;
10441 }
10442
10443 theta -= num / den;
10444
10445 if (TMath::Abs(num / den) < 1e-4) break;
10446 }
10447
10448 Al = l * TMath::Cos(theta);
10449 Ab = 90 * TMath::Sin(theta);
10450
10451 return 0;
10452}
10453
10454////////////////////////////////////////////////////////////////////////////////
10455/// Recompute the histogram range following graphics operations.
10456
10458{
10459
10460 if (Hoption.Same) return;
10461
10462 // Compute x,y range
10464 xmax = Hparam.xmax,
10465 ymin = Hparam.ymin,
10466 ymax = Hparam.ymax,
10467 xscale = 1;
10468
10469 std::function<Int_t(Double_t,Double_t,Double_t&,Double_t&)> func;
10470
10471 if (Hoption.Proj == 1) {
10472 func = ProjectAitoff2xy;
10473 xscale = 0.9999;
10474 } else if (Hoption.Proj == 2) {
10475 if (Hparam.ymin <= -90 || Hparam.ymax >= 90) {
10476 Warning("Mercator Projection", "Latitude out of range %f or %f", Hparam.ymin, Hparam.ymax);
10477 Hoption.Proj = 0;
10478 } else {
10481 }
10482 } else if (Hoption.Proj == 3) {
10483 func = ProjectSinusoidal2xy;
10484 } else if (Hoption.Proj == 4) {
10485 func = ProjectParabolic2xy;
10486 } else if (Hoption.Proj == 5) {
10487 func = ProjectMollweide2xy;
10488 }
10489
10490 if (func) {
10492
10496 func(Hparam.xmax, Hparam.ymin, xmax, ymin);
10497
10498 if (xmin > xmin_aid) xmin = xmin_aid;
10499 if (ymin > ymin_aid) ymin = ymin_aid;
10500 if (xmax < xmax_aid) xmax = xmax_aid;
10501 if (ymax < ymax_aid) ymax = ymax_aid;
10502 if (Hparam.ymin < 0 && Hparam.ymax > 0) {
10503 // there is an 'equator', check its range in the plot..
10504 func(Hparam.xmin*xscale, 0, xmin_aid, ymin_aid);
10505 func(Hparam.xmax*xscale, 0, xmax_aid, ymin_aid);
10506 if (xmin > xmin_aid) xmin = xmin_aid;
10507 if (xmax < xmax_aid) xmax = xmax_aid;
10508 }
10509 if (Hparam.xmin < 0 && Hparam.xmax > 0) {
10510 func(0, Hparam.ymin, xmin_aid, ymin_aid);
10511 func(0, Hparam.ymax, xmax_aid, ymax_aid);
10512 if (ymin > ymin_aid) ymin = ymin_aid;
10513 if (ymax < ymax_aid) ymax = ymax_aid;
10514 }
10515 }
10516
10517 Hparam.xmin = xmin;
10518 Hparam.xmax = xmax;
10519 Hparam.ymin = ymin;
10520 Hparam.ymax = ymax;
10521
10522 Double_t dx = xmax-xmin;
10523 Double_t dy = ymax-ymin;
10524 Double_t dxr = dx/(1 - gPad->GetLeftMargin() - gPad->GetRightMargin());
10525 Double_t dyr = dy/(1 - gPad->GetBottomMargin() - gPad->GetTopMargin());
10526
10527 // Range() could change the size of the pad pixmap and therefore should
10528 // be called before the other paint routines
10529 gPad->Range(xmin - dxr*gPad->GetLeftMargin(),
10530 ymin - dyr*gPad->GetBottomMargin(),
10531 xmax + dxr*gPad->GetRightMargin(),
10532 ymax + dyr*gPad->GetTopMargin());
10533 gPad->RangeAxis(xmin, ymin, xmax, ymax);
10534}
10535
10536////////////////////////////////////////////////////////////////////////////////
10537/// Set current histogram to `h`
10538
10540{
10541
10542 if (h == nullptr) return;
10543 fH = h;
10544 fXaxis = h->GetXaxis();
10545 fYaxis = h->GetYaxis();
10546 fZaxis = h->GetZaxis();
10548}
10549
10550////////////////////////////////////////////////////////////////////////////////
10551/// Initialize various options to draw 2D histograms.
10552
10554{
10555
10556 static const char *where = "TableInit";
10557
10558 Int_t first, last;
10560 Double_t zmin, zmax;
10561 Int_t maximum = 0;
10562 Int_t minimum = 0;
10563 if (fH->GetMaximumStored() != -1111) maximum = 1;
10564 if (fH->GetMinimumStored() != -1111) minimum = 1;
10565
10566 // ----------------- Compute X axis parameters
10567 first = fXaxis->GetFirst();
10568 last = fXaxis->GetLast();
10569 Hparam.xlast = last;
10570 Hparam.xfirst = first;
10575
10576 // if log scale in X, replace xmin,max by the log
10577 if (Hoption.Logx) {
10578 // find the first edge of a bin that is > 0
10579 if (Hparam.xlowedge <=0 ) {
10582 }
10583 if (Hparam.xmin <=0 || Hparam.xmax <=0) {
10584 Error(where, "cannot set X axis to log scale");
10585 return 0;
10586 }
10588 if (Hparam.xfirst < first) Hparam.xfirst = first;
10590 if (Hparam.xlast > last) Hparam.xlast = last;
10593 }
10594
10595 // ----------------- Compute Y axis parameters
10596 first = fYaxis->GetFirst();
10597 last = fYaxis->GetLast();
10598 Hparam.ylast = last;
10599 Hparam.yfirst = first;
10602 if (!Hparam.ybinsize) Hparam.ybinsize = 1;
10605
10606 // if log scale in Y, replace ymin,max by the log
10607 if (Hoption.Logy) {
10608 if (Hparam.ylowedge <=0 ) {
10611 }
10612 if (Hparam.ymin <=0 || Hparam.ymax <=0) {
10613 Error(where, "cannot set Y axis to log scale");
10614 return 0;
10615 }
10617 if (Hparam.yfirst < first) Hparam.yfirst = first;
10619 if (Hparam.ylast > last) Hparam.ylast = last;
10622 }
10623
10624
10625 // ----------------- Compute Z axis parameters
10626 Double_t bigp = TMath::Power(10,32);
10627 zmax = -bigp;
10628 zmin = bigp;
10629 Double_t c1, e1;
10630 Double_t allchan = 0;
10631 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
10632 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10633 c1 = fH->GetBinContent(i,j);
10634 zmax = TMath::Max(zmax,c1);
10635 if (Hoption.Error) {
10636 e1 = fH->GetBinError(i,j);
10637 zmax = TMath::Max(zmax,c1+e1);
10638 }
10639 zmin = TMath::Min(zmin,c1);
10640 allchan += c1;
10641 }
10642 }
10643
10644 // Take into account maximum , minimum
10645
10646 if (maximum) zmax = fH->GetMaximumStored();
10647 if (minimum) zmin = fH->GetMinimumStored();
10648 if (Hoption.Logz && zmax < 0) {
10649 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10650 return 0;
10651 } else if (Hoption.Logz && zmin>=0 && zmax==0) { // empty histogram in log scale
10652 zmin = 0.01;
10653 zmax = 10.;
10654 }
10655 if (zmin >= zmax) {
10656 if (Hoption.Logz) {
10657 if (zmax > 0) zmin = 0.001*zmax;
10658 else {
10659 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10660 return 0;
10661 }
10662 }
10663 }
10664
10665 // take into account normalization factor
10666 Hparam.allchan = allchan;
10667 Double_t factor = allchan;
10668 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
10669 if (allchan) factor /= allchan;
10670 if (factor == 0) factor = 1;
10671 Hparam.factor = factor;
10672 zmax = factor*zmax;
10673 zmin = factor*zmin;
10674 c1 = zmax;
10675 if (TMath::Abs(zmin) > TMath::Abs(c1)) c1 = zmin;
10676
10677 // For log scales, histogram coordinates are log10(ymin) and
10678 // log10(ymax). Final adjustment (if not option "Same")
10679 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
10680 // Maximum and Minimum are not defined.
10681 if (Hoption.Logz) {
10682 if (zmin <= 0) {
10683 zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
10684 fH->SetMinimum(zmin);
10685 }
10686 zmin = TMath::Log10(zmin);
10687 if (!minimum) zmin += TMath::Log10(0.5);
10688 zmax = TMath::Log10(zmax);
10689 if (!maximum) zmax += TMath::Log10(2*(0.9/0.95));
10690 goto LZMIN;
10691 }
10692
10693 // final adjustment of YMAXI for linear scale (if not option "Same"):
10694 // decrease histogram height to MAX% of allowed height if HMAXIM
10695 // has not been called.
10696 // MAX% is the value in percent which has been set in HPLSET
10697 // (default is 90%).
10698 if (!maximum) {
10699 zmax += yMARGIN*(zmax-zmin);
10700 }
10701
10702 // final adjustment of ymin for linear scale.
10703 // if minimum is not set , then ymin is set to zero if >0
10704 // or to ymin - yMARGIN if <0.
10705 if (!minimum) {
10706 if (Hoption.MinimumZero) {
10707 if (zmin >= 0) zmin = 0;
10708 else zmin -= yMARGIN*(zmax-zmin);
10709 } else {
10710 Double_t dzmin = yMARGIN*(zmax-zmin);
10711 if (zmin >= 0 && (zmin-dzmin <= 0)) zmin = 0;
10712 else zmin -= dzmin;
10713 }
10714 }
10715
10716LZMIN:
10717 Hparam.zmin = zmin;
10718 Hparam.zmax = zmax;
10719
10720 // Set bar offset and width
10723
10724 return 1;
10725}
10726
10727////////////////////////////////////////////////////////////////////////////////
10728/// This function returns the best format to print the error value (e)
10729/// knowing the parameter value (v) and the format (f) used to print it.
10730
10732{
10733
10734 static TString ef;
10735 TString tf, tv;
10736
10737 // print v with the format f in tv.
10738 tf.Form("%s%s","%",f);
10739 tv.Form(tf.Data(),v);
10740
10741 // Analyse tv.
10742 int ie = tv.Index("e");
10743 int iE = tv.Index("E");
10744 int id = tv.Index(".");
10745
10746 // v has been printed with the exponent notation.
10747 // There is 2 cases, the exponent is positive or negative
10748 if (ie >= 0 || iE >= 0) {
10749 if (tv.Index("+") >= 0) {
10750 if (e < 1) {
10751 ef.Form("%s.1f","%");
10752 } else {
10753 if (ie >= 0) {
10754 ef.Form("%s.%de","%",ie-id-1);
10755 } else {
10756 ef.Form("%s.%dE","%",iE-id-1);
10757 }
10758 }
10759 } else {
10760 if (ie >= 0) {
10761 ef.Form("%s.%de","%",ie-id-1);
10762 } else {
10763 ef.Form("%s.%dE","%",iE-id-1);
10764 }
10765 }
10766
10767 // There is not '.' in tv. e will be printed with one decimal digit.
10768 } else if (id < 0) {
10769 ef.Form("%s.1f","%");
10770
10771 // There is a '.' in tv and no exponent notation. e's decimal part will
10772 // have the same number of digits as v's one.
10773 } else {
10774 ef.Form("%s.%df","%",tv.Length()-id-1);
10775 }
10776
10777 return ef.Data();
10778}
10779
10780////////////////////////////////////////////////////////////////////////////////
10781/// Set projection.
10782
10784{
10785 if (fShowProjection2) {
10786 auto name2 = TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2);
10787 auto c2 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name2.Data()));
10788 if (c2) c2->Close();
10789 fShowProjection2 = 0;
10790 }
10791 if (fShowProjection) {
10792 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10793 auto c1 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name1.Data()));
10794 if (c1) c1->Close();
10795 fShowProjection = 0;
10796 }
10797
10798 if (nbins <= 0) return;
10799
10800 TString opt = option;
10801 opt.ToLower();
10802 Int_t projection = 0;
10803 if (opt.Contains("x")) projection = 1;
10804 if (opt.Contains("y")) projection = 2;
10805 if (opt.Contains("z")) projection = 3;
10806 if (opt.Contains("xy")) projection = 4;
10807 if (opt.Contains("yx")) projection = 5;
10808 if (opt.Contains("xz")) projection = 6;
10809 if (opt.Contains("zx")) projection = 7;
10810 if (opt.Contains("yz")) projection = 8;
10811 if (opt.Contains("zy")) projection = 9;
10812 if (projection < 4) fShowOption = option+1;
10813 else fShowOption = option+2;
10814 fShowProjection = projection+100*nbins;
10815 fShowProjection2 = 0;
10816 gROOT->MakeDefCanvas();
10817 gPad->SetName(TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection).Data());
10818 gPad->SetGrid();
10819}
10820
10822{
10823 if (fShowProjection2) {
10824 auto name2 = TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2);
10825 auto c2 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name2.Data()));
10826 if (c2) c2->Close();
10827 fShowProjection2 = 0;
10828 }
10829 if (fShowProjection) {
10830 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10831 auto c1 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name1.Data()));
10832 if (c1) c1->Close();
10833 fShowProjection = 0;
10834 }
10835
10836 if ((nbinsX <= 0) || (nbinsY <= 0)) return;
10837
10838
10839 TString opt = option;
10840 opt.ToLower();
10841 Int_t projection = 0;
10842 if (opt.Contains("x")) projection = 1;
10843 if (opt.Contains("y")) projection = 2;
10844 if (opt.Contains("z")) projection = 3;
10845 if (opt.Contains("xy")) projection = 4;
10846 if (opt.Contains("yx")) projection = 5;
10847 if (opt.Contains("xz")) projection = 6;
10848 if (opt.Contains("zx")) projection = 7;
10849 if (opt.Contains("yz")) projection = 8;
10850 if (opt.Contains("zy")) projection = 9;
10851 if (projection < 4) fShowOption = option+1;
10852 else fShowOption = option+2;
10855 gROOT->MakeDefCanvas();
10856 gPad->SetName(TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection).Data());
10857 gPad->SetGrid();
10858 gROOT->MakeDefCanvas();
10859 gPad->SetName(TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2).Data());
10860 gPad->SetGrid();
10861}
10862
10863
10864////////////////////////////////////////////////////////////////////////////////
10865/// Show projection onto X.
10866
10868{
10869
10870 Int_t nbins = (Int_t)fShowProjection/100;
10871 gPad->SetDoubleBuffer(0); // turn off double buffer mode
10872 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
10873
10874 // Erase old position and draw a line at current position
10875 static int pyold1 = 0;
10876 static int pyold2 = 0;
10877 float uxmin = gPad->GetUxmin();
10878 float uxmax = gPad->GetUxmax();
10879 int pxmin = gPad->XtoAbsPixel(uxmin);
10880 int pxmax = gPad->XtoAbsPixel(uxmax);
10881 Float_t upy = gPad->AbsPixeltoY(py);
10882 Float_t y = gPad->PadtoY(upy);
10883 Int_t biny1 = fH->GetYaxis()->FindBin(y);
10884 Int_t biny2 = TMath::Min(biny1+nbins-1, fH->GetYaxis()->GetNbins());
10885 Int_t py1 = gPad->YtoAbsPixel(gPad->GetLogy() ? TMath::Log10(fH->GetYaxis()->GetBinLowEdge(biny1)) : fH->GetYaxis()->GetBinLowEdge(biny1));
10886 Int_t py2 = gPad->YtoAbsPixel(gPad->GetLogy() ? TMath::Log10(fH->GetYaxis()->GetBinUpEdge(biny2)) : fH->GetYaxis()->GetBinUpEdge(biny2));
10887
10889 gVirtualX->DrawBox(pxmin,py1,pxmax,py2,TVirtualX::kFilled);
10890 pyold1 = py1;
10891 pyold2 = py2;
10892
10893 // Create or set the new canvas proj x
10895 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10896 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(name1.Data());
10897 if (c) {
10898 c->Clear();
10899 } else {
10900 fShowProjection = 0;
10901 fShowProjection2 = 0;
10902 pyold1 = 0;
10903 pyold2 = 0;
10904 return;
10905 }
10906 c->cd();
10907 c->SetLogy(ctxt.GetSaved()->GetLogz());
10908 c->SetLogx(ctxt.GetSaved()->GetLogx());
10909
10910 // Draw slice corresponding to mouse position
10911 TString prjName = TString::Format("slice_px_of_%s",fH->GetName());
10912 TH1D *hp = ((TH2*)fH)->ProjectionX(prjName, biny1, biny2);
10913 if (hp) {
10914 hp->SetFillColor(38);
10915 // apply a patch from Oliver Freyermuth to set the title in the projection
10916 // using the range of the projected Y values
10917 if (biny1 == biny2) {
10920 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
10922 if (fH->GetYaxis()->GetLabels() != nullptr) {
10923 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf] %s", biny1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetYaxis()->GetBinLabel(biny1)));
10924 } else {
10925 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf]", biny1, valuePrecision, valueFrom, valuePrecision, valueTo));
10926 }
10927 } else {
10930 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
10931 // biny1 is used here to get equal precision no matter how large the binrange is,
10932 // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
10934 if (fH->GetYaxis()->GetLabels() != nullptr) {
10935 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)));
10936 } else {
10937 hp->SetTitle(TString::Format("ProjectionX of biny=[%d,%d] [y=%.*lf..%.*lf]", biny1, biny2, valuePrecision, valueFrom, valuePrecision, valueTo));
10938 }
10939 }
10940 hp->SetXTitle(fH->GetXaxis()->GetTitle());
10941 hp->SetYTitle(((TH2*)fH)->GetZaxis()->GetTitle() ? ((TH2*)fH)->GetZaxis()->GetTitle() : "Number of Entries");
10942 hp->Draw();
10943 c->Update();
10944 }
10945}
10946
10947////////////////////////////////////////////////////////////////////////////////
10948/// Show projection onto Y.
10949
10951{
10952
10953 Int_t nbins = (Int_t)fShowProjection/100;
10954 if (fShowProjection2)
10955 nbins = (Int_t)fShowProjection2/100;
10956 gPad->SetDoubleBuffer(0); // turn off double buffer mode
10957 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
10958
10959 // Erase old position and draw a line at current position
10960 static int pxold1 = 0;
10961 static int pxold2 = 0;
10962 float uymin = gPad->GetUymin();
10963 float uymax = gPad->GetUymax();
10964 int pymin = gPad->YtoAbsPixel(uymin);
10965 int pymax = gPad->YtoAbsPixel(uymax);
10966 Float_t upx = gPad->AbsPixeltoX(px);
10967 Float_t x = gPad->PadtoX(upx);
10968 Int_t binx1 = fH->GetXaxis()->FindBin(x);
10969 Int_t binx2 = TMath::Min(binx1+nbins-1, fH->GetXaxis()->GetNbins());
10970 Int_t px1 = gPad->XtoAbsPixel(gPad->GetLogx() ? TMath::Log10(fH->GetXaxis()->GetBinLowEdge(binx1)) : fH->GetXaxis()->GetBinLowEdge(binx1));
10971 Int_t px2 = gPad->XtoAbsPixel(gPad->GetLogx() ? TMath::Log10(fH->GetXaxis()->GetBinUpEdge(binx2)) : fH->GetXaxis()->GetBinUpEdge(binx2));
10972
10974 gVirtualX->DrawBox(px1,pymin,px2,pymax,TVirtualX::kFilled);
10975 pxold1 = px1;
10976 pxold2 = px2;
10977
10978 // Create or set the new canvas proj y
10980
10981 TString name2 = fShowProjection2 ? TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2)
10982 : TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10983
10984 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(name2.Data());
10985 if (c) {
10986 c->Clear();
10987 } else {
10988 fShowProjection = 0;
10989 fShowProjection2 = 0;
10990 pxold1 = 0;
10991 pxold2 = 0;
10992 return;
10993 }
10994 c->cd();
10995 c->SetLogy(ctxt.GetSaved()->GetLogz());
10996 c->SetLogx(ctxt.GetSaved()->GetLogy());
10997
10998 // Draw slice corresponding to mouse position
10999 TString prjName = TString::Format("slice_py_of_%s",fH->GetName());
11000 TH1D *hp = ((TH2*)fH)->ProjectionY(prjName, binx1, binx2);
11001 if (hp) {
11002 hp->SetFillColor(38);
11003 // apply a patch from Oliver Freyermuth to set the title in the projection
11004 // using the range of the projected X values
11005 if (binx1 == binx2) {
11008 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11010 if (fH->GetXaxis()->GetLabels() != nullptr) {
11011 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf] [%s]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetXaxis()->GetBinLabel(binx1)));
11012 } else {
11013 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo));
11014 }
11015 } else {
11018 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11019 // binx1 is used here to get equal precision no matter how large the binrange is,
11020 // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
11022 if (fH->GetXaxis()->GetLabels() != nullptr) {
11023 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)));
11024 } else {
11025 hp->SetTitle(TString::Format("ProjectionY of binx=[%d,%d] [x=%.*lf..%.*lf]", binx1, binx2, valuePrecision, valueFrom, valuePrecision, valueTo));
11026 }
11027 }
11028 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11029 hp->SetYTitle(((TH2*)fH)->GetZaxis()->GetTitle() ? ((TH2*)fH)->GetZaxis()->GetTitle() : "Number of Entries");
11030 hp->Draw(fShowProjection2 ? "hbar" : "");
11031 c->Update();
11032 }
11033}
11034
11035////////////////////////////////////////////////////////////////////////////////
11036/// Show projection (specified by `fShowProjection`) of a `TH3`.
11037/// The drawing option for the projection is in `fShowOption`.
11038///
11039/// First implementation; R.Brun
11040///
11041/// Full implementation: Tim Tran (timtran@jlab.org) April 2006
11042
11044{
11045
11046 Int_t nbins=(Int_t)fShowProjection/100; //decode nbins
11047 if (fH->GetDimension() < 3) {
11048 if (fShowProjection2 % 100 == 1) {
11049 ShowProjectionY(px, py);
11050 }
11051 if (fShowProjection % 100 == 1) {
11052 ShowProjectionX(px, py);
11053 return;
11054 }
11055 if (fShowProjection % 100 == 2) {
11056 ShowProjectionY(px, py);
11057 return;
11058 }
11059 }
11060
11061 gPad->SetDoubleBuffer(0); // turn off double buffer mode
11062 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
11063
11064 // Erase old position and draw a line at current position
11065 TView *view = gPad->GetView();
11066 if (!view) return;
11067 TH3 *h3 = (TH3*)fH;
11068 TAxis *xaxis = h3->GetXaxis();
11069 TAxis *yaxis = h3->GetYaxis();
11070 TAxis *zaxis = h3->GetZaxis();
11071 Double_t u[3],xx[3];
11072
11073 static TPoint line1[2];//store end points of a line, initialised 0 by default
11074 static TPoint line2[2];// second line when slice thickness > 1 bin thickness
11075 static TPoint line3[2];
11076 static TPoint line4[2];
11077 static TPoint endface1[5];
11078 static TPoint endface2[5];
11079 static TPoint rect1[5];//store vertices of the polyline (rectangle), initialsed 0 by default
11080 static TPoint rect2[5];// second rectangle when slice thickness > 1 bin thickness
11081
11082 Double_t uxmin = gPad->GetUxmin();
11083 Double_t uxmax = gPad->GetUxmax();
11084 Double_t uymin = gPad->GetUymin();
11085 Double_t uymax = gPad->GetUymax();
11086
11087 int pxmin = gPad->XtoAbsPixel(uxmin);
11088 int pxmax = gPad->XtoAbsPixel(uxmax);
11089 if (pxmin==pxmax) return;
11090 int pymin = gPad->YtoAbsPixel(uymin);
11091 int pymax = gPad->YtoAbsPixel(uymax);
11092 if (pymin==pymax) return;
11095 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(TString::Format("c_%zx_projection_%d",
11096 (size_t)fH, fShowProjection).Data());
11097 if (!c) {
11098 fShowProjection = 0;
11099 return;
11100 }
11101
11103
11104 switch ((Int_t)fShowProjection%100) {
11105 case 1:
11106 // "x"
11107 {
11108 Int_t firstY = yaxis->GetFirst();
11109 Int_t lastY = yaxis->GetLast();
11111 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11112 yaxis->SetRange(biny,biny2);
11113 Int_t firstZ = zaxis->GetFirst();
11114 Int_t lastZ = zaxis->GetLast();
11116 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11117 zaxis->SetRange(binz,binz2);
11118 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11119 if (nbins>1 && line1[0].GetX()) {
11120 gVirtualX->DrawPolyLine(2,line2);
11121 gVirtualX->DrawPolyLine(2,line3);
11122 gVirtualX->DrawPolyLine(2,line4);
11123 gVirtualX->DrawPolyLine(5,endface1);
11124 gVirtualX->DrawPolyLine(5,endface2);
11125 }
11126 xx[0] = xaxis->GetXmin();
11127 xx[2] = zaxis->GetBinCenter(binz);
11128 xx[1] = yaxis->GetBinCenter(biny);
11129 view->WCtoNDC(xx,u);
11130 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11131 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11132 xx[0] = xaxis->GetXmax();
11133 view->WCtoNDC(xx,u);
11134 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11135 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11136 gVirtualX->DrawPolyLine(2,line1);
11137 if (nbins>1) {
11138 xx[0] = xaxis->GetXmin();
11139 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11140 xx[1] = yaxis->GetBinCenter(biny);
11141 view->WCtoNDC(xx,u);
11142 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11143 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11144 xx[0] = xaxis->GetXmax();
11145 view->WCtoNDC(xx,u);
11146 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11147 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11148
11149 xx[0] = xaxis->GetXmin();
11150 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11151 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11152 view->WCtoNDC(xx,u);
11153 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11154 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11155 xx[0] = xaxis->GetXmax();
11156 view->WCtoNDC(xx,u);
11157 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11158 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11159
11160 xx[0] = xaxis->GetXmin();
11161 xx[2] = zaxis->GetBinCenter(binz);
11162 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11163 view->WCtoNDC(xx,u);
11164 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11165 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11166 xx[0] = xaxis->GetXmax();
11167 view->WCtoNDC(xx,u);
11168 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11169 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11170
11171 endface1[0].SetX(line1[0].GetX());
11172 endface1[0].SetY(line1[0].GetY());
11173 endface1[1].SetX(line2[0].GetX());
11174 endface1[1].SetY(line2[0].GetY());
11175 endface1[2].SetX(line3[0].GetX());
11176 endface1[2].SetY(line3[0].GetY());
11177 endface1[3].SetX(line4[0].GetX());
11178 endface1[3].SetY(line4[0].GetY());
11179 endface1[4].SetX(line1[0].GetX());
11180 endface1[4].SetY(line1[0].GetY());
11181
11182 endface2[0].SetX(line1[1].GetX());
11183 endface2[0].SetY(line1[1].GetY());
11184 endface2[1].SetX(line2[1].GetX());
11185 endface2[1].SetY(line2[1].GetY());
11186 endface2[2].SetX(line3[1].GetX());
11187 endface2[2].SetY(line3[1].GetY());
11188 endface2[3].SetX(line4[1].GetX());
11189 endface2[3].SetY(line4[1].GetY());
11190 endface2[4].SetX(line1[1].GetX());
11191 endface2[4].SetY(line1[1].GetY());
11192
11193 gVirtualX->DrawPolyLine(2,line2);
11194 gVirtualX->DrawPolyLine(2,line3);
11195 gVirtualX->DrawPolyLine(2,line4);
11196 gVirtualX->DrawPolyLine(5,endface1);
11197 gVirtualX->DrawPolyLine(5,endface2);
11198 }
11199 c->Clear();
11200 c->cd();
11201 TH1 *hp = h3->Project3D("x");
11202 yaxis->SetRange(firstY,lastY);
11203 zaxis->SetRange(firstZ,lastZ);
11204 if (hp) {
11205 hp->SetFillColor(38);
11206 if (nbins == 1)
11207 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny),
11208 binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
11209 else {
11210 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),
11211 binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
11212 }
11213 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11214 hp->SetYTitle("Number of Entries");
11215 hp->Draw(fShowOption.Data());
11216 }
11217 }
11218 break;
11219
11220 case 2:
11221 // "y"
11222 {
11223 Int_t firstX = xaxis->GetFirst();
11224 Int_t lastX = xaxis->GetLast();
11226 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11227 xaxis->SetRange(binx,binx2);
11228 Int_t firstZ = zaxis->GetFirst();
11229 Int_t lastZ = zaxis->GetLast();
11231 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11232 zaxis->SetRange(binz,binz2);
11233 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11234 if (nbins>1 && line1[0].GetX()) {
11235 gVirtualX->DrawPolyLine(2,line2);
11236 gVirtualX->DrawPolyLine(2,line3);
11237 gVirtualX->DrawPolyLine(2,line4);
11238 gVirtualX->DrawPolyLine(5,endface1);
11239 gVirtualX->DrawPolyLine(5,endface2);
11240 }
11241 xx[0]=xaxis->GetBinCenter(binx);
11242 xx[2] = zaxis->GetBinCenter(binz);
11243 xx[1] = yaxis->GetXmin();
11244 view->WCtoNDC(xx,u);
11245 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11246 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11247 xx[1] = yaxis->GetXmax();
11248 view->WCtoNDC(xx,u);
11249 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11250 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11251 gVirtualX->DrawPolyLine(2,line1);
11252 if (nbins>1) {
11253 xx[1] = yaxis->GetXmin();
11254 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11255 xx[0] = xaxis->GetBinCenter(binx);
11256 view->WCtoNDC(xx,u);
11257 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11258 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11259 xx[1] = yaxis->GetXmax();
11260 view->WCtoNDC(xx,u);
11261 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11262 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11263
11264 xx[1] = yaxis->GetXmin();
11265 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11266 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11267 view->WCtoNDC(xx,u);
11268 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11269 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11270 xx[1] = yaxis->GetXmax();
11271 view->WCtoNDC(xx,u);
11272 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11273 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11274
11275 xx[1] = yaxis->GetXmin();
11276 xx[2] = zaxis->GetBinCenter(binz);
11277 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11278 view->WCtoNDC(xx,u);
11279 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11280 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11281 xx[1] = yaxis->GetXmax();
11282 view->WCtoNDC(xx,u);
11283 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11284 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11285
11286 endface1[0].SetX(line1[0].GetX());
11287 endface1[0].SetY(line1[0].GetY());
11288 endface1[1].SetX(line2[0].GetX());
11289 endface1[1].SetY(line2[0].GetY());
11290 endface1[2].SetX(line3[0].GetX());
11291 endface1[2].SetY(line3[0].GetY());
11292 endface1[3].SetX(line4[0].GetX());
11293 endface1[3].SetY(line4[0].GetY());
11294 endface1[4].SetX(line1[0].GetX());
11295 endface1[4].SetY(line1[0].GetY());
11296
11297 endface2[0].SetX(line1[1].GetX());
11298 endface2[0].SetY(line1[1].GetY());
11299 endface2[1].SetX(line2[1].GetX());
11300 endface2[1].SetY(line2[1].GetY());
11301 endface2[2].SetX(line3[1].GetX());
11302 endface2[2].SetY(line3[1].GetY());
11303 endface2[3].SetX(line4[1].GetX());
11304 endface2[3].SetY(line4[1].GetY());
11305 endface2[4].SetX(line1[1].GetX());
11306 endface2[4].SetY(line1[1].GetY());
11307
11308 gVirtualX->DrawPolyLine(2,line2);
11309 gVirtualX->DrawPolyLine(2,line3);
11310 gVirtualX->DrawPolyLine(2,line4);
11311 gVirtualX->DrawPolyLine(5,endface1);
11312 gVirtualX->DrawPolyLine(5,endface2);
11313 }
11314 c->Clear();
11315 c->cd();
11316 TH1 *hp = h3->Project3D("y");
11317 xaxis->SetRange(firstX,lastX);
11318 zaxis->SetRange(firstZ,lastZ);
11319 if (hp) {
11320 hp->SetFillColor(38);
11321 if (nbins == 1)
11322 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
11323 binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
11324 else
11325 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),
11326 binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
11327 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11328 hp->SetYTitle("Number of Entries");
11329 hp->Draw(fShowOption.Data());
11330 }
11331 }
11332 break;
11333
11334 case 3:
11335 // "z"
11336 {
11337 Int_t firstX = xaxis->GetFirst();
11338 Int_t lastX = xaxis->GetLast();
11340 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11341 xaxis->SetRange(binx,binx2);
11342 Int_t firstY = yaxis->GetFirst();
11343 Int_t lastY = yaxis->GetLast();
11345 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11346 yaxis->SetRange(biny,biny2);
11347 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11348 if (nbins>1 && line1[0].GetX()) {
11349 gVirtualX->DrawPolyLine(2,line2);
11350 gVirtualX->DrawPolyLine(2,line3);
11351 gVirtualX->DrawPolyLine(2,line4);
11352 gVirtualX->DrawPolyLine(5,endface1);
11353 gVirtualX->DrawPolyLine(5,endface2);
11354 }
11355 xx[0] = xaxis->GetBinCenter(binx);
11356 xx[1] = yaxis->GetBinCenter(biny);
11357 xx[2] = zaxis->GetXmin();
11358 view->WCtoNDC(xx,u);
11359 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11360 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11361 xx[2] = zaxis->GetXmax();
11362 view->WCtoNDC(xx,u);
11363 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11364 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11365 gVirtualX->DrawPolyLine(2,line1);
11366 if (nbins>1) {
11367 xx[2] = zaxis->GetXmin();
11368 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11369 xx[0] = xaxis->GetBinCenter(binx);
11370 view->WCtoNDC(xx,u);
11371 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11372 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11373 xx[2] = zaxis->GetXmax();
11374 view->WCtoNDC(xx,u);
11375 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11376 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11377
11378 xx[2] = zaxis->GetXmin();
11379 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11380 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11381 view->WCtoNDC(xx,u);
11382 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11383 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11384 xx[2] = zaxis->GetXmax();
11385 view->WCtoNDC(xx,u);
11386 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11387 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11388
11389 xx[2] = zaxis->GetXmin();
11390 xx[1] = yaxis->GetBinCenter(biny);
11391 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11392 view->WCtoNDC(xx,u);
11393 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11394 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11395 xx[2] = zaxis->GetXmax();
11396 view->WCtoNDC(xx,u);
11397 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11398 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11399
11400 endface1[0].SetX(line1[0].GetX());
11401 endface1[0].SetY(line1[0].GetY());
11402 endface1[1].SetX(line2[0].GetX());
11403 endface1[1].SetY(line2[0].GetY());
11404 endface1[2].SetX(line3[0].GetX());
11405 endface1[2].SetY(line3[0].GetY());
11406 endface1[3].SetX(line4[0].GetX());
11407 endface1[3].SetY(line4[0].GetY());
11408 endface1[4].SetX(line1[0].GetX());
11409 endface1[4].SetY(line1[0].GetY());
11410
11411 endface2[0].SetX(line1[1].GetX());
11412 endface2[0].SetY(line1[1].GetY());
11413 endface2[1].SetX(line2[1].GetX());
11414 endface2[1].SetY(line2[1].GetY());
11415 endface2[2].SetX(line3[1].GetX());
11416 endface2[2].SetY(line3[1].GetY());
11417 endface2[3].SetX(line4[1].GetX());
11418 endface2[3].SetY(line4[1].GetY());
11419 endface2[4].SetX(line1[1].GetX());
11420 endface2[4].SetY(line1[1].GetY());
11421
11422 gVirtualX->DrawPolyLine(2,line2);
11423 gVirtualX->DrawPolyLine(2,line3);
11424 gVirtualX->DrawPolyLine(2,line4);
11425 gVirtualX->DrawPolyLine(5,endface1);
11426 gVirtualX->DrawPolyLine(5,endface2);
11427 }
11428 c->Clear();
11429 c->cd();
11430 TH1 *hp = h3->Project3D("z");
11431 xaxis->SetRange(firstX,lastX);
11432 yaxis->SetRange(firstY,lastY);
11433 if (hp) {
11434 hp->SetFillColor(38);
11435 if (nbins == 1)
11436 hp->SetTitle(TString::Format("ProjectionZ of binx=%d [x=%.1f..%.1f] biny=%d [y=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
11437 biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny)));
11438 else
11439 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),
11440 biny, biny2, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny2) ) );
11441 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11442 hp->SetYTitle("Number of Entries");
11443 hp->Draw(fShowOption.Data());
11444 }
11445 }
11446 break;
11447
11448 case 4:
11449 // "xy"
11450 {
11451 Int_t first = zaxis->GetFirst();
11452 Int_t last = zaxis->GetLast();
11453 Int_t binz = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11454 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11455 zaxis->SetRange(binz,binz2);
11456 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11457 if (nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11458 xx[0] = xaxis->GetXmin();
11459 xx[1] = yaxis->GetXmax();
11460 xx[2] = zaxis->GetBinCenter(binz);
11461 view->WCtoNDC(xx,u);
11462 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11463 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11464 rect1[4].SetX(rect1[0].GetX());
11465 rect1[4].SetY(rect1[0].GetY());
11466 xx[0] = xaxis->GetXmax();
11467 view->WCtoNDC(xx,u);
11468 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11469 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11470 xx[1] = yaxis->GetXmin();
11471 view->WCtoNDC(xx,u);
11472 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11473 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11474 xx[0] = xaxis->GetXmin();
11475 view->WCtoNDC(xx,u);
11476 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11477 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11478 gVirtualX->DrawPolyLine(5,rect1);
11479 if (nbins>1) {
11480 xx[0] = xaxis->GetXmin();
11481 xx[1] = yaxis->GetXmax();
11482 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11483 view->WCtoNDC(xx,u);
11484 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11485 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11486 rect2[4].SetX(rect2[0].GetX());
11487 rect2[4].SetY(rect2[0].GetY());
11488 xx[0] = xaxis->GetXmax();
11489 view->WCtoNDC(xx,u);
11490 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11491 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11492 xx[1] = yaxis->GetXmin();
11493 view->WCtoNDC(xx,u);
11494 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11495 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11496 xx[0] = xaxis->GetXmin();
11497 view->WCtoNDC(xx,u);
11498 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11499 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11500 gVirtualX->DrawPolyLine(5,rect2);
11501 }
11502
11503 c->Clear();
11504 c->cd();
11505 TH2 *hp = (TH2*)h3->Project3D("xy");
11506 zaxis->SetRange(first,last);
11507 if (hp) {
11508 hp->SetFillColor(38);
11509 if (nbins==1)hp->SetTitle(TString::Format("ProjectionXY of binz=%d [z=%.1f..%.f]", binz,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz)));
11510 else hp->SetTitle(TString::Format("ProjectionXY, binz=[%d,%d] [z=%.1f..%.1f]", binz,binz2,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz2)));
11511 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11512 hp->SetYTitle(fH->GetXaxis()->GetTitle());
11513 hp->SetZTitle("Number of Entries");
11514 hp->Draw(fShowOption.Data());
11515 }
11516 }
11517 break;
11518
11519 case 5:
11520 // "yx"
11521 {
11522 Int_t first = zaxis->GetFirst();
11523 Int_t last = zaxis->GetLast();
11524 Int_t binz = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11525 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11526 zaxis->SetRange(binz,binz2);
11527 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11528 if (nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11529 xx[0] = xaxis->GetXmin();
11530 xx[1] = yaxis->GetXmax();
11531 xx[2] = zaxis->GetBinCenter(binz);
11532 view->WCtoNDC(xx,u);
11533 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11534 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11535 rect1[4].SetX(rect1[0].GetX());
11536 rect1[4].SetY(rect1[0].GetY());
11537 xx[0] = xaxis->GetXmax();
11538 view->WCtoNDC(xx,u);
11539 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11540 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11541 xx[1] = yaxis->GetXmin();
11542 view->WCtoNDC(xx,u);
11543 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11544 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11545 xx[0] = xaxis->GetXmin();
11546 view->WCtoNDC(xx,u);
11547 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11548 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11549 gVirtualX->DrawPolyLine(5,rect1);
11550 if (nbins>1) {
11551 xx[0] = xaxis->GetXmin();
11552 xx[1] = yaxis->GetXmax();
11553 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11554 view->WCtoNDC(xx,u);
11555 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11556 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11557 rect2[4].SetX(rect2[0].GetX());
11558 rect2[4].SetY(rect2[0].GetY());
11559 xx[0] = xaxis->GetXmax();
11560 view->WCtoNDC(xx,u);
11561 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11562 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11563 xx[1] = yaxis->GetXmin();
11564 view->WCtoNDC(xx,u);
11565 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11566 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11567 xx[0] = xaxis->GetXmin();
11568 view->WCtoNDC(xx,u);
11569 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11570 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11571 gVirtualX->DrawPolyLine(5,rect2);
11572 }
11573 c->Clear();
11574 c->cd();
11575 TH2 *hp = (TH2*)h3->Project3D("yx");
11576 zaxis->SetRange(first,last);
11577 if (hp) {
11578 hp->SetFillColor(38);
11579 if (nbins==1)hp->SetTitle(TString::Format("ProjectionYX of binz=%d [z=%.1f..%.f]", binz,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz)));
11580 else hp->SetTitle(TString::Format("ProjectionYX, binz=[%d,%d] [z=%.1f..%.1f]", binz,binz2,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz2)));
11581 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11582 hp->SetYTitle(fH->GetYaxis()->GetTitle());
11583 hp->SetZTitle("Number of Entries");
11584 hp->Draw(fShowOption.Data());
11585 }
11586 }
11587 break;
11588
11589 case 6:
11590 // "xz"
11591 {
11592 Int_t first = yaxis->GetFirst();
11593 Int_t last = yaxis->GetLast();
11594 Int_t biny = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11595 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11596 yaxis->SetRange(biny,biny2);
11597 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11598 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11599 xx[0] = xaxis->GetXmin();
11600 xx[2] = zaxis->GetXmax();
11601 xx[1] = yaxis->GetBinCenter(biny);
11602 view->WCtoNDC(xx,u);
11603 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11604 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11605 rect1[4].SetX(rect1[0].GetX());
11606 rect1[4].SetY(rect1[0].GetY());
11607 xx[0] = xaxis->GetXmax();
11608 view->WCtoNDC(xx,u);
11609 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11610 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11611 xx[2] = zaxis->GetXmin();
11612 view->WCtoNDC(xx,u);
11613 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11614 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11615 xx[0] = xaxis->GetXmin();
11616 view->WCtoNDC(xx,u);
11617 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11618 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11619 gVirtualX->DrawPolyLine(5,rect1);
11620 if (nbins>1) {
11621 xx[0] = xaxis->GetXmin();
11622 xx[2] = zaxis->GetXmax();
11623 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11624 view->WCtoNDC(xx,u);
11625 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11626 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11627 rect2[4].SetX(rect2[0].GetX());
11628 rect2[4].SetY(rect2[0].GetY());
11629 xx[0] = xaxis->GetXmax();
11630 view->WCtoNDC(xx,u);
11631 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11632 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11633 xx[2] = zaxis->GetXmin();
11634 view->WCtoNDC(xx,u);
11635 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11636 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11637 xx[0] = xaxis->GetXmin();
11638 view->WCtoNDC(xx,u);
11639 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11640 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11641 gVirtualX->DrawPolyLine(5,rect2);
11642 }
11643 c->Clear();
11644 c->cd();
11645 TH2 *hp = (TH2*)h3->Project3D("xz");
11646 yaxis->SetRange(first,last);
11647 if (hp) {
11648 hp->SetFillColor(38);
11649 if (nbins==1)hp->SetTitle(TString::Format("ProjectionXZ of biny=%d [y=%.1f..%.f]", biny,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny)));
11650 else hp->SetTitle(TString::Format("ProjectionXZ, biny=[%d,%d] [y=%.1f..%.1f]", biny,biny2,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny2)));
11651 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11652 hp->SetYTitle(fH->GetXaxis()->GetTitle());
11653 hp->SetZTitle("Number of Entries");
11654 hp->Draw(fShowOption.Data());
11655 }
11656 }
11657 break;
11658
11659 case 7:
11660 // "zx"
11661 {
11662 Int_t first = yaxis->GetFirst();
11663 Int_t last = yaxis->GetLast();
11664 Int_t biny = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11665 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11666 yaxis->SetRange(biny,biny2);
11667 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11668 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11669 xx[0] = xaxis->GetXmin();
11670 xx[2] = zaxis->GetXmax();
11671 xx[1] = yaxis->GetBinCenter(biny);
11672 view->WCtoNDC(xx,u);
11673 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11674 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11675 rect1[4].SetX(rect1[0].GetX());
11676 rect1[4].SetY(rect1[0].GetY());
11677 xx[0] = xaxis->GetXmax();
11678 view->WCtoNDC(xx,u);
11679 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11680 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11681 xx[2] = zaxis->GetXmin();
11682 view->WCtoNDC(xx,u);
11683 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11684 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11685 xx[0] = xaxis->GetXmin();
11686 view->WCtoNDC(xx,u);
11687 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11688 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11689 gVirtualX->DrawPolyLine(5,rect1);
11690 if (nbins>1) {
11691 xx[0] = xaxis->GetXmin();
11692 xx[2] = zaxis->GetXmax();
11693 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11694 view->WCtoNDC(xx,u);
11695 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11696 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11697 rect2[4].SetX(rect2[0].GetX());
11698 rect2[4].SetY(rect2[0].GetY());
11699 xx[0] = xaxis->GetXmax();
11700 view->WCtoNDC(xx,u);
11701 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11702 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11703 xx[2] = zaxis->GetXmin();
11704 view->WCtoNDC(xx,u);
11705 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11706 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11707 xx[0] = xaxis->GetXmin();
11708 view->WCtoNDC(xx,u);
11709 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11710 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11711 gVirtualX->DrawPolyLine(5,rect2);
11712 }
11713 c->Clear();
11714 c->cd();
11715 TH2 *hp = (TH2*)h3->Project3D("zx");
11716 yaxis->SetRange(first,last);
11717 if (hp) {
11718 hp->SetFillColor(38);
11719 if (nbins==1)hp->SetTitle(TString::Format("ProjectionZX of biny=%d [y=%.1f..%.f]", biny,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny)));
11720 else hp->SetTitle(TString::Format("ProjectionZX, biny=[%d,%d] [y=%.1f..%.1f]", biny,biny2,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny2)));
11721 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11722 hp->SetYTitle(fH->GetZaxis()->GetTitle());
11723 hp->SetZTitle("Number of Entries");
11724 hp->Draw(fShowOption.Data());
11725 }
11726 }
11727 break;
11728
11729 case 8:
11730 // "yz"
11731 {
11732 Int_t first = xaxis->GetFirst();
11733 Int_t last = xaxis->GetLast();
11734 Int_t binx = first + Int_t((last-first)*(px-pxmin)/(pxmax-pxmin));
11735 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11736 xaxis->SetRange(binx,binx2);
11737 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11738 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11739 xx[2] = zaxis->GetXmin();
11740 xx[1] = yaxis->GetXmax();
11741 xx[0] = xaxis->GetBinCenter(binx);
11742 view->WCtoNDC(xx,u);
11743 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11744 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11745 rect1[4].SetX(rect1[0].GetX());
11746 rect1[4].SetY(rect1[0].GetY());
11747 xx[2] = zaxis->GetXmax();
11748 view->WCtoNDC(xx,u);
11749 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11750 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11751 xx[1] = yaxis->GetXmin();
11752 view->WCtoNDC(xx,u);
11753 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11754 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11755 xx[2] = zaxis->GetXmin();
11756 view->WCtoNDC(xx,u);
11757 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11758 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11759 gVirtualX->DrawPolyLine(5,rect1);
11760 if (nbins>1) {
11761 xx[2] = zaxis->GetXmin();
11762 xx[1] = yaxis->GetXmax();
11763 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11764 view->WCtoNDC(xx,u);
11765 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11766 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11767 rect2[4].SetX(rect2[0].GetX());
11768 rect2[4].SetY(rect2[0].GetY());
11769 xx[2] = zaxis->GetXmax();
11770 view->WCtoNDC(xx,u);
11771 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11772 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11773 xx[1] = yaxis->GetXmin();
11774 view->WCtoNDC(xx,u);
11775 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11776 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11777 xx[2] = zaxis->GetXmin();
11778 view->WCtoNDC(xx,u);
11779 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11780 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11781 gVirtualX->DrawPolyLine(5,rect2);
11782 }
11783 c->Clear();
11784 c->cd();
11785 TH2 *hp = (TH2*)h3->Project3D("yz");
11786 xaxis->SetRange(first,last);
11787 if (hp) {
11788 hp->SetFillColor(38);
11789 if (nbins==1)hp->SetTitle(TString::Format("ProjectionYZ of binx=%d [x=%.1f..%.f]", binx,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx)));
11790 else hp->SetTitle(TString::Format("ProjectionYZ, binx=[%d,%d] [x=%.1f..%.1f]", binx,binx2,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx2)));
11791 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11792 hp->SetYTitle(fH->GetYaxis()->GetTitle());
11793 hp->SetZTitle("Number of Entries");
11794 hp->Draw(fShowOption.Data());
11795 }
11796 }
11797 break;
11798
11799 case 9:
11800 // "zy"
11801 {
11802 Int_t first = xaxis->GetFirst();
11803 Int_t last = xaxis->GetLast();
11804 Int_t binx = first + Int_t((last-first)*(px-pxmin)/(pxmax-pxmin));
11805 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11806 xaxis->SetRange(binx,binx2);
11807 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11808 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11809 xx[2] = zaxis->GetXmin();
11810 xx[1] = yaxis->GetXmax();
11811 xx[0] = xaxis->GetBinCenter(binx);
11812 view->WCtoNDC(xx,u);
11813 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11814 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11815 rect1[4].SetX(rect1[0].GetX());
11816 rect1[4].SetY(rect1[0].GetY());
11817 xx[2] = zaxis->GetXmax();
11818 view->WCtoNDC(xx,u);
11819 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11820 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11821 xx[1] = yaxis->GetXmin();
11822 view->WCtoNDC(xx,u);
11823 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11824 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11825 xx[2] = zaxis->GetXmin();
11826 view->WCtoNDC(xx,u);
11827 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11828 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11829 gVirtualX->DrawPolyLine(5,rect1);
11830 if (nbins>1) {
11831 xx[2] = zaxis->GetXmin();
11832 xx[1] = yaxis->GetXmax();
11833 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11834 view->WCtoNDC(xx,u);
11835 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11836 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11837 rect2[4].SetX(rect2[0].GetX());
11838 rect2[4].SetY(rect2[0].GetY());
11839 xx[2] = zaxis->GetXmax();
11840 view->WCtoNDC(xx,u);
11841 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11842 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11843 xx[1] = yaxis->GetXmin();
11844 view->WCtoNDC(xx,u);
11845 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11846 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11847 xx[2] = zaxis->GetXmin();
11848 view->WCtoNDC(xx,u);
11849 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11850 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11851 gVirtualX->DrawPolyLine(5,rect2);
11852 }
11853 c->Clear();
11854 c->cd();
11855 TH2 *hp = (TH2*)h3->Project3D("zy");
11856 xaxis->SetRange(first,last);
11857 if (hp) {
11858 hp->SetFillColor(38);
11859 if (nbins==1)hp->SetTitle(TString::Format("ProjectionZY of binx=%d [x=%.1f..%.f]", binx,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx)));
11860 else hp->SetTitle(TString::Format("ProjectionZY, binx=[%d,%d] [x=%.1f..%.1f]", binx,binx2,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx2)));
11861 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11862 hp->SetYTitle(fH->GetZaxis()->GetTitle());
11863 hp->SetZTitle("Number of Entries");
11864 hp->Draw(fShowOption.Data());
11865 }
11866 }
11867 break;
11868 }
11869 c->Update();
11870}
@ 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:406
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:3073
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:1911
virtual void GetParLimits(Int_t ipar, Double_t &parmin, Double_t &parmax) const
Return limits for parameter ipar.
Definition TF1.cxx:1962
virtual Double_t GetParError(Int_t ipar) const
Return value of parameter number ipar.
Definition TF1.cxx:1952
static TClass * Class()
Double_t GetChisquare() const
Return the Chisquare after fitting. See ROOT::Fit::FitResult::Chi2()
Definition TF1.h: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:3420
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:1922
@ 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:3433
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:1441
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:698
1-D histogram with a float per channel (see TH1 documentation)
Definition TH1.h:650
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:59
TAxis * GetZaxis()
Definition TH1.h:346
virtual EBinErrorOpt GetBinErrorOption() const
Definition TH1.h:290
virtual Float_t GetBarWidth() const
Definition TH1.h:274
virtual Double_t GetMinimumStored() const
Definition TH1.h:310
virtual Float_t GetBarOffset() const
Definition TH1.h:273
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:315
virtual Double_t GetBinError(Int_t bin) const
Return value of error associated to bin number bin.
Definition TH1.cxx:9059
virtual Int_t GetNbinsZ() const
Definition TH1.h:316
virtual Double_t GetNormFactor() const
Definition TH1.h:318
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:300
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:181
@ kUserContour
User specified contour levels.
Definition TH1.h:177
@ kNoStats
Don't draw stats box.
Definition TH1.h:176
TAxis * GetXaxis()
Definition TH1.h:344
virtual Double_t GetSumOfWeights() const
Return the sum of weights across all bins excluding under/overflows.
Definition TH1.h:332
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:314
virtual void SetMaximum(Double_t maximum=-1111)
Definition TH1.h:424
TAxis * GetYaxis()
Definition TH1.h:345
virtual Double_t GetBinErrorLow(Int_t bin) const
Return lower error associated to bin number bin.
Definition TH1.cxx:9075
virtual void SetMinimum(Double_t minimum=-1111)
Definition TH1.h:425
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:9218
virtual Double_t GetBinLowEdge(Int_t bin) const
Return bin lower edge for 1D histogram.
Definition TH1.cxx:9148
virtual Double_t GetEntries() const
Return the current number of entries.
Definition TH1.cxx:4401
TList * GetListOfFunctions() const
Definition TH1.h:261
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:306
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:65
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:256
virtual Bool_t IsHighlight() const
Definition TH1.h:358
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width for 1D histogram.
Definition TH1.cxx:9159
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:9106
virtual Int_t GetSumw2N() const
Definition TH1.h:335
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