Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
THistPainter.cxx
Go to the documentation of this file.
1// @(#)root/histpainter:$Id$
2// Author: Rene Brun, Olivier Couet
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12#include <cstdlib>
13#include <cstring>
14#include <cstdio>
15#include <cctype>
16#include <iostream>
17
18#include "TROOT.h"
19#include "TSystem.h"
20#include "THistPainter.h"
21#include "TH2.h"
22#include "TH2Poly.h"
23#include "TH3.h"
24#include "TProfile.h"
25#include "TProfile2D.h"
26#include "THStack.h"
27#include "TF2.h"
28#include "TF3.h"
29#include "TCutG.h"
30#include "TMatrixDBase.h"
31#include "TMatrixFBase.h"
32#include "TVectorD.h"
33#include "TVectorF.h"
34#include "TCanvas.h"
35#include "TPad.h"
36#include "TPaveStats.h"
37#include "TFrame.h"
38#include "TLatex.h"
39#include "TPolyLine.h"
40#include "TPoints.h"
41#include "TStyle.h"
42#include "TGraph.h"
43#include "TMultiGraph.h"
44#include "TPie.h"
45#include "TGaxis.h"
46#include "TColor.h"
48#include "TGraph2D.h"
49#include "TGraph2DPainter.h"
50#include "TGraphDelaunay2D.h"
51#include "TView.h"
52#include "TMath.h"
53#include "TRandom2.h"
54#include "TObjArray.h"
55#include "Hoption.h"
56#include "Hparam.h"
57#include "TPluginManager.h"
58#include "TPaletteAxis.h"
59#include "TCrown.h"
60#include "TArrow.h"
61#include "TVirtualPadEditor.h"
62#include "TVirtualX.h"
63#include "TEnv.h"
64#include "TPoint.h"
65#include "TImage.h"
66#include "TCandle.h"
67#include "strlcpy.h"
68
69/*! \class THistPainter
70 \ingroup Histpainter
71 \brief The histogram painter class. Implements all histograms' drawing's options.
72
73- [Introduction](\ref HP00)
74- [Histograms' plotting options](\ref HP01)
75 - [Options supported for 1D and 2D histograms](\ref HP01a)
76 - [Options supported for 1D histograms](\ref HP01b)
77 - [Options supported for 2D histograms](\ref HP01c)
78 - [Options supported for 3D histograms](\ref HP01d)
79 - [Options supported for histograms' stacks (THStack)](\ref HP01e)
80- [Setting the Style](\ref HP02)
81- [Setting line, fill, marker, and text attributes](\ref HP03)
82- [Setting Tick marks on the histogram axis](\ref HP04)
83- [Giving titles to the X, Y and Z axis](\ref HP05)
84- [The option SAME](\ref HP060)
85 - [Limitations](\ref HP060a)
86- [Colors automatically picked in palette](\ref HP061)
87- [Superimposing two histograms with different scales in the same pad](\ref HP06)
88- [Statistics Display](\ref HP07)
89- [Fit Statistics](\ref HP08)
90- [The error bars options](\ref HP09)
91- [The bar chart option](\ref HP100)
92- [The BAR and HBAR options](\ref HP10)
93- [The SCATter plot option (legacy draw option)](\ref HP11)
94- [The ARRow option](\ref HP12)
95- [The BOX option](\ref HP13)
96- [The COLor option (default for 2D and 3D histograms)](\ref HP14)
97- [The CANDLE and VIOLIN options](\ref HP140)
98 - [The CANDLE option](\ref HP140a)
99 - [The VIOLIN option](\ref HP140b)
100- [The TEXT and TEXTnn Option](\ref HP15)
101- [The CONTour options](\ref HP16)
102 - [The LIST option](\ref HP16a)
103 - [The AITOFF, MERCATOR, SINUSOIDAL and PARABOLIC options](\ref HP16b)
104- [The LEGO options](\ref HP17)
105- [The SURFace options](\ref HP18)
106- [Cylindrical, Polar, Spherical and PseudoRapidity/Phi options](\ref HP19)
107- [Base line for bar-charts and lego plots](\ref HP20)
108- [TH2Poly Drawing](\ref HP20a)
109- [The SPEC option](\ref HP21)
110- [Option Z : Adding the color palette on the right side of the pad](\ref HP22)
111- [Setting the color palette](\ref HP23)
112- [Drawing a sub-range of a 2-D histogram; the [cutg] option](\ref HP24)
113- [Drawing options for 3D histograms](\ref HP25)
114- [Drawing option for histograms' stacks](\ref HP26)
115- [Drawing of 3D implicit functions](\ref HP27)
116- [Associated functions drawing](\ref HP28)
117- [Drawing using OpenGL](\ref HP29)
118 - [General information: plot types and supported options](\ref HP29a)
119 - [TH3 as color boxes](\ref HP290)
120 - [TH3 as boxes (spheres)](\ref HP29b)
121 - [TH3 as iso-surface(s)](\ref HP29c)
122 - [TF3 (implicit function)](\ref HP29d)
123 - [Parametric surfaces](\ref HP29e)
124 - [Interaction with the plots](\ref HP29f)
125 - [Selectable parts](\ref HP29g)
126 - [Rotation and zooming](\ref HP29h)
127 - [Panning](\ref HP29i)
128 - [Box cut](\ref HP29j)
129 - [Plot specific interactions (dynamic slicing etc.)](\ref HP29k)
130 - [Surface with option GLSURF](\ref HP29l)
131 - [TF3](\ref HP29m)
132 - [Box](\ref HP29n)
133 - [Iso](\ref HP29o)
134 - [Parametric plot](\ref HP29p)
135- [Highlight mode for histogram](\ref HP30)
136 - [Highlight mode and user function](\ref HP30a)
137
138
139\anchor HP00
140## Introduction
141
142
143Histograms are drawn via the `THistPainter` class. Each histogram has a
144pointer to its own painter (to be usable in a multithreaded program). When the
145canvas has to be redrawn, the `Paint` function of each objects in the
146pad is called. In case of histograms, `TH1::Paint` invokes directly
147`THistPainter::Paint`.
148
149To draw a histogram `h` it is enough to do:
150
151 h->Draw();
152
153`h` can be of any kind: 1D, 2D or 3D. To choose how the histogram will
154be drawn, the `Draw()` method can be invoked with an option. For instance
155to draw a 2D histogram as a lego plot it is enough to do:
156
157 h->Draw("lego");
158
159`THistPainter` offers many options to paint 1D, 2D and 3D histograms.
160
161When the `Draw()` method of a histogram is called for the first time
162(`TH1::Draw`), it creates a `THistPainter` object and saves a
163pointer to this "painter" as a data member of the histogram. The
164`THistPainter` class specializes in the drawing of histograms. It is
165separated from the histogram so that one can have histograms without the
166graphics overhead, for example in a batch program. Each histogram having its own
167painter (rather than a central singleton painter painting all histograms), allows
168two histograms to be drawn in two threads without overwriting the painter's
169values.
170
171When a displayed histogram is filled again, there is no need to call the
172`Draw()` method again; the image will be refreshed the next time the
173pad will be updated.
174
175A pad is updated after one of these three actions:
176
1771. a carriage control on the ROOT command line,
1782. a click inside the pad,
1793. a call to `TPad::Update`.
180
181
182By default a call to `TH1::Draw()` clears the pad of all objects
183before drawing the new image of the histogram. One can use the `SAME`
184option to leave the previous display intact and superimpose the new histogram.
185The same histogram can be drawn with different graphics options in different
186pads.
187
188When a displayed histogram is deleted, its image is automatically removed
189from the pad.
190
191To create a copy of the histogram when drawing it, one can use
192`TH1::DrawClone()`. This will clone the histogram and allow to change
193and delete the original one without affecting the clone.
194
195
196\anchor HP01
197### Histograms' plotting options
198
199
200Most options can be concatenated with or without spaces or commas, for example:
201
202 h->Draw("E1 SAME");
203
204The options are not case sensitive:
205
206 h->Draw("e1 same");
207
208
209The default drawing option can be set with `TH1::SetOption` and retrieve
210using `TH1::GetOption`:
211
212 root [0] h->Draw(); // Draw "h" using the standard histogram representation.
213 root [1] h->Draw("E"); // Draw "h" using error bars
214 root [3] h->SetOption("E"); // Change the default drawing option for "h"
215 root [4] h->Draw(); // Draw "h" using error bars
216 root [5] h->GetOption(); // Retrieve the default drawing option for "h"
217 (const Option_t* 0xa3ff948)"E"
218
219
220\anchor HP01a
221#### Options supported for 1D and 2D histograms
222
223| Option | Description |
224|----------|-------------------------------------------------------------------|
225| "E" | Draw error bars. |
226| "AXIS" | Draw only axis. |
227| "AXIG" | Draw only grid (if the grid is requested). |
228| \anchor OPTHIST "HIST" | When an histogram has errors it is visualized by default with error bars. To visualize it without errors use the option "HIST" together with the required option (eg "hist same c"). The "HIST" option can also be used to plot only the histogram and not the associated function(s). |
229| "FUNC" | When an histogram has a fitted function, this option allows to draw the fit result only. |
230| "SAME" | Superimpose on previous picture in the same pad. |
231| "SAMES" | Same as "SAME" and draw the statistics box|
232| "PFC" | Palette Fill Color: histogram's fill color is taken in the current palette. |
233| "PLC" | Palette Line Color: histogram's line color is taken in the current palette. |
234| "PMC" | Palette Marker Color: histogram's marker color is taken in the current palette. |
235| "LEGO" | Draw a lego plot with hidden line removal. |
236| "LEGO1" | Draw a lego plot with hidden surface removal. |
237| "LEGO2" | Draw a lego plot using colors to show the cell contents When the option "0" is used with any LEGO option, the empty bins are not drawn.|
238| "LEGO3" | Draw a lego plot with hidden surface removal, like LEGO1 but the border lines of each lego-bar are not drawn.|
239| "LEGO4" | Draw a lego plot with hidden surface removal, like LEGO1 but without the shadow effect on each lego-bar.|
240| "TEXT" | Draw bin contents as text (format set via `gStyle->SetPaintTextFormat`).|
241| "TEXTnn" | Draw bin contents as text at angle nn (0 < nn <= 90). |
242| "X+" | The X-axis is drawn on the top side of the plot. |
243| "Y+" | The Y-axis is drawn on the right side of the plot. |
244| "MIN0" | Set minimum value for the Y axis to 0, equivalent to gStyle->SetHistMinimumZero(). |
245
246
247\anchor HP01b
248#### Options supported for 1D histograms
249
250| Option | Description |
251|----------|-------------------------------------------------------------------|
252| " " | Default. |
253| "AH" | Draw histogram without axis. "A" can be combined with any drawing option. For instance, "AC" draws the histogram as a smooth Curve without axis.|
254| "][" | When this option is selected the first and last vertical lines of the histogram are not drawn.|
255| "B" | Bar chart option.|
256| "BAR" | Like option "B", but bars can be drawn with a 3D effect.|
257| "HBAR" | Like option "BAR", but bars are drawn horizontally.|
258| "C" | Draw a smooth Curve through the histogram bins.|
259| "E0" | Draw error bars. Markers are drawn for bins with 0 contents. Combined with E1 or E2 it avoids error bars clipping|
260| "E1" | Draw error bars with perpendicular lines at the edges.|
261| "E2" | Draw error bars with rectangles.|
262| "E3" | Draw a fill area through the end points of the vertical error bars.|
263| "E4" | Draw a smoothed filled area through the end points of the error bars.|
264| "E5" | Like E3 but ignore the bins with 0 contents.|
265| "E6" | Like E4 but ignore the bins with 0 contents.|
266| "X0" | When used with one of the "E" option, it suppress the error bar along X as `gStyle->SetErrorX(0)` would do.|
267| "L" | Draw a line through the bin contents.|
268| "P" | Draw current marker at each bin except empty bins.|
269| "P*" | Draw a star marker at each bin except empty bins.|
270| "P0" | Draw current marker at each bin including empty bins.|
271| "PIE" | Draw histogram as a Pie Chart.|
272| "*H" | Draw histogram with a * at each bin.|
273| "LF2" | Draw histogram like with option "L" but with a fill area. Note that "L" draws also a fill area if the hist fill color is set but the fill area corresponds to the histogram contour.|
274
275
276
277\anchor HP01c
278#### Options supported for 2D histograms
279
280| Option | Description |
281|--------------|------------------------------------------------------------------|
282| " " | Default (color plot).|
283| "ARR" | Arrow mode. Shows gradient between adjacent cells.|
284| "BOX" | A box is drawn for each cell with surface proportional to the content's absolute value. A negative content is marked with a X. |
285| "BOX1" | A button is drawn for each cell with surface proportional to content's absolute value. A sunken button is drawn for negative values a raised one for positive.|
286| "COL" | A box is drawn for each cell with a color scale varying with contents. All the none empty bins (bins with content and error equal to 0) are painted. Empty bins are not painted unless some bins have a negative content because in that case the null bins might be not empty. `TProfile2D` histograms are handled differently because, for this type of 2D histograms, it is possible to know if an empty bin has been filled or not. So even if all the bins' contents are positive some empty bins might be painted. And vice versa, if some bins have a negative content some empty bins might be not painted (default).|
287| "COL1" | Same as "COL" but in case of histogram with negative content the empty bins are not drawn.
288| "COLZ" | Same as "COL". In addition the color palette is also drawn.|
289| "COL2" | Alternative rendering algorithm to "COL". Can significantly improve rendering performance for large, non-sparse 2-D histograms.|
290| "COLZ2" | Same as "COL2". In addition the color palette is also drawn.|
291| "Z CJUST" | In combination with colored options "COL","CONT0" etc: Justify labels in the color palette at color boundaries. For more details see `TPaletteAxis`|
292| "CANDLE" | Draw a candle plot along X axis.|
293| "CANDLEX" | Same as "CANDLE".|
294| "CANDLEY" | Draw a candle plot along Y axis.|
295| "CANDLEXn" | Draw a candle plot along X axis. Different candle-styles with n from 1 to 6.|
296| "CANDLEYn" | Draw a candle plot along Y axis. Different candle-styles with n from 1 to 6.|
297| "VIOLIN" | Draw a violin plot along X axis.|
298| "VIOLINX" | Same as "VIOLIN".|
299| "VIOLINY" | Draw a violin plot along Y axis.|
300| "VIOLINXn" | Draw a violin plot along X axis. Different violin-styles with n being 1 or 2.|
301| "VIOLINYn" | Draw a violin plot along Y axis. Different violin-styles with n being 1 or 2.|
302| "CONT" | Draw a contour plot (same as CONT0).|
303| "CONT0" | Draw a contour plot using surface colors to distinguish contours.|
304| "CONT1" | Draw a contour plot using line styles to distinguish contours.|
305| "CONT2" | Draw a contour plot using the same line style for all contours.|
306| "CONT3" | Draw a contour plot using fill area colors.|
307| "CONT4" | Draw a contour plot using surface colors (SURF option at theta = 0).|
308| "LIST" | Generate a list of TGraph objects for each contour.|
309| "SAME0" | Same as "SAME" but do not use the z-axis range of the first plot. |
310| "SAMES0" | Same as "SAMES" but do not use the z-axis range of the first plot. |
311| "CYL" | Use Cylindrical coordinates. The X coordinate is mapped on the angle and the Y coordinate on the cylinder length.|
312| "POL" | Use Polar coordinates. The X coordinate is mapped on the angle and the Y coordinate on the radius.|
313| "SPH" | Use Spherical coordinates. The X coordinate is mapped on the latitude and the Y coordinate on the longitude.|
314| "PSR" | Use PseudoRapidity/Phi coordinates. The X coordinate is mapped on Phi.|
315| "SURF" | Draw a surface plot with hidden line removal.|
316| "SURF1" | Draw a surface plot with hidden surface removal.|
317| "SURF2" | Draw a surface plot using colors to show the cell contents.|
318| "SURF3" | Same as SURF with in addition a contour view drawn on the top.|
319| "SURF4" | Draw a surface using Gouraud shading.|
320| "SURF5" | Same as SURF3 but only the colored contour is drawn. Used with option CYL, SPH or PSR it allows to draw colored contours on a sphere, a cylinder or a in pseudo rapidity space. In cartesian or polar coordinates, option SURF3 is used.|
321| "AITOFF" | Draw a contour via an AITOFF projection.|
322| "MERCATOR" | Draw a contour via an Mercator projection.|
323| "SINUSOIDAL" | Draw a contour via an Sinusoidal projection.|
324| "PARABOLIC" | Draw a contour via an Parabolic projection.|
325| "MOLLWEIDE" | Draw a contour via an Mollweide projection.|
326| "LEGO9" | Draw the 3D axis only. Mainly needed for internal use |
327| "FB" | With LEGO or SURFACE, suppress the Front-Box.|
328| "BB" | With LEGO or SURFACE, suppress the Back-Box.|
329| "A" | With LEGO or SURFACE, suppress the axis.|
330| "SCAT" | Draw a scatter-plot (legacy draw option).|
331| "[cutg]" | Draw only the sub-range selected by the TCutG named "cutg".|
332
333
334
335\anchor HP01d
336#### Options supported for 3D histograms
337
338| Option | Description |
339|----------|-------------------------------------------------------------------|
340| " " | Default (color plot).|
341| "ISO" | Draw a Gouraud shaded 3d iso surface through a 3d histogram. It paints one surface at the value computed as follow: `SumOfWeights/(NbinsX*NbinsY*NbinsZ)`.|
342| "BOX" | Draw a for each cell with volume proportional to the content's absolute value. An hidden line removal algorithm is used|
343| "BOX1" | Same as BOX but an hidden surface removal algorithm is used|
344| "BOX2" | The boxes' colors are picked in the current palette according to the bins' contents|
345| "BOX2Z" | Same as "BOX2". In addition the color palette is also drawn.|
346| "BOX3" | Same as BOX1, but the border lines of each lego-bar are not drawn.|
347| "LEGO" | Same as `BOX`.|
348
349\anchor HP01e
350#### Options supported for histograms' stacks (`THStack`)
351
352| Option | Description |
353|------------|-----------------------------------------------------------------|
354| " " | Default, the histograms are drawn on top of each other (as lego plots for 2D histograms).|
355| "NOSTACK" | Histograms in the stack are all paint in the same pad as if the option `SAME` had been specified.|
356| "NOSTACKB" | Histograms are drawn next to each other as bar charts.|
357| "PADS" | The current pad/canvas is subdivided into a number of pads equal to the number of histograms in the stack and each histogram is paint into a separate pad.|
358| "PFC" | Palette Fill Color: stack's fill color is taken in the current palette. |
359| "PLC" | Palette Line Color: stack's line color is taken in the current palette. |
360| "PMC" | Palette Marker Color: stack's marker color is taken in the current palette. |
361
362
363
364\anchor HP02
365### Setting the Style
366
367
368Histograms use the current style (`gStyle`). When one changes the current
369style and would like to propagate the changes to the histogram,
370`TH1::UseCurrentStyle` should be called. Call `UseCurrentStyle` on
371each histogram is needed.
372
373To force all the histogram to use the current style use:
374
375 gROOT->ForceStyle();
376
377All the histograms read after this call will use the current style.
378
379
380\anchor HP03
381### Setting line, fill, marker, and text attributes
382
383
384The histogram classes inherit from the attribute classes:
385`TAttLine`, `TAttFill` and `TAttMarker`.
386See the description of these classes for the list of options.
387
388
389\anchor HP04
390### Setting Tick marks on the histogram axis
391
392
393The `TPad::SetTicks` method specifies the type of tick marks on the axis.
394If ` tx = gPad->GetTickx()` and `ty = gPad->GetTicky()` then:
395
396 tx = 1; tick marks on top side are drawn (inside)
397 tx = 2; tick marks and labels on top side are drawn
398 ty = 1; tick marks on right side are drawn (inside)
399 ty = 2; tick marks and labels on right side are drawn
400
401By default only the left Y axis and X bottom axis are drawn
402(`tx = ty = 0`)
403
404`TPad::SetTicks(tx,ty)` allows to set these options.
405See also The `TAxis` functions to set specific axis attributes.
406
407In case multiple color filled histograms are drawn on the same pad, the fill
408area may hide the axis tick marks. One can force a redraw of the axis over all
409the histograms by calling:
410
411 gPad->RedrawAxis();
412
413
414\anchor HP05
415### Giving titles to the X, Y and Z axis
416
417
418 h->GetXaxis()->SetTitle("X axis title");
419 h->GetYaxis()->SetTitle("Y axis title");
420
421The histogram title and the axis titles can be any `TLatex` string.
422The titles are part of the persistent histogram.
423
424
425\anchor HP060
426### The option "SAME"
427
428
429By default, when an histogram is drawn, the current pad is cleared before
430drawing. In order to keep the previous drawing and draw on top of it the
431option `SAME` should be use. The histogram drawn with the option
432`SAME` uses the coordinates system available in the current pad.
433
434This option can be used alone or combined with any valid drawing option but
435some combinations must be use with care.
436
437\anchor HP060a
438#### Limitations
439
440- It does not work when combined with the `LEGO` and `SURF` options unless the
441 histogram plotted with the option `SAME` has exactly the same
442 ranges on the X, Y and Z axis as the currently drawn histogram. To superimpose
443 lego plots [histograms' stacks](\ref HP26) should be used.
444
445
446\anchor HP061
447### Colors automatically picked in palette
448
449\since **ROOT version 6.09/01**
450
451When several histograms are painted in the same canvas thanks to the option "SAME"
452or via a `THStack` it might be useful to have an easy and automatic way to choose
453their color. The simplest way is to pick colors in the current active color
454palette. Palette coloring for histogram is activated thanks to the options `PFC`
455(Palette Fill Color), `PLC` (Palette Line Color) and `PMC` (Palette Marker Color).
456When one of these options is given to `TH1::Draw` the histogram get its color
457from the current color palette defined by `gStyle->SetPalette(...)`. The color
458is determined according to the number of objects having palette coloring in
459the current pad.
460
461Begin_Macro(source)
462../../../tutorials/hist/hist005_TH1_palettecolor.C
463End_Macro
464
465Begin_Macro(source)
466../../../tutorials/hist/hist027_THStack_palette_color.C
467End_Macro
468
469Begin_Macro(source)
470../../../tutorials/hist/hist025_THStack_2d_palette_color.C
471End_Macro
472
473\anchor HP06
474### Superimposing two histograms with different scales in the same pad
475
476
477The following example creates two histograms, the second histogram is the bins
478integral of the first one. It shows a procedure to draw the two histograms in
479the same pad and it draws the scale of the second histogram using a new vertical
480axis on the right side. See also the tutorial `transpad.C` for a variant
481of this example.
482
483Begin_Macro(source)
484{
485 auto c1 = new TCanvas("c1","c1",600,400);
486 // create/fill draw h1
487 gStyle->SetOptStat(kFALSE);
488 auto h1 = new TH1F("h1","Superimposing two histograms with different scales",100,-3,3);
489 Int_t i;
490 for (i=0;i<10000;i++) h1->Fill(gRandom->Gaus(0,1));
491 h1->Draw();
492 c1->Update();
493
494 // create hint1 filled with the bins integral of h1
495 auto hint1 = new TH1F("hint1","h1 bins integral",100,-3,3);
496 float sum = 0.f;
497 for (i=1;i<=100;i++) {
498 sum += h1->GetBinContent(i);
499 hint1->SetBinContent(i,sum);
500 }
501
502 // scale hint1 to the pad coordinates
503 float rightmax = 1.1*hint1->GetMaximum();
504 float scale = gPad->GetUymax()/rightmax;
505 hint1->SetLineColor(kRed);
506 hint1->Scale(scale);
507 hint1->Draw("same");
508
509 // draw an axis on the right side
510 auto axis = new TGaxis(gPad->GetUxmax(),gPad->GetUymin(),
511 gPad->GetUxmax(), gPad->GetUymax(),0,rightmax,510,"+L");
512 axis->SetLineColor(kRed);
513 axis->SetTextColor(kRed);
514 axis->Draw();
515}
516End_Macro
517
518
519\anchor HP07
520### Statistics Display
521
522
523The type of information shown in the histogram statistics box can be selected
524with:
525
526 gStyle->SetOptStat(mode);
527
528The `mode` has up to nine digits that can be set to on (1 or 2), off (0).
529
530 mode = ksiourmen (default = 000001111)
531 k = 1; kurtosis printed
532 k = 2; kurtosis and kurtosis error printed
533 s = 1; skewness printed
534 s = 2; skewness and skewness error printed
535 i = 1; integral of bins printed
536 i = 2; integral of bins with option "width" printed
537 o = 1; number of overflows printed
538 u = 1; number of underflows printed
539 r = 1; standard deviation printed
540 r = 2; standard deviation and standard deviation error printed
541 m = 1; mean value printed
542 m = 2; mean and mean error values printed
543 e = 1; number of entries printed
544 n = 1; name of histogram is printed
545
546For example:
547
548 gStyle->SetOptStat(11);
549
550displays only the name of histogram and the number of entries, whereas:
551
552 gStyle->SetOptStat(1101);
553
554displays the name of histogram, mean value and standard deviation.
555
556<b>WARNING 1:</b> never do:
557
558 gStyle->SetOptStat(0001111);
559
560but instead do:
561
562 gStyle->SetOptStat(1111);
563
564because `0001111` will be taken as an octal number!
565
566<b>WARNING 2:</b> for backward compatibility with older versions
567
568 gStyle->SetOptStat(1);
569
570is taken as:
571
572 gStyle->SetOptStat(1111)
573
574To print only the name of the histogram do:
575
576 gStyle->SetOptStat(1000000001);
577
578<b>NOTE</b> that in case of 2D histograms, when selecting only underflow
579(10000) or overflow (100000), the statistics box will show all combinations
580of underflow/overflows and not just one single number.
581
582The parameter mode can be any combination of the letters `kKsSiIourRmMen`
583
584 k : kurtosis printed
585 K : kurtosis and kurtosis error printed
586 s : skewness printed
587 S : skewness and skewness error printed
588 i : integral of bins printed
589 I : integral of bins with option "width" printed
590 o : number of overflows printed
591 u : number of underflows printed
592 r : standard deviation printed
593 R : standard deviation and standard deviation error printed
594 m : mean value printed
595 M : mean value mean error values printed
596 e : number of entries printed
597 n : name of histogram is printed
598
599For example, to print only name of histogram and number of entries do:
600
601 gStyle->SetOptStat("ne");
602
603To print only the name of the histogram do:
604
605 gStyle->SetOptStat("n");
606
607The default value is:
608
609 gStyle->SetOptStat("nemr");
610
611When a histogram is painted, a `TPaveStats` object is created and added
612to the list of functions of the histogram. If a `TPaveStats` object
613already exists in the histogram list of functions, the existing object is just
614updated with the current histogram parameters.
615
616Once a histogram is painted, the statistics box can be accessed using
617`h->FindObject("stats")`. In the command line it is enough to do:
618
619 Root > h->Draw()
620 Root > TPaveStats *st = (TPaveStats*)h->FindObject("stats")
621
622because after `h->Draw()` the histogram is automatically painted. But
623in a script file the painting should be forced using `gPad->Update()`
624in order to make sure the statistics box is created:
625
626 h->Draw();
627 gPad->Update();
628 TPaveStats *st = (TPaveStats*)h->FindObject("stats");
629
630Without `gPad->Update()` the line `h->FindObject("stats")` returns a null pointer.
631
632When a histogram is drawn with the option `SAME`, the statistics box
633is not drawn. To force the statistics box drawing with the option
634`SAME`, the option `SAMES` must be used.
635If the new statistics box hides the previous statistics box, one can change
636its position with these lines (`h` being the pointer to the histogram):
637
638 Root > TPaveStats *st = (TPaveStats*)h->FindObject("stats")
639 Root > st->SetX1NDC(newx1); //new x start position
640 Root > st->SetX2NDC(newx2); //new x end position
641
642To change the type of information for an histogram with an existing
643`TPaveStats` one should do:
644
645 st->SetOptStat(mode);
646
647Where `mode` has the same meaning than when calling `gStyle->SetOptStat(mode)`
648(see above).
649
650One can delete the statistics box for a histogram `TH1* h` with:
651
652 h->SetStats(0)
653
654and activate it again with:
655
656 h->SetStats(1).
657
658Labels used in the statistics box ("Mean", "Std Dev", ...) can be changed from
659`$ROOTSYS/etc/system.rootrc` or `.rootrc` (look for the string `Hist.Stats.`).
660
661
662\anchor HP08
663### Fit Statistics
664
665
666The type of information about fit parameters printed in the histogram statistics
667box can be selected via the parameter mode. The parameter mode can be
668`= pcev` (default `= 0111`)
669
670 p = 1; print Probability
671 c = 1; print Chisquare/Number of degrees of freedom
672 e = 1; print errors (if e=1, v must be 1)
673 v = 1; print name/values of parameters
674
675Example:
676
677 gStyle->SetOptFit(1011);
678
679print fit probability, parameter names/values and errors.
680
6811. When `v = 1` is specified, only the non-fixed parameters are shown.
6822. When `v = 2` all parameters are shown.
683
684Note: `gStyle->SetOptFit(1)` means "default value", so it is equivalent
685to `gStyle->SetOptFit(111)`
686
687
688\anchor HP09
689### The error bars options
690
691
692| Option | Description |
693|----------|-------------------------------------------------------------------|
694| "E" | Default. Shows only the error bars, not a marker.|
695| "E1" | Small lines are drawn at the end of the error bars.|
696| "E2" | Error rectangles are drawn.|
697| "E3" | A filled area is drawn through the end points of the vertical error bars.|
698| "E4" | A smoothed filled area is drawn through the end points of the vertical error bars.|
699| "E0" | Draw error bars. Markers are drawn for bins with 0 contents. Combined with E1 or E2 it avoids error bars clipping|
700| "E5" | Like E3 but ignore the bins with 0 contents.|
701| "E6" | Like E4 but ignore the bins with 0 contents.|
702| "X0" | When used with one of the "E" option, it suppress the error bar along X as `gStyle->SetErrorX(0)` would do.|
703
704Begin_Macro(source)
705{
706 auto c1 = new TCanvas("c1","c1",600,400);
707 auto he = new TH1F("he","Distribution drawn with error bars (option E1) ",100,-3,3);
708 for (int i=0; i<10000; i++) he->Fill(gRandom->Gaus(0,1));
709 gStyle->SetEndErrorSize(3);
710 gStyle->SetErrorX(1.);
711 he->SetMarkerStyle(20);
712 he->Draw("E1");
713}
714End_Macro
715
716The options "E3" and "E4" draw an error band through the end points of the
717vertical error bars. With "E4" the error band is smoothed. Because of the
718smoothing algorithm used some artefacts may appear at the end of the band
719like in the following example. In such cases "E3" should be used instead
720of "E4".
721
722Begin_Macro(source)
723{
724 auto ce4 = new TCanvas("ce4","ce4",600,400);
725 ce4->Divide(2,1);
726 auto he4 = new TH1F("he4","Distribution drawn with option E4",100,-3,3);
727 Int_t i;
728 for (i=0;i<10000;i++) he4->Fill(gRandom->Gaus(0,1));
729 he4->SetFillColor(kRed);
730 he4->GetXaxis()->SetRange(40,48);
731 ce4->cd(1);
732 he4->Draw("E4");
733 ce4->cd(2);
734 auto he3 = (TH1F*)he4->DrawClone("E3");
735 he3->SetTitle("Distribution drawn option E3");
736}
737End_Macro
738
7392D histograms can be drawn with error bars as shown is the following example:
740
741Begin_Macro(source)
742{
743 auto c2e = new TCanvas("c2e","c2e",600,400);
744 auto h2e = new TH2F("h2e","TH2 drawn with option E",40,-4,4,40,-20,20);
745 float px, py;
746 for (Int_t i = 0; i < 25000; i++) {
747 gRandom->Rannor(px,py);
748 h2e->Fill(px,5*py);
749 }
750 h2e->Draw("E");
751}
752End_Macro
753
754
755\anchor HP100
756### The bar chart option
757
758
759The option "B" allows to draw simple vertical bar charts.
760The bar width is controlled with `TH1::SetBarWidth()`,
761and the bar offset within the bin, with `TH1::SetBarOffset()`.
762These two settings are useful to draw several histograms on the
763same plot as shown in the following example:
764
765Begin_Macro(source)
766{
767 int i;
768 const Int_t nx = 8;
769 string os_X[nx] = {"8","32","128","512","2048","8192","32768","131072"};
770 float d_35_0[nx] = {0.75, -3.30, -0.92, 0.10, 0.08, -1.69, -1.29, -2.37};
771 float d_35_1[nx] = {1.01, -3.02, -0.65, 0.37, 0.34, -1.42, -1.02, -2.10};
772
773 auto cb = new TCanvas("cb","cb",600,400);
774 cb->SetGrid();
775
776 gStyle->SetHistMinimumZero();
777
778 auto h1b = new TH1F("h1b","Option B example",nx,0,nx);
779 h1b->SetFillColor(4);
780 h1b->SetBarWidth(0.4);
781 h1b->SetBarOffset(0.1);
782 h1b->SetStats(0);
783 h1b->SetMinimum(-5);
784 h1b->SetMaximum(5);
785
786 for (i=1; i<=nx; i++) {
787 h1b->SetBinContent(i, d_35_0[i-1]);
788 h1b->GetXaxis()->SetBinLabel(i,os_X[i-1].c_str());
789 }
790
791 h1b->Draw("b");
792
793 auto h2b = new TH1F("h2b","h2b",nx,0,nx);
794 h2b->SetFillColor(38);
795 h2b->SetBarWidth(0.4);
796 h2b->SetBarOffset(0.5);
797 h2b->SetStats(0);
798 for (i=1;i<=nx;i++) h2b->SetBinContent(i, d_35_1[i-1]);
799
800 h2b->Draw("b same");
801}
802End_Macro
803
804
805\anchor HP10
806### The "BAR" and "HBAR" options
807
808
809When the option `bar` or `hbar` is specified, a bar chart is drawn. A vertical
810bar-chart is drawn with the options `bar`, `bar0`, `bar1`, `bar2`, `bar3`, `bar4`.
811An horizontal bar-chart is drawn with the options `hbar`, `hbar0`, `hbar1`,
812`hbar2`, `hbar3`, `hbar4` (hist006_TH1_bar_charts.C).
813
814- The bar is filled with the histogram fill color.
815- The left side of the bar is drawn with a light fill color.
816- The right side of the bar is drawn with a dark fill color.
817- The percentage of the bar drawn with either the light or dark color is:
818 - 0% for option "(h)bar" or "(h)bar0"
819 - 10% for option "(h)bar1"
820 - 20% for option "(h)bar2"
821 - 30% for option "(h)bar3"
822 - 40% for option "(h)bar4"
823
824When an histogram has errors the option ["HIST"](\ref OPTHIST) together with the `(h)bar` option.
825
826Begin_Macro(source)
827../../../tutorials/hist/hist006_TH1_bar_charts.C
828End_Macro
829
830To control the bar width (default is the bin width) `TH1::SetBarWidth()`
831should be used.
832
833To control the bar offset (default is 0) `TH1::SetBarOffset()` should
834be used.
835
836These two parameters are useful when several histograms are plotted using
837the option `SAME`. They allow to plot the histograms next to each other.
838
839
840\anchor HP11
841### The SCATter plot option (legacy draw option)
842
843\attention
844Use of option `SCAT` has been deprecated. It was the default drawing option for 2D and
8453D histograms. The new default option is `COL` (heat-map).
846
847
848For each cell (i,j) a number of points proportional to the cell content is
849drawn. A maximum of `kNMAX` points per cell is drawn. If the maximum is above
850`kNMAX` contents are normalized to `kNMAX` (`kNMAX=2000`).
851If option is of the form `scat=ff`, (eg `scat=1.8`,
852`scat=1e-3`), then `ff` is used as a scale factor to compute the
853number of dots. `scat=1` is the default.
854
855By default the scatter plot is painted with a "dot marker" which not scalable
856(see the `TAttMarker` documentation). To change the marker size, a scalable marker
857type should be used. For instance a circle (marker style 20).
858
859Begin_Macro(source)
860{
861 auto c1 = new TCanvas("c1","c1",600,400);
862 auto hscat = new TH2F("hscat","Option SCATter example (default for 2D histograms) ",40,-4,4,40,-20,20);
863 float px, py;
864 for (Int_t i = 0; i < 25000; i++) {
865 gRandom->Rannor(px,py);
866 hscat->Fill(px,5*py);
867 hscat->Fill(3+0.5*px,2*py-10.);
868 }
869 hscat->Draw("scat=0.5"); // This a legacy draw option. Please consider using TScatter
870}
871End_Macro
872
873
874\anchor HP12
875### The ARRow option
876
877
878Shows gradient between adjacent cells. For each cell (i,j) an arrow is drawn
879The orientation of the arrow follows the cell gradient.
880
881Begin_Macro(source)
882{
883 auto c1 = new TCanvas("c1","c1",600,400);
884 auto harr = new TH2F("harr","Option ARRow example",20,-4,4,20,-20,20);
885 harr->SetLineColor(kRed);
886 float px, py;
887 for (Int_t i = 0; i < 25000; i++) {
888 gRandom->Rannor(px,py);
889 harr->Fill(px,5*py);
890 harr->Fill(3+0.5*px,2*py-10.,0.1);
891 }
892 harr->Draw("ARR");
893}
894End_Macro
895
896\since **ROOT version 6.17/01**
897
898The option `ARR` can be combined with the option `COL` or `COLZ`.
899
900Begin_Macro(source)
901{
902 auto c1 = new TCanvas("c1","c1",600,400);
903 auto harr = new TH2F("harr","Option ARR + COLZ example",20,-4,4,20,-20,20);
904 harr->SetStats(0);
905 float px, py;
906 for (Int_t i = 0; i < 25000; i++) {
907 gRandom->Rannor(px,py);
908 harr->Fill(px,5*py);
909 harr->Fill(3+0.5*px,2*py-10.,0.1);
910 }
911 harr->Draw("ARR COLZ");
912}
913End_Macro
914
915
916\anchor HP13
917### The BOX option
918
919
920For each cell (i,j) a box is drawn. The size (surface) of the box is
921proportional to the absolute value of the cell content.
922The cells with a negative content are drawn with a `X` on top of the box.
923
924Begin_Macro(source)
925{
926 auto c1 = new TCanvas("c1","c1",600,400);
927 auto hbox = new TH2F("hbox","Option BOX example",3,0,3,3,0,3);
928 hbox->SetFillColor(42);
929 hbox->Fill(0.5, 0.5, 1.);
930 hbox->Fill(0.5, 1.5, 4.);
931 hbox->Fill(0.5, 2.5, 3.);
932 hbox->Fill(1.5, 0.5, 2.);
933 hbox->Fill(1.5, 1.5, 12.);
934 hbox->Fill(1.5, 2.5, -6.);
935 hbox->Fill(2.5, 0.5, -4.);
936 hbox->Fill(2.5, 1.5, 6.);
937 hbox->Fill(2.5, 2.5, 0.5);
938 hbox->Draw("BOX");
939}
940End_Macro
941
942With option `BOX1` a button is drawn for each cell with surface
943proportional to content's absolute value. A sunken button is drawn for
944negative values a raised one for positive.
945
946Begin_Macro(source)
947{
948 auto c1 = new TCanvas("c1","c1",600,400);
949 auto hbox1 = new TH2F("hbox1","Option BOX1 example",3,0,3,3,0,3);
950 hbox1->SetFillColor(42);
951 hbox1->Fill(0.5, 0.5, 1.);
952 hbox1->Fill(0.5, 1.5, 4.);
953 hbox1->Fill(0.5, 2.5, 3.);
954 hbox1->Fill(1.5, 0.5, 2.);
955 hbox1->Fill(1.5, 1.5, 12.);
956 hbox1->Fill(1.5, 2.5, -6.);
957 hbox1->Fill(2.5, 0.5, -4.);
958 hbox1->Fill(2.5, 1.5, 6.);
959 hbox1->Fill(2.5, 2.5, 0.5);
960 hbox1->Draw("BOX1");
961}
962End_Macro
963
964When the option `SAME` (or "SAMES") is used with the option `BOX`,
965the boxes' sizes are computed taking the previous plots into account. The range
966along the Z axis is imposed by the first plot (the one without option
967`SAME`); therefore the order in which the plots are done is relevant.
968
969Begin_Macro(source)
970{
971 auto c1 = new TCanvas("c1","c1",600,400);
972 auto hb1 = new TH2F("hb1","Example of BOX plots with option SAME ",40,-3,3,40,-3,3);
973 auto hb2 = new TH2F("hb2","hb2",40,-3,3,40,-3,3);
974 auto hb3 = new TH2F("hb3","hb3",40,-3,3,40,-3,3);
975 auto hb4 = new TH2F("hb4","hb4",40,-3,3,40,-3,3);
976 for (Int_t i=0;i<1000;i++) {
977 double x,y;
978 gRandom->Rannor(x,y);
979 if (x>0 && y>0) hb1->Fill(x,y,4);
980 if (x<0 && y<0) hb2->Fill(x,y,3);
981 if (x>0 && y<0) hb3->Fill(x,y,2);
982 if (x<0 && y>0) hb4->Fill(x,y,1);
983 }
984 hb1->SetFillColor(1);
985 hb2->SetFillColor(2);
986 hb3->SetFillColor(3);
987 hb4->SetFillColor(4);
988 hb1->Draw("box");
989 hb2->Draw("box same");
990 hb3->Draw("box same");
991 hb4->Draw("box same");
992}
993End_Macro
994
995\since **ROOT version 6.17/01:**
996
997Sometimes the change of the range of the Z axis is unwanted, in which case, one
998can use `SAME0` (or `SAMES0`) option to opt out of this change.
999
1000Begin_Macro(source)
1001{
1002 auto h2 = new TH2F("h2"," ",10,0,10,10,20,30);
1003 auto hf = (TH2F*)h2->Clone("hf");
1004 h2->SetBit(TH1::kNoStats);
1005 hf->SetBit(TH1::kNoStats);
1006 h2->Fill(5,22);
1007 h2->Fill(5,23);
1008 h2->Fill(6,22);
1009 h2->Fill(6,23);
1010 hf->Fill(6,23);
1011 hf->Fill(6,23);
1012 hf->Fill(6,23);
1013 hf->Fill(6,23);
1014 hf->Fill(5,23);
1015
1016 auto hf_copy1 = hf->Clone("hf_copy1");
1017 TLatex lt;
1018
1019 auto cx = new TCanvas(); cx->Divide(2,1);
1020
1021 cx->cd(1);
1022 h2->Draw("box");
1023 hf->Draw("text colz same");
1024 lt.DrawLatexNDC(0.3,0.5,"SAME");
1025
1026 cx->cd(2);
1027 h2->Draw("box");
1028 hf_copy1->Draw("text colz same0");
1029 lt.DrawLatexNDC(0.3,0.5,"SAME0");
1030}
1031End_Macro
1032
1033
1034\anchor HP14
1035### The COLor option (default for 2D histograms)
1036
1037The magnitude of individual cell (i,j) is represented as a color picked in the current color palette.
1038This data visualization technique is often called a heat map (or heat-map).
1039
1040The color table used is defined in the current style.
1041
1042If the histogram's minimum and maximum are the same (flat histogram), the
1043mapping on colors is not possible, therefore nothing is painted. To paint a
1044flat histogram it is enough to set the histogram minimum
1045(`TH1::SetMinimum()`) different from the bins' content.
1046
1047The default number of color levels used to paint the cells is 20.
1048It can be changed with `TH1::SetContour()` or
1049`TStyle::SetNumberContours()`. The higher this number is, the smoother
1050is the color change between cells.
1051
1052The color palette in TStyle can be modified via `gStyle->SetPalette()`.
1053
1054All the non-empty bins are painted. Empty bins (bins with content and error equal to 0) are
1055not painted unless some bins have a negative content because in that case the null bins
1056might be not empty.
1057
1058`TProfile2D` histograms are handled differently because, for this type of 2D
1059histograms, it is possible to know if an empty bin has been filled or not. So even
1060if all the bins' contents are positive some empty bins might be painted. And vice versa,
1061if some bins have a negative content some empty bins might be not painted.
1062
1063Combined with the option `COL`, the option `Z` allows to
1064display the color palette defined by `gStyle->SetPalette()`.
1065
1066In the following example, the histogram has only positive bins; the empty
1067bins (containing 0) are not drawn.
1068
1069Begin_Macro(source)
1070{
1071 auto c1 = new TCanvas("c1","c1",600,400);
1072 auto hcol1 = new TH2F("hcol1","Option COLor example ",40,-4,4,40,-20,20);
1073 float px, py;
1074 for (Int_t i = 0; i < 25000; i++) {
1075 gRandom->Rannor(px,py);
1076 hcol1->Fill(px,5*py);
1077 }
1078 hcol1->Draw("COLZ");
1079}
1080End_Macro
1081
1082In the first plot of following example, the histogram has some negative bins;
1083the empty bins (containing 0) are drawn. In some cases one wants to not draw
1084empty bins (containing 0) of histograms having a negative minimum. The option
1085`1`, used to produce the second plot in the following picture, allows to do that.
1086
1087Begin_Macro(source)
1088{
1089 auto c1 = new TCanvas("c1","c1",600,600);
1090 c1->Divide(1,2);
1091 auto hcol23 = new TH2F("hcol23","Option COLZ example ",40,-4,4,40,-20,20);
1092 auto hcol24 = new TH2F("hcol24","Option COLZ1 example ",40,-4,4,40,-20,20);
1093 float px, py;
1094 for (Int_t i = 0; i < 25000; i++) {
1095 gRandom->Rannor(px,py);
1096 hcol23->Fill(px,5*py);
1097 hcol24->Fill(px,5*py);
1098 }
1099 hcol23->Fill(0.,0.,-200.);
1100 hcol24->Fill(0.,0.,-200.);
1101 c1->cd(1); hcol23->Draw("COLZ");
1102 c1->cd(2); hcol24->Draw("COLZ1");
1103}
1104End_Macro
1105
1106When the maximum of the histogram is set to a smaller value than the real maximum,
1107 the bins having a content between the new maximum and the real maximum are
1108painted with the color corresponding to the new maximum.
1109
1110When the minimum of the histogram is set to a greater value than the real minimum,
1111 the bins having a value between the real minimum and the new minimum are not drawn
1112 unless the option `0` is set.
1113In other words, option `COLZ0` forces the painting of bins with content < set minimum with
1114 a color corresponding to the set minimum. In contrast, option `COLZ` would not draw values
1115 smaller than the specified minimum. Note that both `COLZ` and `COLZ0` still do not draw
1116 empty bins, ie bins with `content == error == 0`, if the set min is not negative.
1117(Note that option `COLZ0` for TH2Poly has a different behavior than for TH2.)
1118
1119The following example illustrates the option `0` combined with the option `COL`.
1120
1121Begin_Macro(source)
1122{
1123 auto c1 = new TCanvas("c1","c1",600,600);
1124 c1->Divide(1,2);
1125 auto hcol21 = new TH2F("hcol21","Option COLZ",40,-4,4,40,-20,20);
1126 auto hcol22 = new TH2F("hcol22","Option COLZ0",40,-4,4,40,-20,20);
1127 float px, py;
1128 for (Int_t i = 0; i < 25000; i++) {
1129 gRandom->Rannor(px,py);
1130 hcol21->Fill(px,5*py);
1131 hcol22->Fill(px,5*py);
1132 }
1133 hcol21->SetBit(TH1::kNoStats);
1134 hcol22->SetBit(TH1::kNoStats);
1135 c1->cd(1); hcol21->Draw("COLZ");
1136 c1->cd(2); hcol22->Draw("COLZ0");
1137 hcol21->SetMaximum(100);
1138 hcol21->SetMinimum(40);
1139 hcol22->SetMaximum(100);
1140 hcol22->SetMinimum(40);
1141}
1142End_Macro
1143
1144Note that the behavior of `COLZ` is not symmetric: it does not draw values below the specified minimum,
1145but does draw values above the specified maximum by clipping them to the maximum color. In contrast, `COLZ0`
1146clips color on both lower and upper sides. Both `COLZ0` and `COLZ` exclude drawing empty bins (`content == error == 0`),
1147if the set minimum is not negative.
1148
1149\since **ROOT version 6.09/01:**
1150
1151When the option SAME (or "SAMES") is used with the option COL, the boxes' color
1152are computed taking the previous plots into account. The range along the Z axis
1153is imposed by the first plot (the one without option SAME); therefore the order
1154in which the plots are done is relevant. Same as [in the `BOX` option](\ref HP13), one can use
1155`SAME0` (or `SAMES0`) to opt out of this imposition.
1156
1157Begin_Macro(source)
1158{
1159 auto c = new TCanvas("c","Example of col plots with option SAME",200,10,700,500);
1160 auto h1 = new TH2F("h1","h1",40,-3,3,40,-3,3);
1161 auto h2 = new TH2F("h2","h2",40,-3,3,40,-3,3);
1162 auto h3 = new TH2F("h3","h3",40,-3,3,40,-3,3);
1163 auto h4 = new TH2F("h4","h4",40,-3,3,40,-3,3);
1164 h1->SetBit(TH1::kNoStats);
1165 for (Int_t i=0;i<5000;i++) {
1166 double x,y;
1167 gRandom->Rannor(x,y);
1168 if(x>0 && y>0) h1->Fill(x,y,4);
1169 if(x<0 && y<0) h2->Fill(x,y,3);
1170 if(x>0 && y<0) h3->Fill(x,y,2);
1171 if(x<0 && y>0) h4->Fill(x,y,1);
1172 }
1173 h1->Draw("colz");
1174 h2->Draw("col same");
1175 h3->Draw("col same");
1176 h4->Draw("col same");
1177}
1178End_Macro
1179
1180The option `COL` can be combined with the option `POL`:
1181
1182Begin_Macro(source)
1183{
1184 auto c1 = new TCanvas("c1","c1",600,400);
1185 auto hcol1 = new TH2F("hcol1","Option COLor combined with POL",40,-4,4,40,-4,4);
1186 float px, py;
1187 for (Int_t i = 0; i < 25000; i++) {
1188 gRandom->Rannor(px,py);
1189 hcol1->Fill(px,py);
1190 }
1191 hcol1->Draw("COLZPOL");
1192}
1193End_Macro
1194
1195\since **ROOT version 6.07/03:**
1196
1197A second rendering technique is also available with the COL2 and COLZ2 options.
1198
1199These options provide potential performance improvements compared to the standard
1200COL option. The performance comparison of the COL2 to the COL option depends on
1201the histogram and the size of the rendering region in the current pad. In general,
1202a small (approx. less than 100 bins per axis), sparsely populated TH2 will render
1203faster with the COL option.
1204
1205However, for larger histograms (approx. more than 100 bins per axis)
1206that are not sparse, the COL2 option will provide up to 20 times performance improvements.
1207For example, a 1000x1000 bin TH2 that is not sparse will render an order of magnitude
1208faster with the COL2 option.
1209
1210The COL2 option will also scale its performance based on the size of the
1211pixmap the histogram image is being rendered into. It also is much better optimized for
1212sessions where the user is forwarding X11 windows through an `ssh` connection.
1213
1214For the most part, the COL2 and COLZ2 options are a drop in replacement to the COL
1215and COLZ options. There is one major difference and that concerns the treatment of
1216bins with zero content. The COL2 and COLZ2 options color these bins the color of zero.
1217
1218COL2 option renders the histogram as a bitmap. Therefore it cannot be saved in vector
1219graphics file format like PostScript or PDF (an empty image will be generated). It can
1220be saved only in bitmap files like PNG format for instance.
1221
1222
1223\anchor HP140
1224### The CANDLE and VIOLIN options
1225
1226The mechanism behind Candle plots and Violin plots is very similar. Because of this they are
1227implemented in the same class TCandle. The keywords CANDLE or VIOLIN will initiate the drawing of
1228the corresponding plots. Followed by the keyword the user can select a plot direction (X or V for
1229vertical projections, or Y or H for horizontal projections) and/or predefined definitions
1230(1-6 for candles, 1-2 for violins). The order doesn't matter. Default is X and 1.
1231
1232Instead of using the predefined representations, the candle and violin parameters can be
1233changed individually. In that case the option have the following form:
1234
1235 CANDLEX(<option-string>)
1236 CANDLEY(<option-string>)
1237 VIOLINX(<option-string>)
1238 VIOLINY(<option-string>).
1239
1240All zeros at the beginning of `option-string` can be omitted.
1241
1242`option-string` consists eight values, defined as follow:
1243
1244 "CANDLEX(zhpawMmb)"
1245
1246Where:
1247
1248 - `b = 0`; no box drawn
1249 - `b = 1`; the box is drawn. As the candle-plot is also called a box-plot it
1250 makes sense in the very most cases to always draw the box
1251 - `b = 2`; draw a filled box with border
1252
1253 - `m = 0`; no median drawn
1254 - `m = 1`; median is drawn as a line
1255 - `m = 2`; median is drawn with errors (notches)
1256 - `m = 3`; median is drawn as a circle
1257
1258 - `M = 0`; no mean drawn
1259 - `M = 1`; mean is drawn as a dashed line
1260 - `M = 3`; mean is drawn as a circle
1261
1262 - `w = 0`; no whisker drawn
1263 - `w = 1`; whisker is drawn to end of distribution.
1264 - `w = 2`; whisker is drawn to max 1.5*iqr
1265
1266 - `a = 0`; no anchor drawn
1267 - `a = 1`; the anchors are drawn
1268
1269 - `p = 0`; no points drawn
1270 - `p = 1`; only outliers are drawn
1271 - `p = 2`; all datapoints are drawn
1272 - `p = 3`: all datapoints are drawn scattered
1273
1274 - `h = 0`; no histogram is drawn
1275 - `h = 1`; histogram at the left or bottom side is drawn
1276 - `h = 2`; histogram at the right or top side is drawn
1277 - `h = 3`; histogram at left and right or top and bottom (violin-style) is drawn
1278
1279 - `z = 0`; no zero indicator line is drawn
1280 - `z = 1`; zero indicator line is drawn.
1281
1282As one can see all individual options for both candle and violin plots can be accessed by this
1283mechanism. In deed the keywords CANDLE(<option-string>) and VIOLIN(<option-string>) have the same
1284meaning. So you can parametrise an option-string for a candle plot and use the keywords VIOLIN and
1285vice versa, if you wish.
1286
1287Using a logarithmic x- or y-axis is possible for candle and violin charts.
1288
1289\since **ROOT version 6.11/01**
1290
1291a logarithmic z-axis is possible, too but will only affect violin charts of course.
1292
1293\anchor HP140a
1294#### The CANDLE option
1295
1296<a href="http://en.wikipedia.org/wiki/Box_plot">A Candle plot</a> (also known as
1297a "box plot" or "whisker plot") was invented in 1977 by John Tukey. It is a convenient
1298way to describe graphically a data distribution (D) with only five numbers:
1299
1300 1. The minimum value of the distribution D (bottom or left whisker).
1301 2. The lower quartile (Q1): 25% of the data points in D are less than Q1 (bottom of the box).
1302 3. The median (M): 50% of the data points in D are less than M.
1303 4. The upper quartile (Q3): 75% of the data points in D are less than Q3 (top of the box).
1304 5. The maximum value of the distribution D (top or right whisker).
1305
1306In this implementation a TH2 is considered as a collection of TH1 along
1307X (option `CANDLE` or `CANDLEX`) or Y (option `CANDLEY`).
1308Each TH1 is represented as one candle.
1309
1310Begin_Macro(source)
1311../../../tutorials/hist/hist052_Graphics_candle_plot_whiskers.C
1312End_Macro
1313
1314The candle reduces the information coming from a whole distribution into few values.
1315Independently from the number of entries or the significance of the underlying distribution
1316a candle will always look like a candle. So candle plots should be used carefully in
1317particular with unknown distributions. The definition of a candle is based on
1318__unbinned data__. Here, candles are created from binned data. Because of this, the
1319deviation is connected to the bin width used. The calculation of the quantiles
1320normally done on unbinned data also. Because data are binned, this will
1321only work the best possible way within the resolution of one bin
1322
1323Because of all these facts one should take care that:
1324
1325 - there are enough points per candle
1326 - the bin width is small enough (more bins will increase the maximum
1327 available resolution of the quantiles although there will be some
1328 bins with no entries)
1329 - never make a candle-plot if the underlying distribution is double-distributed
1330 - only create candles of distributions that are more-or-less gaussian (the
1331 MPV should be not too far away from the mean).
1332
1333#### What a candle is made of
1334
1335\since **ROOT version 6.07/05**
1336
1337##### The box
1338The box displays the position of the inter-quantile-range of the underlying
1339distribution. The box contains 25% of the distribution below the median
1340and 25% of the distribution above the median. If the underlying distribution is large
1341enough and gaussian shaped the end-points of the box represent \f$ 0.6745\times\sigma \f$
1342(Where \f$ \sigma \f$ is the standard deviation of the gaussian). The width and
1343the position of the box can be modified by SetBarWidth() and SetBarOffset().
1344The +-25% quantiles are calculated by the GetQuantiles() methods.
1345
1346\since **ROOT version 6.11/01**
1347
1348Using the static function TCandle::SetBoxRange(double) the box definition will be
1349overwritten. E.g. using a box range of 0.68 will redefine the area of the lower box edge
1350to the upper box edge in order to cover 68% of the distribution illustrated by that candle.
1351The static function will affect all candle-charts in the running program.
1352Default is 0.5.
1353
1354Using the static function TCandle::SetScaledCandle(bool) the width of the box (and the
1355whole candle) can be influenced. Deactivated, the width is constant (to be set by
1356SetBarWidth() ). Activated, the width of the boxes will be scaled to each other based on the
1357amount of data in the corresponding candle, the maximum width can be influenced by
1358SetBarWidth(). The static function will affect all candle-charts in the running program.
1359Default is false. Scaling between multiple candle-charts (using "same" or THStack) is not
1360supported, yet
1361
1362##### The Median
1363For a sorted list of numbers, the median is the value in the middle of the list.
1364E.g. if a sorted list is made of five numbers "1,2,3,6,7" 3 will be the median
1365because it is in the middle of the list. If the number of entries is even the
1366average of the two values in the middle will be used. As histograms are binned
1367data, the situation is a bit more complex. The following example shows this:
1368
1369~~~ {.cpp}
1370void quantiles() {
1371 auto h = new TH1I("h","h",10,0,10);
1372 //h->Fill(3);
1373 //h->Fill(3);
1374 h->Fill(4);
1375 h->Draw();
1376 double p = 0.;
1377 double q = 0.;
1378 h->GetQuantiles(1,&q,&p);
1379
1380 cout << "Median is: " << q << std::endl;
1381}
1382~~~
1383
1384Here the bin-width is 1.0. If the two Fill(3) are commented out, as there are currently,
1385the example will return a calculated median of 4.5, because that's the bin center
1386of the bin in which the value 4.0 has been dropped. If the two Fill(3) are not
1387commented out, it will return 3.75, because the algorithm tries to evenly distribute
1388the individual values of a bin with bin content > 0. It means the sorted list
1389would be "3.25, 3.75, 4.5".
1390
1391The consequence is a median of 3.75. This shows how important it is to use a
1392small enough bin-width when using candle-plots on binned data.
1393If the distribution is large enough and gaussian shaped the median will be exactly
1394equal to the mean.
1395The median can be shown as a line or as a circle or not shown at all.
1396
1397In order to show the significance of the median notched candle plots apply a "notch" or
1398narrowing of the box around the median. The significance is defined by
1399\f$ 1.57\times\frac{iqr}{N} \f$ and will be represented as the size of the notch
1400(where iqr is the size of the box and N is the number of entries of the whole
1401distribution). Candle plots like these are usually called "notched candle plots".
1402
1403In case the significance of the median is greater that the size of the box, the
1404box will have an unnatural shape. Usually it means the chart has not enough data,
1405or that representing this uncertainty is not useful
1406
1407##### The Mean
1408The mean can be drawn as a dashed line or as a circle or not drawn at all.
1409The mean is the arithmetic average of the values in the distribution.
1410It is calculated using GetMean(). Because histograms are
1411binned data, the mean value can differ from a calculation on the raw-data.
1412If the distribution is large enough and gaussian shaped the mean will be
1413exactly the median.
1414
1415##### The Whiskers
1416The whiskers represent the part of the distribution not covered by the box.
1417The upper 25% and the lower 25% of the distribution are located within the whiskers.
1418Two representations are available.
1419
1420 - A simple one (using w=1) defining the lower whisker from the lowest data value
1421 to the bottom of the box, and the upper whisker from the top of the box to the
1422 highest data value. In this representation the whisker-lines are dashed.
1423 - A more complex one having a further restriction. The whiskers are still connected
1424 to the box but their length cannot exceed \f$ 1.5\times iqr \f$. So it might
1425 be that the outermost part of the underlying distribution will not be covered
1426 by the whiskers. Usually these missing parts will be represented by the outliers
1427 (see points). Of course the upper and the lower whisker may differ in length.
1428 In this representation the whiskers are drawn as solid lines.
1429
1430\since **ROOT version 6.11/01**
1431
1432Using the static function TCandle::SetWhiskerRange(double) the whisker definition w=1
1433will be overwritten. E.g. using a whisker-range of 0.95 and w=1 will redefine the area of
1434the lower whisker to the upper whisker in order to cover 95% of the distribution inside
1435that candle. The static function will affect all candle-charts in the running program.
1436Default is 1.
1437
1438If the distribution is large enough and gaussian shaped, the maximum length of
1439the whisker will be located at \f$ \pm 2.698 \sigma \f$ (when using the
14401.5*iqr-definition (w=2), where \f$ \sigma \f$ is the standard deviation
1441(see picture above). In that case 99.3% of the total distribution will be covered
1442by the box and the whiskers, whereas 0.7% are represented by the outliers.
1443
1444##### The Anchors
1445The anchors have no special meaning in terms of statistical calculation. They mark
1446the end of the whiskers and they have the width of the box. Both representation
1447with and without anchors are common.
1448
1449##### The Points
1450Depending on the configuration the points can have different meanings:
1451 - If p=1 the points represent the outliers. If they are shown, it means
1452 some parts of the underlying distribution are not covered by the whiskers.
1453 This can only occur when the whiskers are set to option w=2. Here the whiskers
1454 can have a maximum length of \f$ 1.5 \times iqr \f$. So any points outside the
1455 whiskers will be drawn as outliers. The outliers will be represented by crosses.
1456 - If p=2 all points in the distribution will be painted as crosses. This is
1457 useful for small datasets only (up to 10 or 20 points per candle).
1458 The outliers are shown along the candle. Because the underlying distribution
1459 is binned, is frequently occurs that a bin contains more than one value.
1460 Because of this the points will be randomly scattered within their bin along
1461 the candle axis. If the bin content for a bin is exactly 1 (usually
1462 this happens for the outliers) if will be drawn in the middle of the bin along
1463 the candle axis. As the maximum number of points per candle is limited by kNMax/2
1464 on very large datasets scaling will be performed automatically. In that case one
1465 would loose all outliers because they have usually a bin content of 1 (and a
1466 bin content between 0 and 1 after the scaling). Because of this all bin contents
1467 between 0 and 1 - after the scaling - will be forced to be 1.
1468 - As the drawing of all values on large datasets can lead to big amounts of crosses,
1469 one can show all values as a scatter plot instead by choosing p=3. The points will be
1470 drawn as dots and will be scattered within the width of the candle. The color
1471 of the points will be the color of the candle-chart.
1472
1473##### Other Options
1474Is is possible to combine all options of candle and violin plots with each other. E.g. a box-plot
1475with a histogram.
1476
1477#### How to use the candle-plots drawing option
1478
1479There are six predefined candle-plot representations:
1480
1481 - "CANDLEX1": Standard candle (whiskers cover the whole distribution)
1482 - "CANDLEX2": Standard candle with better whisker definition + outliers.
1483 It is a good compromise
1484 - "CANDLEX3": Like candle2 but with a mean as a circle.
1485 It is easier to distinguish mean and median
1486 - "CANDLEX4": Like candle3 but showing the uncertainty of the median as well
1487 (notched candle plots).
1488 For bigger datasets per candle
1489 - "CANDLEX5": Like candle2 but showing all data points.
1490 For very small datasets
1491 - "CANDLEX6": Like candle2 but showing all datapoints scattered.
1492 For huge datasets
1493
1494
1495The following picture shows how the six predefined representations look.
1496
1497Begin_Macro
1498{
1499 auto c1 = new TCanvas("c1","c1",700,800);
1500 c1->Divide(2,3);
1501 gStyle->SetOptStat(kFALSE);
1502
1503 auto hcandle = new TH2F("hcandle"," ",10,-4,4,40,-20,20);
1504 float px, py;
1505 for (Int_t i = 0; i < 15000; i++) {
1506 gRandom->Rannor(px,py);
1507 hcandle->Fill(px,5*py);
1508 }
1509 hcandle->SetMarkerSize(0.5);
1510
1511 TH2F *h2;
1512 for (Int_t i=1; i<7; i++) {
1513 c1->cd(i);
1514 h2 = (TH2F*)hcandle->DrawClone(Form("CANDLE%d",i));
1515 h2->SetTitle(Form("CANDLE%d",i));
1516 }
1517}
1518End_Macro
1519
1520
1521#### Example 1
1522Box and improved whisker, no mean, no median, no anchor no outliers
1523
1524 h1->Draw("CANDLEX(2001)");
1525
1526#### Example 2
1527A Candle-definition like "CANDLEX2" (New standard candle with better whisker definition + outliers)
1528
1529 h1->Draw("CANDLEX(112111)");
1530
1531#### Example 3
1532The following example shows how several candle plots can be super-imposed using
1533the option SAME. Note that the bar-width and bar-offset are active on candle plots.
1534Also the color, the line width, the size of the points and so on can be changed by the
1535standard attribute setting methods such as SetLineColor() SetLineWidth().
1536
1537Begin_Macro(source)
1538../../../tutorials/hist/hist049_Graphics_candle_plot.C
1539End_Macro
1540
1541\anchor HP140b
1542#### The VIOLIN option
1543
1544<a href="http://en.wikipedia.org/wiki/Violin_plot">A violin plot</a> is a candle plot
1545that also encodes the pdf information at each point.
1546
1547
1548Quartiles and mean are also represented at each point, with a marker
1549and two lines.
1550
1551In this implementation a TH2 is considered as a collection of TH1 along
1552X (option `VIOLIN` or `VIOLINX`) or Y (option `VIOLINY`).
1553
1554#### What a violin is made of
1555
1556\since **ROOT version 6.09/02**
1557
1558##### The histogram
1559The histogram is typically drawn to both directions with respect to the middle-line of the
1560corresponding bin. This can be achieved by using h=3. It is possible to draw a histogram only to
1561one side (h=1, or h=2).
1562The maximum number of bins in the histogram is limited to 500, if the number of bins in the used
1563histogram is higher it will be rebinned automatically. The maximum height of the histogram can
1564be modified by using SetBarWidth() and the position can be changed with SetBarOffset().
1565A solid fill style is recommended.
1566
1567\since **ROOT version 6.11/01**
1568
1569Using the static function TCandle::SetScaledViolin(bool) the height of the histogram or the
1570violin can be influenced. Activated, the height of the bins of the individual violins will be
1571scaled with respect to each other, the maximum height can be influenced by SetBarWidth().
1572Deactivated, the height of the bin with the maximum content of each individual violin is
1573set to a constant value using SetBarWidth(). The static function will affect all violin-charts
1574in the running program. Default is true. Scaling between multiple violin-charts
1575(using "same" or THStack) is not supported, yet.
1576
1577##### The zero indicator line
1578Typical for violin charts is a line in the background over the whole histogram indicating
1579the bins with zero entries. The zero indicator line can be activated with z=1. The line color
1580will always be the same as the fill-color of the histogram.
1581
1582##### The Mean
1583The Mean is illustrated with the same mechanism as used for candle plots. Usually a circle is used.
1584
1585##### Whiskers
1586The whiskers are illustrated by the same mechanism as used for candle plots. There is only one
1587difference. When using the simple whisker definition (w=1) and the zero indicator line (z=1), then
1588the whiskers will be forced to be solid (usually hashed)
1589
1590##### Points
1591The points are illustrated by the same mechanism as used for candle plots. E.g. VIOLIN2 uses
1592better whisker definition (w=2) and outliers (p=1).
1593
1594##### Other options
1595It is possible to combine all options of candle or violin plots with each other. E.g. a violin plot
1596including a box-plot.
1597
1598#### How to use the violin-plots drawing option
1599
1600There are two predefined violin-plot representations:
1601 - "VIOLINX1": Standard violin (histogram, mean, whisker over full distribution,
1602 zero indicator line)
1603 - "VIOLINX2": Line VIOLINX1 both with better whisker definition + outliers.
1604
1605A solid fill style is recommended for this plot (as opposed to a hollow or
1606hashed style).
1607
1608Begin_Macro(source)
1609{
1610 auto c1 = new TCanvas("c1","c1",600,400);
1611 Int_t nx(6), ny(40);
1612 double xmin(0.0), xmax(+6.0), ymin(0.0), ymax(+4.0);
1613 auto hviolin = new TH2F("hviolin", "Option VIOLIN example", nx, xmin, xmax, ny, ymin, ymax);
1614 TF1 f1("f1", "gaus", +0,0 +4.0);
1615 double x,y;
1616 for (Int_t iBin=1; iBin<hviolin->GetNbinsX(); ++iBin) {
1617 double xc = hviolin->GetXaxis()->GetBinCenter(iBin);
1618 f1.SetParameters(1, 2.0+TMath::Sin(1.0+xc), 0.2+0.1*(xc-xmin)/xmax);
1619 for(Int_t i=0; i<10000; ++i){
1620 x = xc;
1621 y = f1.GetRandom();
1622 hviolin->Fill(x, y);
1623 }
1624 }
1625 hviolin->SetFillColor(kGray);
1626 hviolin->SetMarkerStyle(20);
1627 hviolin->SetMarkerSize(0.5);
1628 hviolin->Draw("VIOLIN");
1629 c1->Update();
1630}
1631End_Macro
1632
1633The next example illustrates a time development of a certain value:
1634
1635Begin_Macro(source)
1636../../../tutorials/hist/hist047_Graphics_candle_decay.C
1637End_Macro
1638
1639
1640\anchor HP15
1641### The TEXT and TEXTnn Option
1642
1643
1644For each bin the content is printed. The text attributes are:
1645
1646- text font = current TStyle font (`gStyle->SetTextFont()`).
1647- text size = 0.02*padheight*markersize (if `h` is the histogram drawn
1648 with the option `TEXT` the marker size can be changed with
1649 `h->SetMarkerSize(markersize)`).
1650- text color = marker color.
1651
1652By default the format `g` is used. This format can be redefined
1653by calling `gStyle->SetPaintTextFormat()`.
1654
1655It is also possible to use `TEXTnn` in order to draw the text with
1656the angle `nn` (`0 < nn <= 90`).
1657
1658For 2D histograms the text is plotted in the center of each non empty cells.
1659It is possible to plot empty cells by calling `gStyle->SetHistMinimumZero()`
1660or providing MIN0 draw option. For 1D histogram the text is plotted at a y
1661position equal to the bin content.
1662
1663For 2D histograms when the option "E" (errors) is combined with the option
1664text ("TEXTE"), the error for each bin is also printed.
1665
1666Begin_Macro(source)
1667{
1668 auto c01 = new TCanvas("c01","c01",700,400);
1669 c01->Divide(2,1);
1670 auto htext1 = new TH1F("htext1","Option TEXT on 1D histograms ",10,-4,4);
1671 auto htext2 = new TH2F("htext2","Option TEXT on 2D histograms ",10,-4,4,10,-20,20);
1672 float px, py;
1673 for (Int_t i = 0; i < 25000; i++) {
1674 gRandom->Rannor(px,py);
1675 htext1->Fill(px,0.1);
1676 htext2->Fill(px,5*py,0.1);
1677 }
1678 gStyle->SetPaintTextFormat("4.1f m");
1679 htext2->SetMarkerSize(1.8);
1680 c01->cd(1);
1681 htext2->Draw("TEXT45");
1682 c01->cd(2);
1683 htext1->Draw();
1684 htext1->Draw("HIST TEXT0 SAME");
1685}
1686End_Macro
1687
1688\since **ROOT version 6.07/07:**
1689
1690In case several histograms are drawn on top ot each other (using option `SAME`),
1691the text can be shifted using `SetBarOffset()`. It specifies an offset for the
1692text position in each cell, in percentage of the bin width.
1693
1694Begin_Macro(source)
1695{
1696 auto c03 = new TCanvas("c03","c03",700,400);
1697 gStyle->SetOptStat(0);
1698 auto htext3 = new TH2F("htext3","Several 2D histograms drawn with option TEXT",10,-4,4,10,-20,20);
1699 auto htext4 = new TH2F("htext4","htext4",10,-4,4,10,-20,20);
1700 auto htext5 = new TH2F("htext5","htext5",10,-4,4,10,-20,20);
1701 float px, py;
1702 for (Int_t i = 0; i < 25000; i++) {
1703 gRandom->Rannor(px,py);
1704 htext3->Fill(4*px,20*py,0.1);
1705 htext4->Fill(4*px,20*py,0.5);
1706 htext5->Fill(4*px,20*py,1.0);
1707 }
1708 htext4->SetMarkerSize(1.8);
1709 htext5->SetMarkerSize(1.8);
1710 htext5->SetMarkerColor(kRed);
1711 htext4->SetBarOffset(0.2);
1712 htext5->SetBarOffset(-0.2);
1713 htext3->Draw("COL");
1714 htext4->Draw("TEXT SAME");
1715 htext5->Draw("TEXT SAME");
1716}
1717End_Macro
1718
1719In the case of profile histograms it is possible to print the number
1720of entries instead of the bin content. It is enough to combine the
1721option "E" (for entries) with the option "TEXT".
1722
1723Begin_Macro(source)
1724{
1725 auto c02 = new TCanvas("c02","c02",700,400);
1726 c02->Divide(2,1);
1727 gStyle->SetPaintTextFormat("g");
1728
1729 auto profile = new TProfile("profile","profile",10,0,10);
1730 profile->SetMarkerSize(2.2);
1731 profile->Fill(0.5,1);
1732 profile->Fill(1.5,2);
1733 profile->Fill(2.5,3);
1734 profile->Fill(3.5,4);
1735 profile->Fill(4.5,5);
1736 profile->Fill(5.5,5);
1737 profile->Fill(6.5,4);
1738 profile->Fill(7.5,3);
1739 profile->Fill(8.5,2);
1740 profile->Fill(9.5,1);
1741 c02->cd(1); profile->Draw("HIST TEXT0");
1742 c02->cd(2); profile->Draw("HIST TEXT0E");
1743}
1744End_Macro
1745
1746\anchor HP16
1747### The CONTour options
1748
1749
1750The following contour options are supported:
1751
1752| Option | Description |
1753|----------|-----------------------------------------------------------------------------|
1754| "CONT" | Draw a contour plot (same as CONT0). |
1755| "CONT0" | Draw a contour plot using surface colors to distinguish contours. |
1756| "CONT1" | Draw a contour plot using the line colors to distinguish contours. |
1757| "CONT2" | Draw a contour plot using the line styles (1 to 5) to distinguish contours. |
1758| "CONT3" | Draw a contour plot using the same line style for all contours. |
1759| "CONT4" | Draw a contour plot using surface colors (`SURF` option at theta = 0). |
1760
1761
1762The following example shows a 2D histogram plotted with the option
1763`CONTZ`. The option `CONT` draws a contour plot using surface
1764colors to distinguish contours. Combined with the option `CONT` (or
1765`CONT0`), the option `Z` allows to display the color palette
1766defined by `gStyle->SetPalette()`.
1767
1768Begin_Macro(source)
1769{
1770 auto c1 = new TCanvas("c1","c1",600,400);
1771 auto hcontz = new TH2F("hcontz","Option CONTZ example ",40,-4,4,40,-20,20);
1772 float px, py;
1773 for (Int_t i = 0; i < 25000; i++) {
1774 gRandom->Rannor(px,py);
1775 hcontz->Fill(px-1,5*py);
1776 hcontz->Fill(2+0.5*px,2*py-10.,0.1);
1777 }
1778 hcontz->Draw("CONTZ");
1779}
1780End_Macro
1781
1782The following example shows a 2D histogram plotted with the option
1783`CONT1Z`. The option `CONT1` draws a contour plot using the
1784line colors to distinguish contours. Combined with the option `CONT1`,
1785the option `Z` allows to display the color palette defined by
1786`gStyle->SetPalette()`.
1787
1788Begin_Macro(source)
1789{
1790 auto c1 = new TCanvas("c1","c1",600,400);
1791 auto hcont1 = new TH2F("hcont1","Option CONT1Z example ",40,-4,4,40,-20,20);
1792 float px, py;
1793 for (Int_t i = 0; i < 25000; i++) {
1794 gRandom->Rannor(px,py);
1795 hcont1->Fill(px-1,5*py);
1796 hcont1->Fill(2+0.5*px,2*py-10.,0.1);
1797 }
1798 hcont1->Draw("CONT1Z");
1799}
1800End_Macro
1801
1802The following example shows a 2D histogram plotted with the option
1803`CONT2`. The option `CONT2` draws a contour plot using the
1804line styles (1 to 5) to distinguish contours.
1805
1806Begin_Macro(source)
1807{
1808 auto c1 = new TCanvas("c1","c1",600,400);
1809 auto hcont2 = new TH2F("hcont2","Option CONT2 example ",40,-4,4,40,-20,20);
1810 float px, py;
1811 for (Int_t i = 0; i < 25000; i++) {
1812 gRandom->Rannor(px,py);
1813 hcont2->Fill(px-1,5*py);
1814 hcont2->Fill(2+0.5*px,2*py-10.,0.1);
1815 }
1816 hcont2->Draw("CONT2");
1817}
1818End_Macro
1819
1820The following example shows a 2D histogram plotted with the option
1821`CONT3`. The option `CONT3` draws contour plot using the same line style for
1822all contours.
1823
1824Begin_Macro(source)
1825{
1826 auto c1 = new TCanvas("c1","c1",600,400);
1827 auto hcont3 = new TH2F("hcont3","Option CONT3 example ",40,-4,4,40,-20,20);
1828 float px, py;
1829 for (Int_t i = 0; i < 25000; i++) {
1830 gRandom->Rannor(px,py);
1831 hcont3->Fill(px-1,5*py);
1832 hcont3->Fill(2+0.5*px,2*py-10.,0.1);
1833 }
1834 hcont3->SetLineStyle(kDotted);
1835 hcont3->Draw("CONT3");
1836}
1837End_Macro
1838
1839The following example shows a 2D histogram plotted with the option
1840`CONT4`. The option `CONT4` draws a contour plot using surface
1841colors to distinguish contours (`SURF` option at theta = 0). Combined
1842with the option `CONT` (or `CONT0`), the option `Z`
1843allows to display the color palette defined by `gStyle->SetPalette()`.
1844
1845Begin_Macro(source)
1846{
1847 auto c1 = new TCanvas("c1","c1",600,400);
1848 auto hcont4 = new TH2F("hcont4","Option CONT4Z example ",40,-4,4,40,-20,20);
1849 float px, py;
1850 for (Int_t i = 0; i < 25000; i++) {
1851 gRandom->Rannor(px,py);
1852 hcont4->Fill(px-1,5*py);
1853 hcont4->Fill(2+0.5*px,2*py-10.,0.1);
1854 }
1855 hcont4->Draw("CONT4Z");
1856}
1857End_Macro
1858
1859The default number of contour levels is 20 equidistant levels and can be changed
1860with `TH1::SetContour()` or `TStyle::SetNumberContours()`.
1861
1862\anchor HP16a
1863#### The LIST option
1864
1865When option `LIST` is specified together with option
1866`CONT`, the points used to draw the contours are saved in
1867`TGraph` objects:
1868
1869 h->Draw("CONT LIST");
1870 gPad->Update();
1871
1872The contour are saved in `TGraph` objects once the pad is painted.
1873Therefore to use this functionality in a macro, `gPad->Update()`
1874should be performed after the histogram drawing. Once the list is
1875built, the contours are accessible in the following way:
1876
1877 TObjArray *contours = (TObjArray*)gROOT->GetListOfSpecials()->FindObject("contours");
1878 Int_t ncontours = contours->GetSize();
1879 TList *list = (TList*)contours->At(i);
1880
1881Where `i` is a contour number, and list contains a list of
1882`TGraph` objects.
1883For one given contour, more than one disjoint polyline may be generated.
1884The number of TGraphs per contour is given by:
1885
1886 list->GetSize();
1887
1888To access the first graph in the list one should do:
1889
1890 TGraph *gr1 = (TGraph*)list->First();
1891
1892
1893The following example (hist102_TH2_contour_list.C) shows how to use this functionality.
1894
1895Begin_Macro(source)
1896../../../tutorials/hist/hist102_TH2_contour_list.C
1897End_Macro
1898
1899\anchor HP16b
1900#### The AITOFF, MERCATOR, SINUSOIDAL and PARABOLIC options
1901
1902The following options select the `CONT4` option and are useful for
1903sky maps or exposure maps (earth.C).
1904
1905| Option | Description |
1906|--------------|---------------------------------------------------------------|
1907| "AITOFF" | Draw a contour via an AITOFF projection.|
1908| "MERCATOR" | Draw a contour via an Mercator projection.|
1909| "SINUSOIDAL" | Draw a contour via an Sinusoidal projection.|
1910| "PARABOLIC" | Draw a contour via an Parabolic projection.|
1911
1912Begin_Macro(source)
1913../../../tutorials/visualisation/graphics/earth.C
1914End_Macro
1915
1916
1917\anchor HP17
1918### The LEGO options
1919
1920
1921In a lego plot the cell contents are drawn as 3-d boxes. The height of each box
1922is proportional to the cell content. The lego aspect is control with the
1923following options:
1924
1925| Option | Description |
1926|----------|-------------------------------------------------------------------|
1927| "LEGO" | Draw a lego plot using the hidden lines removal technique.|
1928| "LEGO1" | Draw a lego plot using the hidden surface removal technique.|
1929| "LEGO2" | Draw a lego plot using colors to show the cell contents.|
1930| "LEGO3" | Draw a lego plot with hidden surface removal, like LEGO1 but the border lines of each lego-bar are not drawn.|
1931| "LEGO4" | Draw a lego plot with hidden surface removal, like LEGO1 but without the shadow effect on each lego-bar.|
1932| "0" | When used with any LEGO option, the empty bins are not drawn.|
1933
1934
1935See the limitations with [the option "SAME"](\ref HP060a).
1936
1937Line attributes can be used in lego plots to change the edges' style.
1938
1939The following example shows a 2D histogram plotted with the option
1940`LEGO`. The option `LEGO` draws a lego plot using the hidden
1941lines removal technique.
1942
1943Begin_Macro(source)
1944{
1945 auto c2 = new TCanvas("c2","c2",600,400);
1946 auto hlego = new TH2F("hlego","Option LEGO example ",40,-4,4,40,-20,20);
1947 float px, py;
1948 for (Int_t i = 0; i < 25000; i++) {
1949 gRandom->Rannor(px,py);
1950 hlego->Fill(px-1,5*py);
1951 hlego->Fill(2+0.5*px,2*py-10.,0.1);
1952 }
1953 hlego->Draw("LEGO");
1954}
1955End_Macro
1956
1957The following example shows a 2D histogram plotted with the option
1958`LEGO1`. The option `LEGO1` draws a lego plot using the
1959hidden surface removal technique. Combined with any `LEGOn` option, the
1960option `0` allows to not drawn the empty bins.
1961
1962Begin_Macro(source)
1963{
1964 auto c2 = new TCanvas("c2","c2",600,400);
1965 auto hlego1 = new TH2F("hlego1","Option LEGO1 example (with option 0) ",40,-4,4,40,-20,20);
1966 float px, py;
1967 for (Int_t i = 0; i < 25000; i++) {
1968 gRandom->Rannor(px,py);
1969 hlego1->Fill(px-1,5*py);
1970 hlego1->Fill(2+0.5*px,2*py-10.,0.1);
1971 }
1972 hlego1->SetFillColor(kYellow);
1973 hlego1->Draw("LEGO1 0");
1974}
1975End_Macro
1976
1977The following example shows a 2D histogram plotted with the option
1978`LEGO3`. Like the option `LEGO1`, the option `LEGO3`
1979draws a lego plot using the hidden surface removal technique but doesn't draw
1980the border lines of each individual lego-bar. This is very useful for histograms
1981having many bins. With such histograms the option `LEGO1` gives a black
1982image because of the border lines. This option also works with stacked legos.
1983
1984Begin_Macro(source)
1985{
1986 auto c2 = new TCanvas("c2","c2",600,400);
1987 auto hlego3 = new TH2F("hlego3","Option LEGO3 example",40,-4,4,40,-20,20);
1988 float px, py;
1989 for (Int_t i = 0; i < 25000; i++) {
1990 gRandom->Rannor(px,py);
1991 hlego3->Fill(px-1,5*py);
1992 hlego3->Fill(2+0.5*px,2*py-10.,0.1);
1993 }
1994 hlego3->SetFillColor(kRed);
1995 hlego3->Draw("LEGO3");
1996}
1997End_Macro
1998
1999The following example shows a 2D histogram plotted with the option
2000`LEGO2`. The option `LEGO2` draws a lego plot using colors to
2001show the cell contents. Combined with the option `LEGO2`, the option
2002`Z` allows to display the color palette defined by
2003`gStyle->SetPalette()`.
2004
2005Begin_Macro(source)
2006{
2007 auto c2 = new TCanvas("c2","c2",600,400);
2008 auto hlego2 = new TH2F("hlego2","Option LEGO2Z example ",40,-4,4,40,-20,20);
2009 float px, py;
2010 for (Int_t i = 0; i < 25000; i++) {
2011 gRandom->Rannor(px,py);
2012 hlego2->Fill(px-1,5*py);
2013 hlego2->Fill(2+0.5*px,2*py-10.,0.1);
2014 }
2015 hlego2->Draw("LEGO2Z");
2016}
2017End_Macro
2018
2019
2020
2021\anchor HP18
2022### The "SURFace" options
2023
2024
2025In a surface plot, cell contents are represented as a mesh.
2026The height of the mesh is proportional to the cell content.
2027
2028| Option | Description |
2029|----------|-------------------------------------------------------------------|
2030| "SURF" | Draw a surface plot using the hidden line removal technique.|
2031| "SURF1" | Draw a surface plot using the hidden surface removal technique.|
2032| "SURF2" | Draw a surface plot using colors to show the cell contents.|
2033| "SURF3" | Same as `SURF` with an additional filled contour plot on top.|
2034| "SURF4" | Draw a surface using the Gouraud shading technique.|
2035| "SURF5" | Used with one of the options CYL, PSR and CYL this option allows to draw a filled contour plot.|
2036| "SURF6" | This option should not be used directly. It is used internally when the CONT is used with option the option SAME on a 3D plot.|
2037| "SURF7" | Same as `SURF2` with an additional line contour plot on top.|
2038
2039
2040
2041See the limitations with [the option "SAME"](\ref HP060a).
2042
2043The following example shows a 2D histogram plotted with the option
2044`SURF`. The option `SURF` draws a lego plot using the hidden
2045lines removal technique.
2046
2047Begin_Macro(source)
2048{
2049 auto c2 = new TCanvas("c2","c2",600,400);
2050 auto hsurf = new TH2F("hsurf","Option SURF example ",30,-4,4,30,-20,20);
2051 float px, py;
2052 for (Int_t i = 0; i < 25000; i++) {
2053 gRandom->Rannor(px,py);
2054 hsurf->Fill(px-1,5*py);
2055 hsurf->Fill(2+0.5*px,2*py-10.,0.1);
2056 }
2057 hsurf->Draw("SURF");
2058}
2059End_Macro
2060
2061The following example shows a 2D histogram plotted with the option
2062`SURF1`. The option `SURF1` draws a surface plot using the
2063hidden surface removal technique. Combined with the option `SURF1`,
2064the option `Z` allows to display the color palette defined by
2065`gStyle->SetPalette()`.
2066
2067Begin_Macro(source)
2068{
2069 auto c2 = new TCanvas("c2","c2",600,400);
2070 auto hsurf1 = new TH2F("hsurf1","Option SURF1 example ",30,-4,4,30,-20,20);
2071 float px, py;
2072 for (Int_t i = 0; i < 25000; i++) {
2073 gRandom->Rannor(px,py);
2074 hsurf1->Fill(px-1,5*py);
2075 hsurf1->Fill(2+0.5*px,2*py-10.,0.1);
2076 }
2077 hsurf1->Draw("SURF1");
2078}
2079End_Macro
2080
2081The following example shows a 2D histogram plotted with the option
2082`SURF2`. The option `SURF2` draws a surface plot using colors
2083to show the cell contents. Combined with the option `SURF2`, the option
2084`Z` allows to display the color palette defined by
2085`gStyle->SetPalette()`.
2086
2087Begin_Macro(source)
2088{
2089 auto c2 = new TCanvas("c2","c2",600,400);
2090 auto hsurf2 = new TH2F("hsurf2","Option SURF2 example ",30,-4,4,30,-20,20);
2091 float px, py;
2092 for (Int_t i = 0; i < 25000; i++) {
2093 gRandom->Rannor(px,py);
2094 hsurf2->Fill(px-1,5*py);
2095 hsurf2->Fill(2+0.5*px,2*py-10.,0.1);
2096 }
2097 hsurf2->Draw("SURF2");
2098}
2099End_Macro
2100
2101The following example shows a 2D histogram plotted with the option
2102`SURF3`. The option `SURF3` draws a surface plot using the
2103hidden line removal technique with, in addition, a filled contour view drawn on the
2104top. Combined with the option `SURF3`, the option `Z` allows
2105to display the color palette defined by `gStyle->SetPalette()`.
2106
2107Begin_Macro(source)
2108{
2109 auto c2 = new TCanvas("c2","c2",600,400);
2110 auto hsurf3 = new TH2F("hsurf3","Option SURF3 example ",30,-4,4,30,-20,20);
2111 float px, py;
2112 for (Int_t i = 0; i < 25000; i++) {
2113 gRandom->Rannor(px,py);
2114 hsurf3->Fill(px-1,5*py);
2115 hsurf3->Fill(2+0.5*px,2*py-10.,0.1);
2116 }
2117 hsurf3->Draw("SURF3");
2118}
2119End_Macro
2120
2121The following example shows a 2D histogram plotted with the option
2122`SURF4`. The option `SURF4` draws a surface using the Gouraud
2123shading technique.
2124
2125Begin_Macro(source)
2126{
2127 auto c2 = new TCanvas("c2","c2",600,400);
2128 auto hsurf4 = new TH2F("hsurf4","Option SURF4 example ",30,-4,4,30,-20,20);
2129 float px, py;
2130 for (Int_t i = 0; i < 25000; i++) {
2131 gRandom->Rannor(px,py);
2132 hsurf4->Fill(px-1,5*py);
2133 hsurf4->Fill(2+0.5*px,2*py-10.,0.1);
2134 }
2135 hsurf4->SetFillColor(kOrange);
2136 hsurf4->Draw("SURF4");
2137}
2138End_Macro
2139
2140The following example shows a 2D histogram plotted with the option
2141`SURF5 CYL`. Combined with the option `SURF5`, the option
2142`Z` allows to display the color palette defined by `gStyle->SetPalette()`.
2143
2144Begin_Macro(source)
2145{
2146 auto c2 = new TCanvas("c2","c2",600,400);
2147 auto hsurf5 = new TH2F("hsurf4","Option SURF5 example ",30,-4,4,30,-20,20);
2148 float px, py;
2149 for (Int_t i = 0; i < 25000; i++) {
2150 gRandom->Rannor(px,py);
2151 hsurf5->Fill(px-1,5*py);
2152 hsurf5->Fill(2+0.5*px,2*py-10.,0.1);
2153 }
2154 hsurf5->Draw("SURF5 CYL");
2155}
2156End_Macro
2157
2158The following example shows a 2D histogram plotted with the option
2159`SURF7`. The option `SURF7` draws a surface plot using the
2160hidden surfaces removal technique with, in addition, a line contour view drawn on the
2161top. Combined with the option `SURF7`, the option `Z` allows
2162to display the color palette defined by `gStyle->SetPalette()`.
2163
2164Begin_Macro(source)
2165{
2166 auto c2 = new TCanvas("c2","c2",600,400);
2167 auto hsurf7 = new TH2F("hsurf3","Option SURF7 example ",30,-4,4,30,-20,20);
2168 float px, py;
2169 for (Int_t i = 0; i < 25000; i++) {
2170 gRandom->Rannor(px,py);
2171 hsurf7->Fill(px-1,5*py);
2172 hsurf7->Fill(2+0.5*px,2*py-10.,0.1);
2173 }
2174 hsurf7->Draw("SURF7");
2175}
2176End_Macro
2177
2178As shown in the following example, when a contour plot is painted on top of a
2179surface plot using the option `SAME`, the contours appear in 3D on the
2180surface.
2181
2182Begin_Macro(source)
2183{
2184 auto c20=new TCanvas("c20","c20",600,400);
2185 int NBins = 50;
2186 double d = 2;
2187 auto hsc = new TH2F("hsc", "Surface and contour with option SAME ", NBins, -d, d, NBins, -d, d);
2188 for (int bx = 1; bx <= NBins; ++bx) {
2189 for (int by = 1; by <= NBins; ++by) {
2190 double x = hsc->GetXaxis()->GetBinCenter(bx);
2191 double y = hsc->GetYaxis()->GetBinCenter(by);
2192 hsc->SetBinContent(bx, by, exp(-x*x)*exp(-y*y));
2193 }
2194 }
2195 hsc->Draw("surf2");
2196 hsc->Draw("CONT1 SAME");
2197}
2198End_Macro
2199
2200
2201\anchor HP19
2202### Cylindrical, Polar, Spherical and PseudoRapidity/Phi options
2203
2204
2205Legos and surfaces plots are represented by default in Cartesian coordinates.
2206Combined with any `LEGOn` or `SURFn` options the following
2207options allow to draw a lego or a surface in other coordinates systems.
2208
2209| Option | Description |
2210|----------|-------------------------------------------------------------------|
2211| "CYL" | Use Cylindrical coordinates. The X coordinate is mapped on the angle and the Y coordinate on the cylinder length.|
2212| "POL" | Use Polar coordinates. The X coordinate is mapped on the angle and the Y coordinate on the radius.|
2213| "SPH" | Use Spherical coordinates. The X coordinate is mapped on the latitude and the Y coordinate on the longitude.|
2214| "PSR" | Use PseudoRapidity/Phi coordinates. The X coordinate is mapped on Phi.|
2215
2216
2217
2218<b>WARNING:</b> Axis are not drawn with these options.
2219
2220The following example shows the same histogram as a lego plot is the four
2221different coordinates systems.
2222
2223Begin_Macro(source)
2224{
2225 auto c3 = new TCanvas("c3","c3",600,400);
2226 c3->Divide(2,2);
2227 auto hlcc = new TH2F("hlcc","Cylindrical coordinates",20,-4,4,20,-20,20);
2228 float px, py;
2229 for (Int_t i = 0; i < 25000; i++) {
2230 gRandom->Rannor(px,py);
2231 hlcc->Fill(px-1,5*py);
2232 hlcc->Fill(2+0.5*px,2*py-10.,0.1);
2233 }
2234 hlcc->SetFillColor(kYellow);
2235 c3->cd(1); hlcc->Draw("LEGO1 CYL");
2236 c3->cd(2); auto hlpc = (TH2F*) hlcc->DrawClone("LEGO1 POL");
2237 hlpc->SetTitle("Polar coordinates");
2238 c3->cd(3); auto hlsc = (TH2F*) hlcc->DrawClone("LEGO1 SPH");
2239 hlsc->SetTitle("Spherical coordinates");
2240 c3->cd(4); auto hlprpc = (TH2F*) hlcc->DrawClone("LEGO1 PSR");
2241 hlprpc->SetTitle("PseudoRapidity/Phi coordinates");
2242}
2243End_Macro
2244
2245The following example shows the same histogram as a surface plot is the four different coordinates systems.
2246
2247Begin_Macro(source)
2248{
2249 auto c4 = new TCanvas("c4","c4",600,400);
2250 c4->Divide(2,2);
2251 auto hscc = new TH2F("hscc","Cylindrical coordinates",20,-4,4,20,-20,20);
2252 float px, py;
2253 for (Int_t i = 0; i < 25000; i++) {
2254 gRandom->Rannor(px,py);
2255 hscc->Fill(px-1,5*py);
2256 hscc->Fill(2+0.5*px,2*py-10.,0.1);
2257 }
2258 c4->cd(1); hscc->Draw("SURF1 CYL");
2259 c4->cd(2); auto hspc = (TH2F*) hscc->DrawClone("SURF1 POL");
2260 hspc->SetTitle("Polar coordinates");
2261 c4->cd(3); auto hssc = (TH2F*) hscc->DrawClone("SURF1 SPH");
2262 hssc->SetTitle("Spherical coordinates");
2263 c4->cd(4); auto hsprpc = (TH2F*) hscc->DrawClone("SURF1 PSR");
2264 hsprpc->SetTitle("PseudoRapidity/Phi coordinates");
2265}
2266End_Macro
2267
2268
2269\anchor HP20
2270### Base line for bar-charts and lego plots
2271
2272
2273By default the base line used to draw the boxes for bar-charts and lego plots is
2274the histogram minimum. It is possible to force this base line to be 0, using MIN0 draw
2275option or with the command:
2276
2277 gStyle->SetHistMinimumZero();
2278
2279Begin_Macro(source)
2280{
2281 auto c5 = new TCanvas("c5","c5",700,400);
2282 c5->Divide(2,1);
2283 auto hz1 = new TH1F("hz1","Bar-chart drawn from 0",20,-3,3);
2284 auto hz2 = new TH2F("hz2","Lego plot drawn from 0",20,-3,3,20,-3,3);
2285 Int_t i;
2286 double x,y;
2287 hz1->SetFillColor(kBlue);
2288 hz2->SetFillColor(kBlue);
2289 for (i=0;i<10000;i++) {
2290 x = gRandom->Gaus(0,1);
2291 y = gRandom->Gaus(0,1);
2292 if (x>0) {
2293 hz1->Fill(x,1);
2294 hz2->Fill(x,y,1);
2295 } else {
2296 hz1->Fill(x,-1);
2297 hz2->Fill(x,y,-2);
2298 }
2299 }
2300 c5->cd(1); hz1->Draw("bar2 min0");
2301 c5->cd(2); hz2->Draw("lego1 min0");
2302}
2303End_Macro
2304
2305This option also works for horizontal plots. The example given in the section
2306["The bar chart option"](\ref HP100) appears as follow:
2307
2308Begin_Macro(source)
2309{
2310 int i;
2311 const Int_t nx = 8;
2312 string os_X[nx] = {"8","32","128","512","2048","8192","32768","131072"};
2313 float d_35_0[nx] = {0.75, -3.30, -0.92, 0.10, 0.08, -1.69, -1.29, -2.37};
2314 float d_35_1[nx] = {1.01, -3.02, -0.65, 0.37, 0.34, -1.42, -1.02, -2.10};
2315
2316 auto cbh = new TCanvas("cbh","cbh",400,600);
2317 cbh->SetGrid();
2318
2319 auto h1bh = new TH1F("h1bh","Option HBAR centered on 0",nx,0,nx);
2320 h1bh->SetFillColor(4);
2321 h1bh->SetBarWidth(0.4);
2322 h1bh->SetBarOffset(0.1);
2323 h1bh->SetStats(0);
2324 h1bh->SetMinimum(-5);
2325 h1bh->SetMaximum(5);
2326
2327 for (i=1; i<=nx; i++) {
2328 h1bh->Fill(os_X[i-1].c_str(), d_35_0[i-1]);
2329 h1bh->GetXaxis()->SetBinLabel(i,os_X[i-1].c_str());
2330 }
2331
2332 h1bh->Draw("hbar min0");
2333
2334 auto h2bh = new TH1F("h2bh","h2bh",nx,0,nx);
2335 h2bh->SetFillColor(38);
2336 h2bh->SetBarWidth(0.4);
2337 h2bh->SetBarOffset(0.5);
2338 h2bh->SetStats(0);
2339 for (i=1;i<=nx;i++) h2bh->Fill(os_X[i-1].c_str(), d_35_1[i-1]);
2340
2341 h2bh->Draw("hbar min0 same");
2342}
2343End_Macro
2344
2345
2346\anchor HP20a
2347### TH2Poly Drawing
2348
2349
2350The following options are supported:
2351
2352| Option | Description |
2353|----------|-------------------------------------------------------------------|
2354| "SCAT" | Draw a scatter plot (legacy draw option).|
2355| "COL" | Draw a color plot. All the bins are painted even the empty bins (default).|
2356| "COLZ" | Same as "COL". In addition the color palette is also drawn.|
2357| "0" | When used with any COL options, the empty bins are not drawn.|
2358| "TEXT" | Draw bin contents as text (format set via `gStyle->SetPaintTextFormat`).|
2359| "TEXTN" | Draw bin names as text.|
2360| "TEXTnn" | Draw bin contents as text at angle nn (0 < nn <= 90).|
2361| "L" | Draw the bins boundaries as lines. The lines attributes are the TGraphs ones.|
2362| "P" | Draw the bins boundaries as markers. The markers attributes are the TGraphs ones.|
2363| "F" | Draw the bins boundaries as filled polygons. The filled polygons attributes are the TGraphs ones.|
2364
2365
2366
2367`TH2Poly` can be drawn as a color plot (option COL). `TH2Poly` bins can have any
2368shapes. The bins are defined as graphs. The following macro is a very simple
2369example showing how to book a TH2Poly and draw it.
2370
2371Begin_Macro(source)
2372{
2373 auto ch2p1 = new TCanvas("ch2p1","ch2p1",600,400);
2374 auto h2p = new TH2Poly();
2375 h2p->SetName("h2poly_name");
2376 h2p->SetTitle("h2poly_title");
2377 double px1[] = {0, 5, 6};
2378 double py1[] = {0, 0, 5};
2379 double px2[] = {0, -1, -1, 0};
2380 double py2[] = {0, 0, -1, 3};
2381 double px3[] = {4, 3, 0, 1, 2.4};
2382 double py3[] = {4, 3.7, 1, 3.7, 2.5};
2383 h2p->AddBin(3, px1, py1);
2384 h2p->AddBin(4, px2, py2);
2385 h2p->AddBin(5, px3, py3);
2386 h2p->Fill(0.1, 0.01, 3);
2387 h2p->Fill(-0.5, -0.5, 7);
2388 h2p->Fill(-0.7, -0.5, 1);
2389 h2p->Fill(1, 3, 1.5);
2390 double fx[] = {0.1, -0.5, -0.7, 1};
2391 double fy[] = {0.01, -0.5, -0.5, 3};
2392 double fw[] = {3, 1, 1, 1.5};
2393 h2p->FillN(4, fx, fy, fw);
2394 h2p->Draw("col");
2395}
2396End_Macro
2397
2398Rectangular bins are a frequent case. The special version of
2399the `AddBin` method allows to define them more easily like
2400shown in the following example (hist037_TH2Poly_boxes.C).
2401
2402Begin_Macro(source)
2403../../../tutorials/hist/hist037_TH2Poly_boxes.C
2404End_Macro
2405
2406One `TH2Poly` bin can be a list of polygons. Such bins are defined
2407by calling `AddBin` with a `TMultiGraph`. The following example
2408shows a such case:
2409
2410Begin_Macro(source)
2411{
2412 auto ch2p2 = new TCanvas("ch2p2","ch2p2",600,400);
2413
2414 Int_t i, bin;
2415 const Int_t nx = 48;
2416 const char *states [nx] = {
2417 "alabama", "arizona", "arkansas", "california",
2418 "colorado", "connecticut", "delaware", "florida",
2419 "georgia", "idaho", "illinois", "indiana",
2420 "iowa", "kansas", "kentucky", "louisiana",
2421 "maine", "maryland", "massachusetts", "michigan",
2422 "minnesota", "mississippi", "missouri", "montana",
2423 "nebraska", "nevada", "new_hampshire", "new_jersey",
2424 "new_mexico", "new_york", "north_carolina", "north_dakota",
2425 "ohio", "oklahoma", "oregon", "pennsylvania",
2426 "rhode_island", "south_carolina", "south_dakota", "tennessee",
2427 "texas", "utah", "vermont", "virginia",
2428 "washington", "west_virginia", "wisconsin", "wyoming"
2429 };
2430 Double_t pop[nx] = {
2431 4708708, 6595778, 2889450, 36961664, 5024748, 3518288, 885122, 18537969,
2432 9829211, 1545801, 12910409, 6423113, 3007856, 2818747, 4314113, 4492076,
2433 1318301, 5699478, 6593587, 9969727, 5266214, 2951996, 5987580, 974989,
2434 1796619, 2643085, 1324575, 8707739, 2009671, 19541453, 9380884, 646844,
2435 11542645, 3687050, 3825657, 12604767, 1053209, 4561242, 812383, 6296254,
2436 24782302, 2784572, 621760, 7882590, 6664195, 1819777, 5654774, 544270
2437 };
2438
2439 Double_t lon1 = -130;
2440 Double_t lon2 = -65;
2441 Double_t lat1 = 24;
2442 Double_t lat2 = 50;
2443 auto p = new TH2Poly("USA","USA Population",lon1,lon2,lat1,lat2);
2444
2445 TFile::SetCacheFileDir(".");
2446 auto f = TFile::Open("http://root.cern/files/usa.root", "CACHEREAD");
2447
2448 TMultiGraph *mg;
2449 TKey *key;
2450 TIter nextkey(gDirectory->GetListOfKeys());
2451 while ((key = (TKey*)nextkey())) {
2452 TObject *obj = key->ReadObj();
2453 if (obj->InheritsFrom("TMultiGraph")) {
2454 mg = (TMultiGraph*)obj;
2455 bin = p->AddBin(mg);
2456 }
2457 }
2458
2459 for (i=0; i<nx; i++) p->Fill(states[i], pop[i]);
2460
2461 gStyle->SetOptStat(11);
2462 p->Draw("COLZ L");
2463}
2464End_Macro
2465
2466`TH2Poly` histograms can also be plotted using the GL interface using
2467the option "GLLEGO".
2468
2469\since **ROOT version 6.09/01**
2470
2471In some cases it can be useful to not draw the empty bins. the option "0"
2472combined with the option "COL" and "COLZ" allows to do that.
2473
2474Begin_Macro(source)
2475{
2476 auto chc = new TCanvas("chc","chc",600,400);
2477
2478 auto hc = new TH2Poly();
2479 hc->Honeycomb(0,0,.1,25,25);
2480 hc->SetName("hc");
2481 hc->SetTitle("Option COLZ 0");
2482 TRandom ran;
2483 for (int i = 0; i<300; i++) hc->Fill(ran.Gaus(2.,1), ran.Gaus(2.,1));
2484 hc->Draw("colz 0");
2485}
2486End_Macro
2487
2488\anchor HP21
2489### The SPEC option
2490
2491
2492This option allows to use the `TSpectrum2Painter` tools. See the full
2493documentation in `TSpectrum2Painter::PaintSpectrum`.
2494
2495
2496\anchor HP22
2497### Option "Z" : Adding the color palette on the right side of the pad
2498
2499
2500When this option is specified, a color palette with an axis indicating the value
2501of the corresponding color is drawn on the right side of the picture. In case,
2502not enough space is left, one can increase the size of the right margin by
2503calling `TPad::SetRightMargin()`. The attributes used to display the
2504palette axis values are taken from the Z axis of the object. For example, to
2505set the labels size on the palette axis do:
2506
2507 hist->GetZaxis()->SetLabelSize().
2508
2509<b>WARNING:</b> The palette axis is always drawn vertically.
2510
2511
2512\anchor HP23
2513### Setting the color palette
2514
2515
2516To change the color palette `TStyle::SetPalette` should be used, eg:
2517
2518 gStyle->SetPalette(ncolors,colors);
2519
2520For example the option `COL` draws a 2D histogram with cells
2521represented by a box filled with a color index which is a function
2522of the cell content.
2523If the cell content is N, the color index used will be the color number
2524in `colors[N]`, etc. If the maximum cell content is greater than
2525`ncolors`, all cell contents are scaled to `ncolors`.
2526
2527If ` ncolors <= 0`, a default palette (see below) of 50 colors is
2528defined. This palette is recommended for pads, labels ...
2529
2530`if ncolors == 1 && colors == 0`, then a Pretty Palette with a
2531Spectrum Violet->Red is created with 50 colors. That's the default rain bow
2532palette.
2533
2534Other pre-defined palettes with 255 colors are available when `colors == 0`.
2535The following value of `ncolors` give access to:
2536
2537
2538 if ncolors = 51 and colors=0, a Deep Sea palette is used.
2539 if ncolors = 52 and colors=0, a Grey Scale palette is used.
2540 if ncolors = 53 and colors=0, a Dark Body Radiator palette is used.
2541 if ncolors = 54 and colors=0, a two-color hue palette palette is used.(dark blue through neutral gray to bright
2542yellow) if ncolors = 55 and colors=0, a Rain Bow palette is used. if ncolors = 56 and colors=0, an inverted Dark Body
2543Radiator palette is used.
2544
2545
2546If `ncolors > 0 && colors == 0`, the default palette is used with a maximum of ncolors.
2547
2548The default palette defines:
2549
2550- index 0 to 9 : shades of grey
2551- index 10 to 19 : shades of brown
2552- index 20 to 29 : shades of blue
2553- index 30 to 39 : shades of red
2554- index 40 to 49 : basic colors
2555
2556The color numbers specified in the palette can be viewed by selecting
2557the item `colors` in the `VIEW` menu of the canvas tool bar.
2558The red, green, and blue components of a color can be changed thanks to
2559`TColor::SetRGB()`.
2560
2561\since **ROOT version 6.19/01**
2562
2563As default labels and ticks are drawn by `TGAxis` at equidistant (lin or log)
2564points as controlled by SetNdivisions.
2565If option "CJUST" is given labels and ticks are justified at the
2566color boundaries defined by the contour levels.
2567For more details see `TPaletteAxis`
2568
2569\anchor HP24
2570### Drawing a sub-range of a 2D histogram; the [cutg] option
2571
2572
2573Using a `TCutG` object, it is possible to draw a sub-range of a 2D
2574histogram. One must create a graphical cut (mouse or C++) and specify the name
2575of the cut between `[]` in the `Draw()` option.
2576For example (fit2a.C), with a `TCutG` named `cutg`, one can call:
2577
2578 myhist->Draw("surf1 [cutg]");
2579
2580To invert the cut, it is enough to put a `-` in front of its name:
2581
2582 myhist->Draw("surf1 [-cutg]");
2583
2584It is possible to apply several cuts (`,` means logical AND):
2585
2586 myhist->Draw("surf1 [cutg1,cutg2]");
2587
2588Begin_Macro(source)
2589../../../tutorials/fit/fit2a.C
2590End_Macro
2591
2592\anchor HP25
2593### Drawing options for 3D histograms
2594
2595
2596| Option | Description |
2597|----------|-------------------------------------------------------------------|
2598| "SCAT" | Draw a scatter plot (legacy draw option).|
2599| "ISO" | Draw a Gouraud shaded 3d iso surface through a 3d histogram. It paints one surface at the value computed as follow: `SumOfWeights/(NbinsX*NbinsY*NbinsZ)`|
2600| "BOX" | Draw a for each cell with volume proportional to the content's absolute value. An hidden line removal algorithm is used|
2601| "BOX1" | Same as BOX but an hidden surface removal algorithm is used|
2602| "BOX2" | Same as "COL". The boxes' colors are picked in the current palette according to the bins' contents (default)|
2603| "BOX2Z" | Same as "BOX2". In addition the color palette is also drawn.|
2604| "BOX3" | Same as BOX1, but the border lines of each lego-bar are not drawn.|
2605
2606Note that instead of `BOX` one can also use `LEGO`.
2607
2608By default, 3D histograms are drawn as a colored box plots.
2609
2610The following example shows a 3D histogram plotted as a scatter plot.
2611
2612Begin_Macro(source)
2613{
2614 auto c06 = new TCanvas("c06","c06",600,400);
2615 gStyle->SetOptStat(kFALSE);
2616 auto h3scat = new TH3F("h3scat","Option SCAT",15,-2,2,15,-2,2,15,0,4);
2617 double x, y, z;
2618 for (Int_t i=0;i<10000;i++) {
2619 gRandom->Rannor(x, y);
2620 z = x*x + y*y;
2621 h3scat->Fill(x,y,z);
2622 }
2623 h3scat->Draw("SCAT"); // This a legacy draw option
2624}
2625End_Macro
2626
2627The following example shows a 3D histogram plotted with the option `BOX`.
2628
2629Begin_Macro(source)
2630{
2631 auto c16 = new TCanvas("c16","c16",600,400);
2632 gStyle->SetOptStat(kFALSE);
2633 auto h3box = new TH3F("h3box","Option BOX",15,-2,2,15,-2,2,15,0,4);
2634 double x, y, z;
2635 for (Int_t i=0;i<10000;i++) {
2636 gRandom->Rannor(x, y);
2637 z = x*x + y*y;
2638 h3box->Fill(x,y,z);
2639 }
2640 h3box->Draw("BOX");
2641}
2642End_Macro
2643
2644The following example shows a 3D histogram plotted with the option `BOX1`.
2645
2646Begin_Macro(source)
2647{
2648 auto c36 = new TCanvas("c36","c36",600,400);
2649 gStyle->SetOptStat(kFALSE);
2650 auto h3box = new TH3F("h3box","Option BOX1",10,-2.,2.,10,-2.,2.,10,-0.5,2.);
2651 double x, y, z;
2652 for (Int_t i=0;i<10000;i++) {
2653 gRandom->Rannor(x, y);
2654 z = abs(sin(x)/x + cos(y)*y);
2655 h3box->Fill(x,y,z);
2656 }
2657 h3box->SetFillColor(9);
2658 h3box->Draw("BOX1");
2659}
2660End_Macro
2661
2662The following example shows a 3D histogram plotted with the option `BOX2`.
2663
2664Begin_Macro(source)
2665{
2666 auto c56 = new TCanvas("c56","c56",600,400);
2667 gStyle->SetOptStat(kFALSE);
2668 auto h3box = new TH3F("h3box","Option BOX2 (default)",10,-2.,2.,10,-2.,2.,10,-0.5,2.);
2669 double x, y, z;
2670 for (Int_t i=0;i<10000;i++) {
2671 gRandom->Rannor(x, y);
2672 z = abs(sin(x)/x + cos(y)*y);
2673 h3box->Fill(x,y,z);
2674 }
2675 h3box->Draw("BOX2 Z");
2676}
2677End_Macro
2678
2679The following example shows a 3D histogram plotted with the option `BOX3`.
2680
2681Begin_Macro(source)
2682{
2683 auto c46 = new TCanvas("c46","c46",600,400);
2684 c46->SetFillColor(38);
2685 gStyle->SetOptStat(kFALSE);
2686 auto h3box = new TH3F("h3box","Option BOX3",15,-2,2,15,-2,2,15,0,4);
2687 double x, y, z;
2688 for (Int_t i=0;i<10000;i++) {
2689 gRandom->Rannor(x, y);
2690 z = x*x + y*y;
2691 h3box->Fill(x,y,z);
2692 }
2693 h3box->Draw("BOX3");
2694}
2695End_Macro
2696
2697For all the `BOX` options each bin is drawn as a 3D box with a volume proportional
2698to the absolute value of the bin content. The bins with a negative content are
2699drawn with a X on each face of the box as shown in the following example:
2700
2701Begin_Macro(source)
2702{
2703 auto c = new TCanvas("c","c",600,400);
2704 gStyle->SetOptStat(kFALSE);
2705 auto h3box = new TH3F("h3box","Option BOX1 with negative bins",3, 0., 4., 3, 0.,4., 3, 0., 4.);
2706 h3box->Fill(0., 2., 2., 10.);
2707 h3box->Fill(2., 2., 2., 5.);
2708 h3box->Fill(2., 2., .5, 2.);
2709 h3box->Fill(2., 2., 3., -1.);
2710 h3box->Fill(3., 2., 2., -10.);
2711 h3box->SetFillColor(8);
2712 h3box->Draw("box1");
2713}
2714End_Macro
2715
2716The following example shows a 3D histogram plotted with the option `ISO`.
2717
2718Begin_Macro(source)
2719{
2720 auto c26 = new TCanvas("c26","c26",600,400);
2721 gStyle->SetOptStat(kFALSE);
2722 auto h3iso = new TH3F("h3iso","Option ISO",15,-2,2,15,-2,2,15,0,4);
2723 double x, y, z;
2724 for (Int_t i=0;i<10000;i++) {
2725 gRandom->Rannor(x, y);
2726 z = x*x + y*y;
2727 h3iso->Fill(x,y,z);
2728 }
2729 h3iso->SetFillColor(kCyan);
2730 h3iso->Draw("ISO");
2731}
2732End_Macro
2733
2734
2735\anchor HP26
2736### Drawing option for histograms' stacks
2737
2738
2739Stacks of histograms are managed with the `THStack`. A `THStack`
2740is a collection of `TH1` (or derived) objects. For painting only the
2741`THStack` containing `TH1` only or
2742`THStack` containing `TH2` only will be considered.
2743
2744By default, histograms are shown stacked:
2745
27461. The first histogram is paint.
27472. The sum of the first and second, etc...
2748
2749If the option `NOSTACK` is specified, the histograms are all paint in
2750the same pad as if the option `SAME` had been specified. This allows to
2751compute X and Y scales common to all the histograms, like
2752`TMultiGraph` does for graphs.
2753
2754If the option `PADS` is specified, the current pad/canvas is
2755subdivided into a number of pads equal to the number of histograms and each
2756histogram is paint into a separate pad.
2757
2758The following example shows various types of stacks (hist023_THStack_simple.C).
2759
2760Begin_Macro(source)
2761../../../tutorials/hist/hist023_THStack_simple.C
2762End_Macro
2763
2764The option `nostackb` allows to draw the histograms next to each
2765other as bar charts:
2766
2767Begin_Macro(source)
2768{
2769 auto cst0 = new TCanvas("cst0","cst0",600,400);
2770 auto hs = new THStack("hs","Stacked 1D histograms: option #font[82]{\"nostackb\"}");
2771
2772 auto h1 = new TH1F("h1","h1",10,-4,4);
2773 h1->FillRandom("gaus",20000);
2774 h1->SetFillColor(kRed);
2775 hs->Add(h1);
2776
2777 auto h2 = new TH1F("h2","h2",10,-4,4);
2778 h2->FillRandom("gaus",15000);
2779 h2->SetFillColor(kBlue);
2780 hs->Add(h2);
2781
2782 auto h3 = new TH1F("h3","h3",10,-4,4);
2783 h3->FillRandom("gaus",10000);
2784 h3->SetFillColor(kGreen);
2785 hs->Add(h3);
2786
2787 hs->Draw("nostackb");
2788 hs->GetXaxis()->SetNdivisions(-10);
2789 cst0->SetGridx();
2790}
2791End_Macro
2792
2793If at least one of the histograms in the stack has errors, the whole stack is
2794visualized by default with error bars. To visualize it without errors the
2795option `HIST` should be used.
2796
2797Begin_Macro(source)
2798{
2799 auto cst1 = new TCanvas("cst1","cst1",700,400);
2800 cst1->Divide(2,1);
2801
2802 auto hst11 = new TH1F("hst11", "", 20, -10, 10);
2803 hst11->Sumw2();
2804 hst11->FillRandom("gaus", 1000);
2805 hst11->SetFillColor(kViolet);
2806 hst11->SetLineColor(kViolet);
2807
2808 auto hst12 = new TH1F("hst12", "", 20, -10, 10);
2809 hst12->FillRandom("gaus", 500);
2810 hst12->SetFillColor(kBlue);
2811 hst12->SetLineColor(kBlue);
2812
2813 THStack st1("st1", "st1");
2814 st1.Add(hst11);
2815 st1.Add(hst12);
2816
2817 cst1->cd(1); st1.Draw();
2818 cst1->cd(2); st1.Draw("hist");
2819}
2820End_Macro
2821
2822\anchor HP27
2823### Drawing of 3D implicit functions
2824
2825
28263D implicit functions (`TF3`) can be drawn as iso-surfaces.
2827The implicit function f(x,y,z) = 0 is drawn in cartesian coordinates.
2828In the following example the options "FB" and "BB" suppress the
2829"Front Box" and "Back Box" around the plot.
2830
2831Begin_Macro(source)
2832{
2833 auto c2 = new TCanvas("c2","c2",600,400);
2834 auto f3 = new TF3("f3","sin(x*x+y*y+z*z-36)",-2,2,-2,2,-2,2);
2835 f3->SetClippingBoxOn(0,0,0);
2836 f3->SetFillColor(30);
2837 f3->SetLineColor(15);
2838 f3->Draw("FBBB");
2839}
2840End_Macro
2841
2842
2843\anchor HP28
2844### Associated functions drawing
2845
2846
2847An associated function is created by `TH1::Fit`. More than on fitted
2848function can be associated with one histogram (see `TH1::Fit`).
2849
2850A `TF1` object `f1` can be added to the list of associated
2851functions of an histogram `h` without calling `TH1::Fit`
2852simply doing:
2853
2854 h->GetListOfFunctions()->Add(f1);
2855
2856or
2857
2858 h->GetListOfFunctions()->Add(f1,someoption);
2859
2860To retrieve a function by name from this list, do:
2861
2862 TF1 *f1 = (TF1*)h->GetListOfFunctions()->FindObject(name);
2863
2864or
2865
2866 TF1 *f1 = h->GetFunction(name);
2867
2868Associated functions are automatically painted when an histogram is drawn.
2869To avoid the painting of the associated functions the option `HIST`
2870should be added to the list of the options used to paint the histogram.
2871
2872
2873\anchor HP29
2874### Drawing using OpenGL
2875
2876
2877The class `TGLHistPainter` allows to paint data set using the OpenGL 3D
2878graphics library. The plotting options start with `GL` keyword.
2879In addition, in order to inform canvases that OpenGL should be used to render
28803D representations, the following option should be set:
2881
2882 gStyle->SetCanvasPreferGL(true);
2883
2884
2885\anchor HP29a
2886#### General information: plot types and supported options
2887
2888The following types of plots are provided:
2889
2890For lego plots the supported options are:
2891
2892| Option | Description |
2893|----------|-------------------------------------------------------------------|
2894| "GLLEGO" | Draw a lego plot. It works also for `TH2Poly`.|
2895| "GLLEGO2"| Bins with color levels.|
2896| "GLLEGO3"| Cylindrical bars.|
2897
2898
2899
2900Lego painter in cartesian supports logarithmic scales for X, Y, Z.
2901In polar only Z axis can be logarithmic, in cylindrical only Y.
2902
2903For surface plots (`TF2` and `TH2`) the supported options are:
2904
2905| Option | Description |
2906|-----------|------------------------------------------------------------------|
2907| "GLSURF" | Draw a surface.|
2908| "GLSURF1" | Surface with color levels|
2909| "GLSURF2" | The same as "GLSURF1" but without polygon outlines.|
2910| "GLSURF3" | Color level projection on top of plot (works only in cartesian coordinate system).|
2911| "GLSURF4" | Same as "GLSURF" but without polygon outlines.|
2912
2913
2914
2915The surface painting in cartesian coordinates supports logarithmic scales along
2916X, Y, Z axis. In polar coordinates only the Z axis can be logarithmic,
2917in cylindrical coordinates only the Y axis.
2918
2919Additional options to SURF and LEGO - Coordinate systems:
2920
2921| Option | Description |
2922|----------|-------------------------------------------------------------------|
2923| " " | Default, cartesian coordinates system.|
2924| "POL" | Polar coordinates system.|
2925| "CYL" | Cylindrical coordinates system.|
2926| "SPH" | Spherical coordinates system.|
2927
2928
2929
2930\anchor HP290
2931#### TH3 as color boxes
2932
2933The supported option is:
2934
2935| Option | Description |
2936|----------|-------------------------------------------------------------------|
2937| "GLCOL" | H3 is drawn using semi-transparent colored boxes. See `$ROOTSYS/tutorials/visualisation/gl/glvox1.C`.|
2938
2939
2940
2941\anchor HP29b
2942#### TH3 as boxes (spheres)
2943
2944The supported options are:
2945
2946| Option | Description |
2947|----------|-------------------------------------------------------------------|
2948| "GLBOX" | TH3 as a set of boxes, size of box is proportional to bin content.|
2949| "GLBOX1" | The same as "glbox", but spheres are drawn instead of boxes.|
2950
2951
2952
2953\anchor HP29c
2954#### TH3 as iso-surface(s)
2955
2956The supported option is:
2957
2958| Option | Description |
2959|----------|-------------------------------------------------------------------|
2960| "GLISO" | TH3 is drawn using iso-surfaces.|
2961
2962
2963
2964\anchor HP29d
2965#### TF3 (implicit function)
2966
2967The supported option is:
2968
2969| Option | Description |
2970|----------|-------------------------------------------------------------------|
2971| "GL" | Draw a TF3.|
2972
2973
2974
2975\anchor HP29e
2976#### Parametric surfaces
2977
2978`$ROOTSYS/tutorials/visualisation/gl/glparametric.C` shows how to create parametric
2979equations and visualize the surface.
2980
2981\anchor HP29f
2982#### Interaction with the plots
2983
2984All the interactions are implemented via standard methods
2985`DistancetoPrimitive()` and `ExecuteEvent()`. That's why all the
2986interactions with the OpenGL plots are possible only when the mouse cursor is
2987in the plot's area (the plot's area is the part of a the pad occupied by
2988gl-produced picture). If the mouse cursor is not above gl-picture, the standard
2989pad interaction is performed.
2990
2991\anchor HP29g
2992#### Selectable parts
2993
2994Different parts of the plot can be selected:
2995
2996- xoz, yoz, xoy back planes: When such a plane selected, it's highlighted in green
2997 if the dynamic slicing by this plane is supported, and it's highlighted in red,
2998 if the dynamic slicing is not supported.
2999- The plot itself:
3000 On surfaces, the selected surface is outlined in red. (TF3 and
3001 ISO are not outlined). On lego plots, the selected bin is
3002 highlighted. The bin number and content are displayed in pad's
3003 status bar. In box plots, the box or sphere is highlighted and
3004 the bin info is displayed in pad's status bar.
3005
3006
3007\anchor HP29h
3008#### Rotation and zooming
3009
3010
3011- Rotation:
3012 When the plot is selected, it can be rotated by pressing and
3013 holding the left mouse button and move the cursor.
3014- Zoom/Unzoom:
3015 Mouse wheel or 'j', 'J', 'k', 'K' keys.
3016
3017
3018\anchor HP29i
3019#### Panning
3020
3021The selected plot can be moved in a pad's area by pressing and
3022holding the left mouse button and the shift key.
3023
3024\anchor HP29j
3025#### Box cut
3026
3027Surface, iso, box, TF3 and parametric painters support box cut by
3028pressing the 'c' or 'C' key when the mouse cursor is in a plot's
3029area. That will display a transparent box, cutting away part of the
3030surface (or boxes) in order to show internal part of plot. This box
3031can be moved inside the plot's area (the full size of the box is
3032equal to the plot's surrounding box) by selecting one of the box
3033cut axes and pressing the left mouse button to move it.
3034
3035\anchor HP29k
3036#### Plot specific interactions (dynamic slicing etc.)
3037
3038Currently, all gl-plots support some form of slicing. When back plane
3039is selected (and if it's highlighted in green) you can press and hold
3040left mouse button and shift key and move this back plane inside
3041plot's area, creating the slice. During this "slicing" plot becomes
3042semi-transparent. To remove all slices (and projected curves for
3043surfaces) double click with left mouse button in a plot's area.
3044
3045\anchor HP29l
3046#### Surface with option "GLSURF"
3047
3048The surface profile is displayed on the slicing plane.
3049The profile projection is drawn on the back plane
3050by pressing `'p'` or `'P'` key.
3051
3052\anchor HP29m
3053#### TF3
3054
3055The contour plot is drawn on the slicing plane. For TF3 the color
3056scheme can be changed by pressing 's' or 'S'.
3057
3058\anchor HP29n
3059#### Box
3060
3061The contour plot corresponding to slice plane position is drawn in real time.
3062
3063\anchor HP29o
3064#### Iso
3065
3066Slicing is similar to "GLBOX" option.
3067
3068\anchor HP29p
3069#### Parametric plot
3070
3071No slicing. Additional keys: 's' or 'S' to change color scheme -
3072about 20 color schemes supported ('s' for "scheme"); 'l' or 'L' to
3073increase number of polygons ('l' for "level" of details), 'w' or 'W'
3074to show outlines ('w' for "wireframe").
3075
3076\anchor HP30
3077#### Highlight mode for histogram
3078
3079\since **ROOT version 6.15/01**
3080
3081\image html hlHisto3_top.gif "Highlight mode"
3082
3083Highlight mode is implemented for `TH1` (and for `TGraph`) class. When
3084highlight mode is on, mouse movement over the bin will be represented
3085graphically. Bin will be highlighted as "bin box" (presented by box
3086object). Moreover, any highlight (change of bin) emits signal
3087`TCanvas::Highlighted()` which allows the user to react and call their own
3088function. For a better understanding see also the tutorial `hist043` to `hist046`
3089lacated in `$ROOTSYS/tutorials/hist/`.
3090
3091Highlight mode is switched on/off by `TH1::SetHighlight()` function
3092or interactively from `TH1` context menu. `TH1::IsHighlight()` to verify
3093whether the highlight mode enabled or disabled, default it is disabled.
3094
3095~~~ {.cpp}
3096 root [0] .x $ROOTSYS/tutorials/hsimple.C
3097 root [1] hpx->SetHighlight(kTRUE) // or interactively from TH1 context menu
3098 root [2] hpx->IsHighlight()
3099 (bool) true
3100~~~
3101
3102\image html hlsimple_nofun.gif "Highlight mode for histogram"
3103
3104\anchor HP30a
3105#### Highlight mode and user function
3106
3107The user can use (connect) `TCanvas::Highlighted()` signal, which is always
3108emitted if there is a highlight bin and call user function via signal
3109and slot communication mechanism. `TCanvas::Highlighted()` is similar
3110`TCanvas::Picked()`
3111
3112- when selected object (histogram as a whole) is different from previous
3113then emit `Picked()` signal
3114- when selected (highlighted) bin from histogram is different from previous
3115then emit `Highlighted()` signal
3116
3117Any user function (or functions) has to be defined
3118`UserFunction(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)`.
3119In example (see below) has name `PrintInfo()`. All parameters of user
3120function are taken from
3121
3122 void TCanvas::Highlighted(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)
3123
3124- `pad` is pointer to pad with highlighted histogram
3125- `obj` is pointer to highlighted histogram
3126- `x` is highlighted x bin for 1D histogram
3127- `y` is highlighted y bin for 2D histogram (for 1D histogram not in use)
3128
3129Example how to create a connection from any `TCanvas` object to a user
3130`UserFunction()` slot (see also `TQObject::Connect()` for additional info)
3131
3132 TQObject::Connect("TCanvas", "Highlighted(TVirtualPad*,TObject*,Int_t,Int_t)",
3133 0, 0, "UserFunction(TVirtualPad*,TObject*,Int_t,Int_t)");
3134
3135or use non-static "simplified" function
3136`TCanvas::HighlightConnect(const char *slot)`
3137
3138 c1->HighlightConnect("UserFunction(TVirtualPad*,TObject*,Int_t,Int_t)");
3139
3140NOTE the signal and slot string must have a form
3141"(TVirtualPad*,TObject*,Int_t,Int_t)"
3142
3143 root [0] .x $ROOTSYS/tutorials/hsimple.C
3144 root [1] hpx->SetHighlight(kTRUE)
3145 root [2] .x hlprint.C
3146
3147file `hlprint.C`
3148~~~ {.cpp}
3149void PrintInfo(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)
3150{
3151 auto h = (TH1F *)obj;
3152 if (!h->IsHighlight()) // after highlight disabled
3153 h->SetTitle("highlight disable");
3154 else
3155 h->SetTitle(TString::Format("bin[%03d] (%5.2f) content %g", x,
3156 h->GetBinCenter(x), h->GetBinContent(x)));
3157 pad->Update();
3158}
3159
3160void hlprint()
3161{
3162 if (!gPad) return;
3163 gPad->GetCanvas()->HighlightConnect("PrintInfo(TVirtualPad*,TObject*,Int_t,Int_t)");
3164}
3165~~~
3166
3167\image html hlsimple.gif "Highlight mode and simple user function"
3168
3169For more complex demo please see for example `$ROOTSYS/tutorials/io/tree/tree200_temperature.C` file.
3170
3171*/
3172
3174
3177
3178const Int_t kNMAX = 2000;
3179
3180const Int_t kMAXCONTOUR = 104;
3182
3183static std::unique_ptr<TBox> gXHighlightBox, gYHighlightBox; // highlight X and Y box
3184
3206
3208
3209////////////////////////////////////////////////////////////////////////////////
3210/// Default constructor.
3211
3213{
3214 fH = nullptr;
3215 fXaxis = nullptr;
3216 fYaxis = nullptr;
3217 fZaxis = nullptr;
3218 fFunctions = nullptr;
3219 fNcuts = 0;
3220 fStack = nullptr;
3221 fShowProjection = 0;
3222 fShowProjection2 = 0;
3223 fShowOption = "";
3224 for (int i=0; i<kMaxCuts; i++) {
3225 fCuts[i] = nullptr;
3226 fCutsOpt[i] = 0;
3227 }
3228 fXHighlightBin = -1;
3229 fYHighlightBin = -1;
3230 fCurrentF3 = nullptr;
3231
3232 gStringEntries = gEnv->GetValue("Hist.Stats.Entries", "Entries");
3233 gStringMean = gEnv->GetValue("Hist.Stats.Mean", "Mean");
3234 gStringMeanX = gEnv->GetValue("Hist.Stats.MeanX", "Mean x");
3235 gStringMeanY = gEnv->GetValue("Hist.Stats.MeanY", "Mean y");
3236 gStringMeanZ = gEnv->GetValue("Hist.Stats.MeanZ", "Mean z");
3237 gStringStdDev = gEnv->GetValue("Hist.Stats.StdDev", "Std Dev");
3238 gStringStdDevX = gEnv->GetValue("Hist.Stats.StdDevX", "Std Dev x");
3239 gStringStdDevY = gEnv->GetValue("Hist.Stats.StdDevY", "Std Dev y");
3240 gStringStdDevZ = gEnv->GetValue("Hist.Stats.StdDevZ", "Std Dev z");
3241 gStringUnderflow = gEnv->GetValue("Hist.Stats.Underflow", "Underflow");
3242 gStringOverflow = gEnv->GetValue("Hist.Stats.Overflow", "Overflow");
3243 gStringIntegral = gEnv->GetValue("Hist.Stats.Integral", "Integral");
3244 gStringIntegralBinWidth = gEnv->GetValue("Hist.Stats.IntegralBinWidth", "Integral(w)");
3245 gStringSkewness = gEnv->GetValue("Hist.Stats.Skewness", "Skewness");
3246 gStringSkewnessX = gEnv->GetValue("Hist.Stats.SkewnessX", "Skewness x");
3247 gStringSkewnessY = gEnv->GetValue("Hist.Stats.SkewnessY", "Skewness y");
3248 gStringSkewnessZ = gEnv->GetValue("Hist.Stats.SkewnessZ", "Skewness z");
3249 gStringKurtosis = gEnv->GetValue("Hist.Stats.Kurtosis", "Kurtosis");
3250 gStringKurtosisX = gEnv->GetValue("Hist.Stats.KurtosisX", "Kurtosis x");
3251 gStringKurtosisY = gEnv->GetValue("Hist.Stats.KurtosisY", "Kurtosis y");
3252 gStringKurtosisZ = gEnv->GetValue("Hist.Stats.KurtosisZ", "Kurtosis z");
3253}
3254
3255////////////////////////////////////////////////////////////////////////////////
3256/// destructor.
3257
3261
3262////////////////////////////////////////////////////////////////////////////////
3263/// Compute the distance from the point px,py to a line.
3264///
3265/// Compute the closest distance of approach from point px,py to elements of
3266/// an histogram. The distance is computed in pixels units.
3267///
3268/// Algorithm: Currently, this simple model computes the distance from the mouse
3269/// to the histogram contour only.
3270
3272{
3273
3274 Double_t defaultLabelSize = 0.04; // See TAttAxis.h for source of this value
3275
3276 const Int_t big = 9999;
3277 const Int_t kMaxDiff = 7;
3278
3279 if (fPie)
3280 return fPie->DistancetoPrimitive(px, py);
3281
3282 Double_t x = gPad->AbsPixeltoX(px);
3283 Double_t x1 = gPad->AbsPixeltoX(px+1);
3284
3285 Int_t puxmin = gPad->XtoAbsPixel(gPad->GetUxmin());
3286 Int_t puymin = gPad->YtoAbsPixel(gPad->GetUymin());
3287 Int_t puxmax = gPad->XtoAbsPixel(gPad->GetUxmax());
3288 Int_t puymax = gPad->YtoAbsPixel(gPad->GetUymax());
3289 Int_t curdist = big;
3291 Bool_t dsame;
3292 TObject *PadPointer = gPad->GetPadPointer();
3293 if (!PadPointer) return 0;
3294 TString doption = PadPointer->GetDrawOption();
3295 Double_t factor = 1;
3296 if (fH->GetNormFactor() != 0) {
3297 factor = fH->GetNormFactor()/fH->GetSumOfWeights();
3298 }
3299 // return if point is not in the histogram area
3300
3301 // If a 3D view exists, check distance to axis
3302 TView *view = gPad->GetView();
3303 Int_t d1,d2,d3;
3304 if (view && Hoption.Contour != 14) {
3305 Double_t ratio;
3306 d3 = view->GetDistancetoAxis(3, px, py, ratio);
3307 if (d3 <= kMaxDiff) {gPad->SetSelected(fZaxis); return 0;}
3308 d1 = view->GetDistancetoAxis(1, px, py, ratio);
3309 if (d1 <= kMaxDiff) {gPad->SetSelected(fXaxis); return 0;}
3310 d2 = view->GetDistancetoAxis(2, px, py, ratio);
3311 if (d2 <= kMaxDiff) {gPad->SetSelected(fYaxis); return 0;}
3312 if ( px > puxmin && px < puxmax && py > puymax && py < puymin) curdist = 1;
3313 goto FUNCTIONS;
3314 }
3315 // check if point is close to an axis
3316 doption.ToLower();
3317 dsame = kFALSE;
3318 if (doption.Contains("same")) dsame = kTRUE;
3319
3321 if (doption.Contains("y+")) {
3323 if (px <= xyaxis+dyaxis && px >= xyaxis && py >puymax && py < puymin) {
3324 if (!dsame) {
3325 if (gPad->IsVertical()) gPad->SetSelected(fYaxis);
3326 else gPad->SetSelected(fXaxis);
3327 return 0;
3328 }
3329 }
3330 } else {
3332 if (px >= xyaxis-dyaxis && px <= xyaxis && py >puymax && py < puymin) {
3333 if (!dsame) {
3334 if (gPad->IsVertical()) gPad->SetSelected(fYaxis);
3335 else gPad->SetSelected(fXaxis);
3336 return 0;
3337 }
3338 }
3339 }
3340
3342 if (doption.Contains("x+")) {
3344 if (py >= yxaxis-dxaxis && py <= yxaxis && px <puxmax && px > puxmin) {
3345 if (!dsame) {
3346 if (gPad->IsVertical()) gPad->SetSelected(fXaxis);
3347 else gPad->SetSelected(fYaxis);
3348 return 0;
3349 }
3350 }
3351 } else {
3353 if (yxaxis < puymin) yxaxis = puymin;
3355 if (!dsame) {
3356 if (gPad->IsVertical()) gPad->SetSelected(fXaxis);
3357 else gPad->SetSelected(fYaxis);
3358 return 0;
3359 }
3360 }
3361 }
3362
3363 if (fH->IsHighlight()) { // only if highlight is enable
3364 if ((px > puxmin) && (py < puymin) && (px < puxmax) && (py > puymax))
3365 HighlightBin(px, py);
3366 }
3367
3368 // if object is 2D or 3D return this object
3369 if (fH->GetDimension() == 2) {
3370 if (fH->InheritsFrom(TH2Poly::Class())) {
3371 TH2Poly *th2 = (TH2Poly*)fH;
3373 gPad->GetRangeAxis(xmin, ymin, xmax, ymax);
3374 Double_t pxu = gPad->AbsPixeltoX(px);
3375 Double_t pyu = gPad->AbsPixeltoY(py);
3376 if ((pxu>xmax) || (pxu < xmin) || (pyu>ymax) || (pyu < ymin)) {
3377 curdist = big;
3378 goto FUNCTIONS;
3379 } else {
3380 Int_t bin = th2->FindBin(pxu, pyu);
3381 if (bin>0) curdist = 1;
3382 else curdist = big;
3383 goto FUNCTIONS;
3384 }
3385 }
3386 Int_t delta2 = 5; //Give a margin of delta2 pixels to be in the 2-d area
3387 if ( px > puxmin + delta2
3388 && px < puxmax - delta2
3389 && py > puymax + delta2
3390 && py < puymin - delta2) {curdist =1; goto FUNCTIONS;}
3391 }
3392
3393 // point is inside histogram area. Find channel number
3394 if (gPad->IsVertical()) {
3395 Int_t bin = fXaxis->FindFixBin(gPad->PadtoX(x));
3396 Int_t binsup = fXaxis->FindFixBin(gPad->PadtoX(x1));
3397 Double_t binval = factor*fH->GetBinContent(bin);
3398 Int_t pybin = gPad->YtoAbsPixel(gPad->YtoPad(binval));
3399 if (binval == 0 && pybin < puymin) pybin = 10000;
3400 // special case if more than one bin for the pixel
3401 if (binsup-bin>1) {
3405 for (Int_t ibin=bin+1; ibin<binsup; ibin++) {
3409 }
3410 Int_t pybinmin = gPad->YtoAbsPixel(gPad->YtoPad(binvalmax));
3411 Int_t pybinmax = gPad->YtoAbsPixel(gPad->YtoPad(binvalmin));
3413 }
3414 if (bin != binsup) { // Mouse on bin border
3416 Int_t pybinsub = gPad->YtoAbsPixel(gPad->YtoPad(binsupval));
3417 if (py <= TMath::Max(pybinsub,pybin) && py >= TMath::Min(pybinsub,pybin) && pybin != 10000) return 0;
3418 }
3419 if (TMath::Abs(py - pybin) <= kMaxDiff) return TMath::Abs(py - pybin);
3420 } else {
3421 Double_t y = gPad->AbsPixeltoY(py);
3422 Double_t y1 = gPad->AbsPixeltoY(py+1);
3423 Int_t bin = fXaxis->FindFixBin(gPad->PadtoY(y));
3424 Int_t binsup = fXaxis->FindFixBin(gPad->PadtoY(y1));
3425 Double_t binval = factor*fH->GetBinContent(bin);
3426 Int_t pxbin = gPad->XtoAbsPixel(gPad->XtoPad(binval));
3427 if (binval == 0 && pxbin > puxmin) pxbin = 10000;
3428 // special case if more than one bin for the pixel
3429 if (binsup-bin>1) {
3433 for (Int_t ibin=bin+1; ibin<binsup; ibin++) {
3437 }
3438 Int_t pxbinmin = gPad->XtoAbsPixel(gPad->XtoPad(binvalmax));
3439 Int_t pxbinmax = gPad->XtoAbsPixel(gPad->XtoPad(binvalmin));
3441 }
3442 if (TMath::Abs(px - pxbin) <= kMaxDiff) return TMath::Abs(px - pxbin);
3443 }
3444 // Loop on the list of associated functions and user objects
3445FUNCTIONS:
3446 TObject *f;
3447 TIter next(fFunctions);
3448 while ((f = (TObject*) next())) {
3449 Int_t dist;
3450 if (f->InheritsFrom(TF1::Class())) dist = f->DistancetoPrimitive(-px,py);
3451 else dist = f->DistancetoPrimitive(px,py);
3452 if (dist < kMaxDiff) {gPad->SetSelected(f); return dist;}
3453 }
3454 return curdist;
3455}
3456
3457////////////////////////////////////////////////////////////////////////////////
3458/// Display a panel with all histogram drawing options.
3459
3461{
3462
3463 gCurrentHist = fH;
3464 if (!gPad) {
3465 Error("DrawPanel", "need to draw histogram first");
3466 return;
3467 }
3469 editor->Show();
3470 gROOT->ProcessLine(TString::Format("((TCanvas*)0x%zx)->Selected((TVirtualPad*)0x%zx,(TObject*)0x%zx,1)",
3471 (size_t)gPad->GetCanvas(), (size_t)gPad, (size_t)fH).Data());
3472}
3473
3474////////////////////////////////////////////////////////////////////////////////
3475/// Execute the actions corresponding to `event`.
3476///
3477/// This function is called when a histogram is clicked with the locator at
3478/// the pixel position px,py.
3479
3481{
3482
3483 if (!gPad) return;
3484
3485 static Int_t bin, px1, py1, px2, py2, pyold;
3486 static std::unique_ptr<TBox> zoombox;
3488
3489 Int_t bin1, bin2;
3490 Double_t xlow, xup, ylow, binval, x, baroffset, barwidth, binwidth;
3491 Bool_t opaque = gPad->OpaqueMoving();
3492
3493 if (!gPad->IsEditable()) return;
3494
3495 if (fPie) {
3496 fPie->ExecuteEvent(event, px, py);
3497 return;
3498 }
3499 // come here if we have a lego/surface in the pad
3500 TView *view = gPad->GetView();
3501
3502 if (!fShowProjection && view && !view->TestBit(kCannotRotate)) {
3503 view->ExecuteRotateView(event, px, py);
3504 return;
3505 }
3506
3507 TAxis *xaxis = fH->GetXaxis();
3508 TAxis *yaxis = fH->GetYaxis();
3509 Int_t dimension = fH->GetDimension();
3510
3511 // In case of option SAME the axis must be the ones of the first drawn histogram
3512 TString IsSame = fH->GetDrawOption();
3513 IsSame.ToLower();
3514 if (IsSame.Index("same")>=0) {
3515 TH1 *h1;
3516 TIter next(gPad->GetListOfPrimitives());
3517 while ((h1 = (TH1 *)next())) {
3518 if (!h1->InheritsFrom(TH1::Class())) continue;
3519 xaxis = h1->GetXaxis();
3520 yaxis = h1->GetYaxis();
3521 break;
3522 }
3523 }
3524
3525 Double_t factor = 1;
3526 if (fH->GetNormFactor() != 0) {
3527 factor = fH->GetNormFactor()/fH->GetSumOfWeights();
3528 }
3529
3530 switch (event) {
3531
3532 case kButton1Down:
3533
3534 if (!opaque) gVirtualX->SetLineColor(-1);
3535 fH->TAttLine::Modify();
3536
3537 if (opaque && dimension ==2) {
3538 zbx1 = gPad->AbsPixeltoX(px);
3539 zbx2 = gPad->AbsPixeltoX(px);
3540 zby1 = gPad->AbsPixeltoY(py);
3541 zby2 = gPad->AbsPixeltoY(py);
3542 px1 = px;
3543 py1 = py;
3544 if (gPad->GetLogx()) {
3545 zbx1 = TMath::Power(10,zbx1);
3546 zbx2 = TMath::Power(10,zbx2);
3547 }
3548 if (gPad->GetLogy()) {
3549 zby1 = TMath::Power(10,zby1);
3550 zby2 = TMath::Power(10,zby2);
3551 }
3552 if (zoombox) Error("ExecuteEvent", "Last zoom box was not deleted");
3553 zoombox = std::make_unique<TBox>(zbx1, zby1, zbx2, zby2);
3554 Int_t ci = TColor::GetColor("#7d7dff");
3555 TColor *zoomcolor = gROOT->GetColor(ci);
3556 if (!TCanvas::SupportAlpha() || !zoomcolor) zoombox->SetFillStyle(3002);
3557 else zoomcolor->SetAlpha(0.5);
3558 zoombox->SetFillColor(ci);
3559 zoombox->Draw();
3560 gPad->Modified();
3561 gPad->Update();
3562 }
3563 // No break !!!
3564
3565 case kMouseMotion:
3566
3567 if (fShowProjection) {ShowProjection3(px,py); break;}
3568
3569 gPad->SetCursor(kPointer);
3570 if (dimension ==1) {
3571 if (Hoption.Bar) {
3572 baroffset = fH->GetBarOffset();
3573 barwidth = fH->GetBarWidth();
3574 } else {
3575 baroffset = 0;
3576 barwidth = 1;
3577 }
3578 x = gPad->AbsPixeltoX(px);
3579 bin = fXaxis->FindFixBin(gPad->PadtoX(x));
3580 binwidth = fXaxis->GetBinWidth(bin);
3581 xlow = gPad->XtoPad(fXaxis->GetBinLowEdge(bin) + baroffset*binwidth);
3582 xup = gPad->XtoPad(xlow + barwidth*binwidth);
3583 ylow = gPad->GetUymin();
3584 px1 = gPad->XtoAbsPixel(xlow);
3585 px2 = gPad->XtoAbsPixel(xup);
3586 py1 = gPad->YtoAbsPixel(ylow);
3587 py2 = py;
3588 pyold = py;
3589 if (gROOT->GetEditHistograms()) gPad->SetCursor(kArrowVer);
3590 }
3591
3592 break;
3593
3594 case kButton1Motion:
3595
3596 if (dimension ==1) {
3597 if (gROOT->GetEditHistograms()) {
3598 if (!opaque) {
3599 gVirtualX->DrawBox(px1, py1, px2, py2,TVirtualX::kHollow); // Draw the old box
3600 py2 += py - pyold;
3601 gVirtualX->DrawBox(px1, py1, px2, py2,TVirtualX::kHollow); // Draw the new box
3602 pyold = py;
3603 } else {
3604 py2 += py - pyold;
3605 pyold = py;
3606 binval = gPad->PadtoY(gPad->AbsPixeltoY(py2))/factor;
3607 fH->SetBinContent(bin,binval);
3608 gPad->Modified(kTRUE);
3609 }
3610 }
3611 }
3612
3613 if (opaque && dimension ==2) {
3614 if (TMath::Abs(px1-px)>5 && TMath::Abs(py1-py)>5) {
3615 zbx2 = gPad->AbsPixeltoX(px);
3616 zby2 = gPad->AbsPixeltoY(py);
3617 if (gPad->GetLogx()) zbx2 = TMath::Power(10,zbx2);
3618 if (gPad->GetLogy()) zby2 = TMath::Power(10,zby2);
3619 if (zoombox) {
3620 zoombox->SetX2(zbx2);
3621 zoombox->SetY2(zby2);
3622 }
3623 gPad->Modified();
3624 gPad->Update();
3625 }
3626 }
3627
3628 break;
3629
3630 case kWheelUp:
3631
3632 if (dimension ==2) {
3633 bin1 = xaxis->GetFirst()+1;
3634 bin2 = xaxis->GetLast()-1;
3635 bin1 = TMath::Max(bin1, 1);
3636 bin2 = TMath::Min(bin2, xaxis->GetNbins());
3637 if (bin2>bin1) xaxis->SetRange(bin1,bin2);
3638 bin1 = yaxis->GetFirst()+1;
3639 bin2 = yaxis->GetLast()-1;
3640 bin1 = TMath::Max(bin1, 1);
3641 bin2 = TMath::Min(bin2, yaxis->GetNbins());
3642 if (bin2>bin1) yaxis->SetRange(bin1,bin2);
3643 }
3644 gPad->Modified();
3645 gPad->Update();
3646
3647 break;
3648
3649 case kWheelDown:
3650
3651 if (dimension == 2) {
3652 bin1 = xaxis->GetFirst()-1;
3653 bin2 = xaxis->GetLast()+1;
3654 bin1 = TMath::Max(bin1, 1);
3655 bin2 = TMath::Min(bin2, xaxis->GetNbins());
3656 const bool resetXaxisRange = bin1 == 1 && xaxis->GetFirst() == 1 && bin2 == xaxis->GetNbins() && xaxis->GetLast() == xaxis->GetNbins();
3657 if (bin2>bin1) xaxis->SetRange(bin1,bin2);
3658 if (resetXaxisRange) xaxis->ResetBit(TAxis::kAxisRange);
3659 bin1 = yaxis->GetFirst()-1;
3660 bin2 = yaxis->GetLast()+1;
3661 bin1 = TMath::Max(bin1, 1);
3662 bin2 = TMath::Min(bin2, yaxis->GetNbins());
3663 const bool resetYaxisRange = bin1 == 1 && yaxis->GetFirst() == 1 && bin2 == yaxis->GetNbins() && yaxis->GetLast() == yaxis->GetNbins();
3664 if (bin2>bin1) yaxis->SetRange(bin1,bin2);
3665 if (resetYaxisRange) yaxis->ResetBit(TAxis::kAxisRange);
3666 }
3667 gPad->Modified();
3668 gPad->Update();
3669
3670 break;
3671
3672 case kButton1Up:
3673 if (dimension ==1) {
3674 if (gROOT->GetEditHistograms()) {
3675 binval = gPad->PadtoY(gPad->AbsPixeltoY(py2))/factor;
3676 fH->SetBinContent(bin,binval);
3677 PaintInit(); // recalculate Hparam structure and recalculate range
3678 }
3679
3680 // might resize pad pixmap so should be called before any paint routine
3682 }
3683 if (opaque && dimension ==2) {
3684 if (zoombox) {
3685 Double_t x1 = TMath::Min(zoombox->GetX1(), zoombox->GetX2());
3686 Double_t x2 = TMath::Max(zoombox->GetX1(), zoombox->GetX2());
3687 Double_t y1 = TMath::Min(zoombox->GetY1(), zoombox->GetY2());
3688 Double_t y2 = TMath::Max(zoombox->GetY1(), zoombox->GetY2());
3689 x1 = TMath::Max(x1,xaxis->GetXmin());
3690 x2 = TMath::Min(x2,xaxis->GetXmax());
3691 y1 = TMath::Max(y1,yaxis->GetXmin());
3692 y2 = TMath::Min(y2,yaxis->GetXmax());
3693 if (x1<x2 && y1<y2) {
3694 xaxis->SetRangeUser(x1, x2);
3695 yaxis->SetRangeUser(y1, y2);
3696 }
3697 zoombox.reset();
3698 }
3699 }
3700 gPad->Modified(kTRUE);
3701 if (opaque) gVirtualX->SetLineColor(-1);
3702
3703 break;
3704
3705 case kButton1Locate:
3706
3707 ExecuteEvent(kButton1Down, px, py);
3708
3709 while (true) {
3710 px = py = 0;
3711 event = gVirtualX->RequestLocator(1, 1, px, py);
3712
3714
3715 if (event != -1) { // button is released
3716 ExecuteEvent(kButton1Up, px, py);
3717 return;
3718 }
3719 }
3720 }
3721}
3722
3723////////////////////////////////////////////////////////////////////////////////
3724/// Get a contour (as a list of TGraphs) using the Delaunay triangulation.
3725
3727{
3728 // Check if fH contains a TGraphDelaunay2D
3730 TGraphDelaunay2D *dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
3731 // try with the old painter
3732 TGraphDelaunay *dtOld = nullptr;
3733 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
3734
3735 if (!dt && !dtOld) return nullptr;
3736
3737 gCurrentHist = fH;
3738
3739 if (!fGraph2DPainter)
3740 ((THistPainter*)this)->fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
3741
3742 return fGraph2DPainter->GetContourList(contour);
3743}
3744
3745////////////////////////////////////////////////////////////////////////////////
3746/// Display the histogram info (bin number, contents, integral up to bin
3747/// corresponding to cursor position px,py.
3748
3750{
3751
3752 if (!gPad) return (char*)"";
3753
3754 Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
3755 Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
3756 Double_t x1 = gPad->PadtoX(gPad->AbsPixeltoX(px+1));
3758 drawOption.ToLower();
3761 if (fH->GetDimension() == 2) {
3762 if (gPad->GetView() || drawOption.Index("cont") >= 0) {
3763 uxmin=gPad->GetUxmin();
3764 uxmax=gPad->GetUxmax();
3767 x = xmin +(xmax-xmin)*(x-uxmin)/(uxmax-uxmin);
3768 uymin=gPad->GetUymin();
3769 uymax=gPad->GetUymax();
3772 y = ymin +(ymax-ymin)*(y-uymin)/(uymax-uymin);
3773 }
3774 }
3776 if (gPad->IsVertical()) {
3777 binx = fXaxis->FindFixBin(x);
3778 if (drawOption.Index("same") >= 0) {
3779 TH1 *h1;
3780 TIter next(gPad->GetListOfPrimitives());
3781 while ((h1 = (TH1 *)next())) {
3782 if (!h1->InheritsFrom(TH1::Class())) continue;
3783 binmin = h1->GetXaxis()->GetFirst();
3784 break;
3785 }
3786 } else {
3787 binmin = fXaxis->GetFirst();
3788 }
3790 // special case if more than 1 bin in x per pixel
3791 if (binx1-binx>1 && fH->GetDimension() == 1) {
3794 for (Int_t ibin=binx+1; ibin<binx1; ibin++) {
3798 binnear=ibin;
3799 }
3800 }
3801 binx = binnear;
3802 }
3803 } else {
3804 x1 = gPad->PadtoY(gPad->AbsPixeltoY(py+1));
3805 binx = fXaxis->FindFixBin(y);
3806 if (drawOption.Index("same") >= 0) {
3807 TH1 *h1;
3808 TIter next(gPad->GetListOfPrimitives());
3809 while ((h1 = (TH1 *)next())) {
3810 if (!h1->InheritsFrom(TH1::Class())) continue;
3811 binmin = h1->GetXaxis()->GetFirst();
3812 break;
3813 }
3814 } else {
3815 binmin = fXaxis->GetFirst();
3816 }
3818 // special case if more than 1 bin in x per pixel
3819 if (binx1-binx>1 && fH->GetDimension() == 1) {
3822 for (Int_t ibin=binx+1; ibin<binx1; ibin++) {
3826 binnear=ibin;
3827 }
3828 }
3829 binx = binnear;
3830 }
3831 }
3832 if (fH->GetDimension() == 1) {
3834 TProfile *tp = (TProfile*)fH;
3835 fObjectInfo.Form("(x=%g, y=%g, binx=%d, binc=%g, bine=%g, binn=%d)",
3837 (Int_t) tp->GetBinEntries(binx));
3838 }
3839 else {
3840 Double_t integ = 0;
3841 for (Int_t bin=binmin;bin<=binx;bin++) {integ += fH->GetBinContent(bin);}
3842 fObjectInfo.Form("(x=%g, y=%g, binx=%d, binc=%g, Sum=%g)",
3844 }
3845 } else if (fH->GetDimension() == 2) {
3846 if (fH->InheritsFrom(TH2Poly::Class())) {
3847 TH2Poly *th2 = (TH2Poly*)fH;
3848 biny = th2->FindBin(x,y);
3849 fObjectInfo.Form("%s (x=%g, y=%g, bin=%d, binc=%g)",
3850 th2->GetBinTitle(biny),x,y,biny,th2->GetBinContent(biny));
3851 }
3852 else if (fH->InheritsFrom(TProfile2D::Class())) {
3854 biny = fYaxis->FindFixBin(y);
3855 Int_t bin = fH->GetBin(binx,biny);
3856 fObjectInfo.Form("(x=%g, y=%g, binx=%d, biny=%d, binc=%g, bine=%g, binn=%d)",
3857 x, y, binx, biny, fH->GetBinContent(bin),
3858 fH->GetBinError(bin), (Int_t) tp->GetBinEntries(bin));
3859 } else {
3860 biny = fYaxis->FindFixBin(y);
3861 fObjectInfo.Form("(x=%g, y=%g, binx=%d, biny=%d, binc=%g bine=%g)",
3864 }
3865 } else {
3866 // 3d case: retrieving the x,y,z bin is not yet implemented
3867 // print just the x,y info
3868 fObjectInfo.Form("(x=%g, y=%g)",x,y);
3869 }
3870
3871 return (char *)fObjectInfo.Data();
3872}
3873
3874////////////////////////////////////////////////////////////////////////////////
3875/// Set highlight (enable/disable) mode for fH
3876
3878{
3879 if (fH->IsHighlight()) return;
3880
3881 fXHighlightBin = -1;
3882 fYHighlightBin = -1;
3883 // delete previous highlight box
3884 if (gXHighlightBox) gXHighlightBox.reset();
3885 if (gYHighlightBox) gYHighlightBox.reset();
3886 // emit Highlighted() signal (user can check on disabled)
3887 if (gPad->GetCanvas()) gPad->GetCanvas()->Highlighted(gPad, fH, fXHighlightBin, fYHighlightBin);
3888}
3889
3890////////////////////////////////////////////////////////////////////////////////
3891/// Check on highlight bin
3892
3894{
3895 // call from DistancetoPrimitive (only if highlight is enable)
3896
3897 Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
3898 Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
3901 if (!gPad->IsVertical()) binx = fXaxis->FindFixBin(y);
3902
3904 if (binx != fXHighlightBin) {
3906 changedBin = kTRUE;
3907 } else if (fH->GetDimension() == 1) return;
3908 if (biny != fYHighlightBin) {
3910 changedBin = kTRUE;
3911 }
3912 if (!changedBin) return;
3913
3914 // Info("HighlightBin", "histo: %p '%s'\txbin: %d, ybin: %d",
3915 // (void *)fH, fH->GetName(), fXHighlightBin, fYHighlightBin);
3916
3917 // paint highlight bin as box (recursive calls PaintHighlightBin)
3918 gPad->Modified(kTRUE);
3919 gPad->Update();
3920
3921 // emit Highlighted() signal
3922 if (gPad->GetCanvas()) gPad->GetCanvas()->Highlighted(gPad, fH, fXHighlightBin, fYHighlightBin);
3923}
3924
3925////////////////////////////////////////////////////////////////////////////////
3926/// Paint highlight bin as TBox object
3927
3929{
3930 // call from PaintTitle
3931
3932 if (!fH->IsHighlight()) return;
3933
3934 Double_t uxmin = gPad->GetUxmin();
3935 Double_t uxmax = gPad->GetUxmax();
3936 Double_t uymin = gPad->GetUymin();
3937 Double_t uymax = gPad->GetUymax();
3938 if (gPad->GetLogx()) {
3939 uxmin = TMath::Power(10.0, uxmin);
3940 uxmax = TMath::Power(10.0, uxmax);
3941 }
3942 if (gPad->GetLogy()) {
3943 uymin = TMath::Power(10.0, uymin);
3944 uymax = TMath::Power(10.0, uymax);
3945 }
3946
3947 // testing specific possibility (after zoom, draw with "same", log, etc.)
3949 if (gPad->IsVertical()) {
3951 if ((hcenter < uxmin) || (hcenter > uxmax)) return;
3952 } else {
3954 if ((hcenter < uymin) || (hcenter > uymax)) return;
3955 }
3956 if (fH->GetDimension() == 2) {
3958 if ((hcenter < uymin) || (hcenter > uymax)) return;
3959 }
3960
3961 // paint X highlight bin (for 1D or 2D)
3963 if (gPad->IsVertical()) {
3966 hby1 = uymin;
3967 hby2 = uymax;
3968 } else {
3969 hbx1 = uxmin;
3970 hbx2 = uxmax;
3973 }
3974
3975 if (!gXHighlightBox) {
3976 gXHighlightBox = std::make_unique<TBox>(hbx1, hby1, hbx2, hby2);
3977 gXHighlightBox->SetBit(kCannotPick);
3978 gXHighlightBox->SetFillColor(TColor::GetColor("#9797ff"));
3979 if (!TCanvas::SupportAlpha()) gXHighlightBox->SetFillStyle(3001);
3980 else gROOT->GetColor(gXHighlightBox->GetFillColor())->SetAlpha(0.5);
3981 }
3982 gXHighlightBox->SetX1(hbx1);
3983 gXHighlightBox->SetX2(hbx2);
3984 gXHighlightBox->SetY1(hby1);
3985 gXHighlightBox->SetY2(hby2);
3986 gXHighlightBox->Paint();
3987
3988 // Info("PaintHighlightBin", "histo: %p '%s'\txbin: %d, ybin: %d",
3989 // (void *)fH, fH->GetName(), fXHighlightBin, fYHighlightBin);
3990
3991 // paint Y highlight bin (only for 2D)
3992 if (fH->GetDimension() != 2) return;
3993 hbx1 = uxmin;
3994 hbx2 = uxmax;
3997
3998 if (!gYHighlightBox) {
3999 gYHighlightBox = std::make_unique<TBox>(hbx1, hby1, hbx2, hby2);
4000 gYHighlightBox->SetBit(kCannotPick);
4001 gYHighlightBox->SetFillColor(gXHighlightBox->GetFillColor());
4002 gYHighlightBox->SetFillStyle(gXHighlightBox->GetFillStyle());
4003 }
4004 gYHighlightBox->SetX1(hbx1);
4005 gYHighlightBox->SetX2(hbx2);
4006 gYHighlightBox->SetY1(hby1);
4007 gYHighlightBox->SetY2(hby2);
4008 gYHighlightBox->Paint();
4009}
4010
4011////////////////////////////////////////////////////////////////////////////////
4012/// Return `kTRUE` if the cell `ix`, `iy` is inside one of the graphical cuts.
4013
4015{
4016
4017 for (Int_t i=0;i<fNcuts;i++) {
4020 if (fCutsOpt[i] > 0) {
4021 if (!fCuts[i]->IsInside(x,y)) return kFALSE;
4022 } else {
4023 if (fCuts[i]->IsInside(x,y)) return kFALSE;
4024 }
4025 }
4026 return kTRUE;
4027}
4028
4029////////////////////////////////////////////////////////////////////////////////
4030/// Return `kTRUE` if the point `x`, `y` is inside one of the graphical cuts.
4031
4033{
4034
4035 for (Int_t i=0;i<fNcuts;i++) {
4036 if (fCutsOpt[i] > 0) {
4037 if (!fCuts[i]->IsInside(x,y)) return kFALSE;
4038 } else {
4039 if (fCuts[i]->IsInside(x,y)) return kFALSE;
4040 }
4041 }
4042 return kTRUE;
4043}
4044
4045////////////////////////////////////////////////////////////////////////////////
4046/// Decode string `choptin` and fill Hoption structure.
4047
4049{
4050
4051 char *l;
4052 char chopt[128];
4054 strlcpy(chopt,choptin,128);
4057
4065 Hoption.Candle = 0;
4066
4067 // special 2D options
4068 Hoption.List = 0;
4069 Hoption.Zscale = 0;
4070 Hoption.FrontBox = 1;
4071 Hoption.BackBox = 1;
4073
4074 Hoption.Zero = 0;
4075
4077
4078 //check for graphical cuts
4079 MakeCuts(chopt);
4080
4081 for (Int_t i=0;i<nch;i++) chopt[i] = toupper(chopt[i]);
4082 if (hdim > 1) Hoption.Color = 1; // Default drawing option for 2D and 3D histograms
4083 if (!nch) Hoption.Hist = 1;
4084 if (fFunctions->First()) Hoption.Func = 1;
4085 if (fH->GetSumw2N() && hdim == 1) Hoption.Error = 2;
4086
4087 char *l1 = strstr(chopt,"PFC"); // Automatic Fill Color
4088 char *l2 = strstr(chopt,"PLC"); // Automatic Line Color
4089 char *l3 = strstr(chopt,"PMC"); // Automatic Marker Color
4090 if (l1 || l2 || l3) {
4091 Int_t i = gPad->NextPaletteColor();
4092 if (l1) {memcpy(l1," ",3); fH->SetFillColor(i);}
4093 if (l2) {memcpy(l2," ",3); fH->SetLineColor(i);}
4094 if (l3) {memcpy(l3," ",3); fH->SetMarkerColor(i);}
4095 Hoption.Hist = 1; // Make sure something is drawn in case there is no drawing option specified.
4096 }
4097
4098 l = strstr(chopt,"MIN0");
4099 if (l) {
4100 Hoption.MinimumZero = 1;
4101 memcpy(l," ",4);
4102 }
4103
4104 l = strstr(chopt,"SPEC");
4105 if (l) {
4106 Hoption.Color = 0;
4107 memcpy(l," ",4);
4108 Int_t bs=0;
4109 l = strstr(chopt,"BF(");
4110 if (l) {
4111 if (sscanf(&l[3],"%d",&bs) > 0) {
4112 Int_t i=0;
4113 while (l[i]!=')') {
4114 l[i] = ' ';
4115 i++;
4116 }
4117 l[i] = ' ';
4118 }
4119 }
4120 Hoption.Spec = TMath::Max(1600,bs);
4121 return 1;
4122 }
4123
4124 l = strstr(chopt,"GL");
4125 if (l) {
4126 memcpy(l," ",2);
4127 }
4128 l = strstr(chopt,"X+");
4129 if (l) {
4130 Hoption.AxisPos = 10;
4131 memcpy(l," ",2);
4132 }
4133 l = strstr(chopt,"Y+");
4134 if (l) {
4135 Hoption.AxisPos += 1;
4136 memcpy(l," ",2);
4137 }
4138 if ((Hoption.AxisPos == 10 || Hoption.AxisPos == 1) && (nch == 2)) Hoption.Hist = 1;
4139 if (Hoption.AxisPos == 11 && nch == 4) Hoption.Hist = 1;
4140
4141 l = strstr(chopt,"SAMES");
4142 if (l) {
4143 if (nch == 5) Hoption.Hist = 1;
4144 Hoption.Same = 2;
4145 memcpy(l," ",5);
4146 if (l[5] == '0') { Hoption.Same += 10; l[5] = ' '; }
4147 }
4148 l = strstr(chopt,"SAME");
4149 if (l) {
4150 if (nch == 4) Hoption.Hist = 1;
4151 Hoption.Same = 1;
4152 memcpy(l," ",4);
4153 if (l[4] == '0') { Hoption.Same += 10; l[4] = ' '; }
4154 }
4155
4156 l = strstr(chopt,"SCAT");
4157 if (l) {
4158 Warning("MakeChopt","option SCAT is deprecated.");
4159 Hoption.Scat = 1;
4160 memcpy(l," ",4);
4161 Hoption.Color = 0;
4162 }
4163
4164 l = strstr(chopt,"PIE");
4165 if (l) {
4166 Hoption.Pie = 1;
4167 memcpy(l," ",3);
4168 }
4169
4170
4171 l = strstr(chopt,"CANDLE");
4172 if (l) {
4174 Hoption.Candle = candle.ParseOption(l);
4175 Hoption.Color = 0;
4176 }
4177
4178 l = strstr(chopt,"VIOLIN");
4179 if (l) {
4181 Hoption.Candle = candle.ParseOption(l);
4182 Hoption.Color = 0;
4183 }
4184
4185 l = strstr(chopt,"LEGO");
4186 if (l) {
4187 Hoption.Color = 0;
4188 Hoption.Lego = 1; memcpy(l," ",4);
4189 if (l[4] == '1') { Hoption.Lego = 11; l[4] = ' '; }
4190 if (l[4] == '2') { Hoption.Lego = 12; l[4] = ' '; }
4191 if (l[4] == '3') { Hoption.Lego = 13; l[4] = ' '; }
4192 if (l[4] == '4') { Hoption.Lego = 14; l[4] = ' '; }
4193 if (l[4] == '9') { Hoption.Lego = 19; l[4] = ' '; }
4194 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4195 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4196 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4197 }
4198
4199 l = strstr(chopt,"SURF");
4200 if (l) {
4201 Hoption.Color = 0;
4202 Hoption.Surf = 1; memcpy(l," ",4);
4203 if (l[4] == '1') { Hoption.Surf = 11; l[4] = ' '; }
4204 if (l[4] == '2') { Hoption.Surf = 12; l[4] = ' '; }
4205 if (l[4] == '3') { Hoption.Surf = 13; l[4] = ' '; }
4206 if (l[4] == '4') { Hoption.Surf = 14; l[4] = ' '; }
4207 if (l[4] == '5') { Hoption.Surf = 15; l[4] = ' '; }
4208 if (l[4] == '6') { Hoption.Surf = 16; l[4] = ' '; }
4209 if (l[4] == '7') { Hoption.Surf = 17; l[4] = ' '; }
4210 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4211 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4212 }
4213
4214 l = strstr(chopt,"TF3");
4215 if (l) {
4216 memcpy(l," ",3);
4217 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4218 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4219 }
4220
4221 l = strstr(chopt,"ISO");
4222 if (l) {
4223 memcpy(l," ",3);
4224 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4225 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4226 Hoption.Color = 0;
4227 }
4228
4229 l = strstr(chopt,"LIST"); if (l) { Hoption.List = 1; memcpy(l," ",4);}
4230
4231 l = strstr(chopt,"CONT");
4232 if (l) {
4233 memcpy(l," ",4);
4234 if (hdim>1) {
4235 Hoption.Color = 0;
4236 Hoption.Contour = 1;
4237 if (l[4] == '1') { Hoption.Contour = 11; l[4] = ' '; }
4238 if (l[4] == '2') { Hoption.Contour = 12; l[4] = ' '; }
4239 if (l[4] == '3') { Hoption.Contour = 13; l[4] = ' '; }
4240 if (l[4] == '4') { Hoption.Contour = 14; l[4] = ' '; }
4241 if (l[4] == '5') { Hoption.Contour = 15; l[4] = ' '; }
4242 } else {
4243 Hoption.Hist = 1;
4244 }
4245 }
4246 l = strstr(chopt,"HBAR");
4247 if (l) {
4248 Hoption.Hist = 0;
4249 Hoption.Bar = 20; memcpy(l," ",4);
4250 if (l[4] == '1') { Hoption.Bar = 21; l[4] = ' '; }
4251 if (l[4] == '2') { Hoption.Bar = 22; l[4] = ' '; }
4252 if (l[4] == '3') { Hoption.Bar = 23; l[4] = ' '; }
4253 if (l[4] == '4') { Hoption.Bar = 24; l[4] = ' '; }
4254 }
4255 l = strstr(chopt,"BAR");
4256 if (l) {
4257 Hoption.Hist = 0;
4258 Hoption.Bar = 10; memcpy(l," ",3);
4259 if (l[3] == '1') { Hoption.Bar = 11; l[3] = ' '; }
4260 if (l[3] == '2') { Hoption.Bar = 12; l[3] = ' '; }
4261 if (l[3] == '3') { Hoption.Bar = 13; l[3] = ' '; }
4262 if (l[3] == '4') { Hoption.Bar = 14; l[3] = ' '; }
4263 }
4264
4265 l = strstr(chopt,"ARR" );
4266 if (l) {
4267 memcpy(l," ", 3);
4268 if (hdim>1) {
4269 Hoption.Arrow = 1;
4270 Hoption.Color = 0;
4271 l = strstr(chopt,"COL"); if (l) { Hoption.Arrow = 2; memcpy(l," ",3); }
4272 l = strstr(chopt,"Z"); if (l) { Hoption.Zscale = 1; memcpy(l," ",1); }
4273 } else {
4274 Hoption.Hist = 1;
4275 }
4276 }
4277 l = strstr(chopt,"BOX" );
4278 if (l) {
4279 memcpy(l," ", 3);
4280 if (hdim>1) {
4281 Hoption.Color = 0;
4282 Hoption.Box = 1;
4283 if (l[3] == '1') { Hoption.Box = 11; l[3] = ' '; }
4284 if (l[3] == '2') { Hoption.Box = 12; l[3] = ' '; }
4285 if (l[3] == '3') { Hoption.Box = 13; l[3] = ' '; }
4286 } else {
4287 Hoption.Hist = 1;
4288 }
4289 }
4290 l = strstr(chopt,"TEXT");
4291 if (l) {
4292 Int_t angle;
4293 if (sscanf(&l[4],"%d",&angle) > 0) {
4294 if (angle < 0) angle=0;
4295 if (angle > 90) angle=90;
4296 Hoption.Text = 1000+angle;
4297 } else {
4298 Hoption.Text = 1;
4299 }
4300 memcpy(l," ", 4);
4301 l = strstr(chopt,"N");
4302 if (l && fH->InheritsFrom(TH2Poly::Class())) Hoption.Text = 3000 + (Hoption.Text != 1 ? Hoption.Text : 0);
4303 Hoption.Color = 0;
4304 }
4305 l = strstr(chopt,"COLZ");
4306 if (l) {
4307 memcpy(l," ",4);
4308 if (hdim > 1) {
4310 Hoption.Color = 1;
4311 Hoption.Zscale = 1;
4312 if (l[4] == '2') { Hoption.Color = 3; l[4] = ' '; }
4313 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4314 l = strstr(chopt,"1"); if (l) { Hoption.Color = 2; memcpy(l," ",1); }
4315 } else {
4316 Hoption.Hist = 1;
4317 }
4318 }
4319 l = strstr(chopt,"COL" );
4320 if (l) {
4321 memcpy(l," ", 3);
4322 if (hdim > 1) {
4324 Hoption.Color = 1;
4325 if (l[3] == '2') { Hoption.Color = 3; l[3] = ' '; }
4326 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4327 l = strstr(chopt,"1"); if (l) { Hoption.Color = 2; memcpy(l," ",1); }
4328 } else {
4329 Hoption.Hist = 1;
4330 }
4331 }
4332 l = strstr(chopt,"FUNC"); if (l) { Hoption.Func = 2; memcpy(l," ",4); Hoption.Hist = 0; }
4333 l = strstr(chopt,"HIST"); if (l) { Hoption.Hist = 2; memcpy(l," ",4); Hoption.Func = 0; Hoption.Error = 0;}
4334 l = strstr(chopt,"AXIS"); if (l) { Hoption.Axis = 1; memcpy(l," ",4); }
4335 l = strstr(chopt,"AXIG"); if (l) { Hoption.Axis = 2; memcpy(l," ",4); }
4336 l = strstr(chopt,"SCAT"); if (l) { Hoption.Scat = 1; memcpy(l," ",4); }
4337 l = strstr(chopt,"POL"); if (l) { Hoption.System = kPOLAR; memcpy(l," ",3); }
4338 l = strstr(chopt,"CYL"); if (l) { Hoption.System = kCYLINDRICAL; memcpy(l," ",3); }
4339 l = strstr(chopt,"SPH"); if (l) { Hoption.System = kSPHERICAL; memcpy(l," ",3); }
4340 l = strstr(chopt,"PSR"); if (l) { Hoption.System = kRAPIDITY; memcpy(l," ",3); }
4341
4342 l = strstr(chopt,"TRI");
4343 if (l) {
4344 if (!explicitColor) Hoption.Color = 0;
4345 Hoption.Tri = 1; memcpy(l," ",3);
4346 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4347 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4348 l = strstr(chopt,"ERR"); if (l) memcpy(l," ",3);
4349 }
4350
4351 l = strstr(chopt,"AITOFF");
4352 if (l) {
4353 Hoption.Proj = 1; memcpy(l," ",6); //Aitoff projection
4354 }
4355 l = strstr(chopt,"MERCATOR");
4356 if (l) {
4357 Hoption.Proj = 2; memcpy(l," ",8); //Mercator projection
4358 }
4359 l = strstr(chopt,"SINUSOIDAL");
4360 if (l) {
4361 Hoption.Proj = 3; memcpy(l," ",10); //Sinusoidal projection
4362 }
4363 l = strstr(chopt,"PARABOLIC");
4364 if (l) {
4365 Hoption.Proj = 4; memcpy(l," ",9); //Parabolic projection
4366 }
4367 l = strstr(chopt,"MOLLWEIDE");
4368 if (l) {
4369 Hoption.Proj = 5; memcpy(l," ",9); //Mollweide projection
4370 }
4371 if (Hoption.Proj > 0) {
4372 if (!explicitColor) Hoption.Color = 0;
4373 Hoption.Contour = 14;
4374 }
4375
4376 if (strstr(chopt,"A")) Hoption.Axis = -1;
4377 if (strstr(chopt,"B")) Hoption.Bar = 1;
4378 if (strstr(chopt,"C") && !strstr(chopt,"CJUST")) { Hoption.Curve =1; Hoption.Hist = -1;}
4379 if (strstr(chopt,"F")) Hoption.Fill =1;
4380 if (strstr(chopt,"][")) {Hoption.Off =1; Hoption.Hist =1;}
4381 if (strstr(chopt,"F2")) Hoption.Fill =2;
4382 if (strstr(chopt,"L")) { Hoption.Line =1; Hoption.Hist = -1;}
4383 if (strstr(chopt,"P")) { Hoption.Mark =1; Hoption.Hist = -1;}
4384 if (strstr(chopt,"Z")) Hoption.Zscale =1;
4385 if (strstr(chopt,"*")) Hoption.Star =1;
4386 if (strstr(chopt,"H")) Hoption.Hist =2;
4387 if (strstr(chopt,"P0")) Hoption.Mark =10;
4388
4389 if (fH->InheritsFrom(TH2Poly::Class())) {
4391 }
4392
4393 if (strstr(chopt,"E")) {
4394 if (hdim == 1) {
4395 Hoption.Error = 1;
4396 if (strstr(chopt,"E1")) Hoption.Error = 11;
4397 if (strstr(chopt,"E2")) Hoption.Error = 12;
4398 if (strstr(chopt,"E3")) Hoption.Error = 13;
4399 if (strstr(chopt,"E4")) Hoption.Error = 14;
4400 if (strstr(chopt,"E5")) Hoption.Error = 15;
4401 if (strstr(chopt,"E6")) Hoption.Error = 16;
4402 if (strstr(chopt,"E0")) Hoption.Error += 40;
4403 if (strstr(chopt,"X0")) {
4404 if (Hoption.Error == 1) Hoption.Error += 20;
4405 Hoption.Error += 10;
4406 }
4408 Hoption.Text += 2000;
4409 Hoption.Error = 0;
4410 }
4411 } else {
4412 if (Hoption.Error == 0) {
4413 Hoption.Error = 100;
4414 if (!explicitColor) Hoption.Color = 0;
4415 }
4416 if (Hoption.Text) {
4417 Hoption.Text += 2000;
4418 Hoption.Error = 0;
4419 }
4420 }
4421 }
4422
4423 if (Hoption.Surf == 15) {
4425 Hoption.Surf = 13;
4426 Warning("MakeChopt","option SURF5 is not supported in Cartesian and Polar modes");
4427 }
4428 }
4429
4430 // Copy options from current style
4431 Hoption.Logx = gPad->GetLogx();
4432 Hoption.Logy = gPad->GetLogy();
4433 Hoption.Logz = gPad->GetLogz();
4434
4435 // Check options incompatibilities
4436 if (Hoption.Bar == 1) Hoption.Hist = -1;
4437 return 1;
4438}
4439
4440////////////////////////////////////////////////////////////////////////////////
4441/// Decode string `choptin` and fill Graphical cuts structure.
4442
4444{
4445
4446 fNcuts = 0;
4447 char *left = (char*)strchr(choptin,'[');
4448 if (!left) return 0;
4449 char *right = (char*)strchr(choptin,']');
4450 if (!right) return 0;
4451 Int_t nch = right-left;
4452 if (nch < 2) return 0;
4453 char *cuts = left+1;
4454 *right = 0;
4455 char *comma, *minus;
4456 Int_t i;
4457 while (true) {
4458 comma = strchr(cuts,',');
4459 if (comma) *comma = 0;
4460 minus = strchr(cuts,'-');
4461 if (minus) cuts = minus+1;
4462 while (*cuts == ' ') cuts++;
4463 Int_t nc = strlen(cuts);
4464 while (cuts[nc-1] == ' ') {cuts[nc-1] = 0; nc--;}
4465 TIter next(gROOT->GetListOfSpecials());
4466 TCutG *cut=nullptr;
4467 TObject *obj;
4468 while ((obj = next())) {
4469 if (!obj->InheritsFrom(TCutG::Class())) continue;
4470 if (strcmp(obj->GetName(),cuts)) continue;
4471 cut = (TCutG*)obj;
4472 break;
4473 }
4474 if (cut) {
4475 fCuts[fNcuts] = cut;
4476 fCutsOpt[fNcuts] = 1;
4477 if (minus) fCutsOpt[fNcuts] = -1;
4478 fNcuts++;
4479 }
4480 if (!comma) break;
4481 cuts = comma+1;
4482 }
4483 for (i=0;i<=nch;i++) left[i] = ' ';
4484 return fNcuts;
4485}
4486
4487////////////////////////////////////////////////////////////////////////////////
4488/// [Control routine to paint any kind of histograms](\ref HP00)
4489
4491{
4492
4493 if (fH->GetBuffer()) fH->BufferEmpty(-1);
4494
4495 //For iOS: put the histogram on the top of stack of pickable objects.
4497
4498 gPad->SetVertical(kTRUE);
4499
4501 gCurrentHist = fH;
4502 TH1 *hsave = fH;
4504
4505 if (!MakeChopt(option)) return; //check options and fill Hoption structure
4506
4507 // Paint using TSpectrum2Painter
4508 if (Hoption.Spec) {
4509 if (!TableInit()) return;
4510 if (!TClass::GetClass("TSpectrum2Painter")) gSystem->Load("libSpectrumPainter");
4511 gROOT->ProcessLineFast(TString::Format("TSpectrum2Painter::PaintSpectrum((TH2F*)0x%zx,\"%s\",%d)",
4512 (size_t)fH, option, Hoption.Spec).Data());
4513 return;
4514 }
4515
4516 // Deflate the labels in case of alphanumeric labels
4520
4521 if (Hoption.Pie) {
4522 if (fH->GetDimension() == 1) {
4523 if (!fPie)
4524 fPie = std::make_unique<TPie>(fH);
4525 fPie->Paint(option);
4526 } else {
4527 Error("Paint", "Option PIE is for 1D histograms only");
4528 }
4529 return;
4530 } else {
4531 fPie.reset();
4532 }
4533
4534 fXbuf.resize(kNMAX);
4535 fYbuf.resize(kNMAX);
4536 if (fH->GetDimension() > 2) {
4537 PaintH3(option);
4539 if (Hoption.Func) {
4544 Hoption = hoptsave;
4545 Hparam = hparsave;
4546 }
4548 fXbuf.clear();
4549 fYbuf.clear();
4550 return;
4551 }
4552 TView *view = gPad->GetView();
4553 if (view) {
4554 if (!Hoption.Lego && !Hoption.Surf && !Hoption.Tri) {
4555 delete view;
4556 gPad->SetView(nullptr);
4557 }
4558 }
4559 if (fH->GetDimension() > 1 || Hoption.Lego || Hoption.Surf) {
4560 // In case of 1D histogram, Z axis becomes Y axis.
4561 Int_t logysav=0, logzsav=0;
4562 if (fH->GetDimension() == 1) {
4565 Hoption.Logz = 0;
4566 if (Hoption.Logy) {
4567 Hoption.Logz = 1;
4568 Hoption.Logy = 0;
4569 }
4570 }
4572 if (Hoption.Func) {
4577 Hoption = hoptsave;
4578 Hparam = hparsave;
4579 }
4582 fXbuf.clear();
4583 fYbuf.clear();
4584 if (fH->GetDimension() == 1) {
4587 }
4588 return;
4589 }
4590
4591 if (Hoption.Bar >= 20) {
4593 fXbuf.clear();
4594 fYbuf.clear();
4595 return;
4596 }
4597
4598 gPad->RangeAxisChanged(); //emit RangeAxisChanged() signal to sync axes
4599 // fill Hparam structure with histo parameters
4600 if (!PaintInit()) {
4601 fXbuf.clear();
4602 fYbuf.clear();
4603 return;
4604 }
4605
4606 // Picture surround (if new page) and page number (if requested).
4607 // Histogram surround (if not option "Same").
4608 PaintFrame();
4609
4610 // Paint histogram axis only
4611 Bool_t gridx = gPad->GetGridx();
4612 Bool_t gridy = gPad->GetGridy();
4613 if (Hoption.Axis > 0) {
4614 if (Hoption.Axis > 1) PaintAxis(kTRUE); //axis with grid
4615 else {
4616 if (gridx) gPad->SetGridx(0);
4617 if (gridy) gPad->SetGridy(0);
4619 if (gridx) gPad->SetGridx(1);
4620 if (gridy) gPad->SetGridy(1);
4621 }
4622 if ((Hoption.Same%10) ==1) Hoption.Same += 1;
4623 goto paintstat;
4624 }
4625 if (gridx || gridy) PaintAxis(kTRUE); // Draw the grid only
4626
4627 // test for options BAR or HBAR
4628 if (Hoption.Bar >= 10) {
4630 }
4631
4632 // do not draw histogram if error bars required
4633 if (!Hoption.Error) {
4634 if (Hoption.Hist && Hoption.Bar<10) PaintHist(option);
4635 }
4636
4637 // test for error bars or option E
4638 if (Hoption.Error) {
4640 if (Hoption.Hist == 2) PaintHist(option);
4641 }
4642
4644
4645 // test for associated function
4646 if (Hoption.Func) {
4651 Hoption = hoptsave;
4652 Hparam = hparsave;
4653 }
4654
4655 if (gridx) gPad->SetGridx(0);
4656 if (gridy) gPad->SetGridy(0);
4658 if (gridx) gPad->SetGridx(1);
4659 if (gridy) gPad->SetGridy(1);
4660
4661 PaintTitle(); // Draw histogram title
4662
4663 // Draw box with histogram statistics and/or fit parameters
4664paintstat:
4665 if ((Hoption.Same%10) != 1 && !fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
4666 TIter next(fFunctions);
4667 TObject *obj = nullptr;
4668 while ((obj = next())) {
4669 if (obj->InheritsFrom(TF1::Class())) break;
4670 obj = nullptr;
4671 }
4672
4673 //Stat is painted twice (first, it will be in canvas' list of primitives),
4674 //second, it will be here, this is not required on iOS.
4675 //Condition is ALWAYS true on a platform different from iOS.
4676 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode())
4677 PaintStat(gStyle->GetOptStat(),(TF1*)obj);
4678 }
4681 fXbuf.clear();
4682 fYbuf.clear();
4683}
4684
4685////////////////////////////////////////////////////////////////////////////////
4686/// [Control function to draw a table as an arrow plot](\ref HP12)
4687
4689{
4691 Double_t dx, dy, x1, x2, y1, y2, xc, yc, dxn, dyn;
4694 Double_t xrg = gPad->GetUxmin();
4695 Double_t yrg = gPad->GetUymin();
4696 Double_t xln = gPad->GetUxmax() - xrg;
4697 Double_t yln = gPad->GetUymax() - yrg;
4698 Double_t cx = (xln/Double_t(ncx))/2.;
4699 Double_t cy = (yln/Double_t(ncy))/2.;
4700 Double_t dn = 1.E-30;
4701
4702 auto arrow = new TArrow();
4703 arrow->SetAngle(30);
4704 arrow->SetFillStyle(1001);
4705 arrow->SetFillColor(fH->GetLineColor());
4706 arrow->SetLineColor(fH->GetLineColor());
4707 arrow->SetLineWidth(fH->GetLineWidth());
4708
4709 // Initialize the levels on the Z axis
4710 Int_t ncolors=0, ndivz=0;
4711 Double_t scale=0.;
4712 if (Hoption.Arrow>1) {
4713 ncolors = gStyle->GetNumberOfColors();
4714 Int_t ndiv = fH->GetContour();
4715 if (ndiv == 0 ) {
4716 ndiv = gStyle->GetNumberContours();
4717 fH->SetContour(ndiv);
4718 }
4719 ndivz = TMath::Abs(ndiv);
4720 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
4722 }
4723
4724 for (Int_t id=1;id<=2;id++) {
4725 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
4728 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
4729 xk = fXaxis->GetBinLowEdge(i);
4730 xstep = fXaxis->GetBinWidth(i);
4731 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
4732 if (i == Hparam.xfirst) {
4733 dx = fH->GetBinContent(i+1, j) - fH->GetBinContent(i, j);
4734 } else if (i == Hparam.xlast) {
4735 dx = fH->GetBinContent(i, j) - fH->GetBinContent(i-1, j);
4736 } else {
4737 dx = 0.5*(fH->GetBinContent(i+1, j) - fH->GetBinContent(i-1, j));
4738 }
4739 if (j == Hparam.yfirst) {
4740 dy = fH->GetBinContent(i, j+1) - fH->GetBinContent(i, j);
4741 } else if (j == Hparam.ylast) {
4742 dy = fH->GetBinContent(i, j) - fH->GetBinContent(i, j-1);
4743 } else {
4744 dy = 0.5*(fH->GetBinContent(i, j+1) - fH->GetBinContent(i, j-1));
4745 }
4746 if (id == 1) {
4749 } else if (id == 2) {
4750 xc = xrg + xln*(Double_t(i - Hparam.xfirst+1)-0.5)/Double_t(ncx);
4751 dxn = cx*dx/dn;
4752 x1 = xc - dxn;
4753 x2 = xc + dxn;
4754 yc = yrg + yln*(Double_t(j - Hparam.yfirst+1)-0.5)/Double_t(ncy);
4755 dyn = cy*dy/dn;
4756 y1 = yc - dyn;
4757 y2 = yc + dyn;
4758 if (Hoption.Arrow>1) {
4759 int color = Int_t(0.01+(fH->GetBinContent(i, j)-fH->GetMinimum())*scale);
4760 Int_t theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
4761 if (theColor > ncolors-1) theColor = ncolors-1;
4762 arrow->SetFillColor(gStyle->GetColorPalette(theColor));
4763 arrow->SetLineColor(gStyle->GetColorPalette(theColor));
4764 }
4765 if (TMath::Abs(x2-x1) > 0. || TMath::Abs(y2-y1) > 0.) {
4766 arrow->PaintArrow(x1, y1, x2, y2, 0.015, "|>");
4767 } else {
4768 arrow->PaintArrow(x1, y1, x2, y2, 0.005, "|>");
4769 }
4770 }
4771 }
4772 }
4773 }
4774
4776}
4777
4778////////////////////////////////////////////////////////////////////////////////
4779/// Draw axis (2D case) of an histogram.
4780///
4781/// If `drawGridOnly` is `TRUE`, only the grid is painted (if needed). This allows
4782/// to draw the grid and the axis separately. In `THistPainter::Paint` this
4783/// feature is used to make sure that the grid is drawn in the background and
4784/// the axis tick marks in the foreground of the pad.
4785
4787{
4788
4789 //On iOS, grid should not be pickable and can not be highlighted.
4790 //Condition is never true on a platform different from iOS.
4791 if (drawGridOnly && (gPad->PadInHighlightMode() || gPad->PadInSelectionMode()))
4792 return;
4793
4794 if (Hoption.Axis == -1) return;
4795 if (Hoption.Same && Hoption.Axis <= 0) return;
4796
4797 // Repainting alphanumeric labels axis on a plot done with
4798 // the option HBAR (horizontal) needs some adjustments.
4799 TAxis *xaxis = nullptr;
4800 TAxis *yaxis = nullptr;
4801 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4802 if (fXaxis->GetLabels() || fYaxis->GetLabels()) { // One axis has alphanumeric labels
4803 TIter next(gPad->GetListOfPrimitives());
4804 TObject *obj;
4805 // Check if the first TH1 of THStack in the pad is drawn with the option HBAR
4806 while ((obj = next())) {
4807 if (!obj->InheritsFrom(TH1::Class()) &&
4808 !obj->InheritsFrom(THStack::Class())) continue;
4809 TString opt = obj->GetDrawOption();
4810 opt.ToLower();
4811 // if drawn with HBAR, the axis should be inverted and the pad set to horizontal
4812 if (strstr(opt,"hbar")) {
4813 gPad->SetVertical(kFALSE);
4814 xaxis = fXaxis;
4815 yaxis = fYaxis;
4816 if (!strcmp(xaxis->GetName(),"xaxis")) {
4817 fXaxis = yaxis;
4818 fYaxis = xaxis;
4819 }
4820 }
4821 break;
4822 }
4823 }
4824 }
4825
4826 static char chopt[10] = "";
4827 Double_t gridl = 0;
4828 Int_t ndiv, ndivx, ndivy, nx1, nx2, ndivsave;
4829 Int_t useHparam = 0;
4833
4834 Double_t axmin = gPad->GetUxmin();
4835 Double_t axmax = gPad->GetUxmax();
4836 Double_t aymin = gPad->GetUymin();
4837 Double_t aymax = gPad->GetUymax();
4838 char *cw = nullptr;
4839 TGaxis axis;
4840
4841 // In case of option 'cont4' or in case of option 'same' over a 'cont4 plot'
4842 // Hparam must be use for the axis limits.
4843 if (Hoption.Contour == 14) useHparam = 1;
4844 if (Hoption.Same) {
4845 TObject *obj;
4846 TIter next(gPad->GetListOfPrimitives());
4847 while ((obj=next())) {
4848 if (strstr(obj->GetDrawOption(),"cont4")) {
4849 useHparam = 1;
4850 break;
4851 }
4852 }
4853 }
4854
4855 // Paint X axis
4856
4857 //To make X-axis selectable on iOS device.
4858 if (gPad->PadInSelectionMode())
4859 gPad->PushSelectableObject(fXaxis);
4860
4861 //This condition is ALWAYS true, unless it works on iOS (can be false on iOS).
4862 if (gPad->PadInSelectionMode() || !gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && gPad->GetSelected() == fXaxis)) {
4864 if (ndivx > 1000) {
4865 nx2 = ndivx/100;
4866 nx1 = TMath::Max(1, ndivx%100);
4867 ndivx = 100*nx2 + Int_t(Float_t(nx1)*gPad->GetAbsWNDC());
4868 }
4869 axis.SetTextAngle(0);
4871
4872 chopt[0] = 0;
4873 strlcat(chopt, "SDH",10);
4874 if (ndivx < 0) strlcat(chopt, "N",10);
4875 if (gPad->GetGridx()) {
4876 gridl = (aymax-aymin)/(gPad->GetY2() - gPad->GetY1());
4877 strlcat(chopt, "W",10);
4878 }
4879
4880 // Define X-Axis limits
4881 if (Hoption.Logx) {
4882 strlcat(chopt, "G",10);
4883 ndiv = TMath::Abs(ndivx);
4884 if (useHparam) {
4887 } else {
4888 umin = TMath::Power(10,axmin);
4889 umax = TMath::Power(10,axmax);
4890 }
4891 } else {
4892 ndiv = TMath::Abs(ndivx);
4893 if (useHparam) {
4894 umin = Hparam.xmin;
4895 umax = Hparam.xmax;
4896 } else {
4897 umin = axmin;
4898 umax = axmax;
4899 }
4900 }
4901
4902 // Display axis as time
4903 if (fXaxis->GetTimeDisplay()) {
4904 strlcat(chopt,"t",10);
4905 if (strlen(fXaxis->GetTimeFormatOnly()) == 0) {
4907 }
4908 }
4909
4910 // The main X axis can be on the bottom or on the top of the pad
4912 if (xAxisPos == 1) {
4913 // Main X axis top
4914 xAxisYPos1 = aymax;
4915 xAxisYPos2 = aymin;
4916 } else {
4917 // Main X axis bottom
4918 xAxisYPos1 = aymin;
4919 xAxisYPos2 = aymax;
4920 }
4921
4922 // Paint the main X axis (always)
4923 uminsave = umin;
4924 umaxsave = umax;
4925 ndivsave = ndiv;
4926 axis.SetOption(chopt);
4927 if (xAxisPos) {
4928 strlcat(chopt, "-",10);
4929 gridl = -gridl;
4930 }
4931 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4932 axis.SetLabelSize(0.);
4933 axis.SetTitle("");
4934 }
4937 umin, umax, ndiv, chopt, gridl, drawGridOnly);
4938
4939 // Paint additional X axis (if needed)
4940 // On iOS, this additional X axis is neither pickable, nor highlighted.
4941 // Additional checks PadInSelectionMode etc. does not effect non-iOS platform.
4942 if (gPad->GetTickx() && !gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
4943 if (xAxisPos) {
4944 cw=strstr(chopt,"-");
4945 *cw='z';
4946 } else {
4947 strlcat(chopt, "-",10);
4948 }
4949 if (gPad->GetTickx() < 2) strlcat(chopt, "U",10);
4950 if ((cw=strstr(chopt,"W"))) *cw='z';
4951 axis.SetTitle("");
4955 }
4956 }//End of "if pad in selection mode etc".
4957
4958 // Paint Y axis
4959 //On iOS, Y axis must pushed into the stack of selectable objects.
4960 if (gPad->PadInSelectionMode())
4961 gPad->PushSelectableObject(fYaxis);
4962
4963 //This conditions is ALWAYS true on a platform, different from iOS (on iOS can be true, can be false).
4964 if (gPad->PadInSelectionMode() || !gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && gPad->GetSelected() == fYaxis)) {
4967
4968 chopt[0] = 0;
4969 strlcat(chopt, "SDH",10);
4970 if (ndivy < 0) strlcat(chopt, "N",10);
4971 if (gPad->GetGridy()) {
4972 gridl = (axmax-axmin)/(gPad->GetX2() - gPad->GetX1());
4973 strlcat(chopt, "W",10);
4974 }
4975
4976 // Define Y-Axis limits
4977 if (Hoption.Logy) {
4978 strlcat(chopt, "G",10);
4979 ndiv = TMath::Abs(ndivy);
4980 if (useHparam) {
4983 } else {
4984 umin = TMath::Power(10,aymin);
4985 umax = TMath::Power(10,aymax);
4986 }
4987 } else {
4988 ndiv = TMath::Abs(ndivy);
4989 if (useHparam) {
4990 umin = Hparam.ymin;
4991 umax = Hparam.ymax;
4992 } else {
4993 umin = aymin;
4994 umax = aymax;
4995 }
4996 }
4997
4998 // Display axis as time
4999 if (fYaxis->GetTimeDisplay()) {
5000 strlcat(chopt,"t",10);
5001 if (strlen(fYaxis->GetTimeFormatOnly()) == 0) {
5003 }
5004 }
5005
5006 // The main Y axis can be on the left or on the right of the pad
5008 if (yAxisPos == 1) {
5009 // Main Y axis left
5010 yAxisXPos1 = axmax;
5011 yAxisXPos2 = axmin;
5012 } else {
5013 // Main Y axis right
5014 yAxisXPos1 = axmin;
5015 yAxisXPos2 = axmax;
5016 }
5017
5018 // Paint the main Y axis (always)
5019 uminsave = umin;
5020 umaxsave = umax;
5021 ndivsave = ndiv;
5022 axis.SetOption(chopt);
5023 if (yAxisPos) {
5024 strlcat(chopt, "+L",10);
5025 gridl = -gridl;
5026 }
5027 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
5028 axis.SetLabelSize(0.);
5029 axis.SetTitle("");
5030 }
5033 umin, umax, ndiv, chopt, gridl, drawGridOnly);
5034
5035 // Paint the additional Y axis (if needed)
5036 // Additional checks for pad mode are required on iOS: this "second" axis is
5037 // neither pickable, nor highlighted. Additional checks have no effect on non-iOS platform.
5038 if (gPad->GetTicky() && !gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
5039 if (gPad->GetTicky() < 2) {
5040 strlcat(chopt, "U",10);
5042 } else {
5043 strlcat(chopt, "+L",10);
5044 }
5045 if ((cw=strstr(chopt,"W"))) *cw='z';
5046 axis.SetTitle("");
5050 }
5051 }//End of "if pad is in selection mode etc."
5052
5053 // Reset the axis if they have been inverted in case of option HBAR
5054 if (xaxis) {
5055 fXaxis = xaxis;
5056 fYaxis = yaxis;
5057 }
5058}
5059
5060////////////////////////////////////////////////////////////////////////////////
5061/// [Draw a bar-chart in a normal pad.](\ref HP10)
5062
5064{
5065
5066 Int_t bar = Hoption.Bar - 10;
5070 TBox box;
5072 if (hcolor == gPad->GetFrameFillColor()) ++hcolor;
5074 box.SetFillColor(hcolor);
5075 box.SetFillStyle(hstyle);
5076 box.SetLineStyle(fH->GetLineStyle());
5077 box.SetLineColor(fH->GetLineColor());
5078 box.SetLineWidth(fH->GetLineWidth());
5079 for (Int_t bin=fXaxis->GetFirst();bin<=fXaxis->GetLast();bin++) {
5080 y = fH->GetBinContent(bin);
5081 xmin = gPad->XtoPad(fXaxis->GetBinLowEdge(bin));
5082 xmax = gPad->XtoPad(fXaxis->GetBinUpEdge(bin));
5083 ymin = gPad->GetUymin();
5084 ymax = gPad->YtoPad(y);
5085 if (ymax < gPad->GetUymin()) continue;
5086 if (ymax > gPad->GetUymax()) ymax = gPad->GetUymax();
5087 if (ymin < gPad->GetUymin()) ymin = gPad->GetUymin();
5088 if (Hoption.MinimumZero && ymin < 0)
5089 ymin=TMath::Min(0.,gPad->GetUymax());
5090 w = (xmax-xmin)*width;
5091 xmin += offset*(xmax-xmin);
5092 xmax = xmin + w;
5093 if (bar < 1) {
5094 box.PaintBox(xmin,ymin,xmax,ymax);
5095 } else {
5096 umin = xmin + bar*(xmax-xmin)/10.;
5097 umax = xmax - bar*(xmax-xmin)/10.;
5098 box.SetFillColor(TColor::GetColorBright(hcolor)); //bright
5099 box.PaintBox(xmin,ymin,umin,ymax);
5100 box.SetFillColor(hcolor);
5101 box.PaintBox(umin,ymin,umax,ymax);
5102 box.SetFillColor(TColor::GetColorDark(hcolor)); //dark
5103 box.PaintBox(umax,ymin,xmax,ymax);
5104 }
5105 }
5106}
5107
5108////////////////////////////////////////////////////////////////////////////////
5109/// [Draw a bar char in a rotated pad (X vertical, Y horizontal)](\ref HP10)
5110
5112{
5113
5114 gPad->SetVertical(kFALSE);
5115
5116 PaintInitH();
5117
5118 TAxis *xaxis = fXaxis;
5119 TAxis *yaxis = fYaxis;
5120 if (!strcmp(xaxis->GetName(),"xaxis")) {
5121 fXaxis = yaxis;
5122 fYaxis = xaxis;
5123 }
5124
5125 PaintFrame();
5127
5128 Int_t bar = Hoption.Bar - 20;
5132 TBox box;
5134 if (hcolor == gPad->GetFrameFillColor()) ++hcolor;
5136 box.SetFillColor(hcolor);
5137 box.SetFillStyle(hstyle);
5138 box.SetLineStyle(fH->GetLineStyle());
5139 box.SetLineColor(fH->GetLineColor());
5140 box.SetLineWidth(fH->GetLineWidth());
5141 for (Int_t bin=fYaxis->GetFirst();bin<=fYaxis->GetLast();bin++) {
5142 ymin = gPad->YtoPad(fYaxis->GetBinLowEdge(bin));
5143 ymax = gPad->YtoPad(fYaxis->GetBinUpEdge(bin));
5144 xmin = gPad->GetUxmin();
5145 xmax = gPad->XtoPad(fH->GetBinContent(bin));
5146 if (xmax < gPad->GetUxmin()) continue;
5147 if (xmax > gPad->GetUxmax()) xmax = gPad->GetUxmax();
5148 if (xmin < gPad->GetUxmin()) xmin = gPad->GetUxmin();
5149 if (Hoption.MinimumZero && xmin < 0)
5150 xmin=TMath::Min(0.,gPad->GetUxmax());
5151 w = (ymax-ymin)*width;
5152 ymin += offset*(ymax-ymin);
5153 ymax = ymin + w;
5154 if (bar < 1) {
5155 box.PaintBox(xmin,ymin,xmax,ymax);
5156 } else {
5157 umin = ymin + bar*(ymax-ymin)/10.;
5158 umax = ymax - bar*(ymax-ymin)/10.;
5159 box.SetFillColor(TColor::GetColorDark(hcolor)); //dark
5160 box.PaintBox(xmin,ymin,xmax,umin);
5161 box.SetFillColor(hcolor);
5162 box.PaintBox(xmin,umin,xmax,umax);
5163 box.SetFillColor(TColor::GetColorBright(hcolor)); //bright
5164 box.PaintBox(xmin,umax,xmax,ymax);
5165 }
5166 }
5167
5168 PaintTitle();
5169
5170 // Draw box with histogram statistics and/or fit parameters
5171 if ((Hoption.Same%10) != 1 && !fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
5172 TIter next(fFunctions);
5173 TObject *obj = nullptr;
5174 while ((obj = next())) {
5175 if (obj->InheritsFrom(TF1::Class())) break;
5176 obj = nullptr;
5177 }
5178 PaintStat(gStyle->GetOptStat(),(TF1*)obj);
5179 }
5180
5181 fXaxis = xaxis;
5182 fYaxis = yaxis;
5183}
5184
5185////////////////////////////////////////////////////////////////////////////////
5186/// [Control function to draw a 2D histogram as a box plot](\ref HP13)
5187
5189{
5190
5193 if (fH->GetFillColor() == 0) fH->SetFillStyle(0);
5194 if (Hoption.Box == 11) fH->SetFillStyle(1001);
5195 fH->TAttLine::Modify();
5196 fH->TAttFill::Modify();
5197
5198 Double_t z, xk,xstep, yk, ystep, xcent, ycent, xlow, xup, ylow, yup;
5199 Double_t ux1 = gPad->PixeltoX(1);
5200 Double_t ux0 = gPad->PixeltoX(0);
5201 Double_t uy1 = gPad->PixeltoY(1);
5202 Double_t uy0 = gPad->PixeltoY(0);
5203 Double_t dxmin = 0.51*(gPad->PadtoX(ux1)-gPad->PadtoX(ux0));
5204 Double_t dymin = 0.51*(gPad->PadtoY(uy0)-gPad->PadtoY(uy1));
5205
5206 Double_t zmin = TMath::Max(fH->GetMinimum(),0.);
5209 Double_t zminlin = zmin, zmaxlin = zmax;
5210
5211 // In case of option SAME, zmin and zmax values are taken from the
5212 // first plotted 2D histogram.
5213 if (Hoption.Same > 0 && Hoption.Same < 10) {
5214 TH2 *h2;
5215 TIter next(gPad->GetListOfPrimitives());
5216 while ((h2 = (TH2 *)next())) {
5217 if (!h2->InheritsFrom(TH2::Class())) continue;
5218 zmin = TMath::Max(h2->GetMinimum(), 0.);
5219 zmax = TMath::Max(TMath::Abs(h2->GetMaximum()),
5220 TMath::Abs(h2->GetMinimum()));
5221 zminlin = zmin;
5222 zmaxlin = zmax;
5223 if (Hoption.Logz) {
5224 if (zmin <= 0) {
5225 zmin = TMath::Log10(zmax*0.001);
5226 } else {
5227 zmin = TMath::Log10(zmin);
5228 }
5229 zmax = TMath::Log10(zmax);
5230 }
5231 break;
5232 }
5233 } else {
5234 if (Hoption.Logz) {
5235 if (zmin > 0) {
5236 zmin = TMath::Log10(zmin);
5237 zmax = TMath::Log10(zmax);
5238 } else {
5239 return;
5240 }
5241 }
5242 }
5243
5244 Double_t zratio, dz = zmax - zmin;
5246 if (fH->GetMinimum()<0) kZminNeg = kTRUE;
5248
5249 // Define the dark and light colors the "button style" boxes.
5250 Color_t color = fH->GetFillColor();
5251 Color_t light=0, dark=0;
5252 if (Hoption.Box == 11) {
5254 dark = TColor::GetColorDark(color);
5255 }
5256
5257 // Loop over all the bins and draw the boxes
5258 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
5261 ycent = 0.5*ystep;
5262 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
5263 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
5264 xk = fXaxis->GetBinLowEdge(i);
5265 xstep = fXaxis->GetBinWidth(i);
5266 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
5267 xcent = 0.5*xstep;
5268 z = Hparam.factor*fH->GetBinContent(bin);
5269 kZNeg = kFALSE;
5270
5271 if (TMath::Abs(z) < zminlin) continue; // Can be the case with ...
5272 if (TMath::Abs(z) > zmaxlin) z = zmaxlin; // ... option Same
5273 if (kZminNeg && z==0) continue; // Do not draw empty bins if case of histo with negative bins.
5274
5275 if (z < 0) {
5276 if (Hoption.Logz) continue;
5277 z = -z;
5278 kZNeg = kTRUE;
5279 }
5280 if (Hoption.Logz) {
5281 if (z != 0) z = TMath::Log10(z);
5282 else z = zmin;
5283 }
5284
5285 if (dz == 0) continue;
5286 zratio = TMath::Sqrt((z-zmin)/dz);
5287 if (zratio == 0) continue;
5288
5289 xup = xcent*zratio + xk + xcent;
5290 xlow = 2*(xk + xcent) - xup;
5291 if (xup-xlow < dxmin) xup = xlow+dxmin;
5292 if (Hoption.Logx) {
5293 if (xup > 0) xup = TMath::Log10(xup);
5294 else continue;
5295 if (xlow > 0) xlow = TMath::Log10(xlow);
5296 else continue;
5297 }
5298
5299 yup = ycent*zratio + yk + ycent;
5300 ylow = 2*(yk + ycent) - yup;
5301 if (yup-ylow < dymin) yup = ylow+dymin;
5302 if (Hoption.Logy) {
5303 if (yup > 0) yup = TMath::Log10(yup);
5304 else continue;
5305 if (ylow > 0) ylow = TMath::Log10(ylow);
5306 else continue;
5307 }
5308
5309 xlow = TMath::Max(xlow, gPad->GetUxmin());
5310 ylow = TMath::Max(ylow, gPad->GetUymin());
5311 xup = TMath::Min(xup , gPad->GetUxmax());
5312 yup = TMath::Min(yup , gPad->GetUymax());
5313
5314 if (xlow >= xup) continue;
5315 if (ylow >= yup) continue;
5316
5317 if (Hoption.Box == 1) {
5318 fH->SetFillColor(color);
5319 fH->TAttFill::Modify();
5320 gPad->PaintBox(xlow, ylow, xup, yup);
5321 if (kZNeg) {
5322 gPad->PaintLine(xlow, ylow, xup, yup);
5323 gPad->PaintLine(xlow, yup, xup, ylow);
5324 }
5325 } else if (Hoption.Box == 11) {
5326 // Draw the center of the box
5327 fH->SetFillColor(color);
5328 fH->TAttFill::Modify();
5329 gPad->PaintBox(xlow, ylow, xup, yup);
5330
5331 // Draw top&left part of the box
5332 Double_t x[7], y[7];
5333 Double_t bwidth = 0.1;
5334 x[0] = xlow; y[0] = ylow;
5335 x[1] = xlow + bwidth*(xup-xlow); y[1] = ylow + bwidth*(yup-ylow);
5336 x[2] = x[1]; y[2] = yup - bwidth*(yup-ylow);
5337 x[3] = xup - bwidth*(xup-xlow); y[3] = y[2];
5338 x[4] = xup; y[4] = yup;
5339 x[5] = xlow; y[5] = yup;
5340 x[6] = xlow; y[6] = ylow;
5341 if (kZNeg) fH->SetFillColor(dark);
5342 else fH->SetFillColor(light);
5343 fH->TAttFill::Modify();
5344 gPad->PaintFillArea(7, x, y);
5345
5346 // Draw bottom&right part of the box
5347 x[0] = xlow; y[0] = ylow;
5348 x[1] = xlow + bwidth*(xup-xlow); y[1] = ylow + bwidth*(yup-ylow);
5349 x[2] = xup - bwidth*(xup-xlow); y[2] = y[1];
5350 x[3] = x[2]; y[3] = yup - bwidth*(yup-ylow);
5351 x[4] = xup; y[4] = yup;
5352 x[5] = xup; y[5] = ylow;
5353 x[6] = xlow; y[6] = ylow;
5354 if (kZNeg) fH->SetFillColor(light);
5355 else fH->SetFillColor(dark);
5356 fH->TAttFill::Modify();
5357 gPad->PaintFillArea(7, x, y);
5358 }
5359 }
5360 }
5361
5365 fH->TAttFill::Modify();
5366}
5367
5368
5369
5370////////////////////////////////////////////////////////////////////////////////
5371/// [Control function to draw a 2D histogram as a candle (box) plot or violin plot](\ref HP14)
5372
5374{
5375 TH1D *hproj = nullptr;
5376 TH2D *h2 = (TH2D*)fH;
5377
5380 myCandle.SetMarkerColor(fH->GetLineColor());
5381 myCandle.SetLineColor(fH->GetLineColor());
5382 myCandle.SetLineWidth(fH->GetLineWidth());
5383 myCandle.SetFillColor(fH->GetFillColor());
5384 myCandle.SetFillStyle(fH->GetFillStyle());
5385 myCandle.SetMarkerSize(fH->GetMarkerSize());
5386 myCandle.SetMarkerStyle(fH->GetMarkerStyle());
5388
5389 Bool_t swapXY = myCandle.IsHorizontal();
5390 const Double_t standardCandleWidth = 0.66;
5391 const Double_t standardHistoWidth = 0.8;
5392
5393 double allMaxContent = 0, allMaxIntegral = 0;
5394 if (myCandle.IsViolinScaled())
5395 allMaxContent = h2->GetBinContent(h2->GetMaximumBin());
5396
5397 if (!swapXY) { // Vertical candle
5398 //Determining the slice with the maximum integral - if necessary
5399 if (myCandle.IsCandleScaled())
5400 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast; i++) {
5401 hproj = h2->ProjectionY("_px", i, i);
5402 if (hproj->Integral() > allMaxIntegral) allMaxIntegral = hproj->Integral();
5403 }
5404 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast; i++) {
5406 Double_t binWidth = fXaxis->GetBinWidth(i);
5407 hproj = h2->ProjectionY("_px", i, i);
5408 if (hproj->GetEntries() != 0) {
5410 Double_t offset = fH->GetBarOffset()*binWidth;
5411 double myMaxContent = hproj->GetBinContent(hproj->GetMaximumBin());
5412 double myIntegral = hproj->Integral();
5414 if (candleWidth > 0.999 && candleWidth < 1.001) {
5417 }
5418 if (Hoption.Logz && myMaxContent > 0) {
5420 if (myCandle.IsViolinScaled() && myMaxContent > 0 && allMaxContent > 0)
5422 } else if (myCandle.IsViolinScaled() && (allMaxContent > 0))
5424 if (myCandle.IsCandleScaled() && (allMaxIntegral > 0))
5426
5427 myCandle.SetAxisPosition(binPosX+binWidth/2. + offset);
5428 myCandle.SetCandleWidth(candleWidth*binWidth);
5429 myCandle.SetHistoWidth(histoWidth*binWidth);
5430 myCandle.SetHistogram(hproj);
5431 myCandle.Paint();
5432 }
5433 }
5434 } else { // Horizontal candle
5435 //Determining the slice with the maximum integral - if necessary
5436 if (myCandle.IsCandleScaled())
5437 for (Int_t i=Hparam.yfirst; i<=Hparam.ylast; i++) {
5438 hproj = h2->ProjectionX("_py", i, i);
5439 if (hproj->Integral() > allMaxIntegral) allMaxIntegral = hproj->Integral();
5440 }
5441 for (Int_t i=Hparam.yfirst; i<=Hparam.ylast; i++) {
5443 Double_t binWidth = fYaxis->GetBinWidth(i);
5444 hproj = h2->ProjectionX("_py", i, i);
5445 if (hproj->GetEntries() != 0) {
5447 Double_t offset = fH->GetBarOffset()*binWidth;
5448 double myMaxContent = hproj->GetBinContent(hproj->GetMaximumBin());
5449 double myIntegral = hproj->Integral();
5451 if (candleWidth > 0.999 && candleWidth < 1.001) {
5454 }
5455 if (Hoption.Logz && myMaxContent > 0) {
5457 if (myCandle.IsViolinScaled() && myMaxContent > 0 && allMaxContent > 0)
5459 } else if (myCandle.IsViolinScaled() && (allMaxContent > 0))
5461 if (myCandle.IsCandleScaled() && (allMaxIntegral > 0))
5463
5464 myCandle.SetAxisPosition(binPosY+binWidth/2. + offset);
5465 myCandle.SetCandleWidth(candleWidth*binWidth);
5466 myCandle.SetHistoWidth(histoWidth*binWidth);
5467 myCandle.SetHistogram(hproj);
5468 myCandle.Paint();
5469 }
5470 }
5471 }
5472 delete hproj;
5473}
5474
5475
5476
5477////////////////////////////////////////////////////////////////////////////////
5478/// Returns the rendering regions for an axis to use in the COL2 option
5479///
5480/// The algorithm analyses the size of the axis compared to the size of
5481/// the rendering region. It figures out the boundaries to use for each color
5482/// of the rendering region. Only one axis is computed here.
5483///
5484/// This allows for a single computation of the boundaries before iterating
5485/// through all of the bins.
5486///
5487/// \param pAxis the axis to consider
5488/// \param nPixels the number of pixels to render axis into
5489/// \param isLog whether the axis is log scale
5490
5491std::vector<THistRenderingRegion>
5493{
5494 std::vector<THistRenderingRegion> regions;
5495
5496 enum STRATEGY { Bins, Pixels } strategy;
5497
5498 Int_t nBins = (pAxis->GetLast() - pAxis->GetFirst() + 1);
5499
5500 if (nBins >= nPixels) {
5501 // more bins than pixels... we should loop over pixels and sample
5502 strategy = Pixels;
5503 } else {
5504 // fewer bins than pixels... we should loop over bins
5505 strategy = Bins;
5506 }
5507
5508 if (isLog) {
5509
5510 Double_t xMin = pAxis->GetBinLowEdge(pAxis->GetFirst());
5511 Int_t binOffset=0;
5512 while (xMin <= 0 && ((pAxis->GetFirst()+binOffset) != pAxis->GetLast()) ) {
5513 binOffset++;
5514 xMin = pAxis->GetBinLowEdge(pAxis->GetFirst()+binOffset);
5515 }
5516 if (xMin <= 0) {
5517 // this should cause an error if we have
5518 return regions;
5519 }
5520 Double_t xMax = pAxis->GetBinUpEdge(pAxis->GetLast());
5521
5522 if (strategy == Bins) {
5523 // logarithmic plot. we find the pixel for the bin
5524 // pixel = eta * log10(V) - alpha
5525 // where eta = nPixels/(log10(Vmax)-log10(Vmin))
5526 // and alpha = nPixels*log10(Vmin)/(log10(Vmax)-log10(Vmin))
5527 // and V is axis value
5529 Double_t offset = -1.0 * eta * TMath::Log10(xMin);
5530
5531 for (Int_t bin=pAxis->GetFirst()+binOffset; bin<=pAxis->GetLast(); bin++) {
5532
5533 // linear plot. we simply need to find the appropriate bin
5534 // for the
5535 Double_t xLowValue = pAxis->GetBinLowEdge(bin);
5536 Double_t xUpValue = pAxis->GetBinUpEdge(bin);
5539 THistRenderingRegion region = {std::make_pair(xPx0, xPx1),
5540 std::make_pair(bin, bin+1)};
5541 regions.push_back(region);
5542 }
5543
5544 } else {
5545
5546 // loop over pixels
5547
5549
5550 for (Int_t pixelIndex=0; pixelIndex<(nPixels-1); pixelIndex++) {
5551 // linear plot
5552 Int_t binLow = pAxis->FindBin(xMin*TMath::Power(10.0, beta*pixelIndex));
5553 Int_t binHigh = pAxis->FindBin(xMin*TMath::Power(10.0, beta*(pixelIndex+1)));
5554 THistRenderingRegion region = { std::make_pair(pixelIndex, pixelIndex+1),
5555 std::make_pair(binLow, binHigh)};
5556 regions.push_back(region);
5557 }
5558 }
5559 } else {
5560 // standard linear plot
5561
5562 if (strategy == Bins) {
5563 // loop over bins
5564 for (Int_t bin=pAxis->GetFirst(); bin<=pAxis->GetLast(); bin++) {
5565
5566 // linear plot. we simply need to find the appropriate bin
5567 // for the
5568 Int_t xPx0 = ((bin - pAxis->GetFirst()) * nPixels)/nBins;
5569 Int_t xPx1 = xPx0 + nPixels/nBins;
5570
5571 // make sure we don't compute beyond our bounds
5572 if (xPx1>= nPixels) xPx1 = nPixels-1;
5573
5574 THistRenderingRegion region = {std::make_pair(xPx0, xPx1),
5575 std::make_pair(bin, bin+1)};
5576 regions.push_back(region);
5577 }
5578 } else {
5579 // loop over pixels
5581 // linear plot
5582 Int_t binLow = (nBins*pixelIndex)/nPixels + pAxis->GetFirst();
5583 Int_t binHigh = binLow + nBins/nPixels;
5584 THistRenderingRegion region = { std::make_pair(pixelIndex, pixelIndex+1),
5585 std::make_pair(binLow, binHigh)};
5586 regions.push_back(region);
5587 }
5588 }
5589 }
5590
5591 return regions;
5592}
5593
5594////////////////////////////////////////////////////////////////////////////////
5595/// [Rendering scheme for the COL2 and COLZ2 options] (\ref HP14)
5596
5598{
5599
5600 if (Hoption.System != kCARTESIAN) {
5601 Error("THistPainter::PaintColorLevelsFast(Option_t*)",
5602 "Only cartesian coordinates supported by 'COL2' option. Using 'COL' option instead.");
5603 PaintColorLevels(nullptr);
5604 return;
5605 }
5606
5607 Double_t z;
5608
5609 // Use existing max or min values. If either is already set
5610 // the appropriate value to use.
5611 Double_t zmin = fH->GetMinimumStored();
5612 Double_t zmax = fH->GetMaximumStored();
5613 Double_t originalZMin = zmin;
5614 Double_t originalZMax = zmax;
5615 if ((zmin == -1111) && (zmax == -1111)) {
5616 fH->GetMinimumAndMaximum(zmin, zmax);
5617 fH->SetMinimum(zmin);
5618 fH->SetMaximum(zmax);
5619 } else if (zmin == -1111) {
5620 zmin = fH->GetMinimum();
5621 fH->SetMinimum(zmin);
5622 } else if (zmax == -1111) {
5623 zmax = fH->GetMaximum();
5624 fH->SetMaximum(zmax);
5625 }
5626
5627 Double_t dz = zmax - zmin;
5628 if (dz <= 0) { // Histogram filled with a constant value
5629 zmax += 0.1*TMath::Abs(zmax);
5630 zmin -= 0.1*TMath::Abs(zmin);
5631 dz = zmax - zmin;
5632 }
5633
5634 if (Hoption.Logz) {
5635 if (zmin > 0) {
5636 zmin = TMath::Log10(zmin);
5637 zmax = TMath::Log10(zmax);
5638 dz = zmax - zmin;
5639 } else {
5640 Error("THistPainter::PaintColorLevelsFast(Option_t*)",
5641 "Cannot plot logz because bin content is less than 0.");
5642 return;
5643 }
5644 }
5645
5646 // Initialize the levels on the Z axis
5647 Int_t ndiv = fH->GetContour();
5648 if (ndiv == 0 ) {
5649 ndiv = gStyle->GetNumberContours();
5650 fH->SetContour(ndiv);
5651 }
5652 std::vector<Double_t> colorBounds(ndiv);
5653 std::vector<Double_t> contours(ndiv, 0);
5654 if (!fH->TestBit(TH1::kUserContour)) {
5655 fH->SetContour(ndiv);
5656 } else {
5657 fH->GetContour(contours.data());
5658 }
5659
5660 Double_t step = 1.0/ndiv;
5661 for (Int_t i=0; i<ndiv; ++i) {
5662 colorBounds[i] = step*i;
5663 }
5664
5665 auto pFrame = gPad->GetFrame();
5666 Int_t px0 = gPad->XtoPixel(pFrame->GetX1());
5667 Int_t px1 = gPad->XtoPixel(pFrame->GetX2());
5668 Int_t py0 = gPad->YtoPixel(pFrame->GetY1());
5669 Int_t py1 = gPad->YtoPixel(pFrame->GetY2());
5670 Int_t nXPixels = px1-px0;
5671 Int_t nYPixels = py0-py1; // y=0 is at the top of the screen
5672
5673 std::vector<Double_t> buffer(nXPixels*nYPixels, 0);
5674
5677 if (xRegions.empty() || yRegions.empty()) {
5678 Error("THistPainter::PaintColorLevelFast(Option_t*)",
5679 "Encountered error while computing rendering regions.");
5680 return;
5681 }
5682
5685 Double_t minValue = 1.;
5686 Double_t maxValue = 0.;
5687 for (auto& yRegion : yRegions) {
5688 for (auto& xRegion : xRegions ) {
5689
5690 const auto& xBinRange = xRegion.fBinRange;
5691 const auto& yBinRange = yRegion.fBinRange;
5692
5693 // sample the range
5694 z = fH->GetBinContent(xBinRange.second-1, yBinRange.second-1);
5695
5696 if (Hoption.Logz) {
5697 if (z > 0) z = TMath::Log10(z);
5698 else z = zmin;
5699 }
5700
5701 // obey the user's max and min values if they were set
5702 if (z > zmax) z = zmax;
5703 if (z < zmin) z = zmin;
5704
5706 // contours are absolute values
5707 auto index = TMath::BinarySearch(contours.size(), contours.data(), z);
5708 z = colorBounds[index];
5709 } else {
5710 Int_t index = 0;
5711 if (dz != 0) {
5712 index = 0.001 + ((z - zmin)/dz)*ndiv;
5713 }
5714
5715 if (index == static_cast<Int_t>(colorBounds.size())) {
5716 index--;
5717 }
5718
5719 // Do a little bookkeeping to use later for getting libAfterImage to produce
5720 // the correct colors
5721 if (index == 0) {
5722 minExists = kTRUE;
5723 } else if (index == static_cast<Int_t>(colorBounds.size()-1)) {
5724 maxExists = kTRUE;
5725 }
5726
5727 z = colorBounds[index];
5728
5729 if (z < minValue) {
5730 minValue = z;
5731 }
5732 if (z > maxValue) {
5733 maxValue = z;
5734 }
5735 }
5736
5737 // fill in the actual pixels
5738 const auto& xPixelRange = xRegion.fPixelRange;
5739 const auto& yPixelRange = yRegion.fPixelRange;
5740 for (Int_t xPx = xPixelRange.first; xPx <= xPixelRange.second; ++xPx) {
5741 for (Int_t yPx = yPixelRange.first; yPx <= yPixelRange.second; ++yPx) {
5743 buffer[pixel] = z;
5744 }
5745 }
5746 } // end px loop
5747 } // end py loop
5748
5749 // This is a bit of a hack to ensure that we span the entire color range and
5750 // don't screw up the colors for a sparse histogram. No one will notice that I set a
5751 // single pixel on the edge of the image to a different color. This is even more
5752 // true because the chosen pixels will be covered by the axis.
5753 if (minValue != maxValue) {
5754 if ( !minExists) {
5755 buffer.front() = 0;
5756 }
5757
5758 if ( !maxExists) {
5759 buffer[buffer.size()-nXPixels] = 0.95;
5760 }
5761 }
5762
5763 // Generate the TImage
5766 pImage->SetImageQuality(TAttImage::kImgBest);
5767 pImage->SetImage(buffer.data(), nXPixels, nYPixels, pPalette);
5768 delete pPalette;
5769
5770 Window_t wid = static_cast<Window_t>(gVirtualX->GetWindowID(gPad->GetPixmapID()));
5771 pImage->PaintImage(wid, px0, py1, 0, 0, nXPixels, nYPixels);
5772 delete pImage;
5773
5775
5776 // Reset the maximum and minimum values to their original values
5777 // when this function was called. If we don't do this, an initial
5778 // value of -1111 will be replaced with the true max or min values.
5781}
5782
5783////////////////////////////////////////////////////////////////////////////////
5784/// [Control function to draw a 2D histogram as a color plot.](\ref HP14)
5785
5787{
5788 Double_t z, e, zc, xk, xstep, yk, ystep, xlow, xup, ylow, yup;
5789
5790 Double_t zmin = fH->GetMinimum();
5791 Double_t zmax = fH->GetMaximum();
5792
5793 Double_t dz = zmax - zmin;
5794 if (dz <= 0) { // Histogram filled with a constant value
5795 zmax += 0.1*TMath::Abs(zmax);
5796 zmin -= 0.1*TMath::Abs(zmin);
5797 dz = zmax - zmin;
5798 }
5799
5800 // In case of option SAME, zmin and zmax values are taken from the
5801 // first plotted 2D histogram.
5802 if (Hoption.Same > 0 && Hoption.Same < 10) {
5803 TH2 *h2;
5804 TIter next(gPad->GetListOfPrimitives());
5805 while ((h2 = (TH2 *)next())) {
5806 if (!h2->InheritsFrom(TH2::Class())) continue;
5807 zmin = h2->GetMinimum();
5808 zmax = h2->GetMaximum();
5809 fH->SetMinimum(zmin);
5810 fH->SetMaximum(zmax);
5811 if (Hoption.Logz) {
5812 if (zmin <= 0) {
5813 zmin = TMath::Log10(zmax*0.001);
5814 } else {
5815 zmin = TMath::Log10(zmin);
5816 }
5817 zmax = TMath::Log10(zmax);
5818 }
5819 dz = zmax - zmin;
5820 break;
5821 }
5822 } else {
5823 if (Hoption.Logz) {
5824 if (zmin > 0) {
5825 zmin = TMath::Log10(zmin);
5826 zmax = TMath::Log10(zmax);
5827 dz = zmax - zmin;
5828 } else {
5829 return;
5830 }
5831 }
5832 }
5833
5836 fH->SetFillStyle(1001);
5837 fH->TAttFill::Modify();
5838
5839 // Initialize the levels on the Z axis
5840 Int_t ncolors = gStyle->GetNumberOfColors();
5841 Int_t ndiv = fH->GetContour();
5842 if (ndiv == 0 ) {
5843 ndiv = gStyle->GetNumberContours();
5844 fH->SetContour(ndiv);
5845 }
5846 Int_t ndivz = TMath::Abs(ndiv);
5847 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
5848 Double_t scale = (dz ? ndivz / dz : 1.0);
5849
5850 Int_t color;
5851 TProfile2D* prof2d = dynamic_cast<TProfile2D*>(fH);
5852 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
5855 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
5856 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
5857 xk = fXaxis->GetBinLowEdge(i);
5858 xstep = fXaxis->GetBinWidth(i);
5859 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
5860 z = fH->GetBinContent(bin);
5861 e = fH->GetBinError(bin);
5862 // if fH is a profile histogram do not draw empty bins
5863 if (prof2d) {
5864 const Double_t binEntries = prof2d->GetBinEntries(bin);
5865 if (binEntries == 0)
5866 continue;
5867 } else {
5868 // don't draw the empty bins for non-profile histograms
5869 // with positive content
5870 if (z == 0 && e == 0) {
5871 if (zmin >= 0 || Hoption.Logz) continue;
5872 if (Hoption.Color == 2) continue;
5873 }
5874 }
5875
5876 if (Hoption.Logz) {
5877 if (z > 0) z = TMath::Log10(z);
5878 else z = zmin;
5879 }
5880 if (z < zmin && !Hoption.Zero) continue;
5881 xup = xk + xstep;
5882 xlow = xk;
5883 if (Hoption.Logx) {
5884 if (xup > 0) xup = TMath::Log10(xup);
5885 else continue;
5886 if (xlow > 0) xlow = TMath::Log10(xlow);
5887 else continue;
5888 }
5889 yup = yk + ystep;
5890 ylow = yk;
5891 if (Hoption.Logy) {
5892 if (yup > 0) yup = TMath::Log10(yup);
5893 else continue;
5894 if (ylow > 0) ylow = TMath::Log10(ylow);
5895 else continue;
5896 }
5897 if (xup < gPad->GetUxmin()) continue;
5898 if (yup < gPad->GetUymin()) continue;
5899 if (xlow > gPad->GetUxmax()) continue;
5900 if (ylow > gPad->GetUymax()) continue;
5901 if (xlow < gPad->GetUxmin()) xlow = gPad->GetUxmin();
5902 if (ylow < gPad->GetUymin()) ylow = gPad->GetUymin();
5903 if (xup > gPad->GetUxmax()) xup = gPad->GetUxmax();
5904 if (yup > gPad->GetUymax()) yup = gPad->GetUymax();
5905
5907 zc = fH->GetContourLevelPad(0);
5908 if (z < zc) continue;
5909 color = -1;
5910 for (Int_t k=0; k<ndiv; k++) {
5911 zc = fH->GetContourLevelPad(k);
5912 if (z < zc) {
5913 continue;
5914 } else {
5915 color++;
5916 }
5917 }
5918 } else {
5919 color = Hoption.Zero ? Int_t(0.01+(std::max(z, zmin)-zmin)*scale) : Int_t(0.01+(z-zmin)*scale);
5920 }
5921
5922 Int_t theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
5923 if (theColor > ncolors-1) theColor = ncolors-1;
5925 if (Hoption.System != kPOLAR) {
5927 fH->TAttFill::Modify();
5928 gPad->PaintBox(xlow, ylow, xup, yup);
5929 } else {
5930 Double_t midx = (gPad->GetUxmin() + gPad->GetUxmax()) / 2,
5931 midy = (gPad->GetUymin() + gPad->GetUymax()) / 2,
5932 a1 = (xlow - gPad->GetUxmin()) / (gPad->GetUxmax() - gPad->GetUxmin()) * 360,
5933 a2 = (xup - gPad->GetUxmin()) / (gPad->GetUxmax() - gPad->GetUxmin()) * 360,
5934 rx = gPad->GetUxmax() - gPad->GetUxmin(),
5935 ry = gPad->GetUymax() - gPad->GetUymin(),
5936 r1 = (ylow - gPad->GetUymin()) / (gPad->GetUymax() - gPad->GetUymin()) * rx / 2,
5937 r2 = (yup - gPad->GetUymin()) / (gPad->GetUymax() - gPad->GetUymin()) * rx / 2;
5938
5939 TCrown crown(midx, midy, r1, r2, a1, a2);
5940 crown.SetYXRatio(rx > 0 ? ry / rx : 1);
5941 crown.SetFillColor(fillColor);
5942 crown.SetLineColor(fH->GetLineColor());
5943 crown.SetLineWidth(fH->GetLineWidth());
5944 crown.SetLineStyle(fH->GetLineStyle());
5945 crown.Paint();
5946 }
5947 }
5948 }
5949
5951
5954 fH->TAttFill::Modify();
5955
5956}
5957
5958////////////////////////////////////////////////////////////////////////////////
5959/// [Control function to draw a 2D histogram as a contour plot.](\ref HP16)
5960
5962{
5963
5964 Int_t i, j, count, ncontour, icol, n, lj, m, ix, jx, ljfill;
5965 Int_t itars, mode, ir[4];
5966 Double_t xsave, ysave, thesave,phisave,x[4], y[4], zc[4];
5967
5968 if (Hoption.Contour == 14) {
5969 Hoption.Surf = 12;
5970 Hoption.Axis = 1;
5971 thesave = gPad->GetTheta();
5972 phisave = gPad->GetPhi();
5973 gPad->SetPhi(0.);
5974 gPad->SetTheta(90.);
5976 gPad->SetPhi(phisave);
5977 gPad->SetTheta(thesave);
5978 TView *view = gPad->GetView();
5979 if (view) view->SetBit(kCannotRotate); //tested in ExecuteEvent
5980 PaintAxis();
5981 return;
5982 }
5983
5984 if (Hoption.Same) {
5985 // If the contour is painted on a 3d plot, the contour lines are
5986 // paint in 3d too.
5987 TObject *obj;
5988 TIter next(gPad->GetListOfPrimitives());
5989 while ((obj=next())) {
5990 if (strstr(obj->GetDrawOption(),"surf") ||
5991 strstr(obj->GetDrawOption(),"lego") ||
5992 strstr(obj->GetDrawOption(),"tri")) {
5993 Hoption.Surf = 16;
5995 return;
5996 }
5997 }
5998 }
5999
6000 if (Hoption.Contour == 15) {
6001 TGraphDelaunay2D *dt = nullptr;
6002 TGraphDelaunay *dtOld = nullptr;
6004 dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
6005 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
6006 if (!dt && !dtOld) return;
6007 if (!fGraph2DPainter)
6008 fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
6009 fGraph2DPainter->Paint(option);
6010 return;
6011 }
6012
6013 gPad->SetBit(TGraph::kClipFrame);
6014
6015 std::vector<Double_t> levels(2*kMAXCONTOUR);
6016 std::vector<Double_t> xarr(2*kMAXCONTOUR);
6017 std::vector<Double_t> yarr(2*kMAXCONTOUR);
6018 std::vector<Int_t> itarr(2*kMAXCONTOUR);
6019
6020 Int_t npmax = 0;
6021 for (i=0;i<2*kMAXCONTOUR;i++) itarr[i] = 0;
6022
6023 ncontour = fH->GetContour();
6024 if (ncontour == 0) {
6027 }
6028 if (ncontour > kMAXCONTOUR) {
6029 Warning("PaintContour", "maximum number of contours is %d, asked for %d",
6032 }
6034
6035 for (i=0;i<ncontour;i++) levels[i] = fH->GetContourLevelPad(i);
6039 if (Hoption.Contour == 13) {
6040 fH->TAttLine::Modify();
6041 }
6042
6043 std::vector<std::unique_ptr<TPolyLine>> polys;
6044 TObjArray *contours = nullptr;
6045 TList *list = nullptr;
6046 TGraph *graph = nullptr;
6047 std::vector<Int_t> np;
6048 if (Hoption.Contour == 1 || (Hoption.List && (Hoption.Contour == 11 || Hoption.Contour == 12 || Hoption.Contour == 13))) {
6049 np.resize(ncontour);
6050 for (i=0;i<ncontour;i++)
6051 np[i] = 0;
6052 for (i=0;i<ncontour;i++)
6053 polys.emplace_back(std::make_unique<TPolyLine>(100));
6054 if (Hoption.List == 1) {
6055 contours = (TObjArray*)gROOT->GetListOfSpecials()->FindObject("contours");
6056 if (contours) {
6057 gROOT->GetListOfSpecials()->Remove(contours);
6058 count = contours->GetSize();
6059 for (i=0;i<count;i++) {
6060 list = (TList*)contours->At(i);
6061 if (list) list->Delete();
6062 }
6063 contours->Delete();
6064 delete contours;
6065 }
6067 contours->SetName("contours");
6068 gROOT->GetListOfSpecials()->Add(contours);
6069 for (i=0;i<ncontour;i++) {
6070 list = new TList();
6071 contours->Add(list);
6072 }
6073 }
6074 }
6076 Int_t ncolors = gStyle->GetNumberOfColors();
6078
6079 Int_t k,ipoly;
6080 for (j=Hparam.yfirst; j<Hparam.ylast; j++) {
6081 y[0] = fYaxis->GetBinCenter(j);
6082 y[1] = y[0];
6083 y[2] = fYaxis->GetBinCenter(j+1);
6084 y[3] = y[2];
6085 for (i=Hparam.xfirst; i<Hparam.xlast; i++) {
6086 zc[0] = fH->GetBinContent(i, j);
6087 zc[1] = fH->GetBinContent(i+1, j);
6088 zc[2] = fH->GetBinContent(i+1, j+1);
6089 zc[3] = fH->GetBinContent(i, j+1);
6090 if (!IsInside(fXaxis->GetBinCenter(i),fYaxis->GetBinCenter(j))) continue;
6091 if (Hoption.Logz) {
6092 if (zc[0] > 0) zc[0] = TMath::Log10(zc[0]);
6093 else zc[0] = Hparam.zmin;
6094 if (zc[1] > 0) zc[1] = TMath::Log10(zc[1]);
6095 else zc[1] = Hparam.zmin;
6096 if (zc[2] > 0) zc[2] = TMath::Log10(zc[2]);
6097 else zc[2] = Hparam.zmin;
6098 if (zc[3] > 0) zc[3] = TMath::Log10(zc[3]);
6099 else zc[3] = Hparam.zmin;
6100 }
6101 for (k=0;k<4;k++) {
6102 ir[k] = TMath::BinarySearch(ncontour, levels.data(), zc[k]);
6103 }
6104 if (ir[0] != ir[1] || ir[1] != ir[2] || ir[2] != ir[3] || ir[3] != ir[0]) {
6105 x[0] = fXaxis->GetBinCenter(i);
6106 x[3] = x[0];
6107 x[1] = fXaxis->GetBinCenter(i+1);
6108 x[2] = x[1];
6109 if (zc[0] <= zc[1]) n = 0; else n = 1;
6110 if (zc[2] <= zc[3]) m = 2; else m = 3;
6111 if (zc[n] > zc[m]) n = m;
6112 n++;
6113 lj=1;
6114 for (ix=1;ix<=4;ix++) {
6115 m = n%4 + 1;
6116 ljfill = PaintContourLine(zc[n-1],ir[n-1],x[n-1],y[n-1],zc[m-1],
6117 ir[m-1],x[m-1],y[m-1], xarr.data()+lj-1,yarr.data()+lj-1,itarr.data()+lj-1, levels.data());
6118 lj += 2*ljfill;
6119 n = m;
6120 }
6121
6122 if (zc[0] <= zc[1]) n = 0; else n = 1;
6123 if (zc[2] <= zc[3]) m = 2; else m = 3;
6124 if (zc[n] > zc[m]) n = m;
6125 n++;
6126 lj=2;
6127 for (ix=1;ix<=4;ix++) {
6128 if (n == 1) m = 4;
6129 else m = n-1;
6130 ljfill = PaintContourLine(zc[n-1],ir[n-1],x[n-1],y[n-1],zc[m-1],
6131 ir[m-1],x[m-1],y[m-1],xarr.data()+lj-1,yarr.data()+lj-1,itarr.data()+lj-1, levels.data());
6132 lj += 2*ljfill;
6133 n = m;
6134 }
6135
6136 // Re-order endpoints
6137
6138 count = 0;
6139 for (ix=1; ix<=lj-5; ix +=2) {
6140 //count = 0;
6141 while (itarr[ix-1] != itarr[ix]) {
6142 xsave = xarr[ix];
6143 ysave = yarr[ix];
6144 itars = itarr[ix];
6145 for (jx=ix; jx<=lj-5; jx +=2) {
6146 xarr[jx] = xarr[jx+2];
6147 yarr[jx] = yarr[jx+2];
6148 itarr[jx] = itarr[jx+2];
6149 }
6150 xarr[lj-3] = xsave;
6151 yarr[lj-3] = ysave;
6152 itarr[lj-3] = itars;
6153 if (count > 100) break;
6154 count++;
6155 }
6156 }
6157
6158 if (count > 100) continue;
6159 for (ix=1; ix<=lj-2; ix +=2) {
6160 theColor = Int_t((itarr[ix-1]+0.99)*Float_t(ncolors)/Float_t(ndivz));
6162 if (Hoption.Contour == 11) {
6164 }
6165 if (Hoption.Contour == 12) {
6166 mode = icol%5;
6167 if (mode == 0) mode = 5;
6169 }
6170 if (Hoption.Contour != 1) {
6171 fH->TAttLine::Modify();
6172 gPad->PaintPolyLine(2,xarr.data()+ix-1,yarr.data()+ix-1);
6173 if ((Hoption.Contour != 11 && Hoption.Contour != 12 && Hoption.Contour != 13) || !Hoption.List)
6174 continue;
6175 }
6176
6177 ipoly = itarr[ix-1];
6178 if (ipoly >=0 && ipoly <ncontour) {
6179 polys[ipoly]->SetPoint(np[ipoly] ,xarr[ix-1],yarr[ix-1]);
6180 polys[ipoly]->SetPoint(np[ipoly]+1,xarr[ix], yarr[ix]);
6181 np[ipoly] += 2;
6182 if (npmax < np[ipoly]) npmax = np[ipoly];
6183 }
6184 }
6185 } // end of if (ir[0]
6186 } //end of for (i
6187 } //end of for (j
6188
6190 std::vector<Double_t> xp, yp;
6192 Int_t istart;
6193 Int_t first = ncontour;
6194 std::vector<Int_t> polysort;
6196 if (Hoption.Contour != 1) {
6197 if (!Hoption.List || (Hoption.Contour != 11 && Hoption.Contour != 12 && Hoption.Contour != 13))
6198 goto theEND;
6199 }
6200
6201 //The 2 points line generated above are now sorted/merged to generate
6202 //a list of consecutive points.
6203 // If the option "List" has been specified, the list of points is saved
6204 // in the form of TGraph objects in the ROOT list of special objects.
6205 xmin = gPad->GetUxmin();
6206 ymin = gPad->GetUymin();
6207 xp.resize(2*npmax);
6208 yp.resize(2*npmax);
6209 polysort.resize(ncontour);
6210 //find first positive contour
6211 for (ipoly=0;ipoly<ncontour;ipoly++) {
6212 if (levels[ipoly] >= 0) {first = ipoly; break;}
6213 }
6214 //store negative contours from 0 to minimum, then all positive contours
6215 k = 0;
6216 for (ipoly=first-1;ipoly>=0;ipoly--) {polysort[k] = ipoly; k++;}
6217 for (ipoly=first;ipoly<ncontour;ipoly++) {polysort[k] = ipoly; k++;}
6218 // if Contour==1 we can now draw sorted contours, otherwise (11,12,13) just store
6219 contListNb = 0;
6220 if (Hoption.Contour == 1) fH->SetFillStyle(1001);
6221 for (k=0;k<ncontour;k++) {
6222 ipoly = polysort[k];
6223 if (Hoption.List) list = (TList*)contours->At(contListNb);
6224 contListNb++;
6225 if (np[ipoly] == 0)
6226 continue;
6227 Double_t *xx = polys[ipoly]->GetX();
6228 Double_t *yy = polys[ipoly]->GetY();
6229 istart = 0;
6230 while (true) {
6231 iminus = npmax;
6232 iplus = iminus+1;
6233 xp[iminus]= xx[istart]; yp[iminus] = yy[istart];
6234 xp[iplus] = xx[istart+1]; yp[iplus] = yy[istart+1];
6235 xx[istart] = xmin; yy[istart] = ymin;
6236 xx[istart+1] = xmin; yy[istart+1] = ymin;
6237 while (true) {
6238 nadd = 0;
6239 for (i=2;i<np[ipoly];i+=2) {
6240 if ((iplus < 2*npmax-1) && (xx[i] == xp[iplus]) && (yy[i] == yp[iplus])) {
6241 iplus++;
6242 xp[iplus] = xx[i+1]; yp[iplus] = yy[i+1];
6243 xx[i] = xmin; yy[i] = ymin;
6244 xx[i+1] = xmin; yy[i+1] = ymin;
6245 nadd++;
6246 }
6247 if ((iminus > 0) && (xx[i+1] == xp[iminus]) && (yy[i+1] == yp[iminus])) {
6248 iminus--;
6249 xp[iminus] = xx[i]; yp[iminus] = yy[i];
6250 xx[i] = xmin; yy[i] = ymin;
6251 xx[i+1] = xmin; yy[i+1] = ymin;
6252 nadd++;
6253 }
6254 }
6255 if (nadd == 0) break;
6256 }
6257 theColor = Int_t((ipoly+0.99)*Float_t(ncolors)/Float_t(ndivz));
6259 if (Hoption.Contour == 1) {
6260 if (ndivz > 1) fH->SetFillColor(icol);
6261 fH->TAttFill::Modify();
6262 gPad->PaintFillArea(iplus-iminus+1,xp.data()+iminus,yp.data()+iminus);
6263 }
6264 if (Hoption.List) {
6265 graph = new TGraph(iplus-iminus+1,xp.data()+iminus,yp.data()+iminus);
6266 if (Hoption.Contour == 1)
6267 graph->SetFillColor(icol);
6268 else if (Hoption.Contour == 11)
6269 graph->SetLineColor(icol);
6270 else if (Hoption.Contour == 12) {
6271 mode = icol%5;
6272 if (mode == 0) mode = 5;
6273 graph->SetLineStyle(mode);
6274 }
6275 graph->SetLineWidth(fH->GetLineWidth());
6276 list->Add(graph);
6277 }
6278 //check if more points are left
6279 istart = 0;
6280 for (i=2;i<np[ipoly];i+=2) {
6281 if (xx[i] != xmin && yy[i] != ymin) {
6282 istart = i;
6283 break;
6284 }
6285 }
6286 if (istart == 0) break;
6287 }
6288 }
6289
6290theEND:
6291 gPad->ResetBit(TGraph::kClipFrame);
6296}
6297
6298////////////////////////////////////////////////////////////////////////////////
6299/// Fill the matrix `xarr` and `yarr` for Contour Plot.
6300
6304{
6305
6306 Bool_t vert;
6308 Int_t n, i, icount;
6309
6310 if (x1 == x2) {
6311 vert = kTRUE;
6312 tlen = y2 - y1;
6313 } else {
6314 vert = kFALSE;
6315 tlen = x2 - x1;
6316 }
6317
6318 n = icont1 +1;
6319 tdif = elev2 - elev1;
6320 i = 0;
6321 icount = 0;
6322 while (n <= icont2 && i <= kMAXCONTOUR/2 -3) {
6323 //elev = fH->GetContourLevel(n);
6324 elev = levels[n];
6325 diff = elev - elev1;
6326 pdif = diff/tdif;
6327 xlen = tlen*pdif;
6328 if (vert) {
6329 if (Hoption.Logx)
6330 xarr[i] = TMath::Log10(x1);
6331 else
6332 xarr[i] = x1;
6333 if (Hoption.Logy)
6334 yarr[i] = TMath::Log10(y1 + xlen);
6335 else
6336 yarr[i] = y1 + xlen;
6337 } else {
6338 if (Hoption.Logx)
6339 xarr[i] = TMath::Log10(x1 + xlen);
6340 else
6341 xarr[i] = x1 + xlen;
6342 if (Hoption.Logy)
6343 yarr[i] = TMath::Log10(y1);
6344 else
6345 yarr[i] = y1;
6346 }
6347 itarr[i] = n;
6348 icount++;
6349 i +=2;
6350 n++;
6351 }
6352 return icount;
6353}
6354
6355////////////////////////////////////////////////////////////////////////////////
6356/// [Draw 1D histograms error bars.](\ref HP09)
6357
6359{
6360
6361 // On iOS, we do not highlight histogram, if it's not picked at the moment
6362 // (but part of histogram (axis or pavestat) was picked, that's why this code
6363 // is called at all. This conditional statement never executes on non-iOS platform.
6364 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH) return;
6365
6366 const Int_t kBASEMARKER=8;
6367 Double_t xp, yp, ex1, ex2, ey1, ey2;
6368 Double_t delta;
6370 Double_t xi1, xi2, xi3, xi4, yi1, yi2, yi3, yi4;
6372 Double_t logxmin = 0;
6373 Double_t logymin = 0;
6374 Double_t offset = 0.;
6375 Double_t width = 0.;
6376 Int_t i, k, npoints, first, last, fixbin;
6377 Int_t if1 = 0;
6378 Int_t if2 = 0;
6381 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};
6382 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};
6383
6384 std::vector<Double_t> xline, yline;
6386 if (Hoption.Error >= 40) {Hoption.Error -=40; option0 = 1;}
6387 if (Int_t(Hoption.Error/10) == 2) {optionEX0 = 1; Hoption.Error -= 10;}
6388 if (Hoption.Error == 31) {optionEX0 = 1; Hoption.Error = 1;}
6389 if (Hoption.Error == 11) option1 = 1;
6390 if (Hoption.Error == 12) option2 = 1;
6391 if (Hoption.Error == 13) option3 = 1;
6392 if (Hoption.Error == 14) {option4 = 1; option3 = 1;}
6393 if (Hoption.Error == 15) {optionI0 = 1; option3 = 1;}
6394 if (Hoption.Error == 16) {optionI0 = 1; option4 = 1; option3 = 1;}
6395 if (option2+option3 == 0) optionE = 1;
6396 if (Hoption.Error == 0) optionE = 0;
6397 if (fXaxis->GetXbins()->fN) fixbin = 0;
6398 else fixbin = 1;
6399
6400 offset = fH->GetBarOffset();
6401 width = fH->GetBarWidth();
6402
6404 if (optionEX0) {
6405 xerror = 0;
6406 } else {
6407 xerror = gStyle->GetErrorX();
6408 }
6410 if (errormarker == 1) symbolsize = 0.01;
6412 if (errormarker >= 20 && errormarker <= 49) {
6413 sbasex *= cxx[errormarker-20];
6414 sbasey *= cyy[errormarker-20];
6415 }
6416 // set the graphics attributes
6417
6418 fH->TAttLine::Modify();
6419 fH->TAttFill::Modify();
6420 fH->TAttMarker::Modify();
6421
6422 // set the first and last bin
6423
6424 Double_t factor = Hparam.factor;
6425 first = Hparam.xfirst;
6426 last = Hparam.xlast;
6427 npoints = last - first +1;
6428 xmin = gPad->GetUxmin();
6429 xmax = gPad->GetUxmax();
6430 ymin = gPad->GetUymin();
6431 ymax = gPad->GetUymax();
6432
6433
6434 if (option3) {
6435 xline.resize(2*npoints);
6436 yline.resize(2*npoints);
6437 if ((npoints > 0) && (xline.empty() || yline.empty())) {
6438 Error("PaintErrors", "too many points, out of memory");
6439 return;
6440 }
6441 if1 = 1;
6442 if2 = 2*npoints;
6443 }
6444
6445 // compute the offset of the error bars due to the symbol size
6446 s2x = gPad->PixeltoX(Int_t(0.5*sbasex)) - gPad->PixeltoX(0);
6447 s2y =-gPad->PixeltoY(Int_t(0.5*sbasey)) + gPad->PixeltoY(0);
6448
6449 // compute size of the lines at the end of the error bars
6451 bxsize = gPad->PixeltoX(dxend) - gPad->PixeltoX(0);
6452 bysize =-gPad->PixeltoY(dxend) + gPad->PixeltoY(0);
6453
6454
6455 if (fixbin) {
6457 else xp = Hparam.xmin + 0.5*Hparam.xbinsize;
6458 } else {
6459 delta = fH->GetBinWidth(first);
6460 xp = fH->GetBinLowEdge(first) + 0.5*delta;
6461 }
6462
6463 // if errormarker = 0 or symbolsize = 0. no symbol is drawn
6466
6467 // ---------------------- Loop over the points---------------------
6468 for (k=first; k<=last; k++) {
6469
6470 // get the data
6471 // xp = X position of the current point
6472 // yp = Y position of the current point
6473 // ex1 = Low X error
6474 // ex2 = Up X error
6475 // ey1 = Low Y error
6476 // ey2 = Up Y error
6477 // (xi,yi) = Error bars coordinates
6478
6479 // apply offset on errors for bar histograms
6480 Double_t xminTmp = gPad->XtoPad(fXaxis->GetBinLowEdge(k));
6481 Double_t xmaxTmp = gPad->XtoPad(fXaxis->GetBinUpEdge(k));
6482 if (Hoption.Logx) {
6485 }
6488 xmaxTmp = xminTmp + w;
6489 xp = (xminTmp+xmaxTmp)/2.;
6490
6491 if (Hoption.Logx) {
6492 if (xp <= 0) goto L30;
6493 if (xp < logxmin) goto L30;
6494 if (xp > TMath::Power(10,xmax)) break;
6495 } else {
6496 if (xp < xmin) goto L30;
6497 if (xp > xmax) break;
6498 }
6499 yp = factor*fH->GetBinContent(k);
6500 if (optionI0 && yp==0) goto L30;
6501 if (fixbin) {
6503 } else {
6504 delta = fH->GetBinWidth(k);
6505 ex1 = xerror*delta;
6506 }
6507 if (fH->GetBinErrorOption() == TH1::kNormal) {
6508 ey1 = factor*fH->GetBinError(k);
6509 ey2 = ey1;
6510 } else {
6511 ey1 = factor*fH->GetBinErrorLow(k);
6512 ey2 = factor*fH->GetBinErrorUp(k);
6513 }
6514 ex2 = ex1;
6515
6516 xi4 = xp;
6517 xi3 = xp;
6518 xi2 = xp + ex2;
6519 xi1 = xp - ex1;
6520
6521 yi1 = yp;
6522 yi2 = yp;
6523 yi3 = yp - ey1;
6524 yi4 = yp + ey2;
6525
6526 // take the LOG if necessary
6527 if (Hoption.Logx) {
6532 }
6533 if (Hoption.Logy) {
6538 }
6539
6540 // test if error bars are not outside the limits
6541 // otherwise they are truncated
6542
6547
6548 // test if the marker is on the frame limits. If "Yes", the
6549 // marker will not be drawn and the error bars will be readjusted.
6550
6551 drawmarker = kTRUE;
6552 if (!option0 && !option3) {
6553 if (Hoption.Logy && yp < logymin) goto L30;
6554 if (yi1 < ymin || yi1 > ymax) goto L30;
6555 if (Hoption.Error != 0 && yp == 0 && ey1 <= 0) drawmarker = kFALSE;
6556 }
6558
6559 // draw the error rectangles
6560 if (option2) {
6561 if (yi3 >= ymax) goto L30;
6562 if (yi4 <= ymin) goto L30;
6563 gPad->PaintBox(xi1,yi3,xi2,yi4);
6564 }
6565
6566 // keep points for fill area drawing
6567 if (option3) {
6568 xline[if1-1] = xi3;
6569 xline[if2-1] = xi3;
6570 yline[if1-1] = yi4;
6571 yline[if2-1] = yi3;
6572 if1++;
6573 if2--;
6574 }
6575
6576 // draw the error bars
6577 if (Hoption.Logy && yp < logymin) drawmarker = kFALSE;
6578 if (optionE && drawmarker) {
6579 if ((yi3 < yi1 - s2y) && (yi3 < ymax)) gPad->PaintLine(xi3,yi3,xi4,TMath::Min(yi1 - s2y,ymax));
6580 if ((yi1 + s2y < yi4) && (yi4 > ymin)) gPad->PaintLine(xi3,TMath::Max(yi1 + s2y, ymin),xi4,yi4);
6581 // don't duplicate the horizontal line
6582 if (Hoption.Hist != 2) {
6584 if (xi1 < xi3 - s2x) gPad->PaintLine(xi1,yi1,xi3 - s2x,yi2);
6585 if (xi3 + s2x < xi2) gPad->PaintLine(xi3 + s2x,yi1,xi2,yi2);
6586 }
6587 }
6588 }
6589 if (optionE && !drawmarker && (ey1 != 0 || ey2 !=0)) {
6590 if ((yi3 < yi1) && (yi3 < ymax)) gPad->PaintLine(xi3,yi3,xi4,TMath::Min(yi1,ymax));
6591 if ((yi1 < yi4) && (yi4 > ymin)) gPad->PaintLine(xi3,TMath::Max(yi1,ymin),xi4,yi4);
6592 // don't duplicate the horizontal line
6593 if (Hoption.Hist != 2) {
6595 if (xi1 < xi3) gPad->PaintLine(xi1,yi1,xi3,yi2);
6596 if (xi3 < xi2) gPad->PaintLine(xi3,yi1,xi2,yi2);
6597 }
6598 }
6599 }
6600
6601 // draw line at the end of the error bars
6602
6603 if (option1 && drawmarker) {
6604
6605 if (yi3 < yi1-s2y && yi3 < ymax && yi3 > ymin) gPad->PaintLine(xi3 - bxsize, yi3 , xi3 + bxsize, yi3);
6606 if (yi4 > yi1+s2y && yi4 < ymax && yi4 > ymin) gPad->PaintLine(xi3 - bxsize, yi4 , xi3 + bxsize, yi4);
6608 if (xi1 < xi3-s2x) gPad->PaintLine(xi1 , yi1 - bysize, xi1 , yi1 + bysize);
6609 if (xi2 > xi3+s2x) gPad->PaintLine(xi2 , yi1 - bysize, xi2 , yi1 + bysize);
6610 }
6611 }
6612
6613 // draw the marker
6614
6615 if (drawmarker) gPad->PaintPolyMarker(1, &xi3, &yi1);
6616
6617L30:
6618 if (fixbin) xp += Hparam.xbinsize;
6619 else {
6620 if (k < last) {
6621 delta = fH->GetBinWidth(k+1);
6622 xp = fH->GetBinLowEdge(k+1) + 0.5*delta;
6623 }
6624 }
6625 } //end of for loop
6626
6627 // draw the filled area
6628
6629 if (option3) {
6630 TGraph graph;
6631 graph.SetLineStyle(fH->GetLineStyle());
6632 graph.SetLineColor(fH->GetLineColor());
6633 graph.SetLineWidth(fH->GetLineWidth());
6634 graph.SetFillStyle(fH->GetFillStyle());
6635 graph.SetFillColor(fH->GetFillColor());
6636 Int_t logx = gPad->GetLogx();
6637 Int_t logy = gPad->GetLogy();
6638 gPad->SetLogx(0);
6639 gPad->SetLogy(0);
6640
6641 // In some cases the number of points in the fill area is smaller than
6642 // 2*npoints. In such cases the array xline and yline must be arranged
6643 // before being plotted. The next loop does that.
6644 if (if2 > npoints) {
6645 for (i=1; i<if1; i++) {
6646 xline[if1-2+i] = xline[if2-1+i];
6647 yline[if1-2+i] = yline[if2-1+i];
6648 }
6649 npoints = if1-1;
6650 }
6651 if (option4) graph.PaintGraph(2*npoints,xline.data(),yline.data(),"FC");
6652 else graph.PaintGraph(2*npoints,xline.data(),yline.data(),"F");
6653 gPad->SetLogx(logx);
6654 gPad->SetLogy(logy);
6655 }
6656}
6657
6658////////////////////////////////////////////////////////////////////////////////
6659/// Draw 2D histograms errors.
6660
6662{
6663
6664 fH->TAttMarker::Modify();
6665 fH->TAttLine::Modify();
6666
6667 // Define the 3D view
6668 fXbuf[0] = Hparam.xmin;
6669 fYbuf[0] = Hparam.xmax;
6670 fXbuf[1] = Hparam.ymin;
6671 fYbuf[1] = Hparam.ymax;
6672 fXbuf[2] = Hparam.zmin;
6673 fYbuf[2] = Hparam.zmax*(1. + gStyle->GetHistTopMargin());
6674 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
6675 TView *view = gPad ? gPad->GetView() : nullptr;
6676 if (!view) {
6677 Error("Paint2DErrors", "no TView in current pad");
6678 return;
6679 }
6680 Double_t thedeg = 90 - gPad->GetTheta();
6681 Double_t phideg = -90 - gPad->GetPhi();
6682 Double_t psideg = view->GetPsi();
6683 Int_t irep;
6684 view->SetView(phideg, thedeg, psideg, irep);
6685
6686 // Set color/style for back box
6687 fLego->SetFillStyle(gPad->GetFrameFillStyle());
6688 fLego->SetFillColor(gPad->GetFrameFillColor());
6689 fLego->TAttFill::Modify();
6690 Int_t backcolor = gPad->GetFrameFillColor();
6691 if (Hoption.System != kCARTESIAN) backcolor = 0;
6692 view->PadRange(backcolor);
6693 fLego->SetFillStyle(fH->GetFillStyle());
6694 fLego->SetFillColor(fH->GetFillColor());
6695 fLego->TAttFill::Modify();
6696
6697 // Paint the Back Box if needed
6698 if (Hoption.BackBox && !Hoption.Same && !Hoption.Lego && !Hoption.Surf) {
6699 fLego->InitMoveScreen(-1.1,1.1);
6700 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
6702 fLego->BackBox(90);
6703 }
6704
6705 // Paint the Errors
6706 Double_t x, ex, x1, x2;
6707 Double_t y, ey, y1, y2;
6708 Double_t z, ez1, ez2, z1, z2;
6709 Double_t temp1[3],temp2[3];
6711 if (Hoption.Error == 110) {
6712 xyerror = 0;
6713 } else {
6715 }
6716
6718 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
6719 y = fYaxis->GetBinCenter(j);
6721 y1 = y-ey;
6722 y2 = y+ey;
6723 if (Hoption.Logy) {
6724 if (y > 0) y = TMath::Log10(y);
6725 else continue;
6726 if (y1 > 0) y1 = TMath::Log10(y1);
6727 else y1 = Hparam.ymin;
6728 if (y2 > 0) y2 = TMath::Log10(y2);
6729 else y2 = Hparam.ymin;
6730 }
6733 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
6734 xk = fXaxis->GetBinLowEdge(i);
6735 xstep = fXaxis->GetBinWidth(i);
6736 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
6737 Int_t bin = fH->GetBin(i,j);
6738 x = fXaxis->GetBinCenter(i);
6740 x1 = x-ex;
6741 x2 = x+ex;
6742 if (Hoption.Logx) {
6743 if (x > 0) x = TMath::Log10(x);
6744 else continue;
6745 if (x1 > 0) x1 = TMath::Log10(x1);
6746 else x1 = Hparam.xmin;
6747 if (x2 > 0) x2 = TMath::Log10(x2);
6748 else x2 = Hparam.xmin;
6749 }
6750 z = fH->GetBinContent(bin);
6751 if (fH->GetBinErrorOption() == TH1::kNormal) {
6752 ez1 = fH->GetBinError(bin);
6753 ez2 = ez1;
6754 }
6755 else {
6756 ez1 = fH->GetBinErrorLow(bin);
6757 ez2 = fH->GetBinErrorUp(bin);
6758 }
6759 z1 = z - ez1;
6760 z2 = z + ez2;
6761 if (Hoption.Logz) {
6762 if (z > 0) z = TMath::Log10(z);
6763 else z = Hparam.zmin;
6764 if (z1 > 0) z1 = TMath::Log10(z1);
6765 else z1 = Hparam.zmin;
6766 if (z2 > 0) z2 = TMath::Log10(z2);
6767 else z2 = Hparam.zmin;
6768
6769 }
6770 if (z <= Hparam.zmin) continue;
6771 if (z > Hparam.zmax) z = Hparam.zmax;
6772
6773 temp1[0] = x1;
6774 temp1[1] = y;
6775 temp1[2] = z;
6776 temp2[0] = x2;
6777 temp2[1] = y;
6778 temp2[2] = z;
6779 gPad->PaintLine3D(temp1, temp2);
6780 temp1[0] = x;
6781 temp1[1] = y1;
6782 temp1[2] = z;
6783 temp2[0] = x;
6784 temp2[1] = y2;
6785 temp2[2] = z;
6786 gPad->PaintLine3D(temp1, temp2);
6787 temp1[0] = x;
6788 temp1[1] = y;
6789 temp1[2] = z1;
6790 temp2[0] = x;
6791 temp2[1] = y;
6792 temp2[2] = z2;
6793 gPad->PaintLine3D(temp1, temp2);
6794 temp1[0] = x;
6795 temp1[1] = y;
6796 temp1[2] = z;
6797 view->WCtoNDC(temp1, &temp2[0]);
6798 gPad->PaintPolyMarker(1, &temp2[0], &temp2[1]);
6799 }
6800 }
6801
6802 // Paint the Front Box if needed
6803 if (Hoption.FrontBox) {
6804 fLego->InitMoveScreen(-1.1,1.1);
6806 fLego->FrontBox(90);
6807 }
6808
6809 // Paint the Axis if needed
6810 if (!Hoption.Axis && !Hoption.Same && !Hoption.Lego && !Hoption.Surf) {
6811 TGaxis axis;
6812 PaintLegoAxis(&axis, 90);
6813 }
6814
6815 fLego.reset();
6816}
6817
6818////////////////////////////////////////////////////////////////////////////////
6819/// Calculate range and clear pad (canvas).
6820
6822{
6823
6824 if (Hoption.Same) return;
6825
6827
6828 if (Hoption.Lego || Hoption.Surf || Hoption.Tri ||
6829 Hoption.Contour == 14 || Hoption.Error >= 100) {
6830 TObject *frame = gPad->FindObject("TFrame");
6831 if (frame) gPad->Remove(frame);
6832 return;
6833 }
6834
6835 //The next statement is always executed on non-iOS platform,
6836 //on iOS depends on pad mode.
6837 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode())
6838 gPad->PaintPadFrame(Hparam.xmin,Hparam.ymin,Hparam.xmax,Hparam.ymax);
6839}
6840
6841////////////////////////////////////////////////////////////////////////////////
6842/// [Paint functions associated to an histogram.](\ref HP28")
6843
6845{
6846 auto lnk = fFunctions->FirstLink();
6847
6848 while (lnk) {
6849 auto obj = lnk->GetObject();
6851 if (obj->InheritsFrom(TF2::Class())) {
6852 if (!obj->TestBit(TF2::kNotDraw)) {
6853 if (Hoption.Lego || Hoption.Surf || Hoption.Error >= 100) {
6854 TF2 *f2 = (TF2*)obj;
6855 f2->SetMinimum(fH->GetMinimum());
6856 f2->SetMaximum(fH->GetMaximum());
6857 f2->SetRange(fH->GetXaxis()->GetXmin(), fH->GetYaxis()->GetXmin(), fH->GetXaxis()->GetXmax(), fH->GetYaxis()->GetXmax() );
6858 f2->Paint("surf same");
6859 } else {
6860 obj->Paint("cont3 same");
6861 }
6862 }
6863 } else if (obj->InheritsFrom(TF1::Class())) {
6864 if (!obj->TestBit(TF1::kNotDraw)) obj->Paint("lsame");
6865 } else {
6866 //Let's make this 'function' selectable on iOS device (for example, it can be TPaveStat).
6867 gPad->PushSelectableObject(obj);
6868
6869 //The next statement is ALWAYS executed on non-iOS platform, on iOS it depends on pad's mode
6870 //and picked object.
6871 if (!gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && obj == gPad->GetSelected()))
6872 obj->Paint(lnk->GetOption());
6873 }
6874 lnk = lnk->Next();
6875 }
6876}
6877
6878////////////////////////////////////////////////////////////////////////////////
6879/// [Control routine to draw 1D histograms](\ref HP01b)
6880
6882{
6883
6884 //On iOS: do not highlight hist, if part of it was selected.
6885 //Never executes on non-iOS platform.
6886 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
6887 return;
6888
6889 static char chopth[17];
6890
6892 Int_t i, j, first, last, nbins, fixbin;
6893 Double_t c1, yb;
6894 yb = 0;
6895
6896 strlcpy(chopth, " ",17);
6897
6900 Double_t baroffset = fH->GetBarOffset();
6901 Double_t barwidth = fH->GetBarWidth();
6904 gStyle->SetBarOffset(baroffset);
6905 gStyle->SetBarWidth(barwidth);
6906
6907 // Create "LIFE" structure to keep current histogram status
6908
6909 first = Hparam.xfirst;
6910 last = Hparam.xlast;
6911 nbins = last - first + 1;
6912
6913 std::vector<Double_t> keepx, keepy;
6914 if (fXaxis->GetXbins()->fN) fixbin = 0;
6915 else fixbin = 1;
6916 if (fixbin) keepx.resize(2);
6917 else keepx.resize(nbins+1);
6918 keepy.resize(nbins);
6919 Double_t logymin = 0;
6921
6922 // Loop on histogram bins
6923
6924 for (j=first; j<=last;j++) {
6926 if (TMath::Abs(ymax-ymin) > 0) {
6928 else yb = c1;
6929 }
6930 if (!Hoption.Line) {
6931 yb = TMath::Max(yb, ymin);
6932 yb = TMath::Min(yb, ymax);
6933 }
6934 keepy[j-first] = yb;
6935 }
6936
6937 // Draw histogram according to value of FillStyle and FillColor
6938
6939 if (fixbin) { keepx[0] = Hparam.xmin; keepx[1] = Hparam.xmax; }
6940 else {
6941 for (i=0; i<nbins; i++) keepx[i] = fXaxis->GetBinLowEdge(i+first);
6942 keepx[nbins] = fXaxis->GetBinUpEdge(nbins-1+first);
6943 }
6944
6945 // Prepare Fill area (systematic with option "Bar").
6946
6948 htype = oldhtype;
6949 if (Hoption.Bar) {
6950 if (htype == 0 || htype == 1000) htype = 1001;
6951 }
6952
6954
6955 // Code option for GrapHist
6956
6957 if (Hoption.Line) chopth[0] = 'L';
6958 if (Hoption.Star) chopth[1] = '*';
6959 if (Hoption.Mark) chopth[2] = 'P';
6960 if (Hoption.Mark == 10) chopth[3] = '0';
6962 if (Hoption.Curve) chopth[3] = 'C';
6963 if (Hoption.Hist > 0) chopth[4] = 'H';
6964 else if (Hoption.Bar) chopth[5] = 'B';
6965 if (Hoption.Logy) chopth[6] = '1';
6966 if (fH->GetFillColor() && htype) {
6967 if (Hoption.Hist > 0 || Hoption.Curve || Hoption.Line) {
6968 chopth[7] = 'F';
6969 }
6970 }
6971 }
6972 if (!fixbin && strlen(chopth)) {
6973 chopth[8] = 'N';
6974 }
6975
6976 if (Hoption.Fill == 2) chopth[13] = '2';
6977
6978 // Option LOGX
6979
6980 if (Hoption.Logx) {
6981 chopth[9] = 'G';
6982 chopth[10] = 'X';
6983 if (fixbin) {
6984 keepx[0] = TMath::Power(10,keepx[0]);
6985 keepx[1] = TMath::Power(10,keepx[1]);
6986 }
6987 }
6988
6989 if (Hoption.Off) {
6990 chopth[11] = ']';
6991 chopth[12] = '[';
6992 }
6993
6994 // Draw the histogram
6995
6996 TGraph graph;
6997 graph.SetLineWidth(lw);
6998 graph.SetLineStyle(fH->GetLineStyle());
6999 graph.SetLineColor(fH->GetLineColor());
7000 graph.SetFillStyle(htype);
7001 graph.SetFillColor(fH->GetFillColor());
7003 graph.SetMarkerSize(fH->GetMarkerSize());
7006
7007 graph.PaintGrapHist(nbins, keepx.data(), keepy.data() ,chopth);
7008
7011
7013}
7014
7015////////////////////////////////////////////////////////////////////////////////
7016/// [Control function to draw a 3D histograms.](\ref HP01d)
7017
7019{
7020
7021 TString cmd;
7022 TString opt = option;
7023 opt.ToLower();
7024 Int_t irep;
7025 Float_t NEntries = fH->GetEntries();
7026
7027 if (fCurrentF3 || strstr(opt,"tf3")) {
7028 PaintTF3();
7029 return;
7030 }
7031
7032 if (NEntries > 0) {
7033 if (Hoption.Box || Hoption.Lego || Hoption.Color) {
7034 if (Hoption.Box == 11 || Hoption.Lego == 11) {
7035 PaintH3Box(1);
7036 } else if (Hoption.Box == 12 || Hoption.Lego == 12 || Hoption.Color == 1) {
7037 PaintH3Box(2);
7038 } else if (Hoption.Box == 13 || Hoption.Lego == 13) {
7039 PaintH3Box(3);
7040 } else {
7042 }
7043 return;
7044 }
7045
7046 if (strstr(opt,"iso")) {
7047 PaintH3Iso();
7048 return;
7049 }
7050 }
7051
7052 TView *view = gPad ? gPad->GetView() : nullptr;
7053 if (!view) return;
7054
7055 if (strstr(opt,"fb")) Hoption.FrontBox = 0;
7056 if (strstr(opt,"bb")) Hoption.BackBox = 0;
7057
7058 Double_t thedeg = 90 - gPad->GetTheta();
7059 Double_t phideg = -90 - gPad->GetPhi();
7060 Double_t psideg = view->GetPsi();
7061 view->SetView(phideg, thedeg, psideg, irep);
7062
7063 if(NEntries > 0) { // Paint as 3D scatter plot
7064 cmd.Form("TPolyMarker3D::PaintH3((TH1 *)0x%zx,\"%s\");",(size_t)fH,option);
7065 gROOT->ProcessLine(cmd.Data());
7066 } else {
7067 TAxis* xAxis = fH->GetXaxis();
7068 TAxis* yAxis = fH->GetYaxis();
7069 TAxis* zAxis = fH->GetZaxis();
7070 Double_t xmin = xAxis->GetXmin();
7071 Double_t xmax = xAxis->GetXmax();
7072 Double_t ymin = yAxis->GetXmin();
7073 Double_t ymax = yAxis->GetXmax();
7074 Double_t zmin = zAxis->GetXmin();
7075 Double_t zmax = zAxis->GetXmax();
7076 view->SetRange(xmin, ymin, zmin, xmax, ymax, zmax); // Set the axis limits (Xmin, Ymin, Zmin, Xmax, Ymax, Zmax)
7077 }
7078
7079 if (Hoption.Same) return;
7080
7081 // Draw axis
7082 view->SetOutlineToCube();
7083 TSeqCollection *ol = view->GetOutline();
7084 if (ol && Hoption.BackBox && Hoption.FrontBox) ol->Paint(option);
7086
7087 if (!Hoption.Axis && !Hoption.Same) {
7088 TGaxis axis;
7089 PaintLegoAxis(&axis, 90);
7090 }
7091
7092 // Draw palette. In case of 4D plot with TTree::Draw() the palette should
7093 // be painted with the option colz.
7094 if (fH->GetDrawOption() && strstr(opt,"colz")) {
7095 Int_t ndiv = fH->GetContour();
7096 if (ndiv == 0 ) {
7097 ndiv = gStyle->GetNumberContours();
7098 fH->SetContour(ndiv);
7099 }
7100 PaintPalette();
7101 }
7102
7103 // Draw title
7104 PaintTitle();
7105
7106 //Draw stats and fit results
7107 TF1 *fit = nullptr;
7108 TIter next(fFunctions);
7109 while (auto obj = next()) {
7110 if (obj->InheritsFrom(TF1::Class())) {
7111 fit = (TF1*)obj;
7112 break;
7113 }
7114 }
7115 if ((Hoption.Same%10) != 1) {
7116 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7118 }
7119 }
7120
7121}
7122
7123////////////////////////////////////////////////////////////////////////////////
7124/// Compute histogram parameters used by the drawing routines.
7125
7127{
7128
7129 if (fH->GetDimension() > 1 || Hoption.Lego || Hoption.Surf) return 1;
7130
7131 Int_t i;
7132 static const char *where = "PaintInit";
7134 Int_t maximum = 0;
7135 Int_t minimum = 0;
7136 if (fH->GetMaximumStored() != -1111) maximum = 1;
7137 if (fH->GetMinimumStored() != -1111) minimum = 1;
7138
7139 // Compute X axis parameters
7140
7141 Int_t last = fXaxis->GetLast();
7142 Int_t first = fXaxis->GetFirst();
7145 Hparam.xlast = last;
7146 Hparam.xfirst = first;
7149
7150 // if log scale in X, replace xmin,max by the log
7151 if (Hoption.Logx) {
7152 if (Hparam.xmax<=0) {
7153 Error(where, "cannot set X axis to log scale");
7154 return 0;
7155 }
7156 if (Hparam.xlowedge <=0 ) {
7157 if (Hoption.Same) {
7158 TH1* h1 = nullptr;
7159 TObject *obj;
7160 TIter next(gPad->GetListOfPrimitives());
7161 while ((obj = (TObject *)next())) {
7162 if (obj->InheritsFrom(TH1::Class())) { h1 = (TH1*)(obj) ; break; }
7163 if (obj->InheritsFrom(THStack::Class())) { h1 = ((THStack*)(obj))->GetHistogram() ; break; }
7164 if (obj->InheritsFrom(TGraph::Class())) { h1 = ((TGraph*)(obj))->GetHistogram() ; break; }
7165 if (obj->InheritsFrom(TMultiGraph::Class())) { h1 = ((TMultiGraph*)(obj))->GetHistogram(); break; }
7166 if (obj->InheritsFrom(TGraph2D::Class())) { h1 = ((TGraph2D*)(obj))->GetHistogram(); break; }
7167 if (obj->InheritsFrom(TF1::Class())) { h1 = ((TF1*)(obj))->GetHistogram(); break; }
7168 }
7169 if (h1) {
7171 } else {
7172 Error(where, "undefined user's coordinates. Cannot use option SAME");
7173 return 0;
7174 }
7175 } else {
7176 for (i=first; i<=last; i++) {
7177 Double_t binLow = fXaxis->GetBinLowEdge(i);
7178 if (binLow>0) {
7179 Hparam.xlowedge = binLow;
7180 break;
7181 }
7182 if (binLow == 0 && fH->GetBinContent(i) !=0) {
7183 Hparam.xlowedge = fXaxis->GetBinUpEdge(i)*0.001;
7184 break;
7185 }
7186 }
7187 if (Hparam.xlowedge<=0) {
7188 Error(where, "cannot set X axis to log scale");
7189 return 0;
7190 }
7191 }
7193 }
7198 if (Hparam.xlast > last) Hparam.xlast = last;
7199 if (Hparam.xfirst < first) Hparam.xfirst = first;
7200 }
7201
7202 // Compute Y axis parameters
7203 Double_t bigp = TMath::Power(10,32);
7204 Double_t ymax = -bigp;
7205 Double_t ymin = bigp;
7206 Double_t c1, e1;
7207 Double_t xv[1];
7208 Double_t fval;
7209 TObject *f;
7210 TF1 *f1;
7211 Double_t allchan = 0;
7212 Int_t nonNullErrors = 0;
7213 TIter next(fFunctions);
7214 for (i=first; i<=last;i++) {
7215 c1 = fH->GetBinContent(i);
7217 if (Hoption.Logy) {
7218 if (c1 > 0) ymin = TMath::Min(ymin,c1);
7219 } else {
7221 }
7222 if (Hoption.Error) {
7224 e1 = fH->GetBinError(i);
7225 else
7226 e1 = fH->GetBinErrorUp(i);
7227 if (e1 > 0) nonNullErrors++;
7230 e1 = fH->GetBinErrorLow(i);
7231
7232 if (Hoption.Logy) {
7233 if (c1-e1>0.01*TMath::Abs(c1)) ymin = TMath::Min(ymin,c1-e1);
7234 } else {
7236 }
7237 }
7238 if (Hoption.Func) {
7239 xv[0] = fXaxis->GetBinCenter(i);
7240 while ((f = (TObject*) next())) {
7241 if (f->IsA() == TF1::Class()) {
7242 f1 = (TF1*)f;
7243 if (xv[0] < f1->GetXmin() || xv[0] > f1->GetXmax()) continue;
7244 fval = f1->Eval(xv[0],0,0);
7245 if (f1->GetMaximumStored() != -1111) fval = TMath::Min(f1->GetMaximumStored(), fval);
7247 if (Hoption.Logy) {
7248 if (c1 > 0 && fval > 0.3*c1) ymin = TMath::Min(ymin,fval);
7249 }
7250 }
7251 }
7252 next.Reset();
7253 }
7254 allchan += c1;
7255 }
7256 if (!nonNullErrors) {
7257 if (Hoption.Error) {
7258 if (!Hoption.Mark && !Hoption.Line && !Hoption.Star && !Hoption.Curve) Hoption.Hist = 2;
7259 Hoption.Error=0;
7260 }
7261 }
7262
7263
7264 // Take into account maximum , minimum
7265
7266 if (Hoption.Logy && ymin <= 0) {
7267 if (ymax >= 1) ymin = TMath::Max(.005,ymax*1e-10);
7268 else ymin = 0.001*ymax;
7269 }
7270
7271 Double_t xm = ymin;
7272 if (maximum) ymax = fH->GetMaximumStored();
7273 if (minimum) xm = fH->GetMinimumStored();
7274 if (Hoption.Logy && xm < 0) {
7275 Error(where, "log scale requested with a negative argument (%f)", xm);
7276 return 0;
7277 } else if (Hoption.Logy && xm>=0 && ymax==0) { // empty histogram in log scale
7278 ymin = 0.01;
7279 ymax = 10.;
7280 } else {
7281 ymin = xm;
7282 }
7283
7284 if (ymin >= ymax) {
7285 if (Hoption.Logy) {
7286 if (ymax > 0) ymin = 0.001*ymax;
7287 else {
7288 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", ymax);
7289 return 0;
7290 }
7291 }
7292 else {
7293 if (ymin > 0) {
7294 ymin = 0;
7295 ymax *= 2;
7296 } else if (ymin < 0) {
7297 ymax = 0;
7298 ymin *= 2;
7299 } else {
7300 ymin = 0;
7301 ymax = 1;
7302 }
7303 }
7304 }
7305
7306 // In some cases, mainly because of precision issues, ymin and ymax could almost equal.
7307 if (TMath::AreEqualRel(ymin,ymax,1E-15)) {
7308 ymin = ymin*(1-1E-14);
7309 ymax = ymax*(1+1E-14);
7310 }
7311
7312 // take into account normalization factor
7313 Hparam.allchan = allchan;
7314 Double_t factor = allchan;
7315 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
7316 if (allchan) factor /= allchan;
7317 if (factor == 0) factor = 1;
7318 Hparam.factor = factor;
7319 ymax = factor*ymax;
7320 ymin = factor*ymin;
7321 //just in case the norm factor is negative
7322 // this may happen with a positive norm factor and a negative integral !
7323 if (ymax < ymin) {
7324 Double_t temp = ymax;
7325 ymax = ymin;
7326 ymin = temp;
7327 }
7328
7329 // For log scales, histogram coordinates are LOG10(ymin) and
7330 // LOG10(ymax). Final adjustment (if not option "Same"
7331 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
7332 // Maximum and Minimum are not defined.
7333 if (Hoption.Logy) {
7334 if (ymin <=0 || ymax <=0) {
7335 Error(where, "Cannot set Y axis to log scale");
7336 return 0;
7337 }
7339 if (!minimum) ymin += TMath::Log10(0.5);
7341 if (!maximum) ymax += TMath::Log10(2*(0.9/0.95));
7342 if (!Hoption.Same) {
7343 Hparam.ymin = ymin;
7344 Hparam.ymax = ymax;
7345 }
7346 return 1;
7347 }
7348
7349 // final adjustment of ymin for linear scale.
7350 // if minimum is not set , then ymin is set to zero if >0
7351 // or to ymin - margin if <0.
7352 if (!minimum) {
7353 if (Hoption.MinimumZero) {
7354 if (ymin >= 0) ymin = 0;
7355 else ymin -= yMARGIN*(ymax-ymin);
7356 } else {
7358 if (ymin >= 0 && (ymin-dymin <= 0)) ymin = 0;
7359 else ymin -= dymin;
7360 }
7361 }
7362
7363 // final adjustment of YMAXI for linear scale (if not option "Same"):
7364 // decrease histogram height to MAX% of allowed height if HMAXIM
7365 // has not been called.
7366 if (!maximum) {
7367 ymax += yMARGIN*(ymax-ymin);
7368 }
7369
7370 Hparam.ymin = ymin;
7371 Hparam.ymax = ymax;
7372 return 1;
7373}
7374
7375////////////////////////////////////////////////////////////////////////////////
7376/// Compute histogram parameters used by the drawing routines for a rotated pad.
7377
7379{
7380
7381 static const char *where = "PaintInitH";
7383 Int_t maximum = 0;
7384 Int_t minimum = 0;
7385 if (fH->GetMaximumStored() != -1111) maximum = 1;
7386 if (fH->GetMinimumStored() != -1111) minimum = 1;
7387
7388 // Compute X axis parameters
7389
7390 Int_t last = fXaxis->GetLast();
7391 Int_t first = fXaxis->GetFirst();
7394 Hparam.xlast = last;
7395 Hparam.xfirst = first;
7398
7399 // if log scale in Y, replace ymin,max by the log
7400 if (Hoption.Logy) {
7401 if (Hparam.xlowedge <=0 ) {
7404 }
7405 if (Hparam.ymin <=0 || Hparam.ymax <=0) {
7406 Error(where, "cannot set Y axis to log scale");
7407 return 0;
7408 }
7413 if (Hparam.xlast > last) Hparam.xlast = last;
7414 }
7415
7416 // Compute Y axis parameters
7417 Double_t bigp = TMath::Power(10,32);
7418 Double_t xmax = -bigp;
7419 Double_t xmin = bigp;
7420 Double_t c1, e1;
7421 Double_t xv[1];
7422 Double_t fval;
7423 Int_t i;
7424 TObject *f;
7425 TF1 *f1;
7426 Double_t allchan = 0;
7427 TIter next(fFunctions);
7428 for (i=first; i<=last;i++) {
7429 c1 = fH->GetBinContent(i);
7432 if (Hoption.Error) {
7433 e1 = fH->GetBinError(i);
7436 }
7437 if (Hoption.Func) {
7438 xv[0] = fXaxis->GetBinCenter(i);
7439 while ((f = (TObject*) next())) {
7440 if (f->IsA() == TF1::Class()) {
7441 f1 = (TF1*)f;
7442 if (xv[0] < f1->GetXmin() || xv[0] > f1->GetXmax()) continue;
7443 fval = f1->Eval(xv[0],0,0);
7445 if (Hoption.Logy) {
7446 if (fval > 0.3*c1) xmin = TMath::Min(xmin,fval);
7447 }
7448 }
7449 }
7450 next.Reset();
7451 }
7452 allchan += c1;
7453 }
7454
7455 // Take into account maximum , minimum
7456
7457 if (Hoption.Logx && xmin <= 0) {
7458 if (xmax >= 1) xmin = TMath::Max(.5,xmax*1e-10);
7459 else xmin = 0.001*xmax;
7460 }
7461 Double_t xm = xmin;
7462 if (maximum) xmax = fH->GetMaximumStored();
7463 if (minimum) xm = fH->GetMinimumStored();
7464 if (Hoption.Logx && xm <= 0) {
7465 Error(where, "log scale requested with zero or negative argument (%f)", xm);
7466 return 0;
7467 }
7468 else xmin = xm;
7469 if (xmin >= xmax) {
7470 if (Hoption.Logx) {
7471 if (xmax > 0) xmin = 0.001*xmax;
7472 else {
7473 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", xmax);
7474 return 0;
7475 }
7476 }
7477 else {
7478 if (xmin > 0) {
7479 xmin = 0;
7480 xmax *= 2;
7481 } else if (xmin < 0) {
7482 xmax = 0;
7483 xmin *= 2;
7484 } else {
7485 xmin = 0;
7486 xmax = 1;
7487 }
7488 }
7489 }
7490
7491 // take into account normalization factor
7492 Hparam.allchan = allchan;
7493 Double_t factor = allchan;
7494 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
7495 if (allchan) factor /= allchan;
7496 if (factor == 0) factor = 1;
7497 Hparam.factor = factor;
7498 xmax = factor*xmax;
7499 xmin = factor*xmin;
7500
7501 // For log scales, histogram coordinates are LOG10(ymin) and
7502 // LOG10(ymax). Final adjustment (if not option "Same"
7503 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
7504 // Maximum and Minimum are not defined.
7505 if (Hoption.Logx) {
7506 if (xmin <=0 || xmax <=0) {
7507 Error(where, "Cannot set Y axis to log scale");
7508 return 0;
7509 }
7511 if (!minimum) xmin += TMath::Log10(0.5);
7513 if (!maximum) xmax += TMath::Log10(2*(0.9/0.95));
7514 if (!Hoption.Same) {
7515 Hparam.xmin = xmin;
7516 Hparam.xmax = xmax;
7517 }
7518 return 1;
7519 }
7520
7521 // final adjustment of ymin for linear scale.
7522 // if minimum is not set , then ymin is set to zero if >0
7523 // or to ymin - margin if <0.
7524 if (!minimum) {
7525 if (xmin >= 0) xmin = 0;
7526 else xmin -= yMARGIN*(xmax-xmin);
7527 }
7528
7529 // final adjustment of YMAXI for linear scale (if not option "Same"):
7530 // decrease histogram height to MAX% of allowed height if HMAXIM
7531 // has not been called.
7532 if (!maximum) {
7533 xmax += yMARGIN*(xmax-xmin);
7534 }
7535 Hparam.xmin = xmin;
7536 Hparam.xmax = xmax;
7537 return 1;
7538}
7539
7540////////////////////////////////////////////////////////////////////////////////
7541/// [Control function to draw a 3D histogram with boxes.](\ref HP25)
7542
7544{
7545 // Predefined box structure
7546 Double_t wxyz[8][3] = { {-1,-1,-1}, {1,-1,-1}, {1,1,-1}, {-1,1,-1},
7547 {-1,-1, 1}, {1,-1, 1}, {1,1, 1}, {-1,1, 1} };
7548 Int_t iface[6][4] = { {0,3,2,1}, {4,5,6,7},
7549 {0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7} };
7550
7551 // Define dimensions of world space
7552 TAxis *xaxis = fH->GetXaxis();
7553 TAxis *yaxis = fH->GetYaxis();
7554 TAxis *zaxis = fH->GetZaxis();
7555
7556 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7557 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7558 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7559 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7560 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7561 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7562
7563 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7564
7565 // Set view
7566 TView *view = gPad ? gPad->GetView() : nullptr;
7567 if (!view) {
7568 Error("PaintH3", "no TView in current pad");
7569 return;
7570 }
7571 Double_t thedeg = 90 - gPad->GetTheta();
7572 Double_t phideg = -90 - gPad->GetPhi();
7573 Double_t psideg = view->GetPsi();
7574 Int_t irep;
7575 view->SetView(phideg, thedeg, psideg, irep);
7576
7577 Int_t backcolor = gPad->GetFrameFillColor();
7578 view->PadRange(backcolor);
7579
7580 // Draw back surfaces of frame box
7581 fLego->InitMoveScreen(-1.1,1.1);
7582 if (Hoption.BackBox) {
7583 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
7585 fLego->BackBox(90);
7586 }
7587
7589
7590 // Define order of drawing
7591 Double_t *tnorm = view->GetTnorm();
7592 if (!tnorm) return;
7593 Int_t incrx = (tnorm[ 8] < 0.) ? -1 : +1;
7594 Int_t incry = (tnorm[ 9] < 0.) ? -1 : +1;
7595 Int_t incrz = (tnorm[10] < 0.) ? -1 : +1;
7596 Int_t ix1 = (incrx == +1) ? xaxis->GetFirst() : xaxis->GetLast();
7597 Int_t iy1 = (incry == +1) ? yaxis->GetFirst() : yaxis->GetLast();
7598 Int_t iz1 = (incrz == +1) ? zaxis->GetFirst() : zaxis->GetLast();
7599 Int_t ix2 = (incrx == +1) ? xaxis->GetLast() : xaxis->GetFirst();
7600 Int_t iy2 = (incry == +1) ? yaxis->GetLast() : yaxis->GetFirst();
7601 Int_t iz2 = (incrz == +1) ? zaxis->GetLast() : zaxis->GetFirst();
7602
7603 // Set graphic attributes (colour, style, etc.)
7608
7609 fH->SetFillStyle(1001);
7610 fH->TAttFill::Modify();
7611 fH->TAttLine::Modify();
7612 Int_t ncolors = gStyle->GetNumberOfColors();
7614
7615 // Create bin boxes and draw
7619
7620 Double_t pmin[3], pmax[3], sxyz[8][3];
7621 for (Int_t ix = ix1; ix !=ix2+incrx; ix += incrx) {
7622 pmin[0] = xaxis->GetBinLowEdge(ix);
7623 pmax[0] = xaxis->GetBinUpEdge(ix);
7624 for (Int_t iy = iy1; iy != iy2+incry; iy += incry) {
7625 pmin[1] = yaxis->GetBinLowEdge(iy);
7626 pmax[1] = yaxis->GetBinUpEdge(iy);
7627 for (Int_t iz = iz1; iz != iz2+incrz; iz += incrz) {
7628 pmin[2] = zaxis->GetBinLowEdge(iz);
7629 pmax[2] = zaxis->GetBinUpEdge(iz);
7630 Double_t w = fH->GetBinContent(fH->GetBin(ix,iy,iz));
7631 Bool_t neg = kFALSE;
7632 Int_t n = 5;
7633 if (w<0) {
7634 w = -w;
7635 neg = kTRUE;
7636 }
7637 if (w < wmin) continue;
7638 if (w > wmax) w = wmax;
7639 Double_t scale = (TMath::Power((w-wmin)/(wmax-wmin),1./3.))/2.;
7640 if (scale == 0) continue;
7641 for (Int_t i=0; i<3; ++i) {
7642 Double_t c = (pmax[i] + pmin[i])*0.5;
7643 Double_t d = (pmax[i] - pmin[i])*scale;
7644 for (Int_t k=0; k<8; ++k) { // set bin box vertices
7645 sxyz[k][i] = wxyz[k][i]*d + c;
7646 }
7647 }
7648 for (Int_t k=0; k<8; ++k) { // transform to normalized space
7649 view->WCtoNDC(&sxyz[k][0],&sxyz[k][0]);
7650 }
7651 Double_t x[8], y[8]; // draw bin box faces
7652 for (Int_t k=0; k<6; ++k) {
7653 for (Int_t i=0; i<4; ++i) {
7654 Int_t iv = iface[k][i];
7655 x[i] = sxyz[iv][0];
7656 y[i] = sxyz[iv][1];
7657 }
7658 x[4] = x[0] ; y[4] = y[0];
7659 if (neg) {
7660 x[5] = x[2] ; y[5] = y[2];
7661 x[6] = x[3] ; y[6] = y[3];
7662 x[7] = x[1] ; y[7] = y[1];
7663 n = 8;
7664 } else {
7665 n = 5;
7666 }
7667 Double_t z = (x[2]-x[0])*(y[3]-y[1]) - (y[2]-y[0])*(x[3]-x[1]);
7668 if (z <= 0.) continue;
7669 if (iopt == 2) {
7670 theColor = ncolors*((w-wmin)/(wmax-wmin)) -1;
7672 } else {
7673 if (k == 3 || k == 5) {
7675 } else if (k == 0 || k == 1) {
7677 } else {
7679 }
7680 }
7681 fH->TAttFill::Modify();
7682 gPad->PaintFillArea(4, x, y);
7683 if (iopt != 3)gPad->PaintPolyLine(n, x, y);
7684 }
7685 }
7686 }
7687 }
7688
7689 // Draw front surfaces of frame box
7690 if (Hoption.FrontBox) fLego->FrontBox(90);
7691
7692 // Draw axis and title
7693 if (!Hoption.Axis && !Hoption.Same) {
7694 TGaxis axis;
7695 PaintLegoAxis(&axis, 90);
7696 }
7697 PaintTitle();
7698
7699 // Draw palette. if needed.
7700 if (Hoption.Zscale) {
7701 Int_t ndiv = fH->GetContour();
7702 if (ndiv == 0 ) {
7703 ndiv = gStyle->GetNumberContours();
7704 fH->SetContour(ndiv);
7705 }
7706 PaintPalette();
7707 }
7708
7709 //Draw stats and fit results
7710 TF1 *fit = nullptr;
7711 TIter next(fFunctions);
7712 while (auto obj = next()) {
7713 if (obj->InheritsFrom(TF1::Class())) {
7714 fit = (TF1*)obj;
7715 break;
7716 }
7717 }
7718 if ((Hoption.Same%10) != 1) {
7719 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7721 }
7722 }
7723
7724 fLego.reset();
7725
7728 fH->TAttFill::Modify();
7729}
7730
7731////////////////////////////////////////////////////////////////////////////////
7732/// [Control function to draw a 3D histogram with boxes.](\ref HP25)
7733
7735{
7736 // Predefined box structure
7737 Double_t wxyz[8][3] = {
7738 {-1,-1,-1}, {1,-1,-1}, {1,1,-1}, {-1,1,-1}, // bottom vertices
7739 {-1,-1, 1}, {1,-1, 1}, {1,1, 1}, {-1,1, 1} // top vertices
7740 };
7741 Int_t iface[6][4] = {
7742 {0,3,2,1}, {4,5,6,7}, // bottom and top faces
7743 {0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7} // side faces
7744 };
7745 Double_t normal[6][3] = {
7746 {0,0,-1}, {0,0,1}, // Z-, Z+
7747 {0,-1,0}, {1,0,0}, {0,1,0}, {-1,0,0} // Y-, X+, Y+, X-
7748 };
7749
7750 // Define dimensions of world space
7751 TAxis *xaxis = fH->GetXaxis();
7752 TAxis *yaxis = fH->GetYaxis();
7753 TAxis *zaxis = fH->GetZaxis();
7754
7755 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7756 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7757 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7758 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7759 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7760 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7761
7762 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7763
7764 // Set view
7765 TView *view = gPad ? gPad->GetView() : nullptr;
7766 if (!view) {
7767 Error("PaintH3", "no TView in current pad");
7768 return;
7769 }
7770 Double_t thedeg = 90 - gPad->GetTheta();
7771 Double_t phideg = -90 - gPad->GetPhi();
7772 Double_t psideg = view->GetPsi();
7773 Int_t irep;
7774 view->SetView(phideg, thedeg, psideg, irep);
7775
7776 Int_t backcolor = gPad->GetFrameFillColor();
7777 view->PadRange(backcolor);
7778
7779 // Draw front surfaces of frame box
7780 if (Hoption.FrontBox) {
7781 fLego->InitMoveScreen(-1.1,1.1);
7783 }
7784
7785 // Initialize hidden line removal algorithm "raster screen"
7786 fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
7787
7788 // Define order of drawing
7789 Double_t *tnorm = view->GetTnorm();
7790 if (!tnorm) return;
7791 Int_t incrx = (tnorm[ 8] < 0.) ? +1 : -1;
7792 Int_t incry = (tnorm[ 9] < 0.) ? +1 : -1;
7793 Int_t incrz = (tnorm[10] < 0.) ? +1 : -1;
7794 Int_t ix1 = (incrx == +1) ? xaxis->GetFirst() : xaxis->GetLast();
7795 Int_t iy1 = (incry == +1) ? yaxis->GetFirst() : yaxis->GetLast();
7796 Int_t iz1 = (incrz == +1) ? zaxis->GetFirst() : zaxis->GetLast();
7797 Int_t ix2 = (incrx == +1) ? xaxis->GetLast() : xaxis->GetFirst();
7798 Int_t iy2 = (incry == +1) ? yaxis->GetLast() : yaxis->GetFirst();
7799 Int_t iz2 = (incrz == +1) ? zaxis->GetLast() : zaxis->GetFirst();
7800
7801 // Set line attributes (colour, style, etc.)
7802 fH->TAttLine::Modify();
7803
7804 // Create bin boxes and draw
7805 const Int_t NTMAX = 100;
7806 Double_t tt[NTMAX][2];
7810 Double_t pmin[3], pmax[3], sxyz[8][3], pp[4][2];
7811 for (Int_t ix = ix1; ix !=ix2+incrx; ix += incrx) {
7812 pmin[0] = xaxis->GetBinLowEdge(ix);
7813 pmax[0] = xaxis->GetBinUpEdge(ix);
7814 for (Int_t iy = iy1; iy != iy2+incry; iy += incry) {
7815 pmin[1] = yaxis->GetBinLowEdge(iy);
7816 pmax[1] = yaxis->GetBinUpEdge(iy);
7817 for (Int_t iz = iz1; iz != iz2+incrz; iz += incrz) {
7818 pmin[2] = zaxis->GetBinLowEdge(iz);
7819 pmax[2] = zaxis->GetBinUpEdge(iz);
7820 Double_t w = fH->GetBinContent(fH->GetBin(ix,iy,iz));
7821 Bool_t neg = kFALSE;
7822 if (w<0) {
7823 w = -w;
7824 neg = kTRUE;
7825 }
7826 if (w < wmin) continue;
7827 if (w > wmax) w = wmax;
7828 Double_t scale = (TMath::Power((w-wmin)/(wmax-wmin),1./3.))/2.;
7829 if (scale == 0) continue;
7830 for (Int_t i=0; i<3; ++i) {
7831 Double_t c = (pmax[i] + pmin[i])*0.5;
7832 Double_t d = (pmax[i] - pmin[i])*scale;
7833 for (Int_t k=0; k<8; ++k) { // set bin box vertices
7834 sxyz[k][i] = wxyz[k][i]*d + c;
7835 }
7836 }
7837 for (Int_t k=0; k<8; ++k) { // transform to normalized space
7838 view->WCtoNDC(&sxyz[k][0],&sxyz[k][0]);
7839 }
7840 for (Int_t k=0; k<6; ++k) { // draw box faces
7841 Double_t zn;
7842 view->FindNormal(normal[k][0], normal[k][1], normal[k][2], zn);
7843 if (zn <= 0) continue;
7844 for (Int_t i=0; i<4; ++i) {
7845 Int_t ip = iface[k][i];
7846 pp[i][0] = sxyz[ip][0];
7847 pp[i][1] = sxyz[ip][1];
7848 }
7849 for (Int_t i=0; i<4; ++i) {
7850 Int_t i1 = i;
7851 Int_t i2 = (i == 3) ? 0 : i + 1;
7852 Int_t nt;
7853 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7854 Double_t xdel = pp[i2][0] - pp[i1][0];
7855 Double_t ydel = pp[i2][1] - pp[i1][1];
7856 Double_t x[2], y[2];
7857 for (Int_t it = 0; it < nt; ++it) {
7858 x[0] = pp[i1][0] + xdel*tt[it][0];
7859 y[0] = pp[i1][1] + ydel*tt[it][0];
7860 x[1] = pp[i1][0] + xdel*tt[it][1];
7861 y[1] = pp[i1][1] + ydel*tt[it][1];
7862 gPad->PaintPolyLine(2, x, y);
7863 }
7864 }
7865 if (neg) {
7866 Int_t i1 = 0;
7867 Int_t i2 = 2;
7868 Int_t nt;
7869 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7870 Double_t xdel = pp[i2][0] - pp[i1][0];
7871 Double_t ydel = pp[i2][1] - pp[i1][1];
7872 Double_t x[2], y[2];
7873 for (Int_t it = 0; it < nt; ++it) {
7874 x[0] = pp[i1][0] + xdel*tt[it][0];
7875 y[0] = pp[i1][1] + ydel*tt[it][0];
7876 x[1] = pp[i1][0] + xdel*tt[it][1];
7877 y[1] = pp[i1][1] + ydel*tt[it][1];
7878 gPad->PaintPolyLine(2, x, y);
7879 }
7880 i1 = 1;
7881 i2 = 3;
7882 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7883 xdel = pp[i2][0] - pp[i1][0];
7884 ydel = pp[i2][1] - pp[i1][1];
7885 for (Int_t it = 0; it < nt; ++it) {
7886 x[0] = pp[i1][0] + xdel*tt[it][0];
7887 y[0] = pp[i1][1] + ydel*tt[it][0];
7888 x[1] = pp[i1][0] + xdel*tt[it][1];
7889 y[1] = pp[i1][1] + ydel*tt[it][1];
7890 gPad->PaintPolyLine(2, x, y);
7891 }
7892 }
7893 fLego->FillPolygonBorder(4, &pp[0][0]); // update raster screen
7894 }
7895 }
7896 }
7897 }
7898
7899 // Draw frame box
7900 if (Hoption.BackBox) {
7901 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
7903 fLego->BackBox(90);
7904 }
7905
7906 if (Hoption.FrontBox) fLego->FrontBox(90);
7907
7908 // Draw axis and title
7909 if (!Hoption.Axis && !Hoption.Same) {
7910 TGaxis axis;
7911 PaintLegoAxis(&axis, 90);
7912 }
7913 PaintTitle();
7914
7915 //Draw stats and fit results
7916 TF1 *fit = nullptr;
7917 TIter next(fFunctions);
7918 while (auto obj = next()) {
7919 if (obj->InheritsFrom(TF1::Class())) {
7920 fit = (TF1*)obj;
7921 break;
7922 }
7923 }
7924 if ((Hoption.Same%10) != 1) {
7925 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7927 }
7928 }
7929
7930 fLego.reset();
7931}
7932
7933////////////////////////////////////////////////////////////////////////////////
7934/// [Control function to draw a 3D histogram with Iso Surfaces.](\ref HP25)
7935
7937{
7938
7939 const Double_t ydiff = 1;
7940 const Double_t yligh1 = 10;
7941 const Double_t qa = 0.15;
7942 const Double_t qd = 0.15;
7943 const Double_t qs = 0.8;
7945 Int_t i, irep;
7946 Int_t nbcol = 28;
7947 Int_t icol1 = 201;
7948 Int_t ic1 = icol1;
7949 Int_t ic2 = ic1+nbcol;
7950 Int_t ic3 = ic2+nbcol;
7951
7952 TAxis *xaxis = fH->GetXaxis();
7953 TAxis *yaxis = fH->GetYaxis();
7954 TAxis *zaxis = fH->GetZaxis();
7955
7956 Int_t nx = fH->GetNbinsX();
7957 Int_t ny = fH->GetNbinsY();
7958 Int_t nz = fH->GetNbinsZ();
7959
7960 std::vector<Double_t> x(nx);
7961 std::vector<Double_t> y(ny);
7962 std::vector<Double_t> z(nz);
7963
7964 for (i=0; i<nx; i++) x[i] = xaxis->GetBinCenter(i+1);
7965 for (i=0; i<ny; i++) y[i] = yaxis->GetBinCenter(i+1);
7966 for (i=0; i<nz; i++) z[i] = zaxis->GetBinCenter(i+1);
7967
7968 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7969 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7970 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7971 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7972 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7973 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7974
7975 Double_t s[3];
7976 s[0] = fH->GetSumOfWeights()/(fH->GetNbinsX()*fH->GetNbinsY()*fH->GetNbinsZ());
7977 s[1] = 0.5*s[0];
7978 s[2] = 1.5*s[0];
7979
7980 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7981
7982 TView *view = gPad ? gPad->GetView() : nullptr;
7983 if (!view) {
7984 Error("PaintH3Iso", "no TView in current pad");
7985 return;
7986 }
7987 Double_t thedeg = 90 - gPad->GetTheta();
7988 Double_t phideg = -90 - gPad->GetPhi();
7989 Double_t psideg = view->GetPsi();
7990 view->SetView(phideg, thedeg, psideg, irep);
7991
7992 Int_t backcolor = gPad->GetFrameFillColor();
7993 if (Hoption.System != kCARTESIAN) backcolor = 0;
7994 view->PadRange(backcolor);
7995
7996 Double_t dcol = 0.5/Double_t(nbcol);
7997 TColor *colref = gROOT->GetColor(fH->GetFillColor());
7998 if (!colref) {
7999 return;
8000 }
8001 Float_t r, g, b, hue, light, satur;
8002 colref->GetRGB(r,g,b);
8004 TColor *acol;
8005 for (Int_t col=0;col<nbcol;col++) {
8006 acol = gROOT->GetColor(col+icol1);
8007 TColor::HLStoRGB(hue, .4+col*dcol, satur, r, g, b);
8008 if (acol) acol->SetRGB(r, g, b);
8009 }
8010
8011 fLego->InitMoveScreen(-1.1,1.1);
8012
8013 if (Hoption.BackBox) {
8014 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
8016 fLego->BackBox(90);
8017 }
8018
8019 fLego->LightSource(0, ydiff, 0, 0, 0, irep);
8020 fLego->LightSource(1, yligh1, 1, 1, 1, irep);
8021 fLego->SurfaceProperty(qa, qd, qs, 1, irep);
8022 fmin = ydiff*qa;
8023 fmax = ydiff*qa + (yligh1+0.1)*(qd+qs);
8024 fLego->SetIsoSurfaceParameters(fmin, fmax, nbcol, ic1, ic2, ic3);
8025
8026 fLego->IsoSurface(1, s, nx, ny, nz, x.data(), y.data(), z.data(), "BF");
8027
8028 if (Hoption.FrontBox) {
8029 fLego->InitMoveScreen(-1.1,1.1);
8031 fLego->FrontBox(90);
8032 }
8033 if (!Hoption.Axis && !Hoption.Same) {
8034 TGaxis axis;
8035 PaintLegoAxis(&axis, 90);
8036 }
8037
8038 PaintTitle();
8039
8040 //Draw stats and fit results
8041 TF1 *fit = nullptr;
8042 TIter next(fFunctions);
8043 while (auto obj = next()) {
8044 if (obj->InheritsFrom(TF1::Class())) {
8045 fit = (TF1*)obj;
8046 break;
8047 }
8048 }
8049 if ((Hoption.Same%10) != 1) {
8050 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
8052 }
8053 }
8054
8055 fLego.reset();
8056}
8057
8058////////////////////////////////////////////////////////////////////////////////
8059/// [Control function to draw a 2D histogram as a lego plot.](\ref HP17)
8060
8062{
8063
8064 Int_t raster = 1;
8065 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
8066 Int_t nx = Hparam.xlast - Hparam.xfirst + 1;
8067 Int_t ny = Hparam.ylast - Hparam.yfirst + 1;
8068 Double_t zmin = Hparam.zmin;
8069 Double_t zmax = Hparam.zmax;
8074 Double_t dangle = 10*3.141592/180; //Delta angle for Rapidity option
8075 Double_t deltaz = TMath::Abs(zmin);
8076 if (deltaz == 0) deltaz = 1;
8077 if (zmin >= zmax) {
8078 zmin -= 0.5*deltaz;
8079 zmax += 0.5*deltaz;
8080 }
8081 Double_t z1c = zmin;
8082 Double_t z2c = zmin + (zmax-zmin)*(1+gStyle->GetHistTopMargin());
8083
8084 // Compute the lego limits and instantiate a lego object
8085 fXbuf[0] = -1;
8086 fYbuf[0] = 1;
8087 fXbuf[1] = -1;
8088 fYbuf[1] = 1;
8089 if (Hoption.System == kPOLAR) {
8090 fXbuf[2] = z1c;
8091 fYbuf[2] = z2c;
8092 } else if (Hoption.System == kCYLINDRICAL) {
8093 if (Hoption.Logy) {
8094 if (ylab1 > 0) fXbuf[2] = TMath::Log10(ylab1);
8095 else fXbuf[2] = 0;
8096 if (ylab2 > 0) fYbuf[2] = TMath::Log10(ylab2);
8097 else fYbuf[2] = 0;
8098 } else {
8099 fXbuf[2] = ylab1;
8100 fYbuf[2] = ylab2;
8101 }
8102 z1c = 0; z2c = 1;
8103 } else if (Hoption.System == kSPHERICAL) {
8104 fXbuf[2] = -1;
8105 fYbuf[2] = 1;
8106 z1c = 0; z2c = 1;
8107 } else if (Hoption.System == kRAPIDITY) {
8108 fXbuf[2] = -1/TMath::Tan(dangle);
8109 fYbuf[2] = 1/TMath::Tan(dangle);
8110 } else {
8111 fXbuf[0] = xlab1;
8112 fYbuf[0] = xlab2;
8113 fXbuf[1] = ylab1;
8114 fYbuf[1] = ylab2;
8115 fXbuf[2] = z1c;
8116 fYbuf[2] = z2c;
8117 raster = 0;
8118 }
8119
8120 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data(), Hoption.System);
8121
8122 Int_t nids = -1;
8123 TH1 * hid = nullptr;
8124 Color_t colormain = -1, colordark = -1;
8126
8127 // LEGO3 is like LEGO1 except that the black lines around each lego are not drawn.
8128 if (Hoption.Lego == 13) {
8129 Hoption.Lego = 11;
8130 fLego->SetMesh(0);
8131 }
8132 // LEGO4 is like LEGO1 except no shadows are drawn.
8133 if (Hoption.Lego == 14) {
8134 Hoption.Lego = 11;
8136 }
8137
8138 // Initialize the levels on the Z axis
8139 Int_t ndiv = fH->GetContour();
8140 if (ndiv == 0 ) {
8141 ndiv = gStyle->GetNumberContours();
8142 fH->SetContour(ndiv);
8143 }
8144 Int_t ndivz = TMath::Abs(ndiv);
8145 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
8146
8147 // Initialize colors
8148 if (!fStack) {
8149 fLego->SetEdgeAtt(fH->GetLineColor(),fH->GetLineStyle(),fH->GetLineWidth(),0);
8150 } else {
8151 for (Int_t id=0;id<=fStack->GetSize();id++) {
8152 hid = (TH1*)fStack->At((id==0)?id:id-1);
8153 fLego->SetEdgeAtt(hid->GetLineColor(),hid->GetLineStyle(),hid->GetLineWidth(),id);
8154 }
8155 }
8156
8157 if (Hoption.Lego == 11) {
8158 nids = 1;
8159 if (fStack) nids = fStack->GetSize();
8160 hid = fH;
8161 for (Int_t id=0;id<=nids;id++) {
8162 if (id > 0 && fStack) hid = (TH1*)fStack->At(id-1);
8163 colormain = hid->GetFillColor();
8164 if (colormain == 1) colormain = 17; //avoid drawing with black
8166 else colordark = colormain;
8167 fLego->SetColorMain(colormain,id);
8168 fLego->SetColorDark(colordark,id);
8169 if (id <= 1) fLego->SetColorMain(colormain,-1); // Set Bottom color
8170 if (id == nids) fLego->SetColorMain(colormain,99); // Set Top color
8171 }
8172 }
8173
8174 // Now ready to draw the lego plot
8175 Int_t irep = 0;
8176
8177 TView *view = gPad ? gPad->GetView() : nullptr;
8178 if (!view) {
8179 Error("PaintLego", "no TView in current pad");
8180 return;
8181 }
8182
8183 Double_t thedeg = 90 - gPad->GetTheta();
8184 Double_t phideg = -90 - gPad->GetPhi();
8185 Double_t psideg = view->GetPsi();
8186 view->SetView(phideg, thedeg, psideg, irep);
8187
8188 fLego->SetLineColor(kBlack); // zgrid color for lego1 & lego2
8189 fLego->SetFillStyle(fH->GetFillStyle());
8190
8191 // Set color/style for back box
8192 fLego->SetFillStyle(gPad->GetFrameFillStyle());
8193 fLego->SetFillColor(gPad->GetFrameFillColor());
8194 fLego->TAttFill::Modify();
8195
8196 Int_t backcolor = gPad->GetFrameFillColor();
8197 if (Hoption.System != kCARTESIAN) backcolor = 0;
8198 view->PadRange(backcolor);
8199
8200 fLego->SetFillStyle(fH->GetFillStyle());
8201 fLego->SetFillColor(fH->GetFillColor());
8202 fLego->TAttFill::Modify();
8203
8204 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
8205
8206 if (raster) fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
8207 else fLego->InitMoveScreen(-1.1,1.1);
8208
8209 if (Hoption.Lego == 19) {
8211 if (Hoption.BackBox) fLego->BackBox(90);
8212 if (Hoption.FrontBox) fLego->FrontBox(90);
8213 if (!Hoption.Axis) { TGaxis axis; PaintLegoAxis(&axis, 90); }
8214 return;
8215 }
8216
8217 if (Hoption.Lego == 11 || Hoption.Lego == 12) {
8220 fLego->BackBox(90);
8221 }
8222 }
8223
8224 if (Hoption.Lego == 12) DefineColorLevels(ndivz);
8225
8226 fLego->SetLegoFunction(&TPainter3dAlgorithms::LegoFunction);
8228 if (Hoption.Lego == 11) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode3);
8229 if (Hoption.Lego == 12) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode2);
8230 if (Hoption.System == kPOLAR) {
8231 if (Hoption.Lego == 1) fLego->LegoPolar(1,nx,ny,"FB");
8232 if (Hoption.Lego == 11) fLego->LegoPolar(1,nx,ny,"BF");
8233 if (Hoption.Lego == 12) fLego->LegoPolar(1,nx,ny,"BF");
8234 } else if (Hoption.System == kCYLINDRICAL) {
8235 if (Hoption.Lego == 1) fLego->LegoCylindrical(1,nx,ny,"FB");
8236 if (Hoption.Lego == 11) fLego->LegoCylindrical(1,nx,ny,"BF");
8237 if (Hoption.Lego == 12) fLego->LegoCylindrical(1,nx,ny,"BF");
8238 } else if (Hoption.System == kSPHERICAL) {
8239 if (Hoption.Lego == 1) fLego->LegoSpherical(0,1,nx,ny,"FB");
8240 if (Hoption.Lego == 11) fLego->LegoSpherical(0,1,nx,ny,"BF");
8241 if (Hoption.Lego == 12) fLego->LegoSpherical(0,1,nx,ny,"BF");
8242 } else if (Hoption.System == kRAPIDITY) {
8243 if (Hoption.Lego == 1) fLego->LegoSpherical(1,1,nx,ny,"FB");
8244 if (Hoption.Lego == 11) fLego->LegoSpherical(1,1,nx,ny,"BF");
8245 if (Hoption.Lego == 12) fLego->LegoSpherical(1,1,nx,ny,"BF");
8246 } else {
8247 if (Hoption.Lego == 1) {
8249 fLego->LegoCartesian(90,nx,ny,"FB");}
8250 if (Hoption.Lego == 11) fLego->LegoCartesian(90,nx,ny,"BF");
8251 if (Hoption.Lego == 12) fLego->LegoCartesian(90,nx,ny,"BF");
8252 }
8253
8254 if (Hoption.Lego == 1 || Hoption.Lego == 11) {
8257 fLego->BackBox(90);
8258 }
8259 }
8260 if (Hoption.System == kCARTESIAN) {
8261 fLego->InitMoveScreen(-1.1,1.1);
8263 if (Hoption.FrontBox) fLego->FrontBox(90);
8264 }
8265 if (!Hoption.Axis && !Hoption.Same) {
8266 TGaxis axis;
8267 PaintLegoAxis(&axis, 90);
8268 }
8270 fLego.reset();
8271}
8272
8273////////////////////////////////////////////////////////////////////////////////
8274/// Draw the axis for legos and surface plots.
8275
8277{
8278
8279 static Double_t epsil = 0.001;
8280
8283 Double_t r[24] /* was [3][8] */;
8284 Int_t ndivx, ndivy, ndivz, i;
8285 Double_t x1[3], x2[3], y1[3], y2[3], z1[3], z2[3], av[24] /* was [3][8] */;
8286 static char chopax[8], chopay[8], chopaz[8];
8287 Int_t ix1, ix2, iy1, iy2, iz1, iz2;
8288 Double_t rad;
8289
8290 TView *view = gPad ? gPad->GetView() : nullptr;
8291 if (!view) {
8292 Error("PaintLegoAxis", "no TView in current pad");
8293 return;
8294 }
8295
8296 // In polar coordinates, draw a short line going from the external circle
8297 // corresponding to r = 1 up to r = 1.1
8298 if (Hoption.System == kPOLAR) {
8299 r[0] = 1;
8300 r[1] = 0;
8301 r[2] = 0;
8302 view->WCtoNDC(r, x1);
8303 r[0] = 1.1;
8304 r[1] = 0;
8305 r[2] = 0;
8306 view->WCtoNDC(r, x2);
8307 gPad->PaintLine(x1[0],x1[1],x2[0],x2[1]);
8308 return;
8309 }
8310
8311 if (Hoption.System != kCARTESIAN) return;
8312
8313 rad = TMath::ATan(1.) * 4. /180.;
8314 cosa = TMath::Cos(ang*rad);
8315 sina = TMath::Sin(ang*rad);
8316
8317 view->AxisVertex(ang, av, ix1, ix2, iy1, iy2, iz1, iz2);
8318 for (i = 1; i <= 8; ++i) {
8319 r[i*3 - 3] = av[i*3 - 3] + av[i*3 - 2]*cosa;
8320 r[i*3 - 2] = av[i*3 - 2]*sina;
8321 r[i*3 - 1] = av[i*3 - 1];
8322 }
8323
8324 view->WCtoNDC(&r[ix1*3 - 3], x1);
8325 view->WCtoNDC(&r[ix2*3 - 3], x2);
8326 view->WCtoNDC(&r[iy1*3 - 3], y1);
8327 view->WCtoNDC(&r[iy2*3 - 3], y2);
8328 view->WCtoNDC(&r[iz1*3 - 3], z1);
8329 view->WCtoNDC(&r[iz2*3 - 3], z2);
8330
8331 view->SetAxisNDC(x1, x2, y1, y2, z1, z2);
8332
8333 Double_t *rmin = view->GetRmin();
8334 Double_t *rmax = view->GetRmax();
8335 if (!rmin || !rmax) return;
8336
8337 // Initialize the axis options
8338 if (x1[0] > x2[0]) strlcpy(chopax, "SDH=+",8);
8339 else strlcpy(chopax, "SDH=-",8);
8340 if (y1[0] > y2[0]) strlcpy(chopay, "SDH=+",8);
8341 else strlcpy(chopay, "SDH=-",8);
8342 if (z2[1] > z1[1]) strlcpy(chopaz, "SDH=+",8);
8343 else strlcpy(chopaz, "SDH=-",8);
8344
8345 // Option LOG is required ?
8346 if (Hoption.Logx) strlcat(chopax,"G",8);
8347 if (Hoption.Logy) strlcat(chopay,"G",8);
8348 if (Hoption.Logz) strlcat(chopaz,"G",8);
8349
8350 // Initialize the number of divisions. If the
8351 // number of divisions is negative, option 'N' is required.
8355 if (ndivx < 0) {
8357 strlcat(chopax, "N",8);
8358 }
8359 if (ndivy < 0) {
8361 strlcat(chopay, "N",8);
8362 }
8363 if (ndivz < 0) {
8365 strlcat(chopaz, "N",8);
8366 }
8367
8368 // Set Axis attributes.
8369 // The variable SCALE rescales the VSIZ
8370 // in order to have the same label size for all angles.
8371
8372 axis->SetLineWidth(1);
8373
8374 // X axis drawing
8375 if (TMath::Abs(x1[0] - x2[0]) >= epsil || TMath::Abs(x1[1] - x2[1]) > epsil) {
8378 if (Hoption.Logx && !fH->InheritsFrom(TH3::Class())) {
8379 bmin = TMath::Power(10, rmin[0]);
8380 bmax = TMath::Power(10, rmax[0]);
8381 } else {
8382 bmin = rmin[0];
8383 bmax = rmax[0];
8384 }
8385 // Option time display is required ?
8386 if (fXaxis->GetTimeDisplay()) {
8387 strlcat(chopax,"t",8);
8388 if (strlen(fXaxis->GetTimeFormatOnly()) == 0) {
8390 } else {
8392 }
8393 }
8394 axis->SetOption(chopax);
8395 axis->PaintAxis(x1[0], x1[1], x2[0], x2[1], bmin, bmax, ndivx, chopax);
8396 }
8397
8398 // Y axis drawing
8399 if (TMath::Abs(y1[0] - y2[0]) >= epsil || TMath::Abs(y1[1] - y2[1]) > epsil) {
8402 if (fYaxis->GetTitleOffset() == 0) axis->SetTitleOffset(1.5);
8403
8404 if (fH->GetDimension() < 2) {
8405 strlcpy(chopay, "V=+UN",8);
8406 ndivy = 0;
8407 }
8408 if (TMath::Abs(y1[0] - y2[0]) < epsil) {
8409 y2[0] = y1[0];
8410 }
8411 if (Hoption.Logy && !fH->InheritsFrom(TH3::Class())) {
8412 bmin = TMath::Power(10, rmin[1]);
8413 bmax = TMath::Power(10, rmax[1]);
8414 } else {
8415 bmin = rmin[1];
8416 bmax = rmax[1];
8417 }
8418 // Option time display is required ?
8419 if (fYaxis->GetTimeDisplay()) {
8420 strlcat(chopay,"t",8);
8421 if (strlen(fYaxis->GetTimeFormatOnly()) == 0) {
8423 } else {
8425 }
8426 }
8427 axis->SetOption(chopay);
8428 axis->PaintAxis(y1[0], y1[1], y2[0], y2[1], bmin, bmax, ndivy, chopay);
8429 }
8430
8431 // Z axis drawing
8432 if (TMath::Abs(z1[0] - z2[0]) >= 100*epsil || TMath::Abs(z1[1] - z2[1]) > 100*epsil) {
8434 if (Hoption.Logz && !fH->InheritsFrom(TH3::Class())) {
8435 bmin = TMath::Power(10, rmin[2]);
8436 bmax = TMath::Power(10, rmax[2]);
8437 } else {
8438 bmin = rmin[2];
8439 bmax = rmax[2];
8440 }
8441 // Option time display is required ?
8442 if (fZaxis->GetTimeDisplay()) {
8443 strlcat(chopaz,"t",8);
8444 if (strlen(fZaxis->GetTimeFormatOnly()) == 0) {
8446 } else {
8448 }
8449 }
8450 axis->SetOption(chopaz);
8452 if (ztit.Index(";")>0) {
8453 ztit.Remove(ztit.Index(";"),ztit.Length());
8454 axis->SetTitle(ztit.Data());
8455 }
8456 axis->PaintAxis(z1[0], z1[1], z2[0], z2[1], bmin, bmax, ndivz, chopaz);
8457 }
8458
8459 //fH->SetLineStyle(1); /// otherwise fEdgeStyle[i] gets overwritten!
8460}
8461
8462////////////////////////////////////////////////////////////////////////////////
8463/// [Paint the color palette on the right side of the pad.](\ref HP22)
8464
8466{
8468 TView *view = gPad ? gPad->GetView() : nullptr;
8469 if (palette) {
8470 if (view) {
8471 if (!palette->TestBit(TPaletteAxis::kHasView)) {
8473 delete palette; palette = nullptr;
8474 }
8475 } else {
8476 if (palette->TestBit(TPaletteAxis::kHasView)) {
8478 delete palette; palette = nullptr;
8479 }
8480 }
8481 // make sure the histogram member of the palette is setup correctly. It may not be after a Clone()
8482 if (palette && !palette->GetHistogram()) palette->SetHistogram(fH);
8483 }
8484
8485 if (!palette) {
8486 Double_t xup = gPad->GetUxmax();
8487 Double_t x2 = gPad->PadtoX(gPad->GetX2());
8488 Double_t ymin = gPad->PadtoY(gPad->GetUymin());
8489 Double_t ymax = gPad->PadtoY(gPad->GetUymax());
8490 Double_t xr = 0.05*(gPad->GetX2() - gPad->GetX1());
8491 Double_t xmin = gPad->PadtoX(xup +0.1*xr);
8492 Double_t xmax = gPad->PadtoX(xup + xr);
8493 if (xmax > x2) xmax = gPad->PadtoX(gPad->GetX2()-0.01*xr);
8496 palette->Paint();
8497 }
8498}
8499
8500////////////////////////////////////////////////////////////////////////////////
8501/// [Control function to draw a 2D histogram as a scatter plot.](\ref HP11)
8502
8504{
8505
8506 fH->TAttMarker::Modify();
8507
8508 Int_t k, marker;
8509 Double_t dz, z, xk,xstep, yk, ystep;
8510 Double_t scale = 1;
8512 Double_t zmax = fH->GetMaximum();
8513 Double_t zmin = fH->GetMinimum();
8514 if (zmin == 0 && zmax == 0) return;
8515 if (zmin == zmax) {
8516 zmax += 0.1*TMath::Abs(zmax);
8517 zmin -= 0.1*TMath::Abs(zmin);
8518 }
8520 if (Hoption.Logz) {
8521 if (zmin > 0) zmin = TMath::Log10(zmin);
8522 else zmin = 0;
8523 if (zmax > 0) zmax = TMath::Log10(zmax);
8524 else zmax = 0;
8525 if (zmin == 0 && zmax == 0) return;
8526 dz = zmax - zmin;
8527 scale = 100/dz;
8528 if (ncells > 10000) scale /= 5;
8529 ltest = kTRUE;
8530 } else {
8531 dz = zmax - zmin;
8532 if (dz >= kNMAX || zmax < 1) {
8533 scale = (kNMAX-1)/dz;
8534 if (ncells > 10000) scale /= 5;
8535 ltest = kTRUE;
8536 }
8537 }
8538 if (fH->GetMinimumStored() == -1111) {
8540 if (Hoption.MinimumZero) {
8541 if (zmin >= 0) zmin = 0;
8542 else zmin -= yMARGIN*(zmax-zmin);
8543 } else {
8544 Double_t dzmin = yMARGIN*(zmax-zmin);
8545 if (zmin >= 0 && (zmin-dzmin <= 0)) zmin = 0;
8546 else zmin -= dzmin;
8547 }
8548 }
8549
8550 TString opt = option;
8551 opt.ToLower();
8552 if (opt.Contains("scat=")) {
8553 char optscat[100];
8554 strlcpy(optscat,opt.Data(),100);
8555 char *oscat = strstr(optscat,"scat=");
8556 char *blank = strstr(oscat," "); if (blank) *blank = 0;
8557 sscanf(oscat+5,"%lg",&scale);
8558 }
8559 // use an independent instance of a random generator
8560 // instead of gRandom to avoid conflicts and
8561 // to get same random numbers when drawing the same histogram
8563 marker=0;
8564 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
8567 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
8568 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
8569 xk = fXaxis->GetBinLowEdge(i);
8570 xstep = fXaxis->GetBinWidth(i);
8571 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
8572 z = fH->GetBinContent(bin);
8573 if (z < zmin) z = zmin;
8574 if (z > zmax) z = zmax;
8575 if (Hoption.Logz) {
8576 if (z > 0) z = TMath::Log10(z) - zmin;
8577 } else {
8578 z -= zmin;
8579 }
8580 if (z <= 0) continue;
8581 k = Int_t(z*scale);
8582 if (ltest) k++;
8583 if (k > 0) {
8584 for (Int_t loop=0; loop<k; loop++) {
8585 if (k+marker >= kNMAX) {
8586 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
8587 marker=0;
8588 }
8589 fXbuf[marker] = (random.Rndm()*xstep) + xk;
8590 fYbuf[marker] = (random.Rndm()*ystep) + yk;
8591 if (Hoption.Logx) {
8592 if (fXbuf[marker] > 0) fXbuf[marker] = TMath::Log10(fXbuf[marker]);
8593 else break;
8594 }
8595 if (Hoption.Logy) {
8596 if (fYbuf[marker] > 0) fYbuf[marker] = TMath::Log10(fYbuf[marker]);
8597 else break;
8598 }
8599 if (fXbuf[marker] < gPad->GetUxmin()) break;
8600 if (fYbuf[marker] < gPad->GetUymin()) break;
8601 if (fXbuf[marker] > gPad->GetUxmax()) break;
8602 if (fYbuf[marker] > gPad->GetUymax()) break;
8603 marker++;
8604 }
8605 }
8606 }
8607 }
8608 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
8609
8611}
8612
8613////////////////////////////////////////////////////////////////////////////////
8614/// Static function to paint special objects like vectors and matrices.
8615/// This function is called via `gROOT->ProcessLine` to paint these objects
8616/// without having a direct dependency of the graphics or histogramming
8617/// system.
8618
8620{
8621
8622 if (!obj) return;
8625
8626 if (obj->InheritsFrom(TMatrixFBase::Class())) {
8627 // case TMatrixF
8628 TH2F *R__TMatrixFBase = new TH2F((TMatrixFBase &)*obj);
8629 R__TMatrixFBase->SetBit(kCanDelete);
8630 R__TMatrixFBase->Draw(option);
8631
8632 } else if (obj->InheritsFrom(TMatrixDBase::Class())) {
8633 // case TMatrixD
8634 TH2D *R__TMatrixDBase = new TH2D((TMatrixDBase &)*obj);
8635 R__TMatrixDBase->SetBit(kCanDelete);
8636 R__TMatrixDBase->Draw(option);
8637
8638 } else if (obj->InheritsFrom(TVectorF::Class())) {
8639 //case TVectorF
8640 TH1F *R__TVectorF = new TH1F((TVectorF &)*obj);
8641 R__TVectorF->SetBit(kCanDelete);
8642 R__TVectorF->Draw(option);
8643
8644 } else if (obj->InheritsFrom(TVectorD::Class())) {
8645 //case TVectorD
8646 TH1D *R__TVectorD = new TH1D((TVectorD &)*obj);
8647 R__TVectorD->SetBit(kCanDelete);
8648 R__TVectorD->Draw(option);
8649 }
8650
8651 TH1::AddDirectory(status);
8652}
8653
8654////////////////////////////////////////////////////////////////////////////////
8655/// [Draw the statistics box for 1D and profile histograms.](\ref HP07)
8656
8658{
8659 TString tt, tf;
8660 Int_t dofit;
8661 TPaveStats *stats = nullptr;
8662 TIter next(fFunctions);
8663 while (auto obj = next()) {
8664 if (obj->InheritsFrom(TPaveStats::Class())) {
8665 stats = (TPaveStats*)obj;
8666 break;
8667 }
8668 }
8669
8670 if (stats && dostat) {
8671 dofit = stats->GetOptFit();
8672 dostat = stats->GetOptStat();
8673 } else {
8674 dofit = gStyle->GetOptFit();
8675 }
8676 if (!dofit) fit = nullptr;
8677 if (dofit == 1) dofit = 111;
8678 if (dostat == 1) dostat = 1111;
8679 Int_t print_name = dostat%10;
8680 Int_t print_entries = (dostat/10)%10;
8681 Int_t print_mean = (dostat/100)%10;
8682 Int_t print_stddev = (dostat/1000)%10;
8683 Int_t print_under = (dostat/10000)%10;
8684 Int_t print_over = (dostat/100000)%10;
8685 Int_t print_integral= (dostat/1000000)%10;
8686 Int_t print_skew = (dostat/10000000)%10;
8687 Int_t print_kurt = (dostat/100000000)%10;
8691 Int_t print_fval = dofit%10;
8692 Int_t print_ferrors = (dofit/10)%10;
8693 Int_t print_fchi2 = (dofit/100)%10;
8694 Int_t print_fprob = (dofit/1000)%10;
8696 if (fit) {
8697 if (print_fval < 2) nlinesf += fit->GetNumberFreeParameters();
8698 else nlinesf += fit->GetNpar();
8699 }
8701
8702 // Pavetext with statistics
8703 Bool_t done = kFALSE;
8704 if (!dostat && !fit) {
8705 if (stats) { fFunctions->Remove(stats); delete stats;}
8706 return;
8707 }
8709 if (fit) statw = 1.8*gStyle->GetStatW();
8711 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
8712 stath = 0.25*(nlines+nlinesf)*gStyle->GetStatH();
8713 }
8714 if (stats) {
8715 stats->Clear();
8716 done = kTRUE;
8717 } else {
8718 stats = new TPaveStats(
8721 gStyle->GetStatX(),
8722 gStyle->GetStatY(),"brNDC");
8723
8724 stats->SetParent(fH);
8725 stats->SetOptFit(dofit);
8726 stats->SetOptStat(dostat);
8727 stats->SetFillColor(gStyle->GetStatColor());
8728 stats->SetFillStyle(gStyle->GetStatStyle());
8729 stats->SetBorderSize(gStyle->GetStatBorderSize());
8730 stats->SetTextFont(gStyle->GetStatFont());
8731 if (gStyle->GetStatFont()%10 > 2)
8732 stats->SetTextSize(gStyle->GetStatFontSize());
8733 stats->SetFitFormat(gStyle->GetFitFormat());
8734 stats->SetStatFormat(gStyle->GetStatFormat());
8735 stats->SetName("stats");
8736
8737 stats->SetTextColor(gStyle->GetStatTextColor());
8738 stats->SetTextAlign(12);
8739 stats->SetBit(kCanDelete);
8740 stats->SetBit(kMustCleanup);
8741 }
8742 if (print_name) stats->AddText(fH->GetName());
8743 if (print_entries) {
8744 if (fH->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(fH->GetEntries()+0.5));
8745 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(fH->GetEntries()));
8746 stats->AddText(tt.Data());
8747 }
8748 if (print_mean) {
8749 if (print_mean == 1) {
8750 tf.Form("%s = %s%s",gStringMean.Data(),"%",stats->GetStatFormat());
8751 tt.Form(tf.Data(),fH->GetMean(1));
8752 } else {
8753 tf.Form("%s = %s%s #pm %s%s",gStringMean.Data(),"%",stats->GetStatFormat()
8754 ,"%",stats->GetStatFormat());
8755 tt.Form(tf.Data(),fH->GetMean(1),fH->GetMeanError(1));
8756 }
8757 stats->AddText(tt.Data());
8759 if (print_mean == 1) {
8760 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
8761 tt.Form(tf.Data(),fH->GetMean(2));
8762 } else {
8763 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
8764 ,"%",stats->GetStatFormat());
8765 tt.Form(tf.Data(),fH->GetMean(2),fH->GetMeanError(2));
8766 }
8767 stats->AddText(tt.Data());
8768 }
8769 }
8770 if (print_stddev) {
8771 if (print_stddev == 1) {
8772 tf.Form("%s = %s%s",gStringStdDev.Data(),"%",stats->GetStatFormat());
8773 tt.Form(tf.Data(),fH->GetStdDev(1));
8774 } else {
8775 tf.Form("%s = %s%s #pm %s%s",gStringStdDev.Data(),"%",stats->GetStatFormat()
8776 ,"%",stats->GetStatFormat());
8777 tt.Form(tf.Data(),fH->GetStdDev(1),fH->GetStdDevError(1));
8778 }
8779 stats->AddText(tt.Data());
8781 if (print_stddev == 1) {
8782 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
8783 tt.Form(tf.Data(),fH->GetStdDev(2));
8784 } else {
8785 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
8786 ,"%",stats->GetStatFormat());
8787 tt.Form(tf.Data(),fH->GetStdDev(2),fH->GetStdDevError(2));
8788 }
8789 stats->AddText(tt.Data());
8790 }
8791 }
8792 if (print_under) {
8793 tf.Form("%s = %s%s",gStringUnderflow.Data(),"%",stats->GetStatFormat());
8794 tt.Form(tf.Data(),fH->GetBinContent(0));
8795 stats->AddText(tt.Data());
8796 }
8797 if (print_over) {
8798 tf.Form("%s = %s%s",gStringOverflow.Data(),"%",stats->GetStatFormat());
8799 tt.Form(tf.Data(),fH->GetBinContent(fXaxis->GetNbins()+1));
8800 stats->AddText(tt.Data());
8801 }
8802 if (print_integral) {
8803 if (print_integral == 1) {
8804 tf.Form("%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
8805 tt.Form(tf.Data(),fH->Integral());
8806 } else {
8807 tf.Form("%s = %s%s",gStringIntegralBinWidth.Data(),"%",stats->GetStatFormat());
8808 tt.Form(tf.Data(),fH->Integral("width"));
8809 }
8810 stats->AddText(tt.Data());
8811 }
8812 if (print_skew) {
8813 if (print_skew == 1) {
8814 tf.Form("%s = %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat());
8815 tt.Form(tf.Data(),fH->GetSkewness(1));
8816 } else {
8817 tf.Form("%s = %s%s #pm %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat()
8818 ,"%",stats->GetStatFormat());
8819 tt.Form(tf.Data(),fH->GetSkewness(1),fH->GetSkewness(11));
8820 }
8821 stats->AddText(tt.Data());
8822 }
8823 if (print_kurt) {
8824 if (print_kurt == 1) {
8825 tf.Form("%s = %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat());
8826 tt.Form(tf.Data(),fH->GetKurtosis(1));
8827 } else {
8828 tf.Form("%s = %s%s #pm %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat()
8829 ,"%",stats->GetStatFormat());
8830 tt.Form(tf.Data(),fH->GetKurtosis(1),fH->GetKurtosis(11));
8831 }
8832 stats->AddText(tt.Data());
8833 }
8834
8835 // Draw Fit parameters
8836 if (fit) {
8837 Int_t ndf = fit->GetNDF();
8838 tf.Form("#chi^{2} / ndf = %s%s / %d","%",stats->GetFitFormat(),ndf);
8839 tt.Form(tf.Data(),fit->GetChisquare());
8840 if (print_fchi2) stats->AddText(tt.Data());
8841 if (print_fprob) {
8842 tf.Form("Prob = %s%s","%",stats->GetFitFormat());
8843 tt.Form(tf.Data(),TMath::Prob(fit->GetChisquare(),ndf));
8844 stats->AddText(tt.Data());
8845 }
8846 if (print_fval || print_ferrors) {
8848 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
8849 fit->GetParLimits(ipar,parmin,parmax);
8851 if (print_ferrors) {
8852 tf.Form("%-8s = %s%s #pm %s ", fit->GetParName(ipar), "%",stats->GetFitFormat(),
8853 GetBestFormat(fit->GetParameter(ipar), fit->GetParError(ipar), stats->GetFitFormat()));
8854 tt.Form(tf.Data(),fit->GetParameter(ipar)
8855 ,fit->GetParError(ipar));
8856 } else {
8857 tf.Form("%-8s = %s%s ",fit->GetParName(ipar), "%",stats->GetFitFormat());
8858 tt.Form(tf.Data(),fit->GetParameter(ipar));
8859 }
8860 stats->AddText(tt.Data());
8861 }
8862 }
8863 }
8864
8865 if (!done) fFunctions->Add(stats);
8866 stats->Paint(stats->GetOption());
8867}
8868
8869////////////////////////////////////////////////////////////////////////////////
8870/// [Draw the statistics box for 2D histograms.](\ref HP07)
8871
8873{
8874
8875 if (fH->GetDimension() != 2) return;
8876 TH2 *h2 = (TH2*)fH;
8877
8878 TString tt, tf;
8879 Int_t dofit;
8880 TPaveStats *stats = nullptr;
8881 TIter next(fFunctions);
8882 while (auto obj = next()) {
8883 if (obj->InheritsFrom(TPaveStats::Class())) {
8884 stats = (TPaveStats*)obj;
8885 break;
8886 }
8887 }
8888 if (stats && dostat) {
8889 dofit = stats->GetOptFit();
8890 dostat = stats->GetOptStat();
8891 } else {
8892 dofit = gStyle->GetOptFit();
8893 }
8894 if (dostat == 1) dostat = 1111;
8895 Int_t print_name = dostat%10;
8896 Int_t print_entries = (dostat/10)%10;
8897 Int_t print_mean = (dostat/100)%10;
8898 Int_t print_stddev = (dostat/1000)%10;
8899 Int_t print_under = (dostat/10000)%10;
8900 Int_t print_over = (dostat/100000)%10;
8901 Int_t print_integral= (dostat/1000000)%10;
8902 Int_t print_skew = (dostat/10000000)%10;
8903 Int_t print_kurt = (dostat/100000000)%10;
8905 if (print_under || print_over) nlines += 3;
8906
8907 // Pavetext with statistics
8908 if (!gStyle->GetOptFit()) fit = nullptr;
8909 Bool_t done = kFALSE;
8910 if (!dostat && !fit) {
8911 if (stats) { fFunctions->Remove(stats); delete stats;}
8912 return;
8913 }
8915 if (fit) statw = 1.8*gStyle->GetStatW();
8917 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
8918 stath = 0.25*nlines*gStyle->GetStatH();
8919 }
8920 if (fit) stath += gStyle->GetStatH();
8921 if (stats) {
8922 stats->Clear();
8923 done = kTRUE;
8924 } else {
8925 stats = new TPaveStats(
8928 gStyle->GetStatX(),
8929 gStyle->GetStatY(),"brNDC");
8930
8931 stats->SetParent(fH);
8932 stats->SetOptFit(dofit);
8933 stats->SetOptStat(dostat);
8934 stats->SetFillColor(gStyle->GetStatColor());
8935 stats->SetFillStyle(gStyle->GetStatStyle());
8936 stats->SetBorderSize(gStyle->GetStatBorderSize());
8937 stats->SetName("stats");
8938
8939 stats->SetTextColor(gStyle->GetStatTextColor());
8940 stats->SetTextAlign(12);
8941 stats->SetTextFont(gStyle->GetStatFont());
8942 if (gStyle->GetStatFont()%10 > 2)
8943 stats->SetTextSize(gStyle->GetStatFontSize());
8944 stats->SetFitFormat(gStyle->GetFitFormat());
8945 stats->SetStatFormat(gStyle->GetStatFormat());
8946 stats->SetBit(kCanDelete);
8947 stats->SetBit(kMustCleanup);
8948 }
8949 if (print_name) stats->AddText(h2->GetName());
8950 if (print_entries) {
8951 if (h2->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(h2->GetEntries()+0.5));
8952 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(h2->GetEntries()));
8953 stats->AddText(tt.Data());
8954 }
8955 if (print_mean) {
8956 if (print_mean == 1) {
8957 tf.Form("%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
8958 tt.Form(tf.Data(),h2->GetMean(1));
8959 stats->AddText(tt.Data());
8960 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
8961 tt.Form(tf.Data(),h2->GetMean(2));
8962 stats->AddText(tt.Data());
8963 } else {
8964 tf.Form("%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
8965 ,"%",stats->GetStatFormat());
8966 tt.Form(tf.Data(),h2->GetMean(1),h2->GetMeanError(1));
8967 stats->AddText(tt.Data());
8968 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
8969 ,"%",stats->GetStatFormat());
8970 tt.Form(tf.Data(),h2->GetMean(2),h2->GetMeanError(2));
8971 stats->AddText(tt.Data());
8972 }
8973 }
8974 if (print_stddev) {
8975 if (print_stddev == 1) {
8976 tf.Form("%s = %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat());
8977 tt.Form(tf.Data(),h2->GetStdDev(1));
8978 stats->AddText(tt.Data());
8979 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
8980 tt.Form(tf.Data(),h2->GetStdDev(2));
8981 stats->AddText(tt.Data());
8982 } else {
8983 tf.Form("%s = %s%s #pm %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat()
8984 ,"%",stats->GetStatFormat());
8985 tt.Form(tf.Data(),h2->GetStdDev(1),h2->GetStdDevError(1));
8986 stats->AddText(tt.Data());
8987 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
8988 ,"%",stats->GetStatFormat());
8989 tt.Form(tf.Data(),h2->GetStdDev(2),h2->GetStdDevError(2));
8990 stats->AddText(tt.Data());
8991 }
8992 }
8993 if (print_integral) {
8994 tf.Form("%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
8995 tt.Form(tf.Data(),fH->Integral());
8996 stats->AddText(tt.Data());
8997 }
8998 if (print_skew) {
8999 if (print_skew == 1) {
9000 tf.Form("%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
9001 tt.Form(tf.Data(),h2->GetSkewness(1));
9002 stats->AddText(tt.Data());
9003 tf.Form("%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
9004 tt.Form(tf.Data(),h2->GetSkewness(2));
9005 stats->AddText(tt.Data());
9006 } else {
9007 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
9008 ,"%",stats->GetStatFormat());
9009 tt.Form(tf.Data(),h2->GetSkewness(1),h2->GetSkewness(11));
9010 stats->AddText(tt.Data());
9011 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
9012 ,"%",stats->GetStatFormat());
9013 tt.Form(tf.Data(),h2->GetSkewness(2),h2->GetSkewness(12));
9014 stats->AddText(tt.Data());
9015 }
9016 }
9017 if (print_kurt) {
9018 if (print_kurt == 1) {
9019 tf.Form("%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
9020 tt.Form(tf.Data(),h2->GetKurtosis(1));
9021 stats->AddText(tt.Data());
9022 tf.Form("%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
9023 tt.Form(tf.Data(),h2->GetKurtosis(2));
9024 stats->AddText(tt.Data());
9025 } else {
9026 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
9027 ,"%",stats->GetStatFormat());
9028 tt.Form(tf.Data(),h2->GetKurtosis(1),h2->GetKurtosis(11));
9029 stats->AddText(tt.Data());
9030 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
9031 ,"%",stats->GetStatFormat());
9032 tt.Form(tf.Data(),h2->GetKurtosis(2),h2->GetKurtosis(12));
9033 stats->AddText(tt.Data());
9034 }
9035 }
9036 if (print_under || print_over) {
9037 //get 3*3 under/overflows for 2d hist
9038 Double_t unov[9];
9039
9040 Int_t cellsX = h2->GetXaxis()->GetNbins() + 1;
9041 Int_t cellsY = h2->GetYaxis()->GetNbins() + 1;
9042 Int_t firstX = std::max(1, h2->GetXaxis()->GetFirst());
9043 Int_t firstY = std::max(1, h2->GetYaxis()->GetFirst());
9044 Int_t lastX = std::min(h2->GetXaxis()->GetLast(), h2->GetXaxis()->GetNbins());
9045 Int_t lastY = std::min(h2->GetYaxis()->GetLast(), h2->GetYaxis()->GetNbins());
9046
9047 unov[0] = h2->Integral( 0, firstX-1, lastY+1, cellsY );
9048 unov[1] = h2->Integral(firstX , lastX , lastY+1, cellsY );
9049 unov[2] = h2->Integral(lastX+1, cellsX , lastY+1, cellsY );
9050 unov[3] = h2->Integral( 0, firstX-1, firstY , lastY );
9051 unov[4] = h2->Integral(firstX , lastX , firstY , lastY );
9052 unov[5] = h2->Integral(lastX+1, cellsX , firstY , lastY );
9053 unov[6] = h2->Integral( 0, firstX-1, 0, firstY-1);
9054 unov[7] = h2->Integral(firstX, lastX, 0, firstY-1);
9055 unov[8] = h2->Integral(lastX+1, cellsX , 0, firstY-1);
9056
9057 tt.Form("%g|%g|%g\n", unov[0], unov[1], unov[2]);
9058 stats->AddText(tt.Data());
9059 tt.Form("%g|%g|%g\n", unov[3], unov[4], unov[5]);
9060 stats->AddText(tt.Data());
9061 tt.Form("%g|%g|%g\n", unov[6], unov[7], unov[8]);
9062 stats->AddText(tt.Data());
9063 }
9064
9065 // Draw Fit parameters
9066 if (fit) {
9067 Int_t ndf = fit->GetNDF();
9068 tt.Form("#chi^{2} / ndf = %6.4g / %d",fit->GetChisquare(),ndf);
9069 stats->AddText(tt.Data());
9070 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
9071 tt.Form("%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
9072 ,fit->GetParameter(ipar)
9073 ,fit->GetParError(ipar));
9074 stats->AddText(tt.Data());
9075 }
9076 }
9077
9078 if (!done) fFunctions->Add(stats);
9079 stats->Paint(stats->GetOption());
9080}
9081
9082////////////////////////////////////////////////////////////////////////////////
9083/// [Draw the statistics box for 3D histograms.](\ref HP07)
9084
9086{
9087
9088 if (fH->GetDimension() != 3) return;
9089 TH3 *h3 = (TH3*)fH;
9090
9091 TString tt, tf;
9092 Int_t dofit;
9093 TPaveStats *stats = nullptr;
9094 TIter next(fFunctions);
9095 while (auto obj = next()) {
9096 if (obj->InheritsFrom(TPaveStats::Class())) {
9097 stats = (TPaveStats*)obj;
9098 break;
9099 }
9100 }
9101 if (stats && dostat) {
9102 dofit = stats->GetOptFit();
9103 dostat = stats->GetOptStat();
9104 } else {
9105 dofit = gStyle->GetOptFit();
9106 }
9107 if (dostat == 1) dostat = 1111;
9108 Int_t print_name = dostat%10;
9109 Int_t print_entries = (dostat/10)%10;
9110 Int_t print_mean = (dostat/100)%10;
9111 Int_t print_stddev = (dostat/1000)%10;
9112 Int_t print_under = (dostat/10000)%10;
9113 Int_t print_over = (dostat/100000)%10;
9114 Int_t print_integral= (dostat/1000000)%10;
9115 Int_t print_skew = (dostat/10000000)%10;
9116 Int_t print_kurt = (dostat/100000000)%10;
9118 if (print_under || print_over) nlines += 3;
9119
9120 // Pavetext with statistics
9121 if (!gStyle->GetOptFit()) fit = nullptr;
9122 Bool_t done = kFALSE;
9123 if (!dostat && !fit) {
9124 if (stats) { fFunctions->Remove(stats); delete stats;}
9125 return;
9126 }
9128 if (fit) statw = 1.8*gStyle->GetStatW();
9130 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
9131 stath = 0.25*nlines*gStyle->GetStatH();
9132 }
9133 if (fit) stath += gStyle->GetStatH();
9134 if (stats) {
9135 stats->Clear();
9136 done = kTRUE;
9137 } else {
9138 stats = new TPaveStats(
9141 gStyle->GetStatX(),
9142 gStyle->GetStatY(),"brNDC");
9143
9144 stats->SetParent(fH);
9145 stats->SetOptFit(dofit);
9146 stats->SetOptStat(dostat);
9147 stats->SetFillColor(gStyle->GetStatColor());
9148 stats->SetFillStyle(gStyle->GetStatStyle());
9149 stats->SetBorderSize(gStyle->GetStatBorderSize());
9150 stats->SetName("stats");
9151
9152 stats->SetTextColor(gStyle->GetStatTextColor());
9153 stats->SetTextAlign(12);
9154 stats->SetTextFont(gStyle->GetStatFont());
9155 stats->SetFitFormat(gStyle->GetFitFormat());
9156 stats->SetStatFormat(gStyle->GetStatFormat());
9157 stats->SetBit(kCanDelete);
9158 stats->SetBit(kMustCleanup);
9159 }
9160 if (print_name) stats->AddText(h3->GetName());
9161 if (print_entries) {
9162 if (h3->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(h3->GetEntries()+0.5));
9163 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(h3->GetEntries()+0.5));
9164 stats->AddText(tt.Data());
9165 }
9166 if (print_mean) {
9167 if (print_mean == 1) {
9168 tf.Form("%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
9169 tt.Form(tf.Data(),h3->GetMean(1));
9170 stats->AddText(tt.Data());
9171 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
9172 tt.Form(tf.Data(),h3->GetMean(2));
9173 stats->AddText(tt.Data());
9174 tf.Form("%s = %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat());
9175 tt.Form(tf.Data(),h3->GetMean(3));
9176 stats->AddText(tt.Data());
9177 } else {
9178 tf.Form("%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
9179 ,"%",stats->GetStatFormat());
9180 tt.Form(tf.Data(),h3->GetMean(1),h3->GetMeanError(1));
9181 stats->AddText(tt.Data());
9182 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
9183 ,"%",stats->GetStatFormat());
9184 tt.Form(tf.Data(),h3->GetMean(2),h3->GetMeanError(2));
9185 stats->AddText(tt.Data());
9186 tf.Form("%s = %s%s #pm %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat()
9187 ,"%",stats->GetStatFormat());
9188 tt.Form(tf.Data(),h3->GetMean(3),h3->GetMeanError(3));
9189 stats->AddText(tt.Data());
9190 }
9191 }
9192 if (print_stddev) {
9193 if (print_stddev == 1) {
9194 tf.Form("%s = %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat());
9195 tt.Form(tf.Data(),h3->GetStdDev(1));
9196 stats->AddText(tt.Data());
9197 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
9198 tt.Form(tf.Data(),h3->GetStdDev(2));
9199 stats->AddText(tt.Data());
9200 tf.Form("%s = %s%s",gStringStdDevZ.Data(),"%",stats->GetStatFormat());
9201 tt.Form(tf.Data(),h3->GetStdDev(3));
9202 stats->AddText(tt.Data());
9203 } else {
9204 tf.Form("%s = %s%s #pm %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat()
9205 ,"%",stats->GetStatFormat());
9206 tt.Form(tf.Data(),h3->GetStdDev(1),h3->GetStdDevError(1));
9207 stats->AddText(tt.Data());
9208 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
9209 ,"%",stats->GetStatFormat());
9210 tt.Form(tf.Data(),h3->GetStdDev(2),h3->GetStdDevError(2));
9211 stats->AddText(tt.Data());
9212 tf.Form("%s = %s%s #pm %s%s",gStringStdDevZ.Data(),"%",stats->GetStatFormat()
9213 ,"%",stats->GetStatFormat());
9214 tt.Form(tf.Data(),h3->GetStdDev(3),h3->GetStdDevError(3));
9215 stats->AddText(tt.Data());
9216 }
9217 }
9218 if (print_integral) {
9219 tt.Form("%s = %6.4g",gStringIntegral.Data(),h3->Integral());
9220 stats->AddText(tt.Data());
9221 }
9222 if (print_skew) {
9223 if (print_skew == 1) {
9224 tf.Form("%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
9225 tt.Form(tf.Data(),h3->GetSkewness(1));
9226 stats->AddText(tt.Data());
9227 tf.Form("%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
9228 tt.Form(tf.Data(),h3->GetSkewness(2));
9229 stats->AddText(tt.Data());
9230 tf.Form("%s = %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat());
9231 tt.Form(tf.Data(),h3->GetSkewness(3));
9232 stats->AddText(tt.Data());
9233 } else {
9234 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
9235 ,"%",stats->GetStatFormat());
9236 tt.Form(tf.Data(),h3->GetSkewness(1),h3->GetSkewness(11));
9237 stats->AddText(tt.Data());
9238 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
9239 ,"%",stats->GetStatFormat());
9240 tt.Form(tf.Data(),h3->GetSkewness(2),h3->GetSkewness(12));
9241 stats->AddText(tt.Data());
9242 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat()
9243 ,"%",stats->GetStatFormat());
9244 tt.Form(tf.Data(),h3->GetSkewness(3),h3->GetSkewness(13));
9245 stats->AddText(tt.Data());
9246 }
9247 }
9248 if (print_kurt) {
9249 if (print_kurt == 1) {
9250 tf.Form("%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
9251 tt.Form(tf.Data(),h3->GetKurtosis(1));
9252 stats->AddText(tt.Data());
9253 tf.Form("%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
9254 tt.Form(tf.Data(),h3->GetKurtosis(2));
9255 stats->AddText(tt.Data());
9256 tf.Form("%s = %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat());
9257 tt.Form(tf.Data(),h3->GetKurtosis(3));
9258 stats->AddText(tt.Data());
9259 } else {
9260 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
9261 ,"%",stats->GetStatFormat());
9262 tt.Form(tf.Data(),h3->GetKurtosis(1),h3->GetKurtosis(11));
9263 stats->AddText(tt.Data());
9264 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
9265 ,"%",stats->GetStatFormat());
9266 tt.Form(tf.Data(),h3->GetKurtosis(2),h3->GetKurtosis(12));
9267 stats->AddText(tt.Data());
9268 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat()
9269 ,"%",stats->GetStatFormat());
9270 tt.Form(tf.Data(),h3->GetKurtosis(3),h3->GetKurtosis(13));
9271 stats->AddText(tt.Data());
9272 }
9273 }
9274 if (print_under || print_over) {
9275 // no underflow - overflow printing for a 3D histogram
9276 // one would need a 3D table
9277 }
9278
9279 // Draw Fit parameters
9280 if (fit) {
9281 Int_t ndf = fit->GetNDF();
9282 tt.Form("#chi^{2} / ndf = %6.4g / %d",fit->GetChisquare(),ndf);
9283 stats->AddText(tt.Data());
9284 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
9285 tt.Form("%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
9286 ,fit->GetParameter(ipar)
9287 ,fit->GetParError(ipar));
9288 stats->AddText(tt.Data());
9289 }
9290 }
9291
9292 if (!done) fFunctions->Add(stats);
9293 stats->Paint(stats->GetOption());
9294}
9295
9296////////////////////////////////////////////////////////////////////////////////
9297/// [Control function to draw a 2D histogram as a surface plot.](\ref HP18)
9298
9300{
9301
9302 const Double_t ydiff = 1;
9303 const Double_t yligh1 = 10;
9304 const Double_t qa = 0.15;
9305 const Double_t qd = 0.15;
9306 const Double_t qs = 0.8;
9308 Int_t raster = 0;
9309 Int_t irep = 0;
9310
9311 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
9314 Double_t zmin = Hparam.zmin;
9315 Double_t zmax = Hparam.zmax;
9320 Double_t dangle = 10*3.141592/180; //Delta angle for Rapidity option
9321 Double_t deltaz = TMath::Abs(zmin);
9322 if (deltaz == 0) deltaz = 1;
9323 if (zmin >= zmax) {
9324 zmin -= 0.5*deltaz;
9325 zmax += 0.5*deltaz;
9326 }
9327 Double_t z1c = zmin;
9328 Double_t z2c = zmin + (zmax-zmin)*(1+gStyle->GetHistTopMargin());
9329 // Compute the lego limits and instantiate a lego object
9330 fXbuf[0] = -1;
9331 fYbuf[0] = 1;
9332 fXbuf[1] = -1;
9333 fYbuf[1] = 1;
9334 if (Hoption.System >= kPOLAR && (Hoption.Surf == 1 || Hoption.Surf == 13)) raster = 1;
9335 if (Hoption.System == kPOLAR) {
9336 fXbuf[2] = z1c;
9337 fYbuf[2] = z2c;
9338 } else if (Hoption.System == kCYLINDRICAL) {
9339 if (Hoption.Logy) {
9340 if (ylab1 > 0) fXbuf[2] = TMath::Log10(ylab1);
9341 else fXbuf[2] = 0;
9342 if (ylab2 > 0) fYbuf[2] = TMath::Log10(ylab2);
9343 else fYbuf[2] = 0;
9344 } else {
9345 fXbuf[2] = ylab1;
9346 fYbuf[2] = ylab2;
9347 }
9348 z1c = 0; z2c = 1;
9349 } else if (Hoption.System == kSPHERICAL) {
9350 fXbuf[2] = -1;
9351 fYbuf[2] = 1;
9352 z1c = 0; z2c = 1;
9353 } else if (Hoption.System == kRAPIDITY) {
9354 fXbuf[2] = -1/TMath::Tan(dangle);
9355 fYbuf[2] = 1/TMath::Tan(dangle);
9356 } else {
9357 fXbuf[0] = xlab1;
9358 fYbuf[0] = xlab2;
9359 fXbuf[1] = ylab1;
9360 fYbuf[1] = ylab2;
9361 fXbuf[2] = z1c;
9362 fYbuf[2] = z2c;
9363 }
9364
9365 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data(), Hoption.System);
9366 fLego->SetEdgeAtt(fH->GetLineColor(),fH->GetLineStyle(),fH->GetLineWidth(),0);
9367 fLego->SetFillColor(fH->GetFillColor());
9368
9369 // Initialize the levels on the Z axis
9370 Int_t ndiv = fH->GetContour();
9371 if (ndiv == 0 ) {
9372 ndiv = gStyle->GetNumberContours();
9373 fH->SetContour(ndiv);
9374 }
9375 Int_t ndivz = TMath::Abs(ndiv);
9376 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
9377
9378 if (Hoption.Surf == 13 || Hoption.Surf == 15) fLego->SetMesh(3);
9379 if (Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) fLego->SetMesh(0);
9380
9381 // Close the surface in case of non cartesian coordinates.
9382
9383 if (Hoption.System != kCARTESIAN) {nx++; ny++;}
9384
9385 // Now ready to draw the surface plot
9386
9387 TView *view = gPad ? gPad->GetView() : nullptr;
9388 if (!view) {
9389 Error("PaintSurface", "no TView in current pad");
9390 return;
9391 }
9392
9393 Double_t thedeg = 90 - gPad->GetTheta();
9394 Double_t phideg = -90 - gPad->GetPhi();
9395 Double_t psideg = view->GetPsi();
9396 view->SetView(phideg, thedeg, psideg, irep);
9397
9398 // Set color/style for back box
9399 if (Hoption.Same) {
9400 fLego->SetFillStyle(0);
9401 fLego->SetFillColor(1);
9402 } else {
9403 fLego->SetFillStyle(gPad->GetFrameFillStyle());
9404 fLego->SetFillColor(gPad->GetFrameFillColor());
9405 }
9406 fLego->TAttFill::Modify();
9407
9408 Int_t backcolor = gPad->GetFrameFillColor();
9409 if (Hoption.System != kCARTESIAN) backcolor = 0;
9410 view->PadRange(backcolor);
9411
9412 fLego->SetFillStyle(fH->GetFillStyle());
9413 fLego->SetFillColor(fH->GetFillColor());
9414 fLego->TAttFill::Modify();
9415
9416 // Draw the filled contour on top
9418
9420 if (Hoption.Surf == 13 || Hoption.Surf == 15) {
9422 Hoption.Surf = 23;
9423 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9425 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"BF");
9426 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9427 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9428 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9429 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"BF");
9431 fLego->SetMesh(1);
9432 }
9433
9434 if (raster) fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
9435 else fLego->InitMoveScreen(-1.1,1.1);
9436
9437 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) {
9438 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9441 fLego->BackBox(90);
9442 }
9443 }
9444
9445 // Gouraud Shading surface
9446 if (Hoption.Surf == 14) {
9447 // Set light sources
9448 fLego->LightSource(0, ydiff, 0,0,0,irep);
9449 fLego->LightSource(1, yligh1 ,1,1,1,irep);
9450 fLego->SurfaceProperty(qa, qd, qs, 1, irep);
9451 fmin = ydiff*qa;
9452 fmax = fmin + (yligh1+0.1)*(qd+qs);
9453 Int_t nbcol = 28;
9454 icol1 = 201;
9455 Double_t dcol = 0.5/Double_t(nbcol);
9456 TColor *colref = gROOT->GetColor(fH->GetFillColor());
9457 if (!colref) return;
9459 colref->GetRGB(r,g,b);
9461 TColor *acol;
9462 for (Int_t col=0;col<nbcol;col++) {
9463 acol = gROOT->GetColor(col+icol1);
9464 TColor::HLStoRGB(hue,.4+col*dcol,satur,r,g,b);
9465 if (acol) acol->SetRGB(r,g,b);
9466 }
9467 fLego->Spectrum(nbcol, fmin, fmax, icol1, 1, irep);
9468 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::GouraudFunction);
9470 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"BF");
9471 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9472 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9473 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9474 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"BF");
9475 } else if (Hoption.Surf == 15) {
9476 // The surface is not drawn in this case.
9477 } else {
9478 // Draw the surface
9479 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 16 || Hoption.Surf == 17) {
9481 } else {
9482 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9483 }
9484 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9485 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceRaster1);
9486 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode2);
9487 if (Hoption.System == kPOLAR) {
9488 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfacePolar(1,nx,ny,"FB");
9489 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfacePolar(1,nx,ny,"BF");
9490 } else if (Hoption.System == kCYLINDRICAL) {
9491 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceCylindrical(1,nx,ny,"FB");
9492 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9493 } else if (Hoption.System == kSPHERICAL) {
9494 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceSpherical(0,1,nx,ny,"FB");
9495 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9496 } else if (Hoption.System == kRAPIDITY) {
9497 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceSpherical(1,1,nx,ny,"FB");
9498 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9499 } else {
9500 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove1);
9501 if (Hoption.Surf == 16) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove3);
9502 if (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16) fLego->SurfaceCartesian(90,nx,ny,"FB");
9503 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCartesian(90,nx,ny,"BF");
9504 }
9505 }
9506
9507 // Paint the line contour on top for option SURF7
9508 if (Hoption.Surf == 17) {
9509 fLego->InitMoveScreen(-1.1,1.1);
9510 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9511 Hoption.Surf = 23;
9512 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9514 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"FB");
9515 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"FB");
9516 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"FB");
9517 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"FB");
9518 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"FB");
9519 }
9520
9521 if ((!Hoption.Same) &&
9522 (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16)) {
9525 fLego->BackBox(90);
9526 }
9527 }
9528 if (Hoption.System == kCARTESIAN) {
9529 fLego->InitMoveScreen(-1.1,1.1);
9531 if (Hoption.FrontBox) fLego->FrontBox(90);
9532 }
9533 if (!Hoption.Axis && !Hoption.Same) {
9534 TGaxis axis;
9535 PaintLegoAxis(&axis, 90);
9536 }
9537
9539
9540 fLego.reset();
9541}
9542
9543////////////////////////////////////////////////////////////////////////////////
9544/// Control function to draw a table using Delaunay triangles.
9545
9547{
9548
9549 TGraphDelaunay2D *dt = nullptr;
9550 TGraphDelaunay *dtOld = nullptr;
9551
9552 // Check if fH contains a TGraphDelaunay2D
9554 dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
9555 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
9556 if (!dt && !dtOld) return;
9557
9558 // If needed, create a TGraph2DPainter
9559 if (!fGraph2DPainter)
9560 fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
9561
9562 // Define the 3D view
9563 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
9564 if (Hoption.Same) {
9565 TView *viewsame = gPad ? gPad->GetView() : nullptr;
9566 if (!viewsame) {
9567 Error("PaintTriangles", "no TView in current pad, do not use option SAME");
9568 return;
9569 }
9570 Double_t *rmin = viewsame->GetRmin();
9571 Double_t *rmax = viewsame->GetRmax();
9572 if (!rmin || !rmax) return;
9573 fXbuf[0] = rmin[0];
9574 fYbuf[0] = rmax[0];
9575 fXbuf[1] = rmin[1];
9576 fYbuf[1] = rmax[1];
9577 fXbuf[2] = rmin[2];
9578 fYbuf[2] = rmax[2];
9579 fH->SetMaximum(rmax[2]);
9580 fH->SetMinimum(rmin[2]);
9581 fH->GetXaxis()->SetRangeUser(rmin[0],rmax[0]);
9582 fH->GetYaxis()->SetRangeUser(rmin[1],rmax[1]);
9583 } else {
9584 fXbuf[0] = Hparam.xmin;
9585 fYbuf[0] = Hparam.xmax;
9586 fXbuf[1] = Hparam.ymin;
9587 fYbuf[1] = Hparam.ymax;
9588 fXbuf[2] = Hparam.zmin;
9589 fYbuf[2] = Hparam.zmax;
9590 }
9591
9592 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
9593 TView *view = gPad ? gPad->GetView() : nullptr;
9594 if (!view) {
9595 Error("PaintTriangles", "no TView in current pad");
9596 return;
9597 }
9598 Double_t thedeg = 90 - gPad->GetTheta();
9599 Double_t phideg = -90 - gPad->GetPhi();
9600 Double_t psideg = view->GetPsi();
9601 Int_t irep;
9602 view->SetView(phideg, thedeg, psideg, irep);
9603
9604 // Set color/style for back box
9605 fLego->SetFillStyle(gPad->GetFrameFillStyle());
9606 fLego->SetFillColor(gPad->GetFrameFillColor());
9607 fLego->TAttFill::Modify();
9608 Int_t backcolor = gPad->GetFrameFillColor();
9609 if (Hoption.System != kCARTESIAN) backcolor = 0;
9610 view->PadRange(backcolor);
9611 fLego->SetFillStyle(fH->GetFillStyle());
9612 fLego->SetFillColor(fH->GetFillColor());
9613 fLego->TAttFill::Modify();
9614
9615 // Paint the Back Box if needed
9616 if (Hoption.BackBox && !Hoption.Same) {
9617 fLego->InitMoveScreen(-1.1,1.1);
9618 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9620 fLego->BackBox(90);
9621 }
9622
9623 // Paint the triangles
9624 fGraph2DPainter->Paint(option);
9625
9626 // Paint the Front Box if needed
9627 if (Hoption.FrontBox) {
9628 fLego->InitMoveScreen(-1.1,1.1);
9630 fLego->FrontBox(90);
9631 }
9632
9633 // Paint the Axis if needed
9634 if (!Hoption.Axis && !Hoption.Same) {
9635 TGaxis axis;
9636 PaintLegoAxis(&axis, 90);
9637 }
9638
9640
9641 fLego.reset();
9642}
9643
9644////////////////////////////////////////////////////////////////////////////////
9645/// Define the color levels used to paint legos, surfaces etc..
9646
9648{
9649
9650 Int_t i, irep;
9651
9652 // Initialize the color levels
9653 if (ndivz >= 100) {
9654 Warning("PaintSurface", "too many color levels, %d >= 100, reset to 99", ndivz);
9655 ndivz = 99;
9656 }
9657 std::vector<Double_t> funlevel(ndivz+1);
9658 std::vector<Int_t> colorlevel(ndivz+1);
9660 Int_t ncolors = gStyle->GetNumberOfColors();
9661 for (i = 0; i < ndivz; ++i) {
9663 theColor = Int_t((i+0.99)*Float_t(ncolors)/Float_t(ndivz));
9665 }
9666 colorlevel[ndivz] = gStyle->GetColorPalette(ncolors-1);
9667 fLego->ColorFunction(ndivz, funlevel.data(), colorlevel.data(), irep);
9668}
9669
9670////////////////////////////////////////////////////////////////////////////////
9671/// [Control function to draw 2D/3D histograms (tables).](\ref HP01c)
9672
9674{
9675
9676 // Fill Hparam structure with histo parameters
9677 if (!TableInit()) return;
9678
9679 // Draw histogram frame
9680 PaintFrame();
9681
9682 // If palette option not specified, delete a possible existing palette
9683 if (!Hoption.Zscale) {
9684 TObject *palette = fFunctions->FindObject("palette");
9685 if (palette) { fFunctions->Remove(palette); delete palette;}
9686 }
9687
9688 // Do not draw the histogram. Only the attached functions will be drawn.
9689 if (Hoption.Func == 2) {
9690 if (Hoption.Zscale) {
9691 Int_t ndiv = fH->GetContour();
9692 if (ndiv == 0 ) {
9693 ndiv = gStyle->GetNumberContours();
9694 fH->SetContour(ndiv);
9695 }
9696 PaintPalette();
9697 }
9698
9699 // Draw the histogram according to the option
9700 } else {
9701 if (fH->InheritsFrom(TH2Poly::Class()) && Hoption.Axis<=0) {
9702 if (Hoption.Fill) PaintTH2PolyBins("f");
9706 if (Hoption.Line) PaintTH2PolyBins("l");
9707 if (Hoption.Mark) PaintTH2PolyBins("P");
9708 } else if (Hoption.Axis<=0) {
9712 if (Hoption.Color) {
9715 }
9718 if (Hoption.Error >= 100) Paint2DErrors(option);
9720 }
9724 }
9725
9726 // Draw histogram title
9727 PaintTitle();
9728
9729 // Draw the axes
9730 if (!Hoption.Lego && !Hoption.Surf &&
9731 !Hoption.Tri && !(Hoption.Error >= 100)) PaintAxis(kFALSE);
9732
9733 TF1 *fit = nullptr;
9734 TIter next(fFunctions);
9735 while (auto obj = next()) {
9736 if (obj->InheritsFrom(TF1::Class())) {
9737 fit = (TF1*)obj;
9738 break;
9739 }
9740 }
9741 if ((Hoption.Same%10) != 1) {
9742 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
9743 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
9744 //ALWAYS executed on non-iOS platform.
9745 //On iOS, depends on mode.
9747 }
9748 }
9749 }
9750}
9751
9752////////////////////////////////////////////////////////////////////////////////
9753/// Control function to draw a TH2Poly bins' contours.
9754///
9755/// - option = "F" draw the bins as filled areas.
9756/// - option = "L" draw the bins as line.
9757/// - option = "P" draw the bins as markers.
9758
9760{
9761
9762 //Do not highlight the histogram, if its part was picked.
9763 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH) return;
9764
9765 TString opt = option;
9766 opt.ToLower();
9767 Bool_t line = kFALSE;
9768 Bool_t fill = kFALSE;
9769 Bool_t mark = kFALSE;
9770 if (opt.Contains("l")) line = kTRUE;
9771 if (opt.Contains("f")) fill = kTRUE;
9772 if (opt.Contains("p")) mark = kTRUE;
9773
9774 TH2PolyBin *b;
9775 Double_t z;
9776
9777 TIter next(((TH2Poly*)fH)->GetBins());
9778 TObject *obj, *poly;
9779
9780 while ((obj=next())) {
9781 b = (TH2PolyBin*)obj;
9782 z = b->GetContent();
9783 if (z==0 && Hoption.Zero) continue; // Do not draw empty bins in case of option "COL0 L"
9784 poly = b->GetPolygon();
9785
9786 // Paint the TGraph bins.
9787 if (poly->IsA() == TGraph::Class()) {
9788 TGraph *g = (TGraph*)poly;
9789 g->TAttLine::Modify();
9790 g->TAttMarker::Modify();
9791 g->TAttFill::Modify();
9792 if (line) {
9793 Int_t fs = g->GetFillStyle();
9795 g->SetFillStyle(0);
9797 g->Paint("F");
9799 g->SetFillStyle(fs);
9800 }
9801 if (fill) g->Paint("F");
9802 if (mark) g->Paint("P");
9803 }
9804
9805 // Paint the TMultiGraph bins.
9806 if (poly->IsA() == TMultiGraph::Class()) {
9808 TList *gl = mg->GetListOfGraphs();
9809 if (!gl) return;
9810 TGraph *g;
9811 TIter nextg(gl);
9812 while ((g = (TGraph*) nextg())) {
9813 g->TAttLine::Modify();
9814 g->TAttMarker::Modify();
9815 g->TAttFill::Modify();
9816 if (line) {
9817 Int_t fs = g->GetFillStyle();
9819 g->SetFillStyle(0);
9821 g->Paint("F");
9823 g->SetFillStyle(fs);
9824 }
9825 if (fill) g->Paint("F");
9826 if (mark) g->Paint("P");
9827 }
9828 }
9829 }
9830}
9831
9832////////////////////////////////////////////////////////////////////////////////
9833/// [Control function to draw a TH2Poly as a color plot.](\ref HP20a)
9834
9836{
9837
9838 //Do not highlight the histogram, if its part was picked.
9839 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
9840 return;
9841
9842 Int_t ncolors, color, theColor;
9843 Double_t z, zc;
9844 Double_t zmin = fH->GetMinimum();
9845 Double_t zmax = fH->GetMaximum();
9846 if (Hoption.Logz) {
9847 if (zmax > 0) {
9848 if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
9849 zmin = TMath::Log10(zmin);
9850 zmax = TMath::Log10(zmax);
9851 } else {
9852 return;
9853 }
9854 }
9855 Double_t dz = zmax - zmin;
9856
9857 // Initialize the levels on the Z axis
9858 ncolors = gStyle->GetNumberOfColors();
9859 Int_t ndiv = fH->GetContour();
9860 if (ndiv == 0 ) {
9861 ndiv = gStyle->GetNumberContours();
9862 fH->SetContour(ndiv);
9863 }
9864 Int_t ndivz = TMath::Abs(ndiv);
9865 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
9867
9868 TIter next(((TH2Poly*)fH)->GetBins());
9869
9870 while (auto obj = next()) {
9871 TH2PolyBin *b = (TH2PolyBin*)obj;
9872 TObject *poly = b->GetPolygon();
9873
9874 z = b->GetContent();
9875 if (z==0 && Hoption.Zero) continue;
9876 if (Hoption.Logz) {
9877 if (z > 0) z = TMath::Log10(z);
9878 else z = zmin;
9879 }
9880 if (z < zmin) continue;
9881
9882 // Define the bin color.
9884 zc = fH->GetContourLevelPad(0);
9885 if (z < zc) continue;
9886 color = -1;
9887 for (Int_t k=0; k<ndiv; k++) {
9888 zc = fH->GetContourLevelPad(k);
9889 if (z < zc) {
9890 continue;
9891 } else {
9892 color++;
9893 }
9894 }
9895 } else {
9896 color = Int_t(0.01+(z-zmin)*scale);
9897 }
9898 theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
9899 if (theColor > ncolors-1) theColor = ncolors-1;
9900
9901 // Paint the TGraph bins.
9902 if (poly->IsA() == TGraph::Class()) {
9903 TGraph *g = (TGraph*)poly;
9904 g->SetFillColor(gStyle->GetColorPalette(theColor));
9905 g->TAttFill::Modify();
9906 g->Paint("F");
9907 }
9908
9909 // Paint the TMultiGraph bins.
9910 if (poly->IsA() == TMultiGraph::Class()) {
9912 TList *gl = mg->GetListOfGraphs();
9913 if (!gl) return;
9914 TGraph *g;
9915 TIter nextg(gl);
9916 while ((g = (TGraph*) nextg())) {
9917 g->SetFillColor(gStyle->GetColorPalette(theColor));
9918 g->TAttFill::Modify();
9919 g->Paint("F");
9920 }
9921 }
9922 }
9924}
9925
9926////////////////////////////////////////////////////////////////////////////////
9927/// [Control function to draw a TH2Poly as a scatter plot.](\ref HP20a)
9928
9930{
9931
9932 //Do not highlight the histogram, if its part was selected.
9933 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
9934 return;
9935
9936 Int_t k, loop, marker=0;
9937 Double_t z, xk,xstep, yk, ystep, xp, yp;
9938 Double_t scale = 1;
9939 Double_t zmin = fH->GetMinimum();
9940 Double_t zmax = fH->GetMaximum();
9941 if (Hoption.Logz) {
9942 if (zmax > 0) {
9943 if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
9944 zmin = TMath::Log10(zmin);
9945 zmax = TMath::Log10(zmax);
9946 } else {
9947 return;
9948 }
9949 }
9950 Double_t dz = zmax - zmin;
9951 scale = (kNMAX-1)/dz;
9952
9953
9954 // use an independent instance of a random generator
9955 // instead of gRandom to avoid conflicts and
9956 // to get same random numbers when drawing the same histogram
9958
9959 TH2PolyBin *b;
9960
9961 TIter next(((TH2Poly*)fH)->GetBins());
9962 TObject *obj, *poly;
9963
9964 Double_t maxarea = 0, a;
9965 while ((obj=next())) {
9966 b = (TH2PolyBin*)obj;
9967 a = b->GetArea();
9968 if (a>maxarea) maxarea = a;
9969 }
9970
9971 next.Reset();
9972
9973 while ((obj=next())) {
9974 b = (TH2PolyBin*)obj;
9975 poly = b->GetPolygon();
9976 z = b->GetContent();
9977 if (z < zmin) z = zmin;
9978 if (z > zmax) z = zmax;
9979 if (Hoption.Logz) {
9980 if (z > 0) z = TMath::Log10(z) - zmin;
9981 } else {
9982 z -= zmin;
9983 }
9984 k = Int_t((z*scale)*(b->GetArea()/maxarea));
9985 xk = b->GetXMin();
9986 yk = b->GetYMin();
9987 xstep = b->GetXMax()-xk;
9988 ystep = b->GetYMax()-yk;
9989
9990 // Paint the TGraph bins.
9991 if (poly->IsA() == TGraph::Class()) {
9992 TGraph *g = (TGraph*)poly;
9993 if (k <= 0 || z <= 0) continue;
9994 loop = 0;
9995 while (loop<k) {
9996 if (k+marker >= kNMAX) {
9997 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
9998 marker=0;
9999 }
10000 xp = (random.Rndm()*xstep) + xk;
10001 yp = (random.Rndm()*ystep) + yk;
10002 if (g->IsInside(xp,yp)) {
10003 fXbuf[marker] = xp;
10004 fYbuf[marker] = yp;
10005 marker++;
10006 loop++;
10007 }
10008 }
10009 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10010 }
10011
10012 // Paint the TMultiGraph bins.
10013 if (poly->IsA() == TMultiGraph::Class()) {
10015 TList *gl = mg->GetListOfGraphs();
10016 if (!gl) return;
10017 if (k <= 0 || z <= 0) continue;
10018 loop = 0;
10019 while (loop<k) {
10020 if (k+marker >= kNMAX) {
10021 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10022 marker=0;
10023 }
10024 xp = (random.Rndm()*xstep) + xk;
10025 yp = (random.Rndm()*ystep) + yk;
10026 if (mg->IsInside(xp,yp)) {
10027 fXbuf[marker] = xp;
10028 fYbuf[marker] = yp;
10029 marker++;
10030 loop++;
10031 }
10032 }
10033 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10034 }
10035 }
10036 PaintTH2PolyBins("l");
10037}
10038
10039////////////////////////////////////////////////////////////////////////////////
10040/// [Control function to draw a TH2Poly as a text plot.](\ref HP20a)
10041
10043{
10044
10045 TLatex text;
10046 text.SetTextFont(gStyle->GetTextFont());
10047 text.SetTextColor(fH->GetMarkerColor());
10048 text.SetTextSize(0.02*fH->GetMarkerSize());
10049
10050 Double_t x, y, z, e, angle = 0;
10051 TString tt, tf;
10052 tf.Form("%s%s","%",gStyle->GetPaintTextFormat());
10053 if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
10054 Int_t opt = (Int_t)Hoption.Text/1000;
10055
10056 text.SetTextAlign(22);
10057 if (Hoption.Text == 1) angle = 0;
10058 text.SetTextAngle(angle);
10059 text.TAttText::Modify();
10060
10061 TH2PolyBin *b;
10062
10063 TIter next(((TH2Poly*)fH)->GetBins());
10064 TObject *obj, *p;
10065
10066 while ((obj=next())) {
10067 b = (TH2PolyBin*)obj;
10068 p = b->GetPolygon();
10069 x = (b->GetXMin()+b->GetXMax())/2;
10070 if (Hoption.Logx) {
10071 if (x > 0) x = TMath::Log10(x);
10072 else continue;
10073 }
10074 y = (b->GetYMin()+b->GetYMax())/2;
10075 if (Hoption.Logy) {
10076 if (y > 0) y = TMath::Log10(y);
10077 else continue;
10078 }
10079 z = b->GetContent();
10080 if (z < fH->GetMinimum() || (z == 0 && !Hoption.MinimumZero)) continue;
10081 if (opt==2) {
10082 e = fH->GetBinError(b->GetBinNumber());
10083 tf.Form("#splitline{%s%s}{#pm %s%s}",
10085 "%",gStyle->GetPaintTextFormat());
10086 tt.Form(tf.Data(),z,e);
10087 } else {
10088 tt.Form(tf.Data(),z);
10089 }
10090 if (opt==3) text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),p->GetName());
10091 else text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),tt.Data());
10092 }
10093
10094 PaintTH2PolyBins("l");
10095}
10096
10097////////////////////////////////////////////////////////////////////////////////
10098/// [Control function to draw a 1D/2D histograms with the bin values.](\ref HP15)
10099
10101{
10102
10103 TLatex text;
10104 text.SetTextFont(((int)gStyle->GetTextFont()/10)*10+2); // font precision must be 2
10105 text.SetTextColor(fH->GetMarkerColor());
10106 text.SetTextSize(0.02*fH->GetMarkerSize());
10107
10108 Double_t x, y, z, e, angle = 0;
10109 TString tt, tf;
10110 tf.Form("%s%s","%",gStyle->GetPaintTextFormat());
10111 if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
10112
10113 // 1D histograms
10114 if (fH->GetDimension() == 1) {
10116 Double_t yt;
10117 TProfile *hp = (TProfile*)fH;
10118 if (Hoption.Text>2000 && fH->InheritsFrom(TProfile::Class())) {
10119 Hoption.Text = Hoption.Text-2000;
10120 getentries = kTRUE;
10121 }
10122 if (Hoption.Text == 1) angle = 90;
10123 text.SetTextAlign(11);
10124 if (angle == 90) text.SetTextAlign(12);
10125 if (angle == 0) text.SetTextAlign(21);
10126 text.TAttText::Modify();
10127 Double_t dt = 0.02*(gPad->GetY2()-gPad->GetY1());
10128 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10129 if (Hoption.Bar) {
10130 x = fH->GetXaxis()->GetBinLowEdge(i)+
10131 fH->GetXaxis()->GetBinWidth(i)*
10132 (fH->GetBarOffset()+0.5*fH->GetBarWidth());
10133 } else {
10134 x = fH->GetXaxis()->GetBinCenter(i);
10135 }
10136 y = fH->GetBinContent(i);
10137 yt = y;
10138 if (Hoption.MinimumZero && y<0) y = 0;
10139 if (getentries) yt = hp->GetBinEntries(i);
10140 if (yt == 0.) continue;
10141 tt.Form(tf.Data(),yt);
10142 if (Hoption.Logx) {
10143 if (x > 0) x = TMath::Log10(x);
10144 else continue;
10145 }
10146 if (Hoption.Logy) {
10147 if (y > 0) y = TMath::Log10(y);
10148 else continue;
10149 }
10150 if (y >= gPad->GetY2()) continue;
10151 if (y <= gPad->GetY1()) continue;
10152 text.PaintLatex(x,y+0.2*dt,angle,0.02*fH->GetMarkerSize(),tt.Data());
10153 }
10154
10155 // 2D histograms
10156 } else {
10157 Double_t zmin = Hparam.zmin;
10158 if (Hoption.Logz) zmin = TMath::Power(10,Hparam.zmin);
10159
10160 text.SetTextAlign(22);
10161 if (Hoption.Text == 1) angle = 0;
10162 text.SetTextAngle(angle);
10163 text.TAttText::Modify();
10164 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
10165 y = fYaxis->GetBinCenter(j);
10166 if (Hoption.Logy) {
10167 if (y > 0) y = TMath::Log10(y);
10168 else continue;
10169 }
10170 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10171 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
10172 x = fXaxis->GetBinCenter(i);
10173 if (Hoption.Logx) {
10174 if (x > 0) x = TMath::Log10(x);
10175 else continue;
10176 }
10177 if (!IsInside(x,y)) continue;
10178 z = fH->GetBinContent(bin);
10179 if (z < zmin || (z == 0 && !Hoption.MinimumZero)) continue;
10180 if (Hoption.Text>2000) {
10181 e = fH->GetBinError(bin);
10182 tf.Form("#splitline{%s%s}{#pm %s%s}",
10184 "%",gStyle->GetPaintTextFormat());
10185 tt.Form(tf.Data(),z,e);
10186 } else {
10187 tt.Form(tf.Data(),z);
10188 }
10189 text.PaintLatex(x,y+fH->GetBarOffset()*fYaxis->GetBinWidth(j),
10190 angle,0.02*fH->GetMarkerSize(),tt.Data());
10191 }
10192 }
10193 }
10194}
10195
10196////////////////////////////////////////////////////////////////////////////////
10197/// [Control function to draw a 3D implicit functions.](\ref HP27)
10198
10200{
10201
10202 Int_t irep;
10203
10204 TAxis *xaxis = fH->GetXaxis();
10205 TAxis *yaxis = fH->GetYaxis();
10206 TAxis *zaxis = fH->GetZaxis();
10207
10208 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
10209 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
10210 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
10211 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
10212 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
10213 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
10214
10215 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
10216
10217 TView *view = gPad ? gPad->GetView() : nullptr;
10218 if (!view) {
10219 Error("PaintTF3", "no TView in current pad");
10220 return;
10221 }
10222 Double_t thedeg = 90 - gPad->GetTheta();
10223 Double_t phideg = -90 - gPad->GetPhi();
10224 Double_t psideg = view->GetPsi();
10225 view->SetView(phideg, thedeg, psideg, irep);
10226
10227 fLego->InitMoveScreen(-1.1,1.1);
10228
10229 if (Hoption.BackBox) {
10230 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
10232 fLego->BackBox(90);
10233 }
10234
10236
10237 fLego->ImplicitFunction(fCurrentF3, fXbuf.data(), fYbuf.data(), fH->GetNbinsX(),
10238 fH->GetNbinsY(),
10239 fH->GetNbinsZ(), "BF");
10240
10241 if (Hoption.FrontBox) {
10242 fLego->InitMoveScreen(-1.1,1.1);
10244 fLego->FrontBox(90);
10245 }
10246 if (!Hoption.Axis && !Hoption.Same) {
10247 TGaxis axis;
10248 PaintLegoAxis(&axis, 90);
10249 }
10250
10251 PaintTitle();
10252
10253 fLego.reset();
10254}
10255
10256/////////////////////////////////////////////////////////////new TGaxis///////////////////
10257/// Draw the histogram title
10258///
10259/// The title is drawn according to the title alignment returned by
10260/// `GetTitleAlign()`. It is a 2 digits integer): hv
10261///
10262/// where `h` is the horizontal alignment and `v` is the
10263/// vertical alignment.
10264///
10265/// - `h` can get the values 1 2 3 for left, center, and right
10266/// - `v` can get the values 1 2 3 for bottom, middle and top
10267///
10268/// for instance the default alignment is: 13 (left top)
10269
10271{
10272 // probably best place for calls PaintHighlightBin
10273 // calls after paint histo (1D or 2D) and before paint title and stats
10274 if (!gPad->GetView()) PaintHighlightBin();
10275
10276 if (Hoption.Same) return;
10277 if (fH->TestBit(TH1::kNoTitle)) return;
10278 Int_t nt = strlen(fH->GetTitle());
10279 TPaveText *title = nullptr;
10280 TObject *obj;
10281 TIter next(gPad->GetListOfPrimitives());
10282 while ((obj = next())) {
10283 if (!obj->InheritsFrom(TPaveText::Class())) continue;
10284 title = (TPaveText*)obj;
10285 if (strcmp(title->GetName(),"title")) {title = nullptr; continue;}
10286 break;
10287 }
10288 if (nt == 0 || gStyle->GetOptTitle() <= 0) {
10289 if (title) delete title;
10290 return;
10291 }
10294
10295 if (ht <= 0) {
10296 if (gStyle->GetTitleFont("")%10 == 3) {
10297 Double_t hw = TMath::Max((Double_t)gPad->XtoPixel(gPad->GetX2()),
10298 (Double_t)gPad->YtoPixel(gPad->GetY1()));
10299 ht = 1.1*(gStyle->GetTitleSize("")/hw);
10300 } else {
10301 ht = 1.1*gStyle->GetTitleFontSize();
10302 }
10303 }
10304 if (ht <= 0) ht = 0.05;
10305 if (wt <= 0) {
10306 TLatex l;
10307 l.SetTextSize(ht);
10308 l.SetTitle(fH->GetTitle());
10309 // adjustment in case the title has several lines (#splitline)
10310 ht = TMath::Max(ht, 1.2*l.GetYsize()/(gPad->GetY2() - gPad->GetY1()));
10311 Double_t wndc = l.GetXsize()/(gPad->GetX2() - gPad->GetX1());
10312 wt = TMath::Min(0.7, 0.02+wndc);
10313 }
10314 if (title) {
10315 TText *t0 = (TText*)title->GetLine(0);
10316 if (t0) {
10317 if (!strcmp(t0->GetTitle(),fH->GetTitle())) return;
10318 t0->SetTitle(fH->GetTitle());
10319 if (wt > 0) title->SetX2NDC(title->GetX1NDC()+wt);
10320 }
10321 return;
10322 }
10323
10325 if (talh < 1) talh = 1; else if (talh > 3) talh = 3;
10327 if (talv < 1) talv = 1; else if (talv > 3) talv = 3;
10329 xpos = gStyle->GetTitleX();
10330 ypos = gStyle->GetTitleY();
10331 if (talh == 2) xpos = xpos-wt/2.;
10332 if (talh == 3) xpos = xpos-wt;
10333 if (talv == 2) ypos = ypos+ht/2.;
10334 if (talv == 1) ypos = ypos+ht;
10335
10336 TPaveText *ptitle = new TPaveText(xpos, ypos-ht, xpos+wt, ypos,"blNDC");
10337
10338 // box with the histogram title
10339 ptitle->SetFillColor(gStyle->GetTitleFillColor());
10340 ptitle->SetFillStyle(gStyle->GetTitleStyle());
10341 ptitle->SetName("title");
10342 ptitle->SetBorderSize(gStyle->GetTitleBorderSize());
10343 ptitle->SetTextColor(gStyle->GetTitleTextColor());
10344 ptitle->SetTextFont(gStyle->GetTitleFont(""));
10345 if (gStyle->GetTitleFont("")%10 > 2)
10346 ptitle->SetTextSize(gStyle->GetTitleFontSize());
10347 ptitle->AddText(fH->GetTitle());
10348 ptitle->SetBit(kCanDelete);
10349 ptitle->Draw();
10350 ptitle->Paint("blNDC");
10351
10352 if(!gPad->IsEditable()) delete ptitle;
10353}
10354
10355////////////////////////////////////////////////////////////////////////////////
10356/// Process message `mess`.
10357
10358void THistPainter::ProcessMessage(const char *mess, const TObject *obj)
10359{
10360 if (!strcmp(mess,"SetF3")) {
10361 fCurrentF3 = (TF3 *)obj;
10362 }
10363}
10364
10365////////////////////////////////////////////////////////////////////////////////
10366/// Static function.
10367///
10368/// Convert Right Ascension, Declination to X,Y using an AITOFF projection.
10369/// This procedure can be used to create an all-sky map in Galactic
10370/// coordinates with an equal-area Aitoff projection. Output map
10371/// coordinates are zero longitude centered.
10372/// Also called Hammer-Aitoff projection (first presented by Ernst von Hammer in 1892)
10373///
10374/// source: GMT
10375///
10376/// code from Ernst-Jan Buis
10377
10379{
10380
10381 Double_t x, y;
10382
10384 Double_t delta = b*TMath::DegToRad();
10385 Double_t r2 = TMath::Sqrt(2.);
10386 Double_t f = 2*r2/TMath::Pi();
10387 Double_t cdec = TMath::Cos(delta);
10390 y = TMath::Sin(delta)*r2/denom;
10391 x *= TMath::RadToDeg()/f;
10392 y *= TMath::RadToDeg()/f;
10393 // x *= -1.; // for a skymap swap left<->right
10394 Al = x;
10395 Ab = y;
10396
10397 return 0;
10398}
10399
10400////////////////////////////////////////////////////////////////////////////////
10401/// Static function
10402///
10403/// Probably the most famous of the various map projections, the Mercator projection
10404/// takes its name from Mercator who presented it in 1569. It is a cylindrical, conformal projection
10405/// with no distortion along the equator.
10406/// The Mercator projection has been used extensively for world maps in which the distortion towards
10407/// the polar regions grows rather large, thus incorrectly giving the impression that, for example,
10408/// Greenland is larger than South America. In reality, the latter is about eight times the size of
10409/// Greenland. Also, the Former Soviet Union looks much bigger than Africa or South America. One may wonder
10410/// whether this illusion has had any influence on U.S. foreign policy.' (Source: GMT)
10411/// code from Ernst-Jan Buis
10412
10414{
10415
10416 Al = l;
10418 Ab = TMath::Log(aid);
10419 return 0;
10420}
10421
10422////////////////////////////////////////////////////////////////////////////////
10423/// Static function code for sinusoidal projection
10424/// from Ernst-Jan Buis
10425/// Source https://en.wikipedia.org/wiki/Sinusoidal_projection
10426
10428{
10429
10430 Al = l*cos(b*TMath::DegToRad());
10431 Ab = b;
10432 return 0;
10433}
10434
10435////////////////////////////////////////////////////////////////////////////////
10436/// Static function code for parabolic projection
10437/// from Ernst-Jan Buis
10438
10440{
10441
10442 Al = l*(2.*TMath::Cos(2*b*TMath::DegToRad()/3) - 1);
10443 Ab = 180*TMath::Sin(b*TMath::DegToRad()/3);
10444 return 0;
10445}
10446
10447////////////////////////////////////////////////////////////////////////////////
10448/// Static function.
10449///
10450/// Convert Right Ascension, Declination to X,Y using an MOLLWEIDE projection.
10451/// This procedure can be used to create an all-sky map in Galactic
10452/// coordinates with an equal-area Mollweide projection. Output map
10453/// coordinates are zero longitude centered.
10454/// It is also known as the Babinet projection, homalographic projection, homolographic projection, and elliptical projection.
10455/// Source: https://en.wikipedia.org/wiki/Mollweide_projection
10456///
10457/// code from Marco Meyer-Conde
10458
10460{
10461
10462 Double_t theta0 = b * TMath::DegToRad(), theta = theta0;
10463
10464 for (int i = 0; i < 100; i++) {
10465 Double_t num = 2 * theta + TMath::Sin(2 * theta) - TMath::Pi() * TMath::Sin(theta0);
10466 Double_t den = 4 * TMath::Power(TMath::Cos(theta), 2);
10467
10468 if (den < 1e-20) {
10469 theta = theta0;
10470 break;
10471 }
10472
10473 theta -= num / den;
10474
10475 if (TMath::Abs(num / den) < 1e-4) break;
10476 }
10477
10478 Al = l * TMath::Cos(theta);
10479 Ab = 90 * TMath::Sin(theta);
10480
10481 return 0;
10482}
10483
10484////////////////////////////////////////////////////////////////////////////////
10485/// Recompute the histogram range following graphics operations.
10486
10488{
10489
10490 if (Hoption.Same) return;
10491
10492 // Compute x,y range
10494 xmax = Hparam.xmax,
10495 ymin = Hparam.ymin,
10496 ymax = Hparam.ymax,
10497 xscale = 1;
10498
10499 std::function<Int_t(Double_t,Double_t,Double_t&,Double_t&)> func;
10500
10501 if (Hoption.Proj == 1) {
10502 func = ProjectAitoff2xy;
10503 xscale = 0.9999;
10504 } else if (Hoption.Proj == 2) {
10505 if (Hparam.ymin <= -90 || Hparam.ymax >= 90) {
10506 Warning("Mercator Projection", "Latitude out of range %f or %f", Hparam.ymin, Hparam.ymax);
10507 Hoption.Proj = 0;
10508 } else {
10511 }
10512 } else if (Hoption.Proj == 3) {
10513 func = ProjectSinusoidal2xy;
10514 } else if (Hoption.Proj == 4) {
10515 func = ProjectParabolic2xy;
10516 } else if (Hoption.Proj == 5) {
10517 func = ProjectMollweide2xy;
10518 }
10519
10520 if (func) {
10522
10526 func(Hparam.xmax, Hparam.ymin, xmax, ymin);
10527
10528 if (xmin > xmin_aid) xmin = xmin_aid;
10529 if (ymin > ymin_aid) ymin = ymin_aid;
10530 if (xmax < xmax_aid) xmax = xmax_aid;
10531 if (ymax < ymax_aid) ymax = ymax_aid;
10532 if (Hparam.ymin < 0 && Hparam.ymax > 0) {
10533 // there is an 'equator', check its range in the plot..
10534 func(Hparam.xmin*xscale, 0, xmin_aid, ymin_aid);
10535 func(Hparam.xmax*xscale, 0, xmax_aid, ymin_aid);
10536 if (xmin > xmin_aid) xmin = xmin_aid;
10537 if (xmax < xmax_aid) xmax = xmax_aid;
10538 }
10539 if (Hparam.xmin < 0 && Hparam.xmax > 0) {
10540 func(0, Hparam.ymin, xmin_aid, ymin_aid);
10541 func(0, Hparam.ymax, xmax_aid, ymax_aid);
10542 if (ymin > ymin_aid) ymin = ymin_aid;
10543 if (ymax < ymax_aid) ymax = ymax_aid;
10544 }
10545 }
10546
10547 Hparam.xmin = xmin;
10548 Hparam.xmax = xmax;
10549 Hparam.ymin = ymin;
10550 Hparam.ymax = ymax;
10551
10552 Double_t dx = xmax-xmin;
10553 Double_t dy = ymax-ymin;
10554 Double_t dxr = dx/(1 - gPad->GetLeftMargin() - gPad->GetRightMargin());
10555 Double_t dyr = dy/(1 - gPad->GetBottomMargin() - gPad->GetTopMargin());
10556
10557 // Range() could change the size of the pad pixmap and therefore should
10558 // be called before the other paint routines
10559 gPad->Range(xmin - dxr*gPad->GetLeftMargin(),
10560 ymin - dyr*gPad->GetBottomMargin(),
10561 xmax + dxr*gPad->GetRightMargin(),
10562 ymax + dyr*gPad->GetTopMargin());
10563 gPad->RangeAxis(xmin, ymin, xmax, ymax);
10564}
10565
10566////////////////////////////////////////////////////////////////////////////////
10567/// Set current histogram to `h`
10568
10570{
10571
10572 if (h == nullptr) return;
10573 fH = h;
10574 fXaxis = h->GetXaxis();
10575 fYaxis = h->GetYaxis();
10576 fZaxis = h->GetZaxis();
10578}
10579
10580////////////////////////////////////////////////////////////////////////////////
10581/// Initialize various options to draw 2D histograms.
10582
10584{
10585
10586 static const char *where = "TableInit";
10587
10588 Int_t first, last;
10590 Double_t zmin, zmax;
10591 Int_t maximum = 0;
10592 Int_t minimum = 0;
10593 if (fH->GetMaximumStored() != -1111) maximum = 1;
10594 if (fH->GetMinimumStored() != -1111) minimum = 1;
10595
10596 // ----------------- Compute X axis parameters
10597 first = fXaxis->GetFirst();
10598 last = fXaxis->GetLast();
10599 Hparam.xlast = last;
10600 Hparam.xfirst = first;
10605
10606 // if log scale in X, replace xmin,max by the log
10607 if (Hoption.Logx) {
10608 // find the first edge of a bin that is > 0
10609 if (Hparam.xlowedge <=0 ) {
10612 }
10613 if (Hparam.xmin <=0 || Hparam.xmax <=0) {
10614 Error(where, "cannot set X axis to log scale");
10615 return 0;
10616 }
10618 if (Hparam.xfirst < first) Hparam.xfirst = first;
10620 if (Hparam.xlast > last) Hparam.xlast = last;
10623 }
10624
10625 // ----------------- Compute Y axis parameters
10626 first = fYaxis->GetFirst();
10627 last = fYaxis->GetLast();
10628 Hparam.ylast = last;
10629 Hparam.yfirst = first;
10632 if (!Hparam.ybinsize) Hparam.ybinsize = 1;
10635
10636 // if log scale in Y, replace ymin,max by the log
10637 if (Hoption.Logy) {
10638 if (Hparam.ylowedge <=0 ) {
10641 }
10642 if (Hparam.ymin <=0 || Hparam.ymax <=0) {
10643 Error(where, "cannot set Y axis to log scale");
10644 return 0;
10645 }
10647 if (Hparam.yfirst < first) Hparam.yfirst = first;
10649 if (Hparam.ylast > last) Hparam.ylast = last;
10652 }
10653
10654
10655 // ----------------- Compute Z axis parameters
10656 Double_t bigp = TMath::Power(10,32);
10657 zmax = -bigp;
10658 zmin = bigp;
10659 Double_t c1, e1;
10660 Double_t allchan = 0;
10661 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
10662 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10663 c1 = fH->GetBinContent(i,j);
10664 zmax = TMath::Max(zmax,c1);
10665 if (Hoption.Error) {
10666 e1 = fH->GetBinError(i,j);
10667 zmax = TMath::Max(zmax,c1+e1);
10668 }
10669 zmin = TMath::Min(zmin,c1);
10670 allchan += c1;
10671 }
10672 }
10673
10674 // Take into account maximum , minimum
10675
10676 if (maximum) zmax = fH->GetMaximumStored();
10677 if (minimum) zmin = fH->GetMinimumStored();
10678 if (Hoption.Logz && zmax < 0) {
10679 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10680 return 0;
10681 } else if (Hoption.Logz && zmin>=0 && zmax==0) { // empty histogram in log scale
10682 zmin = 0.01;
10683 zmax = 10.;
10684 }
10685 if (zmin >= zmax) {
10686 if (Hoption.Logz) {
10687 if (zmax > 0) zmin = 0.001*zmax;
10688 else {
10689 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10690 return 0;
10691 }
10692 }
10693 }
10694
10695 // take into account normalization factor
10696 Hparam.allchan = allchan;
10697 Double_t factor = allchan;
10698 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
10699 if (allchan) factor /= allchan;
10700 if (factor == 0) factor = 1;
10701 Hparam.factor = factor;
10702 zmax = factor*zmax;
10703 zmin = factor*zmin;
10704 c1 = zmax;
10705 if (TMath::Abs(zmin) > TMath::Abs(c1)) c1 = zmin;
10706
10707 // For log scales, histogram coordinates are log10(ymin) and
10708 // log10(ymax). Final adjustment (if not option "Same")
10709 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
10710 // Maximum and Minimum are not defined.
10711 if (Hoption.Logz) {
10712 if (zmin <= 0) {
10713 zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
10714 fH->SetMinimum(zmin);
10715 }
10716 zmin = TMath::Log10(zmin);
10717 if (!minimum) zmin += TMath::Log10(0.5);
10718 zmax = TMath::Log10(zmax);
10719 if (!maximum) zmax += TMath::Log10(2*(0.9/0.95));
10720 goto LZMIN;
10721 }
10722
10723 // final adjustment of YMAXI for linear scale (if not option "Same"):
10724 // decrease histogram height to MAX% of allowed height if HMAXIM
10725 // has not been called.
10726 // MAX% is the value in percent which has been set in HPLSET
10727 // (default is 90%).
10728 if (!maximum) {
10729 zmax += yMARGIN*(zmax-zmin);
10730 }
10731
10732 // final adjustment of ymin for linear scale.
10733 // if minimum is not set , then ymin is set to zero if >0
10734 // or to ymin - yMARGIN if <0.
10735 if (!minimum) {
10736 if (Hoption.MinimumZero) {
10737 if (zmin >= 0) zmin = 0;
10738 else zmin -= yMARGIN*(zmax-zmin);
10739 } else {
10740 Double_t dzmin = yMARGIN*(zmax-zmin);
10741 if (zmin >= 0 && (zmin-dzmin <= 0)) zmin = 0;
10742 else zmin -= dzmin;
10743 }
10744 }
10745
10746LZMIN:
10747 Hparam.zmin = zmin;
10748 Hparam.zmax = zmax;
10749
10750 // Set bar offset and width
10753
10754 return 1;
10755}
10756
10757////////////////////////////////////////////////////////////////////////////////
10758/// This function returns the best format to print the error value (e)
10759/// knowing the parameter value (v) and the format (f) used to print it.
10760
10762{
10763
10764 static TString ef;
10765 TString tf, tv;
10766
10767 // print v with the format f in tv.
10768 tf.Form("%s%s","%",f);
10769 tv.Form(tf.Data(),v);
10770
10771 // Analyse tv.
10772 int ie = tv.Index("e");
10773 int iE = tv.Index("E");
10774 int id = tv.Index(".");
10775
10776 // v has been printed with the exponent notation.
10777 // There is 2 cases, the exponent is positive or negative
10778 if (ie >= 0 || iE >= 0) {
10779 if (tv.Index("+") >= 0) {
10780 if (e < 1) {
10781 ef.Form("%s.1f","%");
10782 } else {
10783 if (ie >= 0) {
10784 ef.Form("%s.%de","%",ie-id-1);
10785 } else {
10786 ef.Form("%s.%dE","%",iE-id-1);
10787 }
10788 }
10789 } else {
10790 if (ie >= 0) {
10791 ef.Form("%s.%de","%",ie-id-1);
10792 } else {
10793 ef.Form("%s.%dE","%",iE-id-1);
10794 }
10795 }
10796
10797 // There is not '.' in tv. e will be printed with one decimal digit.
10798 } else if (id < 0) {
10799 ef.Form("%s.1f","%");
10800
10801 // There is a '.' in tv and no exponent notation. e's decimal part will
10802 // have the same number of digits as v's one.
10803 } else {
10804 ef.Form("%s.%df","%",tv.Length()-id-1);
10805 }
10806
10807 return ef.Data();
10808}
10809
10810////////////////////////////////////////////////////////////////////////////////
10811/// Set projection.
10812
10814{
10815 if (fShowProjection2) {
10816 auto name2 = TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2);
10817 auto c2 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name2.Data()));
10818 if (c2) c2->Close();
10819 fShowProjection2 = 0;
10820 }
10821 if (fShowProjection) {
10822 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10823 auto c1 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name1.Data()));
10824 if (c1) c1->Close();
10825 fShowProjection = 0;
10826 }
10827
10828 if (nbins <= 0) return;
10829
10830 TString opt = option;
10831 opt.ToLower();
10832 Int_t projection = 0;
10833 if (opt.Contains("x")) projection = 1;
10834 if (opt.Contains("y")) projection = 2;
10835 if (opt.Contains("z")) projection = 3;
10836 if (opt.Contains("xy")) projection = 4;
10837 if (opt.Contains("yx")) projection = 5;
10838 if (opt.Contains("xz")) projection = 6;
10839 if (opt.Contains("zx")) projection = 7;
10840 if (opt.Contains("yz")) projection = 8;
10841 if (opt.Contains("zy")) projection = 9;
10842 if (projection < 4) fShowOption = option+1;
10843 else fShowOption = option+2;
10844 fShowProjection = projection+100*nbins;
10845 fShowProjection2 = 0;
10846 gROOT->MakeDefCanvas();
10847 gPad->SetName(TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection).Data());
10848 gPad->SetGrid();
10849}
10850
10852{
10853 if (fShowProjection2) {
10854 auto name2 = TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2);
10855 auto c2 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name2.Data()));
10856 if (c2) c2->Close();
10857 fShowProjection2 = 0;
10858 }
10859 if (fShowProjection) {
10860 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10861 auto c1 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name1.Data()));
10862 if (c1) c1->Close();
10863 fShowProjection = 0;
10864 }
10865
10866 if ((nbinsX <= 0) || (nbinsY <= 0)) return;
10867
10868
10869 TString opt = option;
10870 opt.ToLower();
10871 Int_t projection = 0;
10872 if (opt.Contains("x")) projection = 1;
10873 if (opt.Contains("y")) projection = 2;
10874 if (opt.Contains("z")) projection = 3;
10875 if (opt.Contains("xy")) projection = 4;
10876 if (opt.Contains("yx")) projection = 5;
10877 if (opt.Contains("xz")) projection = 6;
10878 if (opt.Contains("zx")) projection = 7;
10879 if (opt.Contains("yz")) projection = 8;
10880 if (opt.Contains("zy")) projection = 9;
10881 if (projection < 4) fShowOption = option+1;
10882 else fShowOption = option+2;
10885 gROOT->MakeDefCanvas();
10886 gPad->SetName(TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection).Data());
10887 gPad->SetGrid();
10888 gROOT->MakeDefCanvas();
10889 gPad->SetName(TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2).Data());
10890 gPad->SetGrid();
10891}
10892
10893
10894////////////////////////////////////////////////////////////////////////////////
10895/// Show projection onto X.
10896
10898{
10899
10900 Int_t nbins = (Int_t)fShowProjection/100;
10901 gPad->SetDoubleBuffer(0); // turn off double buffer mode
10902 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
10903
10904 // Erase old position and draw a line at current position
10905 static int pyold1 = 0;
10906 static int pyold2 = 0;
10907 float uxmin = gPad->GetUxmin();
10908 float uxmax = gPad->GetUxmax();
10909 int pxmin = gPad->XtoAbsPixel(uxmin);
10910 int pxmax = gPad->XtoAbsPixel(uxmax);
10911 Float_t upy = gPad->AbsPixeltoY(py);
10912 Float_t y = gPad->PadtoY(upy);
10913 Int_t biny1 = fH->GetYaxis()->FindBin(y);
10914 Int_t biny2 = TMath::Min(biny1+nbins-1, fH->GetYaxis()->GetNbins());
10915 Int_t py1 = gPad->YtoAbsPixel(gPad->GetLogy() ? TMath::Log10(fH->GetYaxis()->GetBinLowEdge(biny1)) : fH->GetYaxis()->GetBinLowEdge(biny1));
10916 Int_t py2 = gPad->YtoAbsPixel(gPad->GetLogy() ? TMath::Log10(fH->GetYaxis()->GetBinUpEdge(biny2)) : fH->GetYaxis()->GetBinUpEdge(biny2));
10917
10919 gVirtualX->DrawBox(pxmin,py1,pxmax,py2,TVirtualX::kFilled);
10920 pyold1 = py1;
10921 pyold2 = py2;
10922
10923 // Create or set the new canvas proj x
10925 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10926 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(name1.Data());
10927 if (c) {
10928 c->Clear();
10929 } else {
10930 fShowProjection = 0;
10931 fShowProjection2 = 0;
10932 pyold1 = 0;
10933 pyold2 = 0;
10934 return;
10935 }
10936 c->cd();
10937 c->SetLogy(ctxt.GetSaved()->GetLogz());
10938 c->SetLogx(ctxt.GetSaved()->GetLogx());
10939
10940 // Draw slice corresponding to mouse position
10941 TString prjName = TString::Format("slice_px_of_%s",fH->GetName());
10942 TH1D *hp = ((TH2*)fH)->ProjectionX(prjName, biny1, biny2);
10943 if (hp) {
10944 hp->SetFillColor(38);
10945 // apply a patch from Oliver Freyermuth to set the title in the projection
10946 // using the range of the projected Y values
10947 if (biny1 == biny2) {
10950 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
10952 if (fH->GetYaxis()->GetLabels() != nullptr) {
10953 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf] %s", biny1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetYaxis()->GetBinLabel(biny1)));
10954 } else {
10955 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf]", biny1, valuePrecision, valueFrom, valuePrecision, valueTo));
10956 }
10957 } else {
10960 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
10961 // biny1 is used here to get equal precision no matter how large the binrange is,
10962 // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
10964 if (fH->GetYaxis()->GetLabels() != nullptr) {
10965 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)));
10966 } else {
10967 hp->SetTitle(TString::Format("ProjectionX of biny=[%d,%d] [y=%.*lf..%.*lf]", biny1, biny2, valuePrecision, valueFrom, valuePrecision, valueTo));
10968 }
10969 }
10970 hp->SetXTitle(fH->GetXaxis()->GetTitle());
10971 hp->SetYTitle(((TH2*)fH)->GetZaxis()->GetTitle() ? ((TH2*)fH)->GetZaxis()->GetTitle() : "Number of Entries");
10972 hp->Draw();
10973 c->Update();
10974 }
10975}
10976
10977////////////////////////////////////////////////////////////////////////////////
10978/// Show projection onto Y.
10979
10981{
10982
10983 Int_t nbins = (Int_t)fShowProjection/100;
10984 if (fShowProjection2)
10985 nbins = (Int_t)fShowProjection2/100;
10986 gPad->SetDoubleBuffer(0); // turn off double buffer mode
10987 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
10988
10989 // Erase old position and draw a line at current position
10990 static int pxold1 = 0;
10991 static int pxold2 = 0;
10992 float uymin = gPad->GetUymin();
10993 float uymax = gPad->GetUymax();
10994 int pymin = gPad->YtoAbsPixel(uymin);
10995 int pymax = gPad->YtoAbsPixel(uymax);
10996 Float_t upx = gPad->AbsPixeltoX(px);
10997 Float_t x = gPad->PadtoX(upx);
10998 Int_t binx1 = fH->GetXaxis()->FindBin(x);
10999 Int_t binx2 = TMath::Min(binx1+nbins-1, fH->GetXaxis()->GetNbins());
11000 Int_t px1 = gPad->XtoAbsPixel(gPad->GetLogx() ? TMath::Log10(fH->GetXaxis()->GetBinLowEdge(binx1)) : fH->GetXaxis()->GetBinLowEdge(binx1));
11001 Int_t px2 = gPad->XtoAbsPixel(gPad->GetLogx() ? TMath::Log10(fH->GetXaxis()->GetBinUpEdge(binx2)) : fH->GetXaxis()->GetBinUpEdge(binx2));
11002
11004 gVirtualX->DrawBox(px1,pymin,px2,pymax,TVirtualX::kFilled);
11005 pxold1 = px1;
11006 pxold2 = px2;
11007
11008 // Create or set the new canvas proj y
11010
11011 TString name2 = fShowProjection2 ? TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2)
11012 : TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
11013
11014 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(name2.Data());
11015 if (c) {
11016 c->Clear();
11017 } else {
11018 fShowProjection = 0;
11019 fShowProjection2 = 0;
11020 pxold1 = 0;
11021 pxold2 = 0;
11022 return;
11023 }
11024 c->cd();
11025 c->SetLogy(ctxt.GetSaved()->GetLogz());
11026 c->SetLogx(ctxt.GetSaved()->GetLogy());
11027
11028 // Draw slice corresponding to mouse position
11029 TString prjName = TString::Format("slice_py_of_%s",fH->GetName());
11030 TH1D *hp = ((TH2*)fH)->ProjectionY(prjName, binx1, binx2);
11031 if (hp) {
11032 hp->SetFillColor(38);
11033 // apply a patch from Oliver Freyermuth to set the title in the projection
11034 // using the range of the projected X values
11035 if (binx1 == binx2) {
11038 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11040 if (fH->GetXaxis()->GetLabels() != nullptr) {
11041 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf] [%s]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetXaxis()->GetBinLabel(binx1)));
11042 } else {
11043 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo));
11044 }
11045 } else {
11048 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11049 // binx1 is used here to get equal precision no matter how large the binrange is,
11050 // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
11052 if (fH->GetXaxis()->GetLabels() != nullptr) {
11053 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)));
11054 } else {
11055 hp->SetTitle(TString::Format("ProjectionY of binx=[%d,%d] [x=%.*lf..%.*lf]", binx1, binx2, valuePrecision, valueFrom, valuePrecision, valueTo));
11056 }
11057 }
11058 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11059 hp->SetYTitle(((TH2*)fH)->GetZaxis()->GetTitle() ? ((TH2*)fH)->GetZaxis()->GetTitle() : "Number of Entries");
11060 hp->Draw(fShowProjection2 ? "hbar" : "");
11061 c->Update();
11062 }
11063}
11064
11065////////////////////////////////////////////////////////////////////////////////
11066/// Show projection (specified by `fShowProjection`) of a `TH3`.
11067/// The drawing option for the projection is in `fShowOption`.
11068///
11069/// First implementation; R.Brun
11070///
11071/// Full implementation: Tim Tran (timtran@jlab.org) April 2006
11072
11074{
11075
11076 Int_t nbins=(Int_t)fShowProjection/100; //decode nbins
11077 if (fH->GetDimension() < 3) {
11078 if (fShowProjection2 % 100 == 1) {
11079 ShowProjectionY(px, py);
11080 }
11081 if (fShowProjection % 100 == 1) {
11082 ShowProjectionX(px, py);
11083 return;
11084 }
11085 if (fShowProjection % 100 == 2) {
11086 ShowProjectionY(px, py);
11087 return;
11088 }
11089 }
11090
11091 gPad->SetDoubleBuffer(0); // turn off double buffer mode
11092 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
11093
11094 // Erase old position and draw a line at current position
11095 TView *view = gPad->GetView();
11096 if (!view) return;
11097 TH3 *h3 = (TH3*)fH;
11098 TAxis *xaxis = h3->GetXaxis();
11099 TAxis *yaxis = h3->GetYaxis();
11100 TAxis *zaxis = h3->GetZaxis();
11101 Double_t u[3],xx[3];
11102
11103 static TPoint line1[2];//store end points of a line, initialised 0 by default
11104 static TPoint line2[2];// second line when slice thickness > 1 bin thickness
11105 static TPoint line3[2];
11106 static TPoint line4[2];
11107 static TPoint endface1[5];
11108 static TPoint endface2[5];
11109 static TPoint rect1[5];//store vertices of the polyline (rectangle), initialsed 0 by default
11110 static TPoint rect2[5];// second rectangle when slice thickness > 1 bin thickness
11111
11112 Double_t uxmin = gPad->GetUxmin();
11113 Double_t uxmax = gPad->GetUxmax();
11114 Double_t uymin = gPad->GetUymin();
11115 Double_t uymax = gPad->GetUymax();
11116
11117 int pxmin = gPad->XtoAbsPixel(uxmin);
11118 int pxmax = gPad->XtoAbsPixel(uxmax);
11119 if (pxmin==pxmax) return;
11120 int pymin = gPad->YtoAbsPixel(uymin);
11121 int pymax = gPad->YtoAbsPixel(uymax);
11122 if (pymin==pymax) return;
11125 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(TString::Format("c_%zx_projection_%d",
11126 (size_t)fH, fShowProjection).Data());
11127 if (!c) {
11128 fShowProjection = 0;
11129 return;
11130 }
11131
11133
11134 switch ((Int_t)fShowProjection%100) {
11135 case 1:
11136 // "x"
11137 {
11138 Int_t firstY = yaxis->GetFirst();
11139 Int_t lastY = yaxis->GetLast();
11141 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11142 yaxis->SetRange(biny,biny2);
11143 Int_t firstZ = zaxis->GetFirst();
11144 Int_t lastZ = zaxis->GetLast();
11146 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11147 zaxis->SetRange(binz,binz2);
11148 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11149 if (nbins>1 && line1[0].GetX()) {
11150 gVirtualX->DrawPolyLine(2,line2);
11151 gVirtualX->DrawPolyLine(2,line3);
11152 gVirtualX->DrawPolyLine(2,line4);
11153 gVirtualX->DrawPolyLine(5,endface1);
11154 gVirtualX->DrawPolyLine(5,endface2);
11155 }
11156 xx[0] = xaxis->GetXmin();
11157 xx[2] = zaxis->GetBinCenter(binz);
11158 xx[1] = yaxis->GetBinCenter(biny);
11159 view->WCtoNDC(xx,u);
11160 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11161 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11162 xx[0] = xaxis->GetXmax();
11163 view->WCtoNDC(xx,u);
11164 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11165 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11166 gVirtualX->DrawPolyLine(2,line1);
11167 if (nbins>1) {
11168 xx[0] = xaxis->GetXmin();
11169 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11170 xx[1] = yaxis->GetBinCenter(biny);
11171 view->WCtoNDC(xx,u);
11172 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11173 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11174 xx[0] = xaxis->GetXmax();
11175 view->WCtoNDC(xx,u);
11176 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11177 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11178
11179 xx[0] = xaxis->GetXmin();
11180 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11181 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11182 view->WCtoNDC(xx,u);
11183 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11184 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11185 xx[0] = xaxis->GetXmax();
11186 view->WCtoNDC(xx,u);
11187 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11188 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11189
11190 xx[0] = xaxis->GetXmin();
11191 xx[2] = zaxis->GetBinCenter(binz);
11192 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11193 view->WCtoNDC(xx,u);
11194 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11195 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11196 xx[0] = xaxis->GetXmax();
11197 view->WCtoNDC(xx,u);
11198 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11199 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11200
11201 endface1[0].SetX(line1[0].GetX());
11202 endface1[0].SetY(line1[0].GetY());
11203 endface1[1].SetX(line2[0].GetX());
11204 endface1[1].SetY(line2[0].GetY());
11205 endface1[2].SetX(line3[0].GetX());
11206 endface1[2].SetY(line3[0].GetY());
11207 endface1[3].SetX(line4[0].GetX());
11208 endface1[3].SetY(line4[0].GetY());
11209 endface1[4].SetX(line1[0].GetX());
11210 endface1[4].SetY(line1[0].GetY());
11211
11212 endface2[0].SetX(line1[1].GetX());
11213 endface2[0].SetY(line1[1].GetY());
11214 endface2[1].SetX(line2[1].GetX());
11215 endface2[1].SetY(line2[1].GetY());
11216 endface2[2].SetX(line3[1].GetX());
11217 endface2[2].SetY(line3[1].GetY());
11218 endface2[3].SetX(line4[1].GetX());
11219 endface2[3].SetY(line4[1].GetY());
11220 endface2[4].SetX(line1[1].GetX());
11221 endface2[4].SetY(line1[1].GetY());
11222
11223 gVirtualX->DrawPolyLine(2,line2);
11224 gVirtualX->DrawPolyLine(2,line3);
11225 gVirtualX->DrawPolyLine(2,line4);
11226 gVirtualX->DrawPolyLine(5,endface1);
11227 gVirtualX->DrawPolyLine(5,endface2);
11228 }
11229 c->Clear();
11230 c->cd();
11231 TH1 *hp = h3->Project3D("x");
11232 yaxis->SetRange(firstY,lastY);
11233 zaxis->SetRange(firstZ,lastZ);
11234 if (hp) {
11235 hp->SetFillColor(38);
11236 if (nbins == 1)
11237 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny),
11238 binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
11239 else {
11240 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),
11241 binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
11242 }
11243 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11244 hp->SetYTitle("Number of Entries");
11245 hp->Draw(fShowOption.Data());
11246 }
11247 }
11248 break;
11249
11250 case 2:
11251 // "y"
11252 {
11253 Int_t firstX = xaxis->GetFirst();
11254 Int_t lastX = xaxis->GetLast();
11256 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11257 xaxis->SetRange(binx,binx2);
11258 Int_t firstZ = zaxis->GetFirst();
11259 Int_t lastZ = zaxis->GetLast();
11261 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11262 zaxis->SetRange(binz,binz2);
11263 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11264 if (nbins>1 && line1[0].GetX()) {
11265 gVirtualX->DrawPolyLine(2,line2);
11266 gVirtualX->DrawPolyLine(2,line3);
11267 gVirtualX->DrawPolyLine(2,line4);
11268 gVirtualX->DrawPolyLine(5,endface1);
11269 gVirtualX->DrawPolyLine(5,endface2);
11270 }
11271 xx[0]=xaxis->GetBinCenter(binx);
11272 xx[2] = zaxis->GetBinCenter(binz);
11273 xx[1] = yaxis->GetXmin();
11274 view->WCtoNDC(xx,u);
11275 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11276 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11277 xx[1] = yaxis->GetXmax();
11278 view->WCtoNDC(xx,u);
11279 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11280 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11281 gVirtualX->DrawPolyLine(2,line1);
11282 if (nbins>1) {
11283 xx[1] = yaxis->GetXmin();
11284 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11285 xx[0] = xaxis->GetBinCenter(binx);
11286 view->WCtoNDC(xx,u);
11287 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11288 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11289 xx[1] = yaxis->GetXmax();
11290 view->WCtoNDC(xx,u);
11291 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11292 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11293
11294 xx[1] = yaxis->GetXmin();
11295 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11296 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11297 view->WCtoNDC(xx,u);
11298 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11299 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11300 xx[1] = yaxis->GetXmax();
11301 view->WCtoNDC(xx,u);
11302 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11303 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11304
11305 xx[1] = yaxis->GetXmin();
11306 xx[2] = zaxis->GetBinCenter(binz);
11307 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11308 view->WCtoNDC(xx,u);
11309 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11310 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11311 xx[1] = yaxis->GetXmax();
11312 view->WCtoNDC(xx,u);
11313 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11314 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11315
11316 endface1[0].SetX(line1[0].GetX());
11317 endface1[0].SetY(line1[0].GetY());
11318 endface1[1].SetX(line2[0].GetX());
11319 endface1[1].SetY(line2[0].GetY());
11320 endface1[2].SetX(line3[0].GetX());
11321 endface1[2].SetY(line3[0].GetY());
11322 endface1[3].SetX(line4[0].GetX());
11323 endface1[3].SetY(line4[0].GetY());
11324 endface1[4].SetX(line1[0].GetX());
11325 endface1[4].SetY(line1[0].GetY());
11326
11327 endface2[0].SetX(line1[1].GetX());
11328 endface2[0].SetY(line1[1].GetY());
11329 endface2[1].SetX(line2[1].GetX());
11330 endface2[1].SetY(line2[1].GetY());
11331 endface2[2].SetX(line3[1].GetX());
11332 endface2[2].SetY(line3[1].GetY());
11333 endface2[3].SetX(line4[1].GetX());
11334 endface2[3].SetY(line4[1].GetY());
11335 endface2[4].SetX(line1[1].GetX());
11336 endface2[4].SetY(line1[1].GetY());
11337
11338 gVirtualX->DrawPolyLine(2,line2);
11339 gVirtualX->DrawPolyLine(2,line3);
11340 gVirtualX->DrawPolyLine(2,line4);
11341 gVirtualX->DrawPolyLine(5,endface1);
11342 gVirtualX->DrawPolyLine(5,endface2);
11343 }
11344 c->Clear();
11345 c->cd();
11346 TH1 *hp = h3->Project3D("y");
11347 xaxis->SetRange(firstX,lastX);
11348 zaxis->SetRange(firstZ,lastZ);
11349 if (hp) {
11350 hp->SetFillColor(38);
11351 if (nbins == 1)
11352 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
11353 binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
11354 else
11355 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),
11356 binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
11357 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11358 hp->SetYTitle("Number of Entries");
11359 hp->Draw(fShowOption.Data());
11360 }
11361 }
11362 break;
11363
11364 case 3:
11365 // "z"
11366 {
11367 Int_t firstX = xaxis->GetFirst();
11368 Int_t lastX = xaxis->GetLast();
11370 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11371 xaxis->SetRange(binx,binx2);
11372 Int_t firstY = yaxis->GetFirst();
11373 Int_t lastY = yaxis->GetLast();
11375 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11376 yaxis->SetRange(biny,biny2);
11377 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11378 if (nbins>1 && line1[0].GetX()) {
11379 gVirtualX->DrawPolyLine(2,line2);
11380 gVirtualX->DrawPolyLine(2,line3);
11381 gVirtualX->DrawPolyLine(2,line4);
11382 gVirtualX->DrawPolyLine(5,endface1);
11383 gVirtualX->DrawPolyLine(5,endface2);
11384 }
11385 xx[0] = xaxis->GetBinCenter(binx);
11386 xx[1] = yaxis->GetBinCenter(biny);
11387 xx[2] = zaxis->GetXmin();
11388 view->WCtoNDC(xx,u);
11389 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11390 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11391 xx[2] = zaxis->GetXmax();
11392 view->WCtoNDC(xx,u);
11393 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11394 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11395 gVirtualX->DrawPolyLine(2,line1);
11396 if (nbins>1) {
11397 xx[2] = zaxis->GetXmin();
11398 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11399 xx[0] = xaxis->GetBinCenter(binx);
11400 view->WCtoNDC(xx,u);
11401 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11402 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11403 xx[2] = zaxis->GetXmax();
11404 view->WCtoNDC(xx,u);
11405 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11406 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11407
11408 xx[2] = zaxis->GetXmin();
11409 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11410 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11411 view->WCtoNDC(xx,u);
11412 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11413 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11414 xx[2] = zaxis->GetXmax();
11415 view->WCtoNDC(xx,u);
11416 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11417 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11418
11419 xx[2] = zaxis->GetXmin();
11420 xx[1] = yaxis->GetBinCenter(biny);
11421 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11422 view->WCtoNDC(xx,u);
11423 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11424 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11425 xx[2] = zaxis->GetXmax();
11426 view->WCtoNDC(xx,u);
11427 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11428 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11429
11430 endface1[0].SetX(line1[0].GetX());
11431 endface1[0].SetY(line1[0].GetY());
11432 endface1[1].SetX(line2[0].GetX());
11433 endface1[1].SetY(line2[0].GetY());
11434 endface1[2].SetX(line3[0].GetX());
11435 endface1[2].SetY(line3[0].GetY());
11436 endface1[3].SetX(line4[0].GetX());
11437 endface1[3].SetY(line4[0].GetY());
11438 endface1[4].SetX(line1[0].GetX());
11439 endface1[4].SetY(line1[0].GetY());
11440
11441 endface2[0].SetX(line1[1].GetX());
11442 endface2[0].SetY(line1[1].GetY());
11443 endface2[1].SetX(line2[1].GetX());
11444 endface2[1].SetY(line2[1].GetY());
11445 endface2[2].SetX(line3[1].GetX());
11446 endface2[2].SetY(line3[1].GetY());
11447 endface2[3].SetX(line4[1].GetX());
11448 endface2[3].SetY(line4[1].GetY());
11449 endface2[4].SetX(line1[1].GetX());
11450 endface2[4].SetY(line1[1].GetY());
11451
11452 gVirtualX->DrawPolyLine(2,line2);
11453 gVirtualX->DrawPolyLine(2,line3);
11454 gVirtualX->DrawPolyLine(2,line4);
11455 gVirtualX->DrawPolyLine(5,endface1);
11456 gVirtualX->DrawPolyLine(5,endface2);
11457 }
11458 c->Clear();
11459 c->cd();
11460 TH1 *hp = h3->Project3D("z");
11461 xaxis->SetRange(firstX,lastX);
11462 yaxis->SetRange(firstY,lastY);
11463 if (hp) {
11464 hp->SetFillColor(38);
11465 if (nbins == 1)
11466 hp->SetTitle(TString::Format("ProjectionZ of binx=%d [x=%.1f..%.1f] biny=%d [y=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
11467 biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny)));
11468 else
11469 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),
11470 biny, biny2, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny2) ) );
11471 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11472 hp->SetYTitle("Number of Entries");
11473 hp->Draw(fShowOption.Data());
11474 }
11475 }
11476 break;
11477
11478 case 4:
11479 // "xy"
11480 {
11481 Int_t first = zaxis->GetFirst();
11482 Int_t last = zaxis->GetLast();
11483 Int_t binz = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11484 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11485 zaxis->SetRange(binz,binz2);
11486 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11487 if (nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11488 xx[0] = xaxis->GetXmin();
11489 xx[1] = yaxis->GetXmax();
11490 xx[2] = zaxis->GetBinCenter(binz);
11491 view->WCtoNDC(xx,u);
11492 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11493 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11494 rect1[4].SetX(rect1[0].GetX());
11495 rect1[4].SetY(rect1[0].GetY());
11496 xx[0] = xaxis->GetXmax();
11497 view->WCtoNDC(xx,u);
11498 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11499 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11500 xx[1] = yaxis->GetXmin();
11501 view->WCtoNDC(xx,u);
11502 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11503 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11504 xx[0] = xaxis->GetXmin();
11505 view->WCtoNDC(xx,u);
11506 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11507 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11508 gVirtualX->DrawPolyLine(5,rect1);
11509 if (nbins>1) {
11510 xx[0] = xaxis->GetXmin();
11511 xx[1] = yaxis->GetXmax();
11512 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11513 view->WCtoNDC(xx,u);
11514 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11515 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11516 rect2[4].SetX(rect2[0].GetX());
11517 rect2[4].SetY(rect2[0].GetY());
11518 xx[0] = xaxis->GetXmax();
11519 view->WCtoNDC(xx,u);
11520 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11521 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11522 xx[1] = yaxis->GetXmin();
11523 view->WCtoNDC(xx,u);
11524 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11525 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11526 xx[0] = xaxis->GetXmin();
11527 view->WCtoNDC(xx,u);
11528 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11529 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11530 gVirtualX->DrawPolyLine(5,rect2);
11531 }
11532
11533 c->Clear();
11534 c->cd();
11535 TH2 *hp = (TH2*)h3->Project3D("xy");
11536 zaxis->SetRange(first,last);
11537 if (hp) {
11538 hp->SetFillColor(38);
11539 if (nbins==1)hp->SetTitle(TString::Format("ProjectionXY of binz=%d [z=%.1f..%.f]", binz,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz)));
11540 else hp->SetTitle(TString::Format("ProjectionXY, binz=[%d,%d] [z=%.1f..%.1f]", binz,binz2,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz2)));
11541 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11542 hp->SetYTitle(fH->GetXaxis()->GetTitle());
11543 hp->SetZTitle("Number of Entries");
11544 hp->Draw(fShowOption.Data());
11545 }
11546 }
11547 break;
11548
11549 case 5:
11550 // "yx"
11551 {
11552 Int_t first = zaxis->GetFirst();
11553 Int_t last = zaxis->GetLast();
11554 Int_t binz = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11555 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11556 zaxis->SetRange(binz,binz2);
11557 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11558 if (nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11559 xx[0] = xaxis->GetXmin();
11560 xx[1] = yaxis->GetXmax();
11561 xx[2] = zaxis->GetBinCenter(binz);
11562 view->WCtoNDC(xx,u);
11563 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11564 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11565 rect1[4].SetX(rect1[0].GetX());
11566 rect1[4].SetY(rect1[0].GetY());
11567 xx[0] = xaxis->GetXmax();
11568 view->WCtoNDC(xx,u);
11569 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11570 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11571 xx[1] = yaxis->GetXmin();
11572 view->WCtoNDC(xx,u);
11573 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11574 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11575 xx[0] = xaxis->GetXmin();
11576 view->WCtoNDC(xx,u);
11577 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11578 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11579 gVirtualX->DrawPolyLine(5,rect1);
11580 if (nbins>1) {
11581 xx[0] = xaxis->GetXmin();
11582 xx[1] = yaxis->GetXmax();
11583 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11584 view->WCtoNDC(xx,u);
11585 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11586 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11587 rect2[4].SetX(rect2[0].GetX());
11588 rect2[4].SetY(rect2[0].GetY());
11589 xx[0] = xaxis->GetXmax();
11590 view->WCtoNDC(xx,u);
11591 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11592 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11593 xx[1] = yaxis->GetXmin();
11594 view->WCtoNDC(xx,u);
11595 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11596 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11597 xx[0] = xaxis->GetXmin();
11598 view->WCtoNDC(xx,u);
11599 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11600 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11601 gVirtualX->DrawPolyLine(5,rect2);
11602 }
11603 c->Clear();
11604 c->cd();
11605 TH2 *hp = (TH2*)h3->Project3D("yx");
11606 zaxis->SetRange(first,last);
11607 if (hp) {
11608 hp->SetFillColor(38);
11609 if (nbins==1)hp->SetTitle(TString::Format("ProjectionYX of binz=%d [z=%.1f..%.f]", binz,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz)));
11610 else hp->SetTitle(TString::Format("ProjectionYX, binz=[%d,%d] [z=%.1f..%.1f]", binz,binz2,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz2)));
11611 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11612 hp->SetYTitle(fH->GetYaxis()->GetTitle());
11613 hp->SetZTitle("Number of Entries");
11614 hp->Draw(fShowOption.Data());
11615 }
11616 }
11617 break;
11618
11619 case 6:
11620 // "xz"
11621 {
11622 Int_t first = yaxis->GetFirst();
11623 Int_t last = yaxis->GetLast();
11624 Int_t biny = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11625 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11626 yaxis->SetRange(biny,biny2);
11627 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11628 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11629 xx[0] = xaxis->GetXmin();
11630 xx[2] = zaxis->GetXmax();
11631 xx[1] = yaxis->GetBinCenter(biny);
11632 view->WCtoNDC(xx,u);
11633 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11634 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11635 rect1[4].SetX(rect1[0].GetX());
11636 rect1[4].SetY(rect1[0].GetY());
11637 xx[0] = xaxis->GetXmax();
11638 view->WCtoNDC(xx,u);
11639 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11640 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11641 xx[2] = zaxis->GetXmin();
11642 view->WCtoNDC(xx,u);
11643 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11644 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11645 xx[0] = xaxis->GetXmin();
11646 view->WCtoNDC(xx,u);
11647 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11648 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11649 gVirtualX->DrawPolyLine(5,rect1);
11650 if (nbins>1) {
11651 xx[0] = xaxis->GetXmin();
11652 xx[2] = zaxis->GetXmax();
11653 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11654 view->WCtoNDC(xx,u);
11655 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11656 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11657 rect2[4].SetX(rect2[0].GetX());
11658 rect2[4].SetY(rect2[0].GetY());
11659 xx[0] = xaxis->GetXmax();
11660 view->WCtoNDC(xx,u);
11661 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11662 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11663 xx[2] = zaxis->GetXmin();
11664 view->WCtoNDC(xx,u);
11665 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11666 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11667 xx[0] = xaxis->GetXmin();
11668 view->WCtoNDC(xx,u);
11669 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11670 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11671 gVirtualX->DrawPolyLine(5,rect2);
11672 }
11673 c->Clear();
11674 c->cd();
11675 TH2 *hp = (TH2*)h3->Project3D("xz");
11676 yaxis->SetRange(first,last);
11677 if (hp) {
11678 hp->SetFillColor(38);
11679 if (nbins==1)hp->SetTitle(TString::Format("ProjectionXZ of biny=%d [y=%.1f..%.f]", biny,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny)));
11680 else hp->SetTitle(TString::Format("ProjectionXZ, biny=[%d,%d] [y=%.1f..%.1f]", biny,biny2,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny2)));
11681 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11682 hp->SetYTitle(fH->GetXaxis()->GetTitle());
11683 hp->SetZTitle("Number of Entries");
11684 hp->Draw(fShowOption.Data());
11685 }
11686 }
11687 break;
11688
11689 case 7:
11690 // "zx"
11691 {
11692 Int_t first = yaxis->GetFirst();
11693 Int_t last = yaxis->GetLast();
11694 Int_t biny = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11695 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11696 yaxis->SetRange(biny,biny2);
11697 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11698 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11699 xx[0] = xaxis->GetXmin();
11700 xx[2] = zaxis->GetXmax();
11701 xx[1] = yaxis->GetBinCenter(biny);
11702 view->WCtoNDC(xx,u);
11703 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11704 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11705 rect1[4].SetX(rect1[0].GetX());
11706 rect1[4].SetY(rect1[0].GetY());
11707 xx[0] = xaxis->GetXmax();
11708 view->WCtoNDC(xx,u);
11709 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11710 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11711 xx[2] = zaxis->GetXmin();
11712 view->WCtoNDC(xx,u);
11713 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11714 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11715 xx[0] = xaxis->GetXmin();
11716 view->WCtoNDC(xx,u);
11717 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11718 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11719 gVirtualX->DrawPolyLine(5,rect1);
11720 if (nbins>1) {
11721 xx[0] = xaxis->GetXmin();
11722 xx[2] = zaxis->GetXmax();
11723 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11724 view->WCtoNDC(xx,u);
11725 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11726 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11727 rect2[4].SetX(rect2[0].GetX());
11728 rect2[4].SetY(rect2[0].GetY());
11729 xx[0] = xaxis->GetXmax();
11730 view->WCtoNDC(xx,u);
11731 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11732 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11733 xx[2] = zaxis->GetXmin();
11734 view->WCtoNDC(xx,u);
11735 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11736 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11737 xx[0] = xaxis->GetXmin();
11738 view->WCtoNDC(xx,u);
11739 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11740 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11741 gVirtualX->DrawPolyLine(5,rect2);
11742 }
11743 c->Clear();
11744 c->cd();
11745 TH2 *hp = (TH2*)h3->Project3D("zx");
11746 yaxis->SetRange(first,last);
11747 if (hp) {
11748 hp->SetFillColor(38);
11749 if (nbins==1)hp->SetTitle(TString::Format("ProjectionZX of biny=%d [y=%.1f..%.f]", biny,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny)));
11750 else hp->SetTitle(TString::Format("ProjectionZX, biny=[%d,%d] [y=%.1f..%.1f]", biny,biny2,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny2)));
11751 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11752 hp->SetYTitle(fH->GetZaxis()->GetTitle());
11753 hp->SetZTitle("Number of Entries");
11754 hp->Draw(fShowOption.Data());
11755 }
11756 }
11757 break;
11758
11759 case 8:
11760 // "yz"
11761 {
11762 Int_t first = xaxis->GetFirst();
11763 Int_t last = xaxis->GetLast();
11764 Int_t binx = first + Int_t((last-first)*(px-pxmin)/(pxmax-pxmin));
11765 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11766 xaxis->SetRange(binx,binx2);
11767 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11768 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11769 xx[2] = zaxis->GetXmin();
11770 xx[1] = yaxis->GetXmax();
11771 xx[0] = xaxis->GetBinCenter(binx);
11772 view->WCtoNDC(xx,u);
11773 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11774 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11775 rect1[4].SetX(rect1[0].GetX());
11776 rect1[4].SetY(rect1[0].GetY());
11777 xx[2] = zaxis->GetXmax();
11778 view->WCtoNDC(xx,u);
11779 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11780 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11781 xx[1] = yaxis->GetXmin();
11782 view->WCtoNDC(xx,u);
11783 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11784 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11785 xx[2] = zaxis->GetXmin();
11786 view->WCtoNDC(xx,u);
11787 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11788 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11789 gVirtualX->DrawPolyLine(5,rect1);
11790 if (nbins>1) {
11791 xx[2] = zaxis->GetXmin();
11792 xx[1] = yaxis->GetXmax();
11793 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11794 view->WCtoNDC(xx,u);
11795 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11796 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11797 rect2[4].SetX(rect2[0].GetX());
11798 rect2[4].SetY(rect2[0].GetY());
11799 xx[2] = zaxis->GetXmax();
11800 view->WCtoNDC(xx,u);
11801 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11802 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11803 xx[1] = yaxis->GetXmin();
11804 view->WCtoNDC(xx,u);
11805 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11806 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11807 xx[2] = zaxis->GetXmin();
11808 view->WCtoNDC(xx,u);
11809 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11810 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11811 gVirtualX->DrawPolyLine(5,rect2);
11812 }
11813 c->Clear();
11814 c->cd();
11815 TH2 *hp = (TH2*)h3->Project3D("yz");
11816 xaxis->SetRange(first,last);
11817 if (hp) {
11818 hp->SetFillColor(38);
11819 if (nbins==1)hp->SetTitle(TString::Format("ProjectionYZ of binx=%d [x=%.1f..%.f]", binx,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx)));
11820 else hp->SetTitle(TString::Format("ProjectionYZ, binx=[%d,%d] [x=%.1f..%.1f]", binx,binx2,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx2)));
11821 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11822 hp->SetYTitle(fH->GetYaxis()->GetTitle());
11823 hp->SetZTitle("Number of Entries");
11824 hp->Draw(fShowOption.Data());
11825 }
11826 }
11827 break;
11828
11829 case 9:
11830 // "zy"
11831 {
11832 Int_t first = xaxis->GetFirst();
11833 Int_t last = xaxis->GetLast();
11834 Int_t binx = first + Int_t((last-first)*(px-pxmin)/(pxmax-pxmin));
11835 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11836 xaxis->SetRange(binx,binx2);
11837 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11838 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11839 xx[2] = zaxis->GetXmin();
11840 xx[1] = yaxis->GetXmax();
11841 xx[0] = xaxis->GetBinCenter(binx);
11842 view->WCtoNDC(xx,u);
11843 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11844 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11845 rect1[4].SetX(rect1[0].GetX());
11846 rect1[4].SetY(rect1[0].GetY());
11847 xx[2] = zaxis->GetXmax();
11848 view->WCtoNDC(xx,u);
11849 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11850 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11851 xx[1] = yaxis->GetXmin();
11852 view->WCtoNDC(xx,u);
11853 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11854 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11855 xx[2] = zaxis->GetXmin();
11856 view->WCtoNDC(xx,u);
11857 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11858 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11859 gVirtualX->DrawPolyLine(5,rect1);
11860 if (nbins>1) {
11861 xx[2] = zaxis->GetXmin();
11862 xx[1] = yaxis->GetXmax();
11863 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11864 view->WCtoNDC(xx,u);
11865 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11866 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11867 rect2[4].SetX(rect2[0].GetX());
11868 rect2[4].SetY(rect2[0].GetY());
11869 xx[2] = zaxis->GetXmax();
11870 view->WCtoNDC(xx,u);
11871 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11872 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11873 xx[1] = yaxis->GetXmin();
11874 view->WCtoNDC(xx,u);
11875 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11876 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11877 xx[2] = zaxis->GetXmin();
11878 view->WCtoNDC(xx,u);
11879 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11880 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11881 gVirtualX->DrawPolyLine(5,rect2);
11882 }
11883 c->Clear();
11884 c->cd();
11885 TH2 *hp = (TH2*)h3->Project3D("zy");
11886 xaxis->SetRange(first,last);
11887 if (hp) {
11888 hp->SetFillColor(38);
11889 if (nbins==1)hp->SetTitle(TString::Format("ProjectionZY of binx=%d [x=%.1f..%.f]", binx,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx)));
11890 else hp->SetTitle(TString::Format("ProjectionZY, binx=[%d,%d] [x=%.1f..%.1f]", binx,binx2,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx2)));
11891 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11892 hp->SetYTitle(fH->GetZaxis()->GetTitle());
11893 hp->SetZTitle("Number of Entries");
11894 hp->Draw(fShowOption.Data());
11895 }
11896 }
11897 break;
11898 }
11899 c->Update();
11900}
@ kMouseMotion
Definition Buttons.h:23
@ kWheelUp
Definition Buttons.h:18
@ kButton1Motion
Definition Buttons.h:20
@ kButton1Up
Definition Buttons.h:19
@ kWheelDown
Definition Buttons.h:18
@ kButton1Down
Definition Buttons.h:17
@ kButton1Locate
Definition Buttons.h:22
@ kArrowVer
Definition GuiTypes.h:374
@ kPointer
Definition GuiTypes.h:375
Handle_t Window_t
Window handle.
Definition GuiTypes.h:29
#define d(i)
Definition RSha256.hxx:102
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
#define c(i)
Definition RSha256.hxx:101
#define g(i)
Definition RSha256.hxx:105
#define a(i)
Definition RSha256.hxx:99
#define h(i)
Definition RSha256.hxx:106
#define e(i)
Definition RSha256.hxx:103
short Style_t
Definition RtypesCore.h:82
int Int_t
Definition RtypesCore.h:45
short Color_t
Definition RtypesCore.h:85
unsigned int UInt_t
Definition RtypesCore.h:46
short Width_t
Definition RtypesCore.h:84
float Float_t
Definition RtypesCore.h:57
short Short_t
Definition RtypesCore.h:39
constexpr Bool_t kFALSE
Definition RtypesCore.h:94
double Double_t
Definition RtypesCore.h:59
constexpr Bool_t kTRUE
Definition RtypesCore.h:93
const char Option_t
Definition RtypesCore.h:66
#define BIT(n)
Definition Rtypes.h:90
#define ClassImp(name)
Definition Rtypes.h:374
@ kBlack
Definition Rtypes.h:65
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
R__EXTERN TEnv * gEnv
Definition TEnv.h:170
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t option
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void pixel
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t wmin
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize wid
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t np
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize id
Option_t Option_t TPoint TPoint const char x2
Option_t Option_t TPoint TPoint const char x1
Option_t Option_t TPoint TPoint angle
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void xpos
Option_t Option_t TPoint TPoint const char mode
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char backcolor
Option_t Option_t TPoint TPoint const char y2
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void ypos
Option_t Option_t width
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize fs
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t wmax
Option_t Option_t TPoint TPoint const char text
Option_t Option_t TPoint TPoint const char y1
R__EXTERN TH1 * gCurrentHist
R__EXTERN Hoption_t Hoption
float xmin
int ncx
float ymin
int ncy
float xmax
float ymax
static TString gStringStdDevZ
static TString gStringStdDevX
static TString gStringIntegralBinWidth
const UInt_t kCannotRotate
static TString gStringStdDev
const Int_t kNMAX
Hparam_t Hparam
const Int_t kMAXCONTOUR
static TString gStringOverflow
static TString gStringUnderflow
static TString gStringSkewnessY
static TString gStringMean
static TString gStringKurtosis
Hoption_t Hoption
static TString gStringMeanX
static TString gStringEntries
static TString gStringIntegral
static TString gStringKurtosisY
static TString gStringStdDevY
static TString gStringMeanY
static TString gStringSkewnessX
static TString gStringKurtosisX
static std::unique_ptr< TBox > gXHighlightBox
static std::unique_ptr< TBox > gYHighlightBox
static TString gStringSkewnessZ
TH1 * gCurrentHist
static TString gStringMeanZ
static TString gStringSkewness
static TString gStringKurtosisZ
const Int_t kMaxCuts
const Int_t kCYLINDRICAL
const Int_t kSPHERICAL
const Int_t kRAPIDITY
#define gROOT
Definition TROOT.h:414
R__EXTERN TStyle * gStyle
Definition TStyle.h:442
R__EXTERN TSystem * gSystem
Definition TSystem.h:572
const Int_t kCARTESIAN
Definition TView3D.cxx:33
const Int_t kPOLAR
Definition TView3D.cxx:34
#define gPad
#define gVirtualX
Definition TVirtualX.h:337
polygon * polys
Definition X3DBuffer.c:24
Draw all kinds of Arrows.
Definition TArrow.h:29
virtual Int_t GetNdivisions() const
Definition TAttAxis.h:37
virtual Float_t GetLabelOffset() const
Definition TAttAxis.h:41
virtual Float_t GetLabelSize() const
Definition TAttAxis.h:42
virtual Float_t GetTickLength() const
Definition TAttAxis.h:46
virtual Float_t GetTitleOffset() const
Definition TAttAxis.h:44
virtual Color_t GetFillColor() const
Return the fill area color.
Definition TAttFill.h:31
virtual Style_t GetFillStyle() const
Return the fill area style.
Definition TAttFill.h:32
virtual void SetFillColor(Color_t fcolor)
Set the fill area color.
Definition TAttFill.h:38
virtual void SetFillStyle(Style_t fstyle)
Set the fill area style.
Definition TAttFill.h:40
virtual Color_t GetLineColor() const
Return the line color.
Definition TAttLine.h:35
virtual void SetLineStyle(Style_t lstyle)
Set the line style.
Definition TAttLine.h:44
virtual Width_t GetLineWidth() const
Return the line width.
Definition TAttLine.h:37
virtual void SetLineWidth(Width_t lwidth)
Set the line width.
Definition TAttLine.h:45
virtual void SetLineColor(Color_t lcolor)
Set the line color.
Definition TAttLine.h:42
virtual Style_t GetLineStyle() const
Return the line style.
Definition TAttLine.h:36
virtual Style_t GetMarkerStyle() const
Return the marker style.
Definition TAttMarker.h:33
virtual void SetMarkerColor(Color_t mcolor=1)
Set the marker color.
Definition TAttMarker.h:39
virtual Color_t GetMarkerColor() const
Return the marker color.
Definition TAttMarker.h:32
virtual Size_t GetMarkerSize() const
Return the marker size.
Definition TAttMarker.h:34
virtual void SetMarkerStyle(Style_t mstyle=1)
Set the marker style.
Definition TAttMarker.h:41
virtual void SetMarkerSize(Size_t msize=1)
Set the marker size.
Definition TAttMarker.h:46
static Style_t GetMarkerStyleBase(Style_t style)
Internal helper function that returns the corresponding marker style with line width 1 for the given ...
virtual Font_t GetTextFont() const
Return the text font.
Definition TAttText.h:37
virtual void SetTextAngle(Float_t tangle=0)
Set the text angle.
Definition TAttText.h:45
Class to manage histogram axis.
Definition TAxis.h:32
virtual Bool_t GetTimeDisplay() const
Definition TAxis.h:133
Bool_t IsAlphanumeric() const
Definition TAxis.h:90
const char * GetTitle() const override
Returns title of object.
Definition TAxis.h:137
virtual Double_t GetBinCenter(Int_t bin) const
Return center of bin.
Definition TAxis.cxx:482
Bool_t CanExtend() const
Definition TAxis.h:88
const TArrayD * GetXbins() const
Definition TAxis.h:138
Double_t GetXmax() const
Definition TAxis.h:142
@ kAxisRange
Definition TAxis.h:66
const char * GetBinLabel(Int_t bin) const
Return label for bin.
Definition TAxis.cxx:444
virtual Int_t FindBin(Double_t x)
Find bin number corresponding to abscissa x.
Definition TAxis.cxx:296
virtual Double_t GetBinLowEdge(Int_t bin) const
Return low edge of bin.
Definition TAxis.cxx:522
virtual Int_t FindFixBin(Double_t x) const
Find bin number corresponding to abscissa x
Definition TAxis.cxx:423
const char * ChooseTimeFormat(Double_t axislength=0)
Choose a reasonable time format from the coordinates in the active pad and the number of divisions in...
Definition TAxis.cxx:127
Int_t GetLast() const
Return last bin on the axis i.e.
Definition TAxis.cxx:473
virtual const char * GetTimeFormatOnly() const
Return only the time format from the string fTimeFormat.
Definition TAxis.cxx:604
Double_t GetXmin() const
Definition TAxis.h:141
Int_t GetNbins() const
Definition TAxis.h:127
virtual void SetRangeUser(Double_t ufirst, Double_t ulast)
Set the viewing range for the axis from ufirst to ulast (in user coordinates, that is,...
Definition TAxis.cxx:1075
virtual const char * GetTimeFormat() const
Definition TAxis.h:134
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width.
Definition TAxis.cxx:546
virtual Double_t GetBinUpEdge(Int_t bin) const
Return up edge of bin.
Definition TAxis.cxx:532
Int_t GetFirst() const
Return first bin on the axis i.e.
Definition TAxis.cxx:462
THashList * GetLabels() const
Definition TAxis.h:123
Create a Box.
Definition TBox.h:22
The candle plot painter class.
Definition TCandle.h:27
CandleOption
Definition TCandle.h:30
static Bool_t SupportAlpha()
Static function returning "true" if transparency is supported.
Definition TCanvas.cxx:2475
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition TClass.cxx:3074
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
The color creation and management class.
Definition TColor.h:22
static void RGBtoHLS(Float_t r, Float_t g, Float_t b, Float_t &h, Float_t &l, Float_t &s)
Definition TColor.h:83
static Int_t GetColor(const char *hexcolor)
Static method returning color number for color specified by hex color string of form: "#rrggbb",...
Definition TColor.cxx:1927
static Int_t GetColorBright(Int_t color)
Static function: Returns the bright color number corresponding to n If the TColor object does not exi...
Definition TColor.cxx:2096
static Int_t GetColorDark(Int_t color)
Static function: Returns the dark color number corresponding to n If the TColor object does not exist...
Definition TColor.cxx:2139
static void HLStoRGB(Float_t h, Float_t l, Float_t s, Float_t &r, Float_t &g, Float_t &b)
Definition TColor.h:78
To draw a Crown.
Definition TCrown.h:19
Graphical cut class.
Definition TCutG.h:20
static TClass * Class()
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition TEnv.cxx:491
1-Dim function class
Definition TF1.h:234
virtual Double_t GetXmax() const
Definition TF1.h:592
virtual Int_t GetNDF() const
Return the number of degrees of freedom in the fit the fNDF parameter has been previously computed du...
Definition TF1.cxx:1917
virtual void GetParLimits(Int_t ipar, Double_t &parmin, Double_t &parmax) const
Return limits for parameter ipar.
Definition TF1.cxx:1968
virtual Double_t GetParError(Int_t ipar) const
Return value of parameter number ipar.
Definition TF1.cxx:1958
static TClass * Class()
Double_t GetChisquare() const
Return the Chisquare after fitting. See ROOT::Fit::FitResult::Chi2()
Definition TF1.h:476
virtual void SetMaximum(Double_t maximum=-1111)
Set the maximum value along Y for this function In case the function is already drawn,...
Definition TF1.cxx:3426
virtual Double_t GetMaximumStored() const
Definition TF1.h:505
virtual Int_t GetNpar() const
Definition TF1.h:513
virtual Int_t GetNumberFreeParameters() const
Return the number of free parameters.
Definition TF1.cxx:1928
@ kNotDraw
Definition TF1.h:349
virtual void SetMinimum(Double_t minimum=-1111)
Set the minimum value along Y for this function In case the function is already drawn,...
Definition TF1.cxx:3439
virtual const char * GetParName(Int_t ipar) const
Definition TF1.h:561
virtual Double_t Eval(Double_t x, Double_t y=0, Double_t z=0, Double_t t=0) const
Evaluate this function.
Definition TF1.cxx:1447
virtual Double_t GetXmin() const
Definition TF1.h:588
virtual Double_t GetParameter(Int_t ipar) const
Definition TF1.h:544
A 2-Dim function with parameters.
Definition TF2.h:29
void Paint(Option_t *option="") override
Paint this 2-D function with its current attributes.
Definition TF2.cxx:752
void SetRange(Double_t xmin, Double_t xmax) override
Initialize the upper and lower bounds to draw the function.
Definition TF2.h:148
static TClass * Class()
A 3-Dim function with parameters.
Definition TF3.h:28
The axis painter class.
Definition TGaxis.h:26
void SetTimeFormat(const char *tformat)
Change the format used for time plotting.
Definition TGaxis.cxx:2944
virtual void PaintAxis(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax, Double_t &wmin, Double_t &wmax, Int_t &ndiv, Option_t *chopt="", Double_t gridlength=0, Bool_t drawGridOnly=kFALSE)
Control function to draw an axis.
Definition TGaxis.cxx:1008
void SetTitleOffset(Float_t titleoffset=1)
Definition TGaxis.h:130
virtual void SetTitle(const char *title="")
Change the title of the axis.
Definition TGaxis.cxx:2917
void SetLabelOffset(Float_t labeloffset)
Definition TGaxis.h:108
virtual void ImportAxisAttributes(TAxis *axis)
Internal method to import TAxis attributes to this TGaxis.
Definition TGaxis.cxx:955
void SetTickSize(Float_t ticksize)
Definition TGaxis.h:124
void SetLabelSize(Float_t labelsize)
Definition TGaxis.h:109
void SetOption(Option_t *option="")
To set axis options.
Definition TGaxis.cxx:2909
Graphics object made of three arrays X, Y and Z with the same number of points each.
Definition TGraph2D.h:41
static TClass * Class()
TGraphDelaunay2D generates a Delaunay triangulation of a TGraph2D.
TGraphDelaunay generates a Delaunay triangulation of a TGraph2D.
A TGraph is an object made of two arrays X and Y with npoints each.
Definition TGraph.h:41
static TClass * Class()
@ kClipFrame
Clip to the frame boundary.
Definition TGraph.h:75
void PaintGraph(Int_t npoints, const Double_t *x, const Double_t *y, Option_t *chopt)
Draw the (x,y) as a graph.
Definition TGraph.cxx:1987
void PaintGrapHist(Int_t npoints, const Double_t *x, const Double_t *y, Option_t *chopt)
Draw the (x,y) as a histogram.
Definition TGraph.cxx:1996
1-D histogram with a double per channel (see TH1 documentation)
Definition TH1.h:925
1-D histogram with a float per channel (see TH1 documentation)
Definition TH1.h:877
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:108
TAxis * GetZaxis()
Definition TH1.h:573
virtual EBinErrorOpt GetBinErrorOption() const
Definition TH1.h:517
virtual Float_t GetBarWidth() const
Definition TH1.h:501
virtual Double_t GetMinimumStored() const
Definition TH1.h:537
virtual Float_t GetBarOffset() const
Definition TH1.h:500
static TClass * Class()
virtual Double_t GetStdDev(Int_t axis=1) const
Returns the Standard Deviation (Sigma).
Definition TH1.cxx:7602
virtual Int_t GetNbinsY() const
Definition TH1.h:542
virtual Double_t GetBinError(Int_t bin) const
Return value of error associated to bin number bin.
Definition TH1.cxx:9060
virtual Int_t GetNbinsZ() const
Definition TH1.h:543
virtual Double_t GetNormFactor() const
Definition TH1.h:545
virtual Double_t GetMean(Int_t axis=1) const
For axis = 1,2 or 3 returns the mean value of the histogram along X,Y or Z axis.
Definition TH1.cxx:7530
virtual Double_t GetSkewness(Int_t axis=1) const
Definition TH1.cxx:7666
virtual Double_t GetContourLevelPad(Int_t level) const
Return the value of contour number "level" in Pad coordinates.
Definition TH1.cxx:8440
virtual Int_t GetDimension() const
Definition TH1.h:527
static void AddDirectory(Bool_t add=kTRUE)
Sets the flag controlling the automatic add of histograms in memory.
Definition TH1.cxx:1264
@ kNoTitle
Don't draw the histogram title.
Definition TH1.h:408
@ kUserContour
User specified contour levels.
Definition TH1.h:404
@ kNoStats
Don't draw stats box.
Definition TH1.h:403
TAxis * GetXaxis()
Definition TH1.h:571
virtual Double_t GetSumOfWeights() const
Return the sum of weights across all bins excluding under/overflows.
Definition TH1.h:559
virtual Int_t GetBin(Int_t binx, Int_t biny=0, Int_t binz=0) const
Return Global bin number corresponding to binx,y,z.
Definition TH1.cxx:4968
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:8545
virtual Int_t GetNbinsX() const
Definition TH1.h:541
virtual void SetMaximum(Double_t maximum=-1111)
Definition TH1.h:651
TAxis * GetYaxis()
Definition TH1.h:572
virtual Double_t GetBinErrorLow(Int_t bin) const
Return lower error associated to bin number bin.
Definition TH1.cxx:9076
virtual void SetMinimum(Double_t minimum=-1111)
Definition TH1.h:652
virtual Double_t Integral(Option_t *option="") const
Return integral of bin contents.
Definition TH1.cxx:7941
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:9219
virtual Double_t GetBinLowEdge(Int_t bin) const
Return bin lower edge for 1D histogram.
Definition TH1.cxx:9149
virtual Double_t GetEntries() const
Return the current number of entries.
Definition TH1.cxx:4405
TList * GetListOfFunctions() const
Definition TH1.h:488
virtual Double_t GetMeanError(Int_t axis=1) const
Return standard error of mean of this histogram along the X axis.
Definition TH1.cxx:7570
virtual Double_t GetMaximumStored() const
Definition TH1.h:533
virtual void GetMinimumAndMaximum(Double_t &min, Double_t &max) const
Retrieve the minimum and maximum values in the histogram.
Definition TH1.cxx:8731
@ kNormal
Errors with Normal (Wald) approximation: errorUp=errorLow= sqrt(N)
Definition TH1.h:114
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition TH1.cxx:5068
virtual Int_t GetContour(Double_t *levels=nullptr)
Return contour values into array levels if pointer levels is non zero.
Definition TH1.cxx:8411
const Double_t * GetBuffer() const
Definition TH1.h:483
virtual Bool_t IsHighlight() const
Definition TH1.h:585
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width for 1D histogram.
Definition TH1.cxx:9160
virtual void SetContour(Int_t nlevels, const Double_t *levels=nullptr)
Set the number and values of contour levels.
Definition TH1.cxx:8483
virtual Double_t GetBinErrorUp(Int_t bin) const
Return upper error associated to bin number bin.
Definition TH1.cxx:9107
virtual Int_t GetSumw2N() const
Definition TH1.h:562
virtual Double_t GetStdDevError(Int_t axis=1) const
Return error of standard deviation estimation for Normal distribution.
Definition TH1.cxx:7650
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:8635
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:5252
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:7739
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