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| "PADSn" | Like PADS but the current pad/canvas is subdivided into a `n` columns, automatically calculating the number of rows.|
359| "PFC" | Palette Fill Color: stack's fill color is taken in the current palette. |
360| "PLC" | Palette Line Color: stack's line color is taken in the current palette. |
361| "PMC" | Palette Marker Color: stack's marker color is taken in the current palette. |
362
363
364
365\anchor HP02
366### Setting the Style
367
368
369Histograms use the current style (`gStyle`). When one changes the current
370style and would like to propagate the changes to the histogram,
371`TH1::UseCurrentStyle` should be called. Call `UseCurrentStyle` on
372each histogram is needed.
373
374To force all the histogram to use the current style use:
375
376 gROOT->ForceStyle();
377
378All the histograms read after this call will use the current style.
379
380
381\anchor HP03
382### Setting line, fill, marker, and text attributes
383
384
385The histogram classes inherit from the attribute classes:
386`TAttLine`, `TAttFill` and `TAttMarker`.
387See the description of these classes for the list of options.
388
389
390\anchor HP04
391### Setting Tick marks on the histogram axis
392
393
394The `TPad::SetTicks` method specifies the type of tick marks on the axis.
395If ` tx = gPad->GetTickx()` and `ty = gPad->GetTicky()` then:
396
397 tx = 1; tick marks on top side are drawn (inside)
398 tx = 2; tick marks and labels on top side are drawn
399 ty = 1; tick marks on right side are drawn (inside)
400 ty = 2; tick marks and labels on right side are drawn
401
402By default only the left Y axis and X bottom axis are drawn
403(`tx = ty = 0`)
404
405`TPad::SetTicks(tx,ty)` allows to set these options.
406See also The `TAxis` functions to set specific axis attributes.
407
408In case multiple color filled histograms are drawn on the same pad, the fill
409area may hide the axis tick marks. One can force a redraw of the axis over all
410the histograms by calling:
411
412 gPad->RedrawAxis();
413
414
415\anchor HP05
416### Giving titles to the X, Y and Z axis
417
418
419 h->GetXaxis()->SetTitle("X axis title");
420 h->GetYaxis()->SetTitle("Y axis title");
421
422The histogram title and the axis titles can be any `TLatex` string.
423The titles are part of the persistent histogram.
424
425
426\anchor HP060
427### The option "SAME"
428
429
430By default, when an histogram is drawn, the current pad is cleared before
431drawing. In order to keep the previous drawing and draw on top of it the
432option `SAME` should be use. The histogram drawn with the option
433`SAME` uses the coordinates system available in the current pad.
434
435This option can be used alone or combined with any valid drawing option but
436some combinations must be use with care.
437
438\anchor HP060a
439#### Limitations
440
441- It does not work when combined with the `LEGO` and `SURF` options unless the
442 histogram plotted with the option `SAME` has exactly the same
443 ranges on the X, Y and Z axis as the currently drawn histogram. To superimpose
444 lego plots [histograms' stacks](\ref HP26) should be used.
445
446
447\anchor HP061
448### Colors automatically picked in palette
449
450\since **ROOT version 6.09/01**
451
452When several histograms are painted in the same canvas thanks to the option "SAME"
453or via a `THStack` it might be useful to have an easy and automatic way to choose
454their color. The simplest way is to pick colors in the current active color
455palette. Palette coloring for histogram is activated thanks to the options `PFC`
456(Palette Fill Color), `PLC` (Palette Line Color) and `PMC` (Palette Marker Color).
457When one of these options is given to `TH1::Draw` the histogram get its color
458from the current color palette defined by `gStyle->SetPalette(...)`. The color
459is determined according to the number of objects having palette coloring in
460the current pad.
461
462Begin_Macro(source)
463../../../tutorials/hist/hist005_TH1_palettecolor.C
464End_Macro
465
466Begin_Macro(source)
467../../../tutorials/hist/hist027_THStack_palette_color.C
468End_Macro
469
470Begin_Macro(source)
471../../../tutorials/hist/hist025_THStack_2d_palette_color.C
472End_Macro
473
474\anchor HP06
475### Superimposing two histograms with different scales in the same pad
476
477
478The following example creates two histograms, the second histogram is the bins
479integral of the first one. It shows a procedure to draw the two histograms in
480the same pad and it draws the scale of the second histogram using a new vertical
481axis on the right side. See also the tutorial `transpad.C` for a variant
482of this example.
483
484Begin_Macro(source)
485{
486 auto c1 = new TCanvas("c1","c1",600,400);
487 // create/fill draw h1
488 gStyle->SetOptStat(kFALSE);
489 auto h1 = new TH1F("h1","Superimposing two histograms with different scales",100,-3,3);
490 Int_t i;
491 for (i=0;i<10000;i++) h1->Fill(gRandom->Gaus(0,1));
492 h1->Draw();
493 c1->Update();
494
495 // create hint1 filled with the bins integral of h1
496 auto hint1 = new TH1F("hint1","h1 bins integral",100,-3,3);
497 float sum = 0.f;
498 for (i=1;i<=100;i++) {
499 sum += h1->GetBinContent(i);
500 hint1->SetBinContent(i,sum);
501 }
502
503 // scale hint1 to the pad coordinates
504 float rightmax = 1.1*hint1->GetMaximum();
505 float scale = gPad->GetUymax()/rightmax;
506 hint1->SetLineColor(kRed);
507 hint1->Scale(scale);
508 hint1->Draw("same");
509
510 // draw an axis on the right side
511 auto axis = new TGaxis(gPad->GetUxmax(),gPad->GetUymin(),
512 gPad->GetUxmax(), gPad->GetUymax(),0,rightmax,510,"+L");
513 axis->SetLineColor(kRed);
514 axis->SetTextColor(kRed);
515 axis->Draw();
516}
517End_Macro
518
519
520\anchor HP07
521### Statistics Display
522
523
524The type of information shown in the histogram statistics box can be selected
525with:
526
527 gStyle->SetOptStat(mode);
528
529The `mode` has up to nine digits that can be set to on (1 or 2), off (0).
530
531 mode = ksiourmen (default = 000001111)
532 k = 1; kurtosis printed
533 k = 2; kurtosis and kurtosis error printed
534 s = 1; skewness printed
535 s = 2; skewness and skewness error printed
536 i = 1; integral of bins printed
537 i = 2; integral of bins with option "width" printed
538 o = 1; number of overflows printed
539 u = 1; number of underflows printed
540 r = 1; standard deviation printed
541 r = 2; standard deviation and standard deviation error printed
542 m = 1; mean value printed
543 m = 2; mean and mean error values printed
544 e = 1; number of entries printed
545 n = 1; name of histogram is printed
546
547For example:
548
549 gStyle->SetOptStat(11);
550
551displays only the name of histogram and the number of entries, whereas:
552
553 gStyle->SetOptStat(1101);
554
555displays the name of histogram, mean value and standard deviation.
556
557<b>WARNING 1:</b> never do:
558
559 gStyle->SetOptStat(0001111);
560
561but instead do:
562
563 gStyle->SetOptStat(1111);
564
565because `0001111` will be taken as an octal number!
566
567<b>WARNING 2:</b> for backward compatibility with older versions
568
569 gStyle->SetOptStat(1);
570
571is taken as:
572
573 gStyle->SetOptStat(1111)
574
575To print only the name of the histogram do:
576
577 gStyle->SetOptStat(1000000001);
578
579<b>NOTE</b> that in case of 2D histograms, when selecting only underflow
580(10000) or overflow (100000), the statistics box will show all combinations
581of underflow/overflows and not just one single number.
582
583The parameter mode can be any combination of the letters `kKsSiIourRmMen`
584
585 k : kurtosis printed
586 K : kurtosis and kurtosis error printed
587 s : skewness printed
588 S : skewness and skewness error printed
589 i : integral of bins printed
590 I : integral of bins with option "width" printed
591 o : number of overflows printed
592 u : number of underflows printed
593 r : standard deviation printed
594 R : standard deviation and standard deviation error printed
595 m : mean value printed
596 M : mean value mean error values printed
597 e : number of entries printed
598 n : name of histogram is printed
599
600For example, to print only name of histogram and number of entries do:
601
602 gStyle->SetOptStat("ne");
603
604To print only the name of the histogram do:
605
606 gStyle->SetOptStat("n");
607
608The default value is:
609
610 gStyle->SetOptStat("nemr");
611
612When a histogram is painted, a `TPaveStats` object is created and added
613to the list of functions of the histogram. If a `TPaveStats` object
614already exists in the histogram list of functions, the existing object is just
615updated with the current histogram parameters.
616
617Once a histogram is painted, the statistics box can be accessed using
618`h->FindObject("stats")`. In the command line it is enough to do:
619
620 Root > h->Draw()
621 Root > TPaveStats *st = (TPaveStats*)h->FindObject("stats")
622
623because after `h->Draw()` the histogram is automatically painted. But
624in a script file the painting should be forced using `gPad->Update()`
625in order to make sure the statistics box is created:
626
627 h->Draw();
628 gPad->Update();
629 TPaveStats *st = (TPaveStats*)h->FindObject("stats");
630
631Without `gPad->Update()` the line `h->FindObject("stats")` returns a null pointer.
632
633When a histogram is drawn with the option `SAME`, the statistics box
634is not drawn. To force the statistics box drawing with the option
635`SAME`, the option `SAMES` must be used.
636If the new statistics box hides the previous statistics box, one can change
637its position with these lines (`h` being the pointer to the histogram):
638
639 Root > TPaveStats *st = (TPaveStats*)h->FindObject("stats")
640 Root > st->SetX1NDC(newx1); //new x start position
641 Root > st->SetX2NDC(newx2); //new x end position
642
643To change the type of information for an histogram with an existing
644`TPaveStats` one should do:
645
646 st->SetOptStat(mode);
647
648Where `mode` has the same meaning than when calling `gStyle->SetOptStat(mode)`
649(see above).
650
651One can delete the statistics box for a histogram `TH1* h` with:
652
653 h->SetStats(0)
654
655and activate it again with:
656
657 h->SetStats(1).
658
659Labels used in the statistics box ("Mean", "Std Dev", ...) can be changed from
660`$ROOTSYS/etc/system.rootrc` or `.rootrc` (look for the string `Hist.Stats.`).
661
662
663\anchor HP08
664### Fit Statistics
665
666
667The type of information about fit parameters printed in the histogram statistics
668box can be selected via the parameter mode. The parameter mode can be
669`= pcev` (default `= 0111`)
670
671 p = 1; print Probability
672 c = 1; print Chisquare/Number of degrees of freedom
673 e = 1; print errors (if e=1, v must be 1)
674 v = 1; print name/values of parameters
675
676Example:
677
678 gStyle->SetOptFit(1011);
679
680print fit probability, parameter names/values and errors.
681
6821. When `v = 1` is specified, only the non-fixed parameters are shown.
6832. When `v = 2` all parameters are shown.
684
685Note: `gStyle->SetOptFit(1)` means "default value", so it is equivalent
686to `gStyle->SetOptFit(111)`
687
688
689\anchor HP09
690### The error bars options
691
692
693| Option | Description |
694|----------|-------------------------------------------------------------------|
695| "E" | Default. Shows only the error bars, not a marker.|
696| "E1" | Small lines are drawn at the end of the error bars.|
697| "E2" | Error rectangles are drawn.|
698| "E3" | A filled area is drawn through the end points of the vertical error bars.|
699| "E4" | A smoothed filled area is drawn through the end points of the vertical error bars.|
700| "E0" | Draw error bars. Markers are drawn for bins with 0 contents. Combined with E1 or E2 it avoids error bars clipping|
701| "E5" | Like E3 but ignore the bins with 0 contents.|
702| "E6" | Like E4 but ignore the bins with 0 contents.|
703| "X0" | When used with one of the "E" option, it suppress the error bar along X as `gStyle->SetErrorX(0)` would do.|
704
705Begin_Macro(source)
706{
707 auto c1 = new TCanvas("c1","c1",600,400);
708 auto he = new TH1F("he","Distribution drawn with error bars (option E1) ",100,-3,3);
709 for (int i=0; i<10000; i++) he->Fill(gRandom->Gaus(0,1));
710 gStyle->SetEndErrorSize(3);
711 gStyle->SetErrorX(1.);
712 he->SetMarkerStyle(20);
713 he->Draw("E1");
714}
715End_Macro
716
717The options "E3" and "E4" draw an error band through the end points of the
718vertical error bars. With "E4" the error band is smoothed. Because of the
719smoothing algorithm used some artefacts may appear at the end of the band
720like in the following example. In such cases "E3" should be used instead
721of "E4".
722
723Begin_Macro(source)
724{
725 auto ce4 = new TCanvas("ce4","ce4",600,400);
726 ce4->Divide(2,1);
727 auto he4 = new TH1F("he4","Distribution drawn with option E4",100,-3,3);
728 Int_t i;
729 for (i=0;i<10000;i++) he4->Fill(gRandom->Gaus(0,1));
730 he4->SetFillColor(kRed);
731 he4->GetXaxis()->SetRange(40,48);
732 ce4->cd(1);
733 he4->Draw("E4");
734 ce4->cd(2);
735 auto he3 = (TH1F*)he4->DrawClone("E3");
736 he3->SetTitle("Distribution drawn option E3");
737}
738End_Macro
739
7402D histograms can be drawn with error bars as shown is the following example:
741
742Begin_Macro(source)
743{
744 auto c2e = new TCanvas("c2e","c2e",600,400);
745 auto h2e = new TH2F("h2e","TH2 drawn with option E",40,-4,4,40,-20,20);
746 float px, py;
747 for (Int_t i = 0; i < 25000; i++) {
748 gRandom->Rannor(px,py);
749 h2e->Fill(px,5*py);
750 }
751 h2e->Draw("E");
752}
753End_Macro
754
755
756\anchor HP100
757### The bar chart option
758
759
760The option "B" allows to draw simple vertical bar charts.
761The bar width is controlled with `TH1::SetBarWidth()`,
762and the bar offset within the bin, with `TH1::SetBarOffset()`.
763These two settings are useful to draw several histograms on the
764same plot as shown in the following example:
765
766Begin_Macro(source)
767{
768 int i;
769 const Int_t nx = 8;
770 string os_X[nx] = {"8","32","128","512","2048","8192","32768","131072"};
771 float d_35_0[nx] = {0.75, -3.30, -0.92, 0.10, 0.08, -1.69, -1.29, -2.37};
772 float d_35_1[nx] = {1.01, -3.02, -0.65, 0.37, 0.34, -1.42, -1.02, -2.10};
773
774 auto cb = new TCanvas("cb","cb",600,400);
775 cb->SetGrid();
776
777 gStyle->SetHistMinimumZero();
778
779 auto h1b = new TH1F("h1b","Option B example",nx,0,nx);
780 h1b->SetFillColor(4);
781 h1b->SetBarWidth(0.4);
782 h1b->SetBarOffset(0.1);
783 h1b->SetStats(0);
784 h1b->SetMinimum(-5);
785 h1b->SetMaximum(5);
786
787 for (i=1; i<=nx; i++) {
788 h1b->SetBinContent(i, d_35_0[i-1]);
789 h1b->GetXaxis()->SetBinLabel(i,os_X[i-1].c_str());
790 }
791
792 h1b->Draw("b");
793
794 auto h2b = new TH1F("h2b","h2b",nx,0,nx);
795 h2b->SetFillColor(38);
796 h2b->SetBarWidth(0.4);
797 h2b->SetBarOffset(0.5);
798 h2b->SetStats(0);
799 for (i=1;i<=nx;i++) h2b->SetBinContent(i, d_35_1[i-1]);
800
801 h2b->Draw("b same");
802}
803End_Macro
804
805
806\anchor HP10
807### The "BAR" and "HBAR" options
808
809
810When the option `bar` or `hbar` is specified, a bar chart is drawn. A vertical
811bar-chart is drawn with the options `bar`, `bar0`, `bar1`, `bar2`, `bar3`, `bar4`.
812An horizontal bar-chart is drawn with the options `hbar`, `hbar0`, `hbar1`,
813`hbar2`, `hbar3`, `hbar4` (hist006_TH1_bar_charts.C).
814
815- The bar is filled with the histogram fill color.
816- The left side of the bar is drawn with a light fill color.
817- The right side of the bar is drawn with a dark fill color.
818- The percentage of the bar drawn with either the light or dark color is:
819 - 0% for option "(h)bar" or "(h)bar0"
820 - 10% for option "(h)bar1"
821 - 20% for option "(h)bar2"
822 - 30% for option "(h)bar3"
823 - 40% for option "(h)bar4"
824
825When an histogram has errors the option ["HIST"](\ref OPTHIST) together with the `(h)bar` option.
826
827Begin_Macro(source)
828../../../tutorials/hist/hist006_TH1_bar_charts.C
829End_Macro
830
831To control the bar width (default is the bin width) `TH1::SetBarWidth()`
832should be used.
833
834To control the bar offset (default is 0) `TH1::SetBarOffset()` should
835be used.
836
837These two parameters are useful when several histograms are plotted using
838the option `SAME`. They allow to plot the histograms next to each other.
839
840
841\anchor HP11
842### The SCATter plot option (legacy draw option)
843
844\attention
845Use of option `SCAT` has been deprecated. It was the default drawing option for 2D and
8463D histograms. The new default option is `COL` (heat-map).
847
848
849For each cell (i,j) a number of points proportional to the cell content is
850drawn. A maximum of `kNMAX` points per cell is drawn. If the maximum is above
851`kNMAX` contents are normalized to `kNMAX` (`kNMAX=2000`).
852If option is of the form `scat=ff`, (eg `scat=1.8`,
853`scat=1e-3`), then `ff` is used as a scale factor to compute the
854number of dots. `scat=1` is the default.
855
856By default the scatter plot is painted with a "dot marker" which not scalable
857(see the `TAttMarker` documentation). To change the marker size, a scalable marker
858type should be used. For instance a circle (marker style 20).
859
860Begin_Macro(source)
861{
862 auto c1 = new TCanvas("c1","c1",600,400);
863 auto hscat = new TH2F("hscat","Option SCATter example (default for 2D histograms) ",40,-4,4,40,-20,20);
864 float px, py;
865 for (Int_t i = 0; i < 25000; i++) {
866 gRandom->Rannor(px,py);
867 hscat->Fill(px,5*py);
868 hscat->Fill(3+0.5*px,2*py-10.);
869 }
870 hscat->Draw("scat=0.5"); // This a legacy draw option. Please consider using TScatter
871}
872End_Macro
873
874
875\anchor HP12
876### The ARRow option
877
878
879Shows gradient between adjacent cells. For each cell (i,j) an arrow is drawn
880The orientation of the arrow follows the cell gradient.
881
882Begin_Macro(source)
883{
884 auto c1 = new TCanvas("c1","c1",600,400);
885 auto harr = new TH2F("harr","Option ARRow example",20,-4,4,20,-20,20);
886 harr->SetLineColor(kRed);
887 float px, py;
888 for (Int_t i = 0; i < 25000; i++) {
889 gRandom->Rannor(px,py);
890 harr->Fill(px,5*py);
891 harr->Fill(3+0.5*px,2*py-10.,0.1);
892 }
893 harr->Draw("ARR");
894}
895End_Macro
896
897\since **ROOT version 6.17/01**
898
899The option `ARR` can be combined with the option `COL` or `COLZ`.
900
901Begin_Macro(source)
902{
903 auto c1 = new TCanvas("c1","c1",600,400);
904 auto harr = new TH2F("harr","Option ARR + COLZ example",20,-4,4,20,-20,20);
905 harr->SetStats(0);
906 float px, py;
907 for (Int_t i = 0; i < 25000; i++) {
908 gRandom->Rannor(px,py);
909 harr->Fill(px,5*py);
910 harr->Fill(3+0.5*px,2*py-10.,0.1);
911 }
912 harr->Draw("ARR COLZ");
913}
914End_Macro
915
916
917\anchor HP13
918### The BOX option
919
920
921For each cell (i,j) a box is drawn. The size (surface) of the box is
922proportional to the absolute value of the cell content.
923The cells with a negative content are drawn with a `X` on top of the box.
924
925Begin_Macro(source)
926{
927 auto c1 = new TCanvas("c1","c1",600,400);
928 auto hbox = new TH2F("hbox","Option BOX example",3,0,3,3,0,3);
929 hbox->SetFillColor(42);
930 hbox->Fill(0.5, 0.5, 1.);
931 hbox->Fill(0.5, 1.5, 4.);
932 hbox->Fill(0.5, 2.5, 3.);
933 hbox->Fill(1.5, 0.5, 2.);
934 hbox->Fill(1.5, 1.5, 12.);
935 hbox->Fill(1.5, 2.5, -6.);
936 hbox->Fill(2.5, 0.5, -4.);
937 hbox->Fill(2.5, 1.5, 6.);
938 hbox->Fill(2.5, 2.5, 0.5);
939 hbox->Draw("BOX");
940}
941End_Macro
942
943With option `BOX1` a button is drawn for each cell with surface
944proportional to content's absolute value. A sunken button is drawn for
945negative values a raised one for positive.
946
947Begin_Macro(source)
948{
949 auto c1 = new TCanvas("c1","c1",600,400);
950 auto hbox1 = new TH2F("hbox1","Option BOX1 example",3,0,3,3,0,3);
951 hbox1->SetFillColor(42);
952 hbox1->Fill(0.5, 0.5, 1.);
953 hbox1->Fill(0.5, 1.5, 4.);
954 hbox1->Fill(0.5, 2.5, 3.);
955 hbox1->Fill(1.5, 0.5, 2.);
956 hbox1->Fill(1.5, 1.5, 12.);
957 hbox1->Fill(1.5, 2.5, -6.);
958 hbox1->Fill(2.5, 0.5, -4.);
959 hbox1->Fill(2.5, 1.5, 6.);
960 hbox1->Fill(2.5, 2.5, 0.5);
961 hbox1->Draw("BOX1");
962}
963End_Macro
964
965When the option `SAME` (or "SAMES") is used with the option `BOX`,
966the boxes' sizes are computed taking the previous plots into account. The range
967along the Z axis is imposed by the first plot (the one without option
968`SAME`); therefore the order in which the plots are done is relevant.
969
970Begin_Macro(source)
971{
972 auto c1 = new TCanvas("c1","c1",600,400);
973 auto hb1 = new TH2F("hb1","Example of BOX plots with option SAME ",40,-3,3,40,-3,3);
974 auto hb2 = new TH2F("hb2","hb2",40,-3,3,40,-3,3);
975 auto hb3 = new TH2F("hb3","hb3",40,-3,3,40,-3,3);
976 auto hb4 = new TH2F("hb4","hb4",40,-3,3,40,-3,3);
977 for (Int_t i=0;i<1000;i++) {
978 double x,y;
979 gRandom->Rannor(x,y);
980 if (x>0 && y>0) hb1->Fill(x,y,4);
981 if (x<0 && y<0) hb2->Fill(x,y,3);
982 if (x>0 && y<0) hb3->Fill(x,y,2);
983 if (x<0 && y>0) hb4->Fill(x,y,1);
984 }
985 hb1->SetFillColor(1);
986 hb2->SetFillColor(2);
987 hb3->SetFillColor(3);
988 hb4->SetFillColor(4);
989 hb1->Draw("box");
990 hb2->Draw("box same");
991 hb3->Draw("box same");
992 hb4->Draw("box same");
993}
994End_Macro
995
996\since **ROOT version 6.17/01:**
997
998Sometimes the change of the range of the Z axis is unwanted, in which case, one
999can use `SAME0` (or `SAMES0`) option to opt out of this change.
1000
1001Begin_Macro(source)
1002{
1003 auto h2 = new TH2F("h2"," ",10,0,10,10,20,30);
1004 auto hf = (TH2F*)h2->Clone("hf");
1005 h2->SetBit(TH1::kNoStats);
1006 hf->SetBit(TH1::kNoStats);
1007 h2->Fill(5,22);
1008 h2->Fill(5,23);
1009 h2->Fill(6,22);
1010 h2->Fill(6,23);
1011 hf->Fill(6,23);
1012 hf->Fill(6,23);
1013 hf->Fill(6,23);
1014 hf->Fill(6,23);
1015 hf->Fill(5,23);
1016
1017 auto hf_copy1 = hf->Clone("hf_copy1");
1018 TLatex lt;
1019
1020 auto cx = new TCanvas(); cx->Divide(2,1);
1021
1022 cx->cd(1);
1023 h2->Draw("box");
1024 hf->Draw("text colz same");
1025 lt.DrawLatexNDC(0.3,0.5,"SAME");
1026
1027 cx->cd(2);
1028 h2->Draw("box");
1029 hf_copy1->Draw("text colz same0");
1030 lt.DrawLatexNDC(0.3,0.5,"SAME0");
1031}
1032End_Macro
1033
1034
1035\anchor HP14
1036### The COLor option (default for 2D histograms)
1037
1038The magnitude of individual cell (i,j) is represented as a color picked in the current color palette.
1039This data visualization technique is often called a heat map (or heat-map).
1040
1041The color table used is defined in the current style.
1042
1043If the histogram's minimum and maximum are the same (flat histogram), the
1044mapping on colors is not possible, therefore nothing is painted. To paint a
1045flat histogram it is enough to set the histogram minimum
1046(`TH1::SetMinimum()`) different from the bins' content.
1047
1048The default number of color levels used to paint the cells is 20.
1049It can be changed with `TH1::SetContour()` or
1050`TStyle::SetNumberContours()`. The higher this number is, the smoother
1051is the color change between cells.
1052
1053The color palette in TStyle can be modified via `gStyle->SetPalette()`.
1054
1055All the non-empty bins are painted. Empty bins (bins with content and error equal to 0) are
1056not painted unless some bins have a negative content because in that case the null bins
1057might be not empty.
1058
1059`TProfile2D` histograms are handled differently because, for this type of 2D
1060histograms, it is possible to know if an empty bin has been filled or not. So even
1061if all the bins' contents are positive some empty bins might be painted. And vice versa,
1062if some bins have a negative content some empty bins might be not painted.
1063
1064Combined with the option `COL`, the option `Z` allows to
1065display the color palette defined by `gStyle->SetPalette()`.
1066
1067In the following example, the histogram has only positive bins; the empty
1068bins (containing 0) are not drawn.
1069
1070Begin_Macro(source)
1071{
1072 auto c1 = new TCanvas("c1","c1",600,400);
1073 auto hcol1 = new TH2F("hcol1","Option COLor example ",40,-4,4,40,-20,20);
1074 float px, py;
1075 for (Int_t i = 0; i < 25000; i++) {
1076 gRandom->Rannor(px,py);
1077 hcol1->Fill(px,5*py);
1078 }
1079 hcol1->Draw("COLZ");
1080}
1081End_Macro
1082
1083In the first plot of following example, the histogram has some negative bins;
1084the empty bins (containing 0) are drawn. In some cases one wants to not draw
1085empty bins (containing 0) of histograms having a negative minimum. The option
1086`1`, used to produce the second plot in the following picture, allows to do that.
1087
1088Begin_Macro(source)
1089{
1090 auto c1 = new TCanvas("c1","c1",600,600);
1091 c1->Divide(1,2);
1092 auto hcol23 = new TH2F("hcol23","Option COLZ example ",40,-4,4,40,-20,20);
1093 auto hcol24 = new TH2F("hcol24","Option COLZ1 example ",40,-4,4,40,-20,20);
1094 float px, py;
1095 for (Int_t i = 0; i < 25000; i++) {
1096 gRandom->Rannor(px,py);
1097 hcol23->Fill(px,5*py);
1098 hcol24->Fill(px,5*py);
1099 }
1100 hcol23->Fill(0.,0.,-200.);
1101 hcol24->Fill(0.,0.,-200.);
1102 c1->cd(1); hcol23->Draw("COLZ");
1103 c1->cd(2); hcol24->Draw("COLZ1");
1104}
1105End_Macro
1106
1107When the maximum of the histogram is set to a smaller value than the real maximum,
1108 the bins having a content between the new maximum and the real maximum are
1109painted with the color corresponding to the new maximum.
1110
1111When the minimum of the histogram is set to a greater value than the real minimum,
1112 the bins having a value between the real minimum and the new minimum are not drawn
1113 unless the option `0` is set.
1114In other words, option `COLZ0` forces the painting of bins with content < set minimum with
1115 a color corresponding to the set minimum. In contrast, option `COLZ` would not draw values
1116 smaller than the specified minimum. Note that both `COLZ` and `COLZ0` still do not draw
1117 empty bins, ie bins with `content == error == 0`, if the set min is not negative.
1118(Note that option `COLZ0` for TH2Poly has a different behavior than for TH2.)
1119
1120The following example illustrates the option `0` combined with the option `COL`.
1121
1122Begin_Macro(source)
1123{
1124 auto c1 = new TCanvas("c1","c1",600,600);
1125 c1->Divide(1,2);
1126 auto hcol21 = new TH2F("hcol21","Option COLZ",40,-4,4,40,-20,20);
1127 auto hcol22 = new TH2F("hcol22","Option COLZ0",40,-4,4,40,-20,20);
1128 float px, py;
1129 for (Int_t i = 0; i < 25000; i++) {
1130 gRandom->Rannor(px,py);
1131 hcol21->Fill(px,5*py);
1132 hcol22->Fill(px,5*py);
1133 }
1134 hcol21->SetBit(TH1::kNoStats);
1135 hcol22->SetBit(TH1::kNoStats);
1136 c1->cd(1); hcol21->Draw("COLZ");
1137 c1->cd(2); hcol22->Draw("COLZ0");
1138 hcol21->SetMaximum(100);
1139 hcol21->SetMinimum(40);
1140 hcol22->SetMaximum(100);
1141 hcol22->SetMinimum(40);
1142}
1143End_Macro
1144
1145Note that the behavior of `COLZ` is not symmetric: it does not draw values below the specified minimum,
1146but does draw values above the specified maximum by clipping them to the maximum color. In contrast, `COLZ0`
1147clips color on both lower and upper sides. Both `COLZ0` and `COLZ` exclude drawing empty bins (`content == error == 0`),
1148if the set minimum is not negative.
1149
1150\since **ROOT version 6.09/01:**
1151
1152When the option SAME (or "SAMES") is used with the option COL, the boxes' color
1153are computed taking the previous plots into account. The range along the Z axis
1154is imposed by the first plot (the one without option SAME); therefore the order
1155in which the plots are done is relevant. Same as [in the `BOX` option](\ref HP13), one can use
1156`SAME0` (or `SAMES0`) to opt out of this imposition.
1157
1158Begin_Macro(source)
1159{
1160 auto c = new TCanvas("c","Example of col plots with option SAME",200,10,700,500);
1161 auto h1 = new TH2F("h1","h1",40,-3,3,40,-3,3);
1162 auto h2 = new TH2F("h2","h2",40,-3,3,40,-3,3);
1163 auto h3 = new TH2F("h3","h3",40,-3,3,40,-3,3);
1164 auto h4 = new TH2F("h4","h4",40,-3,3,40,-3,3);
1165 h1->SetBit(TH1::kNoStats);
1166 for (Int_t i=0;i<5000;i++) {
1167 double x,y;
1168 gRandom->Rannor(x,y);
1169 if(x>0 && y>0) h1->Fill(x,y,4);
1170 if(x<0 && y<0) h2->Fill(x,y,3);
1171 if(x>0 && y<0) h3->Fill(x,y,2);
1172 if(x<0 && y>0) h4->Fill(x,y,1);
1173 }
1174 h1->Draw("colz");
1175 h2->Draw("col same");
1176 h3->Draw("col same");
1177 h4->Draw("col same");
1178}
1179End_Macro
1180
1181The option `COL` can be combined with the option `POL`:
1182
1183Begin_Macro(source)
1184{
1185 auto c1 = new TCanvas("c1","c1",600,400);
1186 auto hcol1 = new TH2F("hcol1","Option COLor combined with POL",40,-4,4,40,-4,4);
1187 float px, py;
1188 for (Int_t i = 0; i < 25000; i++) {
1189 gRandom->Rannor(px,py);
1190 hcol1->Fill(px,py);
1191 }
1192 hcol1->Draw("COLZPOL");
1193}
1194End_Macro
1195
1196\since **ROOT version 6.07/03:**
1197
1198A second rendering technique is also available with the COL2 and COLZ2 options.
1199
1200These options provide potential performance improvements compared to the standard
1201COL option. The performance comparison of the COL2 to the COL option depends on
1202the histogram and the size of the rendering region in the current pad. In general,
1203a small (approx. less than 100 bins per axis), sparsely populated TH2 will render
1204faster with the COL option.
1205
1206However, for larger histograms (approx. more than 100 bins per axis)
1207that are not sparse, the COL2 option will provide up to 20 times performance improvements.
1208For example, a 1000x1000 bin TH2 that is not sparse will render an order of magnitude
1209faster with the COL2 option.
1210
1211The COL2 option will also scale its performance based on the size of the
1212pixmap the histogram image is being rendered into. It also is much better optimized for
1213sessions where the user is forwarding X11 windows through an `ssh` connection.
1214
1215For the most part, the COL2 and COLZ2 options are a drop in replacement to the COL
1216and COLZ options. There is one major difference and that concerns the treatment of
1217bins with zero content. The COL2 and COLZ2 options color these bins the color of zero.
1218
1219COL2 option renders the histogram as a bitmap. Therefore it cannot be saved in vector
1220graphics file format like PostScript or PDF (an empty image will be generated). It can
1221be saved only in bitmap files like PNG format for instance.
1222
1223
1224\anchor HP140
1225### The CANDLE and VIOLIN options
1226
1227The mechanism behind Candle plots and Violin plots is very similar. Because of this they are
1228implemented in the same class TCandle. The keywords CANDLE or VIOLIN will initiate the drawing of
1229the corresponding plots. Followed by the keyword the user can select a plot direction (X or V for
1230vertical projections, or Y or H for horizontal projections) and/or predefined definitions
1231(1-6 for candles, 1-2 for violins). The order doesn't matter. Default is X and 1.
1232
1233Instead of using the predefined representations, the candle and violin parameters can be
1234changed individually. In that case the option have the following form:
1235
1236 CANDLEX(<option-string>)
1237 CANDLEY(<option-string>)
1238 VIOLINX(<option-string>)
1239 VIOLINY(<option-string>).
1240
1241All zeros at the beginning of `option-string` can be omitted.
1242
1243`option-string` consists eight values, defined as follow:
1244
1245 "CANDLEX(zhpawMmb)"
1246
1247Where:
1248
1249 - `b = 0`; no box drawn
1250 - `b = 1`; the box is drawn. As the candle-plot is also called a box-plot it
1251 makes sense in the very most cases to always draw the box
1252 - `b = 2`; draw a filled box with border
1253
1254 - `m = 0`; no median drawn
1255 - `m = 1`; median is drawn as a line
1256 - `m = 2`; median is drawn with errors (notches)
1257 - `m = 3`; median is drawn as a circle
1258
1259 - `M = 0`; no mean drawn
1260 - `M = 1`; mean is drawn as a dashed line
1261 - `M = 3`; mean is drawn as a circle
1262
1263 - `w = 0`; no whisker drawn
1264 - `w = 1`; whisker is drawn to end of distribution.
1265 - `w = 2`; whisker is drawn to max 1.5*iqr
1266
1267 - `a = 0`; no anchor drawn
1268 - `a = 1`; the anchors are drawn
1269
1270 - `p = 0`; no points drawn
1271 - `p = 1`; only outliers are drawn
1272 - `p = 2`; all datapoints are drawn
1273 - `p = 3`: all datapoints are drawn scattered
1274
1275 - `h = 0`; no histogram is drawn
1276 - `h = 1`; histogram at the left or bottom side is drawn
1277 - `h = 2`; histogram at the right or top side is drawn
1278 - `h = 3`; histogram at left and right or top and bottom (violin-style) is drawn
1279
1280 - `z = 0`; no zero indicator line is drawn
1281 - `z = 1`; zero indicator line is drawn.
1282
1283As one can see all individual options for both candle and violin plots can be accessed by this
1284mechanism. In deed the keywords CANDLE(<option-string>) and VIOLIN(<option-string>) have the same
1285meaning. So you can parametrise an option-string for a candle plot and use the keywords VIOLIN and
1286vice versa, if you wish.
1287
1288Using a logarithmic x- or y-axis is possible for candle and violin charts.
1289
1290\since **ROOT version 6.11/01**
1291
1292a logarithmic z-axis is possible, too but will only affect violin charts of course.
1293
1294\anchor HP140a
1295#### The CANDLE option
1296
1297<a href="http://en.wikipedia.org/wiki/Box_plot">A Candle plot</a> (also known as
1298a "box plot" or "whisker plot") was invented in 1977 by John Tukey. It is a convenient
1299way to describe graphically a data distribution (D) with only five numbers:
1300
1301 1. The minimum value of the distribution D (bottom or left whisker).
1302 2. The lower quartile (Q1): 25% of the data points in D are less than Q1 (bottom of the box).
1303 3. The median (M): 50% of the data points in D are less than M.
1304 4. The upper quartile (Q3): 75% of the data points in D are less than Q3 (top of the box).
1305 5. The maximum value of the distribution D (top or right whisker).
1306
1307In this implementation a TH2 is considered as a collection of TH1 along
1308X (option `CANDLE` or `CANDLEX`) or Y (option `CANDLEY`).
1309Each TH1 is represented as one candle.
1310
1311Begin_Macro(source)
1312../../../tutorials/hist/hist052_Graphics_candle_plot_whiskers.C
1313End_Macro
1314
1315The candle reduces the information coming from a whole distribution into few values.
1316Independently from the number of entries or the significance of the underlying distribution
1317a candle will always look like a candle. So candle plots should be used carefully in
1318particular with unknown distributions. The definition of a candle is based on
1319__unbinned data__. Here, candles are created from binned data. Because of this, the
1320deviation is connected to the bin width used. The calculation of the quantiles
1321normally done on unbinned data also. Because data are binned, this will
1322only work the best possible way within the resolution of one bin
1323
1324Because of all these facts one should take care that:
1325
1326 - there are enough points per candle
1327 - the bin width is small enough (more bins will increase the maximum
1328 available resolution of the quantiles although there will be some
1329 bins with no entries)
1330 - never make a candle-plot if the underlying distribution is double-distributed
1331 - only create candles of distributions that are more-or-less gaussian (the
1332 MPV should be not too far away from the mean).
1333
1334#### What a candle is made of
1335
1336\since **ROOT version 6.07/05**
1337
1338##### The box
1339The box displays the position of the inter-quantile-range of the underlying
1340distribution. The box contains 25% of the distribution below the median
1341and 25% of the distribution above the median. If the underlying distribution is large
1342enough and gaussian shaped the end-points of the box represent \f$ 0.6745\times\sigma \f$
1343(Where \f$ \sigma \f$ is the standard deviation of the gaussian). The width and
1344the position of the box can be modified by SetBarWidth() and SetBarOffset().
1345The +-25% quantiles are calculated by the GetQuantiles() methods.
1346
1347\since **ROOT version 6.11/01**
1348
1349Using the static function TCandle::SetBoxRange(double) the box definition will be
1350overwritten. E.g. using a box range of 0.68 will redefine the area of the lower box edge
1351to the upper box edge in order to cover 68% of the distribution illustrated by that candle.
1352The static function will affect all candle-charts in the running program.
1353Default is 0.5.
1354
1355Using the static function TCandle::SetScaledCandle(bool) the width of the box (and the
1356whole candle) can be influenced. Deactivated, the width is constant (to be set by
1357SetBarWidth() ). Activated, the width of the boxes will be scaled to each other based on the
1358amount of data in the corresponding candle, the maximum width can be influenced by
1359SetBarWidth(). The static function will affect all candle-charts in the running program.
1360Default is false. Scaling between multiple candle-charts (using "same" or THStack) is not
1361supported, yet
1362
1363##### The Median
1364For a sorted list of numbers, the median is the value in the middle of the list.
1365E.g. if a sorted list is made of five numbers "1,2,3,6,7" 3 will be the median
1366because it is in the middle of the list. If the number of entries is even the
1367average of the two values in the middle will be used. As histograms are binned
1368data, the situation is a bit more complex. The following example shows this:
1369
1370~~~ {.cpp}
1371void quantiles() {
1372 auto h = new TH1I("h","h",10,0,10);
1373 //h->Fill(3);
1374 //h->Fill(3);
1375 h->Fill(4);
1376 h->Draw();
1377 double p = 0.;
1378 double q = 0.;
1379 h->GetQuantiles(1,&q,&p);
1380
1381 cout << "Median is: " << q << std::endl;
1382}
1383~~~
1384
1385Here the bin-width is 1.0. If the two Fill(3) are commented out, as there are currently,
1386the example will return a calculated median of 4.5, because that's the bin center
1387of the bin in which the value 4.0 has been dropped. If the two Fill(3) are not
1388commented out, it will return 3.75, because the algorithm tries to evenly distribute
1389the individual values of a bin with bin content > 0. It means the sorted list
1390would be "3.25, 3.75, 4.5".
1391
1392The consequence is a median of 3.75. This shows how important it is to use a
1393small enough bin-width when using candle-plots on binned data.
1394If the distribution is large enough and gaussian shaped the median will be exactly
1395equal to the mean.
1396The median can be shown as a line or as a circle or not shown at all.
1397
1398In order to show the significance of the median notched candle plots apply a "notch" or
1399narrowing of the box around the median. The significance is defined by
1400\f$ 1.57\times\frac{iqr}{N} \f$ and will be represented as the size of the notch
1401(where iqr is the size of the box and N is the number of entries of the whole
1402distribution). Candle plots like these are usually called "notched candle plots".
1403
1404In case the significance of the median is greater that the size of the box, the
1405box will have an unnatural shape. Usually it means the chart has not enough data,
1406or that representing this uncertainty is not useful
1407
1408##### The Mean
1409The mean can be drawn as a dashed line or as a circle or not drawn at all.
1410The mean is the arithmetic average of the values in the distribution.
1411It is calculated using GetMean(). Because histograms are
1412binned data, the mean value can differ from a calculation on the raw-data.
1413If the distribution is large enough and gaussian shaped the mean will be
1414exactly the median.
1415
1416##### The Whiskers
1417The whiskers represent the part of the distribution not covered by the box.
1418The upper 25% and the lower 25% of the distribution are located within the whiskers.
1419Two representations are available.
1420
1421 - A simple one (using w=1) defining the lower whisker from the lowest data value
1422 to the bottom of the box, and the upper whisker from the top of the box to the
1423 highest data value. In this representation the whisker-lines are dashed.
1424 - A more complex one having a further restriction. The whiskers are still connected
1425 to the box but their length cannot exceed \f$ 1.5\times iqr \f$. So it might
1426 be that the outermost part of the underlying distribution will not be covered
1427 by the whiskers. Usually these missing parts will be represented by the outliers
1428 (see points). Of course the upper and the lower whisker may differ in length.
1429 In this representation the whiskers are drawn as solid lines.
1430
1431\since **ROOT version 6.11/01**
1432
1433Using the static function TCandle::SetWhiskerRange(double) the whisker definition w=1
1434will be overwritten. E.g. using a whisker-range of 0.95 and w=1 will redefine the area of
1435the lower whisker to the upper whisker in order to cover 95% of the distribution inside
1436that candle. The static function will affect all candle-charts in the running program.
1437Default is 1.
1438
1439If the distribution is large enough and gaussian shaped, the maximum length of
1440the whisker will be located at \f$ \pm 2.698 \sigma \f$ (when using the
14411.5*iqr-definition (w=2), where \f$ \sigma \f$ is the standard deviation
1442(see picture above). In that case 99.3% of the total distribution will be covered
1443by the box and the whiskers, whereas 0.7% are represented by the outliers.
1444
1445##### The Anchors
1446The anchors have no special meaning in terms of statistical calculation. They mark
1447the end of the whiskers and they have the width of the box. Both representation
1448with and without anchors are common.
1449
1450##### The Points
1451Depending on the configuration the points can have different meanings:
1452 - If p=1 the points represent the outliers. If they are shown, it means
1453 some parts of the underlying distribution are not covered by the whiskers.
1454 This can only occur when the whiskers are set to option w=2. Here the whiskers
1455 can have a maximum length of \f$ 1.5 \times iqr \f$. So any points outside the
1456 whiskers will be drawn as outliers. The outliers will be represented by crosses.
1457 - If p=2 all points in the distribution will be painted as crosses. This is
1458 useful for small datasets only (up to 10 or 20 points per candle).
1459 The outliers are shown along the candle. Because the underlying distribution
1460 is binned, is frequently occurs that a bin contains more than one value.
1461 Because of this the points will be randomly scattered within their bin along
1462 the candle axis. If the bin content for a bin is exactly 1 (usually
1463 this happens for the outliers) if will be drawn in the middle of the bin along
1464 the candle axis. As the maximum number of points per candle is limited by kNMax/2
1465 on very large datasets scaling will be performed automatically. In that case one
1466 would loose all outliers because they have usually a bin content of 1 (and a
1467 bin content between 0 and 1 after the scaling). Because of this all bin contents
1468 between 0 and 1 - after the scaling - will be forced to be 1.
1469 - As the drawing of all values on large datasets can lead to big amounts of crosses,
1470 one can show all values as a scatter plot instead by choosing p=3. The points will be
1471 drawn as dots and will be scattered within the width of the candle. The color
1472 of the points will be the color of the candle-chart.
1473
1474##### Other Options
1475Is is possible to combine all options of candle and violin plots with each other. E.g. a box-plot
1476with a histogram.
1477
1478#### How to use the candle-plots drawing option
1479
1480There are six predefined candle-plot representations:
1481
1482 - "CANDLEX1": Standard candle (whiskers cover the whole distribution)
1483 - "CANDLEX2": Standard candle with better whisker definition + outliers.
1484 It is a good compromise
1485 - "CANDLEX3": Like candle2 but with a mean as a circle.
1486 It is easier to distinguish mean and median
1487 - "CANDLEX4": Like candle3 but showing the uncertainty of the median as well
1488 (notched candle plots).
1489 For bigger datasets per candle
1490 - "CANDLEX5": Like candle2 but showing all data points.
1491 For very small datasets
1492 - "CANDLEX6": Like candle2 but showing all datapoints scattered.
1493 For huge datasets
1494
1495
1496The following picture shows how the six predefined representations look.
1497
1498Begin_Macro
1499{
1500 auto c1 = new TCanvas("c1","c1",700,800);
1501 c1->Divide(2,3);
1502 gStyle->SetOptStat(kFALSE);
1503
1504 auto hcandle = new TH2F("hcandle"," ",10,-4,4,40,-20,20);
1505 float px, py;
1506 for (Int_t i = 0; i < 15000; i++) {
1507 gRandom->Rannor(px,py);
1508 hcandle->Fill(px,5*py);
1509 }
1510 hcandle->SetMarkerSize(0.5);
1511
1512 TH2F *h2;
1513 for (Int_t i=1; i<7; i++) {
1514 c1->cd(i);
1515 h2 = (TH2F*)hcandle->DrawClone(Form("CANDLE%d",i));
1516 h2->SetTitle(Form("CANDLE%d",i));
1517 }
1518}
1519End_Macro
1520
1521
1522#### Example 1
1523Box and improved whisker, no mean, no median, no anchor no outliers
1524
1525 h1->Draw("CANDLEX(2001)");
1526
1527#### Example 2
1528A Candle-definition like "CANDLEX2" (New standard candle with better whisker definition + outliers)
1529
1530 h1->Draw("CANDLEX(112111)");
1531
1532#### Example 3
1533The following example shows how several candle plots can be super-imposed using
1534the option SAME. Note that the bar-width and bar-offset are active on candle plots.
1535Also the color, the line width, the size of the points and so on can be changed by the
1536standard attribute setting methods such as SetLineColor() SetLineWidth().
1537
1538Begin_Macro(source)
1539../../../tutorials/hist/hist049_Graphics_candle_plot.C
1540End_Macro
1541
1542\anchor HP140b
1543#### The VIOLIN option
1544
1545<a href="http://en.wikipedia.org/wiki/Violin_plot">A violin plot</a> is a candle plot
1546that also encodes the pdf information at each point.
1547
1548
1549Quartiles and mean are also represented at each point, with a marker
1550and two lines.
1551
1552In this implementation a TH2 is considered as a collection of TH1 along
1553X (option `VIOLIN` or `VIOLINX`) or Y (option `VIOLINY`).
1554
1555#### What a violin is made of
1556
1557\since **ROOT version 6.09/02**
1558
1559##### The histogram
1560The histogram is typically drawn to both directions with respect to the middle-line of the
1561corresponding bin. This can be achieved by using h=3. It is possible to draw a histogram only to
1562one side (h=1, or h=2).
1563The maximum number of bins in the histogram is limited to 500, if the number of bins in the used
1564histogram is higher it will be rebinned automatically. The maximum height of the histogram can
1565be modified by using SetBarWidth() and the position can be changed with SetBarOffset().
1566A solid fill style is recommended.
1567
1568\since **ROOT version 6.11/01**
1569
1570Using the static function TCandle::SetScaledViolin(bool) the height of the histogram or the
1571violin can be influenced. Activated, the height of the bins of the individual violins will be
1572scaled with respect to each other, the maximum height can be influenced by SetBarWidth().
1573Deactivated, the height of the bin with the maximum content of each individual violin is
1574set to a constant value using SetBarWidth(). The static function will affect all violin-charts
1575in the running program. Default is true. Scaling between multiple violin-charts
1576(using "same" or THStack) is not supported, yet.
1577
1578##### The zero indicator line
1579Typical for violin charts is a line in the background over the whole histogram indicating
1580the bins with zero entries. The zero indicator line can be activated with z=1. The line color
1581will always be the same as the fill-color of the histogram.
1582
1583##### The Mean
1584The Mean is illustrated with the same mechanism as used for candle plots. Usually a circle is used.
1585
1586##### Whiskers
1587The whiskers are illustrated by the same mechanism as used for candle plots. There is only one
1588difference. When using the simple whisker definition (w=1) and the zero indicator line (z=1), then
1589the whiskers will be forced to be solid (usually hashed)
1590
1591##### Points
1592The points are illustrated by the same mechanism as used for candle plots. E.g. VIOLIN2 uses
1593better whisker definition (w=2) and outliers (p=1).
1594
1595##### Other options
1596It is possible to combine all options of candle or violin plots with each other. E.g. a violin plot
1597including a box-plot.
1598
1599#### How to use the violin-plots drawing option
1600
1601There are two predefined violin-plot representations:
1602 - "VIOLINX1": Standard violin (histogram, mean, whisker over full distribution,
1603 zero indicator line)
1604 - "VIOLINX2": Line VIOLINX1 both with better whisker definition + outliers.
1605
1606A solid fill style is recommended for this plot (as opposed to a hollow or
1607hashed style).
1608
1609Begin_Macro(source)
1610{
1611 auto c1 = new TCanvas("c1","c1",600,400);
1612 Int_t nx(6), ny(40);
1613 double xmin(0.0), xmax(+6.0), ymin(0.0), ymax(+4.0);
1614 auto hviolin = new TH2F("hviolin", "Option VIOLIN example", nx, xmin, xmax, ny, ymin, ymax);
1615 TF1 f1("f1", "gaus", +0,0 +4.0);
1616 double x,y;
1617 for (Int_t iBin=1; iBin<hviolin->GetNbinsX(); ++iBin) {
1618 double xc = hviolin->GetXaxis()->GetBinCenter(iBin);
1619 f1.SetParameters(1, 2.0+TMath::Sin(1.0+xc), 0.2+0.1*(xc-xmin)/xmax);
1620 for(Int_t i=0; i<10000; ++i){
1621 x = xc;
1622 y = f1.GetRandom();
1623 hviolin->Fill(x, y);
1624 }
1625 }
1626 hviolin->SetFillColor(kGray);
1627 hviolin->SetMarkerStyle(20);
1628 hviolin->SetMarkerSize(0.5);
1629 hviolin->Draw("VIOLIN");
1630 c1->Update();
1631}
1632End_Macro
1633
1634The next example illustrates a time development of a certain value:
1635
1636Begin_Macro(source)
1637../../../tutorials/hist/hist047_Graphics_candle_decay.C
1638End_Macro
1639
1640
1641\anchor HP15
1642### The TEXT and TEXTnn Option
1643
1644
1645For each bin the content is printed. The text attributes are:
1646
1647- text font = current TStyle font (`gStyle->SetTextFont()`).
1648- text size = 0.02*padheight*markersize (if `h` is the histogram drawn
1649 with the option `TEXT` the marker size can be changed with
1650 `h->SetMarkerSize(markersize)`).
1651- text color = marker color.
1652
1653By default the format `g` is used. This format can be redefined
1654by calling `gStyle->SetPaintTextFormat()`.
1655
1656It is also possible to use `TEXTnn` in order to draw the text with
1657the angle `nn` (`0 < nn <= 90`).
1658
1659For 2D histograms the text is plotted in the center of each non empty cells.
1660It is possible to plot empty cells by calling `gStyle->SetHistMinimumZero()`
1661or providing MIN0 draw option. For 1D histogram the text is plotted at a y
1662position equal to the bin content.
1663
1664For 2D histograms when the option "E" (errors) is combined with the option
1665text ("TEXTE"), the error for each bin is also printed.
1666
1667Begin_Macro(source)
1668{
1669 auto c01 = new TCanvas("c01","c01",700,400);
1670 c01->Divide(2,1);
1671 auto htext1 = new TH1F("htext1","Option TEXT on 1D histograms ",10,-4,4);
1672 auto htext2 = new TH2F("htext2","Option TEXT on 2D histograms ",10,-4,4,10,-20,20);
1673 float px, py;
1674 for (Int_t i = 0; i < 25000; i++) {
1675 gRandom->Rannor(px,py);
1676 htext1->Fill(px,0.1);
1677 htext2->Fill(px,5*py,0.1);
1678 }
1679 gStyle->SetPaintTextFormat("4.1f m");
1680 htext2->SetMarkerSize(1.8);
1681 c01->cd(1);
1682 htext2->Draw("TEXT45");
1683 c01->cd(2);
1684 htext1->Draw();
1685 htext1->Draw("HIST TEXT0 SAME");
1686}
1687End_Macro
1688
1689\since **ROOT version 6.07/07:**
1690
1691In case several histograms are drawn on top ot each other (using option `SAME`),
1692the text can be shifted using `SetBarOffset()`. It specifies an offset for the
1693text position in each cell, in percentage of the bin width.
1694
1695Begin_Macro(source)
1696{
1697 auto c03 = new TCanvas("c03","c03",700,400);
1698 gStyle->SetOptStat(0);
1699 auto htext3 = new TH2F("htext3","Several 2D histograms drawn with option TEXT",10,-4,4,10,-20,20);
1700 auto htext4 = new TH2F("htext4","htext4",10,-4,4,10,-20,20);
1701 auto htext5 = new TH2F("htext5","htext5",10,-4,4,10,-20,20);
1702 float px, py;
1703 for (Int_t i = 0; i < 25000; i++) {
1704 gRandom->Rannor(px,py);
1705 htext3->Fill(4*px,20*py,0.1);
1706 htext4->Fill(4*px,20*py,0.5);
1707 htext5->Fill(4*px,20*py,1.0);
1708 }
1709 htext4->SetMarkerSize(1.8);
1710 htext5->SetMarkerSize(1.8);
1711 htext5->SetMarkerColor(kRed);
1712 htext4->SetBarOffset(0.2);
1713 htext5->SetBarOffset(-0.2);
1714 htext3->Draw("COL");
1715 htext4->Draw("TEXT SAME");
1716 htext5->Draw("TEXT SAME");
1717}
1718End_Macro
1719
1720In the case of profile histograms it is possible to print the number
1721of entries instead of the bin content. It is enough to combine the
1722option "E" (for entries) with the option "TEXT".
1723
1724Begin_Macro(source)
1725{
1726 auto c02 = new TCanvas("c02","c02",700,400);
1727 c02->Divide(2,1);
1728 gStyle->SetPaintTextFormat("g");
1729
1730 auto profile = new TProfile("profile","profile",10,0,10);
1731 profile->SetMarkerSize(2.2);
1732 profile->Fill(0.5,1);
1733 profile->Fill(1.5,2);
1734 profile->Fill(2.5,3);
1735 profile->Fill(3.5,4);
1736 profile->Fill(4.5,5);
1737 profile->Fill(5.5,5);
1738 profile->Fill(6.5,4);
1739 profile->Fill(7.5,3);
1740 profile->Fill(8.5,2);
1741 profile->Fill(9.5,1);
1742 c02->cd(1); profile->Draw("HIST TEXT0");
1743 c02->cd(2); profile->Draw("HIST TEXT0E");
1744}
1745End_Macro
1746
1747\anchor HP16
1748### The CONTour options
1749
1750
1751The following contour options are supported:
1752
1753| Option | Description |
1754|----------|-----------------------------------------------------------------------------|
1755| "CONT" | Draw a contour plot (same as CONT0). |
1756| "CONT0" | Draw a contour plot using surface colors to distinguish contours. |
1757| "CONT1" | Draw a contour plot using the line colors to distinguish contours. |
1758| "CONT2" | Draw a contour plot using the line styles (1 to 5) to distinguish contours. |
1759| "CONT3" | Draw a contour plot using the same line style for all contours. |
1760| "CONT4" | Draw a contour plot using surface colors (`SURF` option at theta = 0). |
1761
1762
1763The following example shows a 2D histogram plotted with the option
1764`CONTZ`. The option `CONT` draws a contour plot using surface
1765colors to distinguish contours. Combined with the option `CONT` (or
1766`CONT0`), the option `Z` allows to display the color palette
1767defined by `gStyle->SetPalette()`.
1768
1769Begin_Macro(source)
1770{
1771 auto c1 = new TCanvas("c1","c1",600,400);
1772 auto hcontz = new TH2F("hcontz","Option CONTZ example ",40,-4,4,40,-20,20);
1773 float px, py;
1774 for (Int_t i = 0; i < 25000; i++) {
1775 gRandom->Rannor(px,py);
1776 hcontz->Fill(px-1,5*py);
1777 hcontz->Fill(2+0.5*px,2*py-10.,0.1);
1778 }
1779 hcontz->Draw("CONTZ");
1780}
1781End_Macro
1782
1783The following example shows a 2D histogram plotted with the option
1784`CONT1Z`. The option `CONT1` draws a contour plot using the
1785line colors to distinguish contours. Combined with the option `CONT1`,
1786the option `Z` allows to display the color palette defined by
1787`gStyle->SetPalette()`.
1788
1789Begin_Macro(source)
1790{
1791 auto c1 = new TCanvas("c1","c1",600,400);
1792 auto hcont1 = new TH2F("hcont1","Option CONT1Z example ",40,-4,4,40,-20,20);
1793 float px, py;
1794 for (Int_t i = 0; i < 25000; i++) {
1795 gRandom->Rannor(px,py);
1796 hcont1->Fill(px-1,5*py);
1797 hcont1->Fill(2+0.5*px,2*py-10.,0.1);
1798 }
1799 hcont1->Draw("CONT1Z");
1800}
1801End_Macro
1802
1803The following example shows a 2D histogram plotted with the option
1804`CONT2`. The option `CONT2` draws a contour plot using the
1805line styles (1 to 5) to distinguish contours.
1806
1807Begin_Macro(source)
1808{
1809 auto c1 = new TCanvas("c1","c1",600,400);
1810 auto hcont2 = new TH2F("hcont2","Option CONT2 example ",40,-4,4,40,-20,20);
1811 float px, py;
1812 for (Int_t i = 0; i < 25000; i++) {
1813 gRandom->Rannor(px,py);
1814 hcont2->Fill(px-1,5*py);
1815 hcont2->Fill(2+0.5*px,2*py-10.,0.1);
1816 }
1817 hcont2->Draw("CONT2");
1818}
1819End_Macro
1820
1821The following example shows a 2D histogram plotted with the option
1822`CONT3`. The option `CONT3` draws contour plot using the same line style for
1823all contours.
1824
1825Begin_Macro(source)
1826{
1827 auto c1 = new TCanvas("c1","c1",600,400);
1828 auto hcont3 = new TH2F("hcont3","Option CONT3 example ",40,-4,4,40,-20,20);
1829 float px, py;
1830 for (Int_t i = 0; i < 25000; i++) {
1831 gRandom->Rannor(px,py);
1832 hcont3->Fill(px-1,5*py);
1833 hcont3->Fill(2+0.5*px,2*py-10.,0.1);
1834 }
1835 hcont3->SetLineStyle(kDotted);
1836 hcont3->Draw("CONT3");
1837}
1838End_Macro
1839
1840The following example shows a 2D histogram plotted with the option
1841`CONT4`. The option `CONT4` draws a contour plot using surface
1842colors to distinguish contours (`SURF` option at theta = 0). Combined
1843with the option `CONT` (or `CONT0`), the option `Z`
1844allows to display the color palette defined by `gStyle->SetPalette()`.
1845
1846Begin_Macro(source)
1847{
1848 auto c1 = new TCanvas("c1","c1",600,400);
1849 auto hcont4 = new TH2F("hcont4","Option CONT4Z example ",40,-4,4,40,-20,20);
1850 float px, py;
1851 for (Int_t i = 0; i < 25000; i++) {
1852 gRandom->Rannor(px,py);
1853 hcont4->Fill(px-1,5*py);
1854 hcont4->Fill(2+0.5*px,2*py-10.,0.1);
1855 }
1856 hcont4->Draw("CONT4Z");
1857}
1858End_Macro
1859
1860The default number of contour levels is 20 equidistant levels and can be changed
1861with `TH1::SetContour()` or `TStyle::SetNumberContours()`.
1862
1863\anchor HP16a
1864#### The LIST option
1865
1866When option `LIST` is specified together with option
1867`CONT`, the points used to draw the contours are saved in
1868`TGraph` objects:
1869
1870 h->Draw("CONT LIST");
1871 gPad->Update();
1872
1873The contour are saved in `TGraph` objects once the pad is painted.
1874Therefore to use this functionality in a macro, `gPad->Update()`
1875should be performed after the histogram drawing. Once the list is
1876built, the contours are accessible in the following way:
1877
1878 TObjArray *contours = (TObjArray*)gROOT->GetListOfSpecials()->FindObject("contours");
1879 Int_t ncontours = contours->GetSize();
1880 TList *list = (TList*)contours->At(i);
1881
1882Where `i` is a contour number, and list contains a list of
1883`TGraph` objects.
1884For one given contour, more than one disjoint polyline may be generated.
1885The number of TGraphs per contour is given by:
1886
1887 list->GetSize();
1888
1889To access the first graph in the list one should do:
1890
1891 TGraph *gr1 = (TGraph*)list->First();
1892
1893
1894The following example (hist102_TH2_contour_list.C) shows how to use this functionality.
1895
1896Begin_Macro(source)
1897../../../tutorials/hist/hist102_TH2_contour_list.C
1898End_Macro
1899
1900\anchor HP16b
1901#### The AITOFF, MERCATOR, SINUSOIDAL and PARABOLIC options
1902
1903The following options select the `CONT4` option and are useful for
1904sky maps or exposure maps (earth.C).
1905
1906| Option | Description |
1907|--------------|---------------------------------------------------------------|
1908| "AITOFF" | Draw a contour via an AITOFF projection.|
1909| "MERCATOR" | Draw a contour via an Mercator projection.|
1910| "SINUSOIDAL" | Draw a contour via an Sinusoidal projection.|
1911| "PARABOLIC" | Draw a contour via an Parabolic projection.|
1912
1913Begin_Macro(source)
1914../../../tutorials/visualisation/graphics/earth.C
1915End_Macro
1916
1917
1918\anchor HP17
1919### The LEGO options
1920
1921
1922In a lego plot the cell contents are drawn as 3-d boxes. The height of each box
1923is proportional to the cell content. The lego aspect is control with the
1924following options:
1925
1926| Option | Description |
1927|----------|-------------------------------------------------------------------|
1928| "LEGO" | Draw a lego plot using the hidden lines removal technique.|
1929| "LEGO1" | Draw a lego plot using the hidden surface removal technique.|
1930| "LEGO2" | Draw a lego plot using colors to show the cell contents.|
1931| "LEGO3" | Draw a lego plot with hidden surface removal, like LEGO1 but the border lines of each lego-bar are not drawn.|
1932| "LEGO4" | Draw a lego plot with hidden surface removal, like LEGO1 but without the shadow effect on each lego-bar.|
1933| "0" | When used with any LEGO option, the empty bins are not drawn.|
1934
1935
1936See the limitations with [the option "SAME"](\ref HP060a).
1937
1938Line attributes can be used in lego plots to change the edges' style.
1939
1940The following example shows a 2D histogram plotted with the option
1941`LEGO`. The option `LEGO` draws a lego plot using the hidden
1942lines removal technique.
1943
1944Begin_Macro(source)
1945{
1946 auto c2 = new TCanvas("c2","c2",600,400);
1947 auto hlego = new TH2F("hlego","Option LEGO example ",40,-4,4,40,-20,20);
1948 float px, py;
1949 for (Int_t i = 0; i < 25000; i++) {
1950 gRandom->Rannor(px,py);
1951 hlego->Fill(px-1,5*py);
1952 hlego->Fill(2+0.5*px,2*py-10.,0.1);
1953 }
1954 hlego->Draw("LEGO");
1955}
1956End_Macro
1957
1958The following example shows a 2D histogram plotted with the option
1959`LEGO1`. The option `LEGO1` draws a lego plot using the
1960hidden surface removal technique. Combined with any `LEGOn` option, the
1961option `0` allows to not drawn the empty bins.
1962
1963Begin_Macro(source)
1964{
1965 auto c2 = new TCanvas("c2","c2",600,400);
1966 auto hlego1 = new TH2F("hlego1","Option LEGO1 example (with option 0) ",40,-4,4,40,-20,20);
1967 float px, py;
1968 for (Int_t i = 0; i < 25000; i++) {
1969 gRandom->Rannor(px,py);
1970 hlego1->Fill(px-1,5*py);
1971 hlego1->Fill(2+0.5*px,2*py-10.,0.1);
1972 }
1973 hlego1->SetFillColor(kYellow);
1974 hlego1->Draw("LEGO1 0");
1975}
1976End_Macro
1977
1978The following example shows a 2D histogram plotted with the option
1979`LEGO3`. Like the option `LEGO1`, the option `LEGO3`
1980draws a lego plot using the hidden surface removal technique but doesn't draw
1981the border lines of each individual lego-bar. This is very useful for histograms
1982having many bins. With such histograms the option `LEGO1` gives a black
1983image because of the border lines. This option also works with stacked legos.
1984
1985Begin_Macro(source)
1986{
1987 auto c2 = new TCanvas("c2","c2",600,400);
1988 auto hlego3 = new TH2F("hlego3","Option LEGO3 example",40,-4,4,40,-20,20);
1989 float px, py;
1990 for (Int_t i = 0; i < 25000; i++) {
1991 gRandom->Rannor(px,py);
1992 hlego3->Fill(px-1,5*py);
1993 hlego3->Fill(2+0.5*px,2*py-10.,0.1);
1994 }
1995 hlego3->SetFillColor(kRed);
1996 hlego3->Draw("LEGO3");
1997}
1998End_Macro
1999
2000The following example shows a 2D histogram plotted with the option
2001`LEGO2`. The option `LEGO2` draws a lego plot using colors to
2002show the cell contents. Combined with the option `LEGO2`, the option
2003`Z` allows to display the color palette defined by
2004`gStyle->SetPalette()`.
2005
2006Begin_Macro(source)
2007{
2008 auto c2 = new TCanvas("c2","c2",600,400);
2009 auto hlego2 = new TH2F("hlego2","Option LEGO2Z example ",40,-4,4,40,-20,20);
2010 float px, py;
2011 for (Int_t i = 0; i < 25000; i++) {
2012 gRandom->Rannor(px,py);
2013 hlego2->Fill(px-1,5*py);
2014 hlego2->Fill(2+0.5*px,2*py-10.,0.1);
2015 }
2016 hlego2->Draw("LEGO2Z");
2017}
2018End_Macro
2019
2020
2021
2022\anchor HP18
2023### The "SURFace" options
2024
2025
2026In a surface plot, cell contents are represented as a mesh.
2027The height of the mesh is proportional to the cell content.
2028
2029| Option | Description |
2030|----------|-------------------------------------------------------------------|
2031| "SURF" | Draw a surface plot using the hidden line removal technique.|
2032| "SURF1" | Draw a surface plot using the hidden surface removal technique.|
2033| "SURF2" | Draw a surface plot using colors to show the cell contents.|
2034| "SURF3" | Same as `SURF` with an additional filled contour plot on top.|
2035| "SURF4" | Draw a surface using the Gouraud shading technique.|
2036| "SURF5" | Used with one of the options CYL, PSR and CYL this option allows to draw a filled contour plot.|
2037| "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.|
2038| "SURF7" | Same as `SURF2` with an additional line contour plot on top.|
2039
2040
2041
2042See the limitations with [the option "SAME"](\ref HP060a).
2043
2044The following example shows a 2D histogram plotted with the option
2045`SURF`. The option `SURF` draws a lego plot using the hidden
2046lines removal technique.
2047
2048Begin_Macro(source)
2049{
2050 auto c2 = new TCanvas("c2","c2",600,400);
2051 auto hsurf = new TH2F("hsurf","Option SURF example ",30,-4,4,30,-20,20);
2052 float px, py;
2053 for (Int_t i = 0; i < 25000; i++) {
2054 gRandom->Rannor(px,py);
2055 hsurf->Fill(px-1,5*py);
2056 hsurf->Fill(2+0.5*px,2*py-10.,0.1);
2057 }
2058 hsurf->Draw("SURF");
2059}
2060End_Macro
2061
2062The following example shows a 2D histogram plotted with the option
2063`SURF1`. The option `SURF1` draws a surface plot using the
2064hidden surface removal technique. Combined with the option `SURF1`,
2065the option `Z` allows to display the color palette defined by
2066`gStyle->SetPalette()`.
2067
2068Begin_Macro(source)
2069{
2070 auto c2 = new TCanvas("c2","c2",600,400);
2071 auto hsurf1 = new TH2F("hsurf1","Option SURF1 example ",30,-4,4,30,-20,20);
2072 float px, py;
2073 for (Int_t i = 0; i < 25000; i++) {
2074 gRandom->Rannor(px,py);
2075 hsurf1->Fill(px-1,5*py);
2076 hsurf1->Fill(2+0.5*px,2*py-10.,0.1);
2077 }
2078 hsurf1->Draw("SURF1");
2079}
2080End_Macro
2081
2082The following example shows a 2D histogram plotted with the option
2083`SURF2`. The option `SURF2` draws a surface plot using colors
2084to show the cell contents. Combined with the option `SURF2`, the option
2085`Z` allows to display the color palette defined by
2086`gStyle->SetPalette()`.
2087
2088Begin_Macro(source)
2089{
2090 auto c2 = new TCanvas("c2","c2",600,400);
2091 auto hsurf2 = new TH2F("hsurf2","Option SURF2 example ",30,-4,4,30,-20,20);
2092 float px, py;
2093 for (Int_t i = 0; i < 25000; i++) {
2094 gRandom->Rannor(px,py);
2095 hsurf2->Fill(px-1,5*py);
2096 hsurf2->Fill(2+0.5*px,2*py-10.,0.1);
2097 }
2098 hsurf2->Draw("SURF2");
2099}
2100End_Macro
2101
2102The following example shows a 2D histogram plotted with the option
2103`SURF3`. The option `SURF3` draws a surface plot using the
2104hidden line removal technique with, in addition, a filled contour view drawn on the
2105top. Combined with the option `SURF3`, the option `Z` allows
2106to display the color palette defined by `gStyle->SetPalette()`.
2107
2108Begin_Macro(source)
2109{
2110 auto c2 = new TCanvas("c2","c2",600,400);
2111 auto hsurf3 = new TH2F("hsurf3","Option SURF3 example ",30,-4,4,30,-20,20);
2112 float px, py;
2113 for (Int_t i = 0; i < 25000; i++) {
2114 gRandom->Rannor(px,py);
2115 hsurf3->Fill(px-1,5*py);
2116 hsurf3->Fill(2+0.5*px,2*py-10.,0.1);
2117 }
2118 hsurf3->Draw("SURF3");
2119}
2120End_Macro
2121
2122The following example shows a 2D histogram plotted with the option
2123`SURF4`. The option `SURF4` draws a surface using the Gouraud
2124shading technique.
2125
2126Begin_Macro(source)
2127{
2128 auto c2 = new TCanvas("c2","c2",600,400);
2129 auto hsurf4 = new TH2F("hsurf4","Option SURF4 example ",30,-4,4,30,-20,20);
2130 float px, py;
2131 for (Int_t i = 0; i < 25000; i++) {
2132 gRandom->Rannor(px,py);
2133 hsurf4->Fill(px-1,5*py);
2134 hsurf4->Fill(2+0.5*px,2*py-10.,0.1);
2135 }
2136 hsurf4->SetFillColor(kOrange);
2137 hsurf4->Draw("SURF4");
2138}
2139End_Macro
2140
2141The following example shows a 2D histogram plotted with the option
2142`SURF5 CYL`. Combined with the option `SURF5`, the option
2143`Z` allows to display the color palette defined by `gStyle->SetPalette()`.
2144
2145Begin_Macro(source)
2146{
2147 auto c2 = new TCanvas("c2","c2",600,400);
2148 auto hsurf5 = new TH2F("hsurf4","Option SURF5 example ",30,-4,4,30,-20,20);
2149 float px, py;
2150 for (Int_t i = 0; i < 25000; i++) {
2151 gRandom->Rannor(px,py);
2152 hsurf5->Fill(px-1,5*py);
2153 hsurf5->Fill(2+0.5*px,2*py-10.,0.1);
2154 }
2155 hsurf5->Draw("SURF5 CYL");
2156}
2157End_Macro
2158
2159The following example shows a 2D histogram plotted with the option
2160`SURF7`. The option `SURF7` draws a surface plot using the
2161hidden surfaces removal technique with, in addition, a line contour view drawn on the
2162top. Combined with the option `SURF7`, the option `Z` allows
2163to display the color palette defined by `gStyle->SetPalette()`.
2164
2165Begin_Macro(source)
2166{
2167 auto c2 = new TCanvas("c2","c2",600,400);
2168 auto hsurf7 = new TH2F("hsurf3","Option SURF7 example ",30,-4,4,30,-20,20);
2169 float px, py;
2170 for (Int_t i = 0; i < 25000; i++) {
2171 gRandom->Rannor(px,py);
2172 hsurf7->Fill(px-1,5*py);
2173 hsurf7->Fill(2+0.5*px,2*py-10.,0.1);
2174 }
2175 hsurf7->Draw("SURF7");
2176}
2177End_Macro
2178
2179As shown in the following example, when a contour plot is painted on top of a
2180surface plot using the option `SAME`, the contours appear in 3D on the
2181surface.
2182
2183Begin_Macro(source)
2184{
2185 auto c20=new TCanvas("c20","c20",600,400);
2186 int NBins = 50;
2187 double d = 2;
2188 auto hsc = new TH2F("hsc", "Surface and contour with option SAME ", NBins, -d, d, NBins, -d, d);
2189 for (int bx = 1; bx <= NBins; ++bx) {
2190 for (int by = 1; by <= NBins; ++by) {
2191 double x = hsc->GetXaxis()->GetBinCenter(bx);
2192 double y = hsc->GetYaxis()->GetBinCenter(by);
2193 hsc->SetBinContent(bx, by, exp(-x*x)*exp(-y*y));
2194 }
2195 }
2196 hsc->Draw("surf2");
2197 hsc->Draw("CONT1 SAME");
2198}
2199End_Macro
2200
2201
2202\anchor HP19
2203### Cylindrical, Polar, Spherical and PseudoRapidity/Phi options
2204
2205
2206Legos and surfaces plots are represented by default in Cartesian coordinates.
2207Combined with any `LEGOn` or `SURFn` options the following
2208options allow to draw a lego or a surface in other coordinates systems.
2209
2210| Option | Description |
2211|----------|-------------------------------------------------------------------|
2212| "CYL" | Use Cylindrical coordinates. The X coordinate is mapped on the angle and the Y coordinate on the cylinder length.|
2213| "POL" | Use Polar coordinates. The X coordinate is mapped on the angle and the Y coordinate on the radius.|
2214| "SPH" | Use Spherical coordinates. The X coordinate is mapped on the latitude and the Y coordinate on the longitude.|
2215| "PSR" | Use PseudoRapidity/Phi coordinates. The X coordinate is mapped on Phi.|
2216
2217
2218
2219<b>WARNING:</b> Axis are not drawn with these options.
2220
2221The following example shows the same histogram as a lego plot is the four
2222different coordinates systems.
2223
2224Begin_Macro(source)
2225{
2226 auto c3 = new TCanvas("c3","c3",600,400);
2227 c3->Divide(2,2);
2228 auto hlcc = new TH2F("hlcc","Cylindrical coordinates",20,-4,4,20,-20,20);
2229 float px, py;
2230 for (Int_t i = 0; i < 25000; i++) {
2231 gRandom->Rannor(px,py);
2232 hlcc->Fill(px-1,5*py);
2233 hlcc->Fill(2+0.5*px,2*py-10.,0.1);
2234 }
2235 hlcc->SetFillColor(kYellow);
2236 c3->cd(1); hlcc->Draw("LEGO1 CYL");
2237 c3->cd(2); auto hlpc = (TH2F*) hlcc->DrawClone("LEGO1 POL");
2238 hlpc->SetTitle("Polar coordinates");
2239 c3->cd(3); auto hlsc = (TH2F*) hlcc->DrawClone("LEGO1 SPH");
2240 hlsc->SetTitle("Spherical coordinates");
2241 c3->cd(4); auto hlprpc = (TH2F*) hlcc->DrawClone("LEGO1 PSR");
2242 hlprpc->SetTitle("PseudoRapidity/Phi coordinates");
2243}
2244End_Macro
2245
2246The following example shows the same histogram as a surface plot is the four different coordinates systems.
2247
2248Begin_Macro(source)
2249{
2250 auto c4 = new TCanvas("c4","c4",600,400);
2251 c4->Divide(2,2);
2252 auto hscc = new TH2F("hscc","Cylindrical coordinates",20,-4,4,20,-20,20);
2253 float px, py;
2254 for (Int_t i = 0; i < 25000; i++) {
2255 gRandom->Rannor(px,py);
2256 hscc->Fill(px-1,5*py);
2257 hscc->Fill(2+0.5*px,2*py-10.,0.1);
2258 }
2259 c4->cd(1); hscc->Draw("SURF1 CYL");
2260 c4->cd(2); auto hspc = (TH2F*) hscc->DrawClone("SURF1 POL");
2261 hspc->SetTitle("Polar coordinates");
2262 c4->cd(3); auto hssc = (TH2F*) hscc->DrawClone("SURF1 SPH");
2263 hssc->SetTitle("Spherical coordinates");
2264 c4->cd(4); auto hsprpc = (TH2F*) hscc->DrawClone("SURF1 PSR");
2265 hsprpc->SetTitle("PseudoRapidity/Phi coordinates");
2266}
2267End_Macro
2268
2269
2270\anchor HP20
2271### Base line for bar-charts and lego plots
2272
2273
2274By default the base line used to draw the boxes for bar-charts and lego plots is
2275the histogram minimum. It is possible to force this base line to be 0, using MIN0 draw
2276option or with the command:
2277
2278 gStyle->SetHistMinimumZero();
2279
2280Begin_Macro(source)
2281{
2282 auto c5 = new TCanvas("c5","c5",700,400);
2283 c5->Divide(2,1);
2284 auto hz1 = new TH1F("hz1","Bar-chart drawn from 0",20,-3,3);
2285 auto hz2 = new TH2F("hz2","Lego plot drawn from 0",20,-3,3,20,-3,3);
2286 Int_t i;
2287 double x,y;
2288 hz1->SetFillColor(kBlue);
2289 hz2->SetFillColor(kBlue);
2290 for (i=0;i<10000;i++) {
2291 x = gRandom->Gaus(0,1);
2292 y = gRandom->Gaus(0,1);
2293 if (x>0) {
2294 hz1->Fill(x,1);
2295 hz2->Fill(x,y,1);
2296 } else {
2297 hz1->Fill(x,-1);
2298 hz2->Fill(x,y,-2);
2299 }
2300 }
2301 c5->cd(1); hz1->Draw("bar2 min0");
2302 c5->cd(2); hz2->Draw("lego1 min0");
2303}
2304End_Macro
2305
2306This option also works for horizontal plots. The example given in the section
2307["The bar chart option"](\ref HP100) appears as follow:
2308
2309Begin_Macro(source)
2310{
2311 int i;
2312 const Int_t nx = 8;
2313 string os_X[nx] = {"8","32","128","512","2048","8192","32768","131072"};
2314 float d_35_0[nx] = {0.75, -3.30, -0.92, 0.10, 0.08, -1.69, -1.29, -2.37};
2315 float d_35_1[nx] = {1.01, -3.02, -0.65, 0.37, 0.34, -1.42, -1.02, -2.10};
2316
2317 auto cbh = new TCanvas("cbh","cbh",400,600);
2318 cbh->SetGrid();
2319
2320 auto h1bh = new TH1F("h1bh","Option HBAR centered on 0",nx,0,nx);
2321 h1bh->SetFillColor(4);
2322 h1bh->SetBarWidth(0.4);
2323 h1bh->SetBarOffset(0.1);
2324 h1bh->SetStats(0);
2325 h1bh->SetMinimum(-5);
2326 h1bh->SetMaximum(5);
2327
2328 for (i=1; i<=nx; i++) {
2329 h1bh->Fill(os_X[i-1].c_str(), d_35_0[i-1]);
2330 h1bh->GetXaxis()->SetBinLabel(i,os_X[i-1].c_str());
2331 }
2332
2333 h1bh->Draw("hbar min0");
2334
2335 auto h2bh = new TH1F("h2bh","h2bh",nx,0,nx);
2336 h2bh->SetFillColor(38);
2337 h2bh->SetBarWidth(0.4);
2338 h2bh->SetBarOffset(0.5);
2339 h2bh->SetStats(0);
2340 for (i=1;i<=nx;i++) h2bh->Fill(os_X[i-1].c_str(), d_35_1[i-1]);
2341
2342 h2bh->Draw("hbar min0 same");
2343}
2344End_Macro
2345
2346
2347\anchor HP20a
2348### TH2Poly Drawing
2349
2350
2351The following options are supported:
2352
2353| Option | Description |
2354|----------|-------------------------------------------------------------------|
2355| "SCAT" | Draw a scatter plot (legacy draw option).|
2356| "COL" | Draw a color plot. All the bins are painted even the empty bins (default).|
2357| "COLZ" | Same as "COL". In addition the color palette is also drawn.|
2358| "0" | When used with any COL options, the empty bins are not drawn.|
2359| "TEXT" | Draw bin contents as text (format set via `gStyle->SetPaintTextFormat`).|
2360| "TEXTN" | Draw bin names as text.|
2361| "TEXTnn" | Draw bin contents as text at angle nn (0 < nn <= 90).|
2362| "L" | Draw the bins boundaries as lines. The lines attributes are the TGraphs ones.|
2363| "P" | Draw the bins boundaries as markers. The markers attributes are the TGraphs ones.|
2364| "F" | Draw the bins boundaries as filled polygons. The filled polygons attributes are the TGraphs ones.|
2365
2366
2367
2368`TH2Poly` can be drawn as a color plot (option COL). `TH2Poly` bins can have any
2369shapes. The bins are defined as graphs. The following macro is a very simple
2370example showing how to book a TH2Poly and draw it.
2371
2372Begin_Macro(source)
2373{
2374 auto ch2p1 = new TCanvas("ch2p1","ch2p1",600,400);
2375 auto h2p = new TH2Poly();
2376 h2p->SetName("h2poly_name");
2377 h2p->SetTitle("h2poly_title");
2378 double px1[] = {0, 5, 6};
2379 double py1[] = {0, 0, 5};
2380 double px2[] = {0, -1, -1, 0};
2381 double py2[] = {0, 0, -1, 3};
2382 double px3[] = {4, 3, 0, 1, 2.4};
2383 double py3[] = {4, 3.7, 1, 3.7, 2.5};
2384 h2p->AddBin(3, px1, py1);
2385 h2p->AddBin(4, px2, py2);
2386 h2p->AddBin(5, px3, py3);
2387 h2p->Fill(0.1, 0.01, 3);
2388 h2p->Fill(-0.5, -0.5, 7);
2389 h2p->Fill(-0.7, -0.5, 1);
2390 h2p->Fill(1, 3, 1.5);
2391 double fx[] = {0.1, -0.5, -0.7, 1};
2392 double fy[] = {0.01, -0.5, -0.5, 3};
2393 double fw[] = {3, 1, 1, 1.5};
2394 h2p->FillN(4, fx, fy, fw);
2395 h2p->Draw("col");
2396}
2397End_Macro
2398
2399Rectangular bins are a frequent case. The special version of
2400the `AddBin` method allows to define them more easily like
2401shown in the following example (hist037_TH2Poly_boxes.C).
2402
2403Begin_Macro(source)
2404../../../tutorials/hist/hist037_TH2Poly_boxes.C
2405End_Macro
2406
2407One `TH2Poly` bin can be a list of polygons. Such bins are defined
2408by calling `AddBin` with a `TMultiGraph`. The following example
2409shows a such case:
2410
2411Begin_Macro(source)
2412{
2413 auto ch2p2 = new TCanvas("ch2p2","ch2p2",600,400);
2414
2415 Int_t i, bin;
2416 const Int_t nx = 48;
2417 const char *states [nx] = {
2418 "alabama", "arizona", "arkansas", "california",
2419 "colorado", "connecticut", "delaware", "florida",
2420 "georgia", "idaho", "illinois", "indiana",
2421 "iowa", "kansas", "kentucky", "louisiana",
2422 "maine", "maryland", "massachusetts", "michigan",
2423 "minnesota", "mississippi", "missouri", "montana",
2424 "nebraska", "nevada", "new_hampshire", "new_jersey",
2425 "new_mexico", "new_york", "north_carolina", "north_dakota",
2426 "ohio", "oklahoma", "oregon", "pennsylvania",
2427 "rhode_island", "south_carolina", "south_dakota", "tennessee",
2428 "texas", "utah", "vermont", "virginia",
2429 "washington", "west_virginia", "wisconsin", "wyoming"
2430 };
2431 Double_t pop[nx] = {
2432 4708708, 6595778, 2889450, 36961664, 5024748, 3518288, 885122, 18537969,
2433 9829211, 1545801, 12910409, 6423113, 3007856, 2818747, 4314113, 4492076,
2434 1318301, 5699478, 6593587, 9969727, 5266214, 2951996, 5987580, 974989,
2435 1796619, 2643085, 1324575, 8707739, 2009671, 19541453, 9380884, 646844,
2436 11542645, 3687050, 3825657, 12604767, 1053209, 4561242, 812383, 6296254,
2437 24782302, 2784572, 621760, 7882590, 6664195, 1819777, 5654774, 544270
2438 };
2439
2440 Double_t lon1 = -130;
2441 Double_t lon2 = -65;
2442 Double_t lat1 = 24;
2443 Double_t lat2 = 50;
2444 auto p = new TH2Poly("USA","USA Population",lon1,lon2,lat1,lat2);
2445
2446 TFile::SetCacheFileDir(".");
2447 auto f = TFile::Open("http://root.cern/files/usa.root", "CACHEREAD");
2448
2449 TMultiGraph *mg;
2450 TKey *key;
2451 TIter nextkey(gDirectory->GetListOfKeys());
2452 while ((key = (TKey*)nextkey())) {
2453 TObject *obj = key->ReadObj();
2454 if (obj->InheritsFrom("TMultiGraph")) {
2455 mg = (TMultiGraph*)obj;
2456 bin = p->AddBin(mg);
2457 }
2458 }
2459
2460 for (i=0; i<nx; i++) p->Fill(states[i], pop[i]);
2461
2462 gStyle->SetOptStat(11);
2463 p->Draw("COLZ L");
2464}
2465End_Macro
2466
2467`TH2Poly` histograms can also be plotted using the GL interface using
2468the option "GLLEGO".
2469
2470\since **ROOT version 6.09/01**
2471
2472In some cases it can be useful to not draw the empty bins. the option "0"
2473combined with the option "COL" and "COLZ" allows to do that.
2474
2475Begin_Macro(source)
2476{
2477 auto chc = new TCanvas("chc","chc",600,400);
2478
2479 auto hc = new TH2Poly();
2480 hc->Honeycomb(0,0,.1,25,25);
2481 hc->SetName("hc");
2482 hc->SetTitle("Option COLZ 0");
2483 TRandom ran;
2484 for (int i = 0; i<300; i++) hc->Fill(ran.Gaus(2.,1), ran.Gaus(2.,1));
2485 hc->Draw("colz 0");
2486}
2487End_Macro
2488
2489\anchor HP21
2490### The SPEC option
2491
2492
2493This option allows to use the `TSpectrum2Painter` tools. See the full
2494documentation in `TSpectrum2Painter::PaintSpectrum`.
2495
2496
2497\anchor HP22
2498### Option "Z" : Adding the color palette on the right side of the pad
2499
2500
2501When this option is specified, a color palette with an axis indicating the value
2502of the corresponding color is drawn on the right side of the picture. In case,
2503not enough space is left, one can increase the size of the right margin by
2504calling `TPad::SetRightMargin()`. The attributes used to display the
2505palette axis values are taken from the Z axis of the object. For example, to
2506set the labels size on the palette axis do:
2507
2508 hist->GetZaxis()->SetLabelSize().
2509
2510<b>WARNING:</b> The palette axis is always drawn vertically.
2511
2512
2513\anchor HP23
2514### Setting the color palette
2515
2516
2517To change the color palette `TStyle::SetPalette` should be used, eg:
2518
2519 gStyle->SetPalette(ncolors,colors);
2520
2521For example the option `COL` draws a 2D histogram with cells
2522represented by a box filled with a color index which is a function
2523of the cell content.
2524If the cell content is N, the color index used will be the color number
2525in `colors[N]`, etc. If the maximum cell content is greater than
2526`ncolors`, all cell contents are scaled to `ncolors`.
2527
2528If ` ncolors <= 0`, a default palette (see below) of 50 colors is
2529defined. This palette is recommended for pads, labels ...
2530
2531`if ncolors == 1 && colors == 0`, then a Pretty Palette with a
2532Spectrum Violet->Red is created with 50 colors. That's the default rain bow
2533palette.
2534
2535Other pre-defined palettes with 255 colors are available when `colors == 0`.
2536The following value of `ncolors` give access to:
2537
2538
2539 if ncolors = 51 and colors=0, a Deep Sea palette is used.
2540 if ncolors = 52 and colors=0, a Grey Scale palette is used.
2541 if ncolors = 53 and colors=0, a Dark Body Radiator palette is used.
2542 if ncolors = 54 and colors=0, a two-color hue palette palette is used.(dark blue through neutral gray to bright
2543yellow) if ncolors = 55 and colors=0, a Rain Bow palette is used. if ncolors = 56 and colors=0, an inverted Dark Body
2544Radiator palette is used.
2545
2546
2547If `ncolors > 0 && colors == 0`, the default palette is used with a maximum of ncolors.
2548
2549The default palette defines:
2550
2551- index 0 to 9 : shades of grey
2552- index 10 to 19 : shades of brown
2553- index 20 to 29 : shades of blue
2554- index 30 to 39 : shades of red
2555- index 40 to 49 : basic colors
2556
2557The color numbers specified in the palette can be viewed by selecting
2558the item `colors` in the `VIEW` menu of the canvas tool bar.
2559The red, green, and blue components of a color can be changed thanks to
2560`TColor::SetRGB()`.
2561
2562\since **ROOT version 6.19/01**
2563
2564As default labels and ticks are drawn by `TGAxis` at equidistant (lin or log)
2565points as controlled by SetNdivisions.
2566If option "CJUST" is given labels and ticks are justified at the
2567color boundaries defined by the contour levels.
2568For more details see `TPaletteAxis`
2569
2570\anchor HP24
2571### Drawing a sub-range of a 2D histogram; the [cutg] option
2572
2573
2574Using a `TCutG` object, it is possible to draw a sub-range of a 2D
2575histogram. One must create a graphical cut (mouse or C++) and specify the name
2576of the cut between `[]` in the `Draw()` option.
2577For example (fit2a.C), with a `TCutG` named `cutg`, one can call:
2578
2579 myhist->Draw("surf1 [cutg]");
2580
2581To invert the cut, it is enough to put a `-` in front of its name:
2582
2583 myhist->Draw("surf1 [-cutg]");
2584
2585It is possible to apply several cuts (`,` means logical AND):
2586
2587 myhist->Draw("surf1 [cutg1,cutg2]");
2588
2589Begin_Macro(source)
2590../../../tutorials/fit/fit2a.C
2591End_Macro
2592
2593\anchor HP25
2594### Drawing options for 3D histograms
2595
2596
2597| Option | Description |
2598|----------|-------------------------------------------------------------------|
2599| "SCAT" | Draw a scatter plot (legacy draw option).|
2600| "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)`|
2601| "BOX" | Draw a for each cell with volume proportional to the content's absolute value. An hidden line removal algorithm is used|
2602| "BOX1" | Same as BOX but an hidden surface removal algorithm is used|
2603| "BOX2" | Same as "COL". The boxes' colors are picked in the current palette according to the bins' contents (default)|
2604| "BOX2Z" | Same as "BOX2". In addition the color palette is also drawn.|
2605| "BOX3" | Same as BOX1, but the border lines of each lego-bar are not drawn.|
2606
2607Note that instead of `BOX` one can also use `LEGO`.
2608
2609By default, 3D histograms are drawn as a colored box plots.
2610
2611The following example shows a 3D histogram plotted as a scatter plot.
2612
2613Begin_Macro(source)
2614{
2615 auto c06 = new TCanvas("c06","c06",600,400);
2616 gStyle->SetOptStat(kFALSE);
2617 auto h3scat = new TH3F("h3scat","Option SCAT",15,-2,2,15,-2,2,15,0,4);
2618 double x, y, z;
2619 for (Int_t i=0;i<10000;i++) {
2620 gRandom->Rannor(x, y);
2621 z = x*x + y*y;
2622 h3scat->Fill(x,y,z);
2623 }
2624 h3scat->Draw("SCAT"); // This a legacy draw option
2625}
2626End_Macro
2627
2628The following example shows a 3D histogram plotted with the option `BOX`.
2629
2630Begin_Macro(source)
2631{
2632 auto c16 = new TCanvas("c16","c16",600,400);
2633 gStyle->SetOptStat(kFALSE);
2634 auto h3box = new TH3F("h3box","Option BOX",15,-2,2,15,-2,2,15,0,4);
2635 double x, y, z;
2636 for (Int_t i=0;i<10000;i++) {
2637 gRandom->Rannor(x, y);
2638 z = x*x + y*y;
2639 h3box->Fill(x,y,z);
2640 }
2641 h3box->Draw("BOX");
2642}
2643End_Macro
2644
2645The following example shows a 3D histogram plotted with the option `BOX1`.
2646
2647Begin_Macro(source)
2648{
2649 auto c36 = new TCanvas("c36","c36",600,400);
2650 gStyle->SetOptStat(kFALSE);
2651 auto h3box = new TH3F("h3box","Option BOX1",10,-2.,2.,10,-2.,2.,10,-0.5,2.);
2652 double x, y, z;
2653 for (Int_t i=0;i<10000;i++) {
2654 gRandom->Rannor(x, y);
2655 z = abs(sin(x)/x + cos(y)*y);
2656 h3box->Fill(x,y,z);
2657 }
2658 h3box->SetFillColor(9);
2659 h3box->Draw("BOX1");
2660}
2661End_Macro
2662
2663The following example shows a 3D histogram plotted with the option `BOX2`.
2664
2665Begin_Macro(source)
2666{
2667 auto c56 = new TCanvas("c56","c56",600,400);
2668 gStyle->SetOptStat(kFALSE);
2669 auto h3box = new TH3F("h3box","Option BOX2 (default)",10,-2.,2.,10,-2.,2.,10,-0.5,2.);
2670 double x, y, z;
2671 for (Int_t i=0;i<10000;i++) {
2672 gRandom->Rannor(x, y);
2673 z = abs(sin(x)/x + cos(y)*y);
2674 h3box->Fill(x,y,z);
2675 }
2676 h3box->Draw("BOX2 Z");
2677}
2678End_Macro
2679
2680The following example shows a 3D histogram plotted with the option `BOX3`.
2681
2682Begin_Macro(source)
2683{
2684 auto c46 = new TCanvas("c46","c46",600,400);
2685 c46->SetFillColor(38);
2686 gStyle->SetOptStat(kFALSE);
2687 auto h3box = new TH3F("h3box","Option BOX3",15,-2,2,15,-2,2,15,0,4);
2688 double x, y, z;
2689 for (Int_t i=0;i<10000;i++) {
2690 gRandom->Rannor(x, y);
2691 z = x*x + y*y;
2692 h3box->Fill(x,y,z);
2693 }
2694 h3box->Draw("BOX3");
2695}
2696End_Macro
2697
2698For all the `BOX` options each bin is drawn as a 3D box with a volume proportional
2699to the absolute value of the bin content. The bins with a negative content are
2700drawn with a X on each face of the box as shown in the following example:
2701
2702Begin_Macro(source)
2703{
2704 auto c = new TCanvas("c","c",600,400);
2705 gStyle->SetOptStat(kFALSE);
2706 auto h3box = new TH3F("h3box","Option BOX1 with negative bins",3, 0., 4., 3, 0.,4., 3, 0., 4.);
2707 h3box->Fill(0., 2., 2., 10.);
2708 h3box->Fill(2., 2., 2., 5.);
2709 h3box->Fill(2., 2., .5, 2.);
2710 h3box->Fill(2., 2., 3., -1.);
2711 h3box->Fill(3., 2., 2., -10.);
2712 h3box->SetFillColor(8);
2713 h3box->Draw("box1");
2714}
2715End_Macro
2716
2717The following example shows a 3D histogram plotted with the option `ISO`.
2718
2719Begin_Macro(source)
2720{
2721 auto c26 = new TCanvas("c26","c26",600,400);
2722 gStyle->SetOptStat(kFALSE);
2723 auto h3iso = new TH3F("h3iso","Option ISO",15,-2,2,15,-2,2,15,0,4);
2724 double x, y, z;
2725 for (Int_t i=0;i<10000;i++) {
2726 gRandom->Rannor(x, y);
2727 z = x*x + y*y;
2728 h3iso->Fill(x,y,z);
2729 }
2730 h3iso->SetFillColor(kCyan);
2731 h3iso->Draw("ISO");
2732}
2733End_Macro
2734
2735
2736\anchor HP26
2737### Drawing option for histograms' stacks
2738
2739
2740Stacks of histograms are managed with the `THStack`. A `THStack`
2741is a collection of `TH1` (or derived) objects. For painting only the
2742`THStack` containing `TH1` only or
2743`THStack` containing `TH2` only will be considered.
2744
2745By default, histograms are shown stacked:
2746
27471. The first histogram is paint.
27482. The sum of the first and second, etc...
2749
2750If the option `NOSTACK` is specified, the histograms are all paint in
2751the same pad as if the option `SAME` had been specified. This allows to
2752compute X and Y scales common to all the histograms, like
2753`TMultiGraph` does for graphs.
2754
2755If the option `PADS` is specified, the current pad/canvas is subdivided into
2756a number of pads equal to the number of histograms and each histogram is paint
2757into a separate pad. With `PADSn`, the current pad/canvas is subdivided into
2758`n` columns, automatically calculating the number of rows.
2759
2760The following example shows various types of stacks (hist023_THStack_simple.C).
2761
2762Begin_Macro(source)
2763../../../tutorials/hist/hist023_THStack_simple.C
2764End_Macro
2765
2766The option `nostackb` allows to draw the histograms next to each
2767other as bar charts:
2768
2769Begin_Macro(source)
2770{
2771 auto cst0 = new TCanvas("cst0","cst0",600,400);
2772 auto hs = new THStack("hs","Stacked 1D histograms: option #font[82]{\"nostackb\"}");
2773
2774 auto h1 = new TH1F("h1","h1",10,-4,4);
2775 h1->FillRandom("gaus",20000);
2776 h1->SetFillColor(kRed);
2777 hs->Add(h1);
2778
2779 auto h2 = new TH1F("h2","h2",10,-4,4);
2780 h2->FillRandom("gaus",15000);
2781 h2->SetFillColor(kBlue);
2782 hs->Add(h2);
2783
2784 auto h3 = new TH1F("h3","h3",10,-4,4);
2785 h3->FillRandom("gaus",10000);
2786 h3->SetFillColor(kGreen);
2787 hs->Add(h3);
2788
2789 hs->Draw("nostackb");
2790 hs->GetXaxis()->SetNdivisions(-10);
2791 cst0->SetGridx();
2792}
2793End_Macro
2794
2795If at least one of the histograms in the stack has errors, the whole stack is
2796visualized by default with error bars. To visualize it without errors the
2797option `HIST` should be used.
2798
2799Begin_Macro(source)
2800{
2801 auto cst1 = new TCanvas("cst1","cst1",700,400);
2802 cst1->Divide(2,1);
2803
2804 auto hst11 = new TH1F("hst11", "", 20, -10, 10);
2805 hst11->Sumw2();
2806 hst11->FillRandom("gaus", 1000);
2807 hst11->SetFillColor(kViolet);
2808 hst11->SetLineColor(kViolet);
2809
2810 auto hst12 = new TH1F("hst12", "", 20, -10, 10);
2811 hst12->FillRandom("gaus", 500);
2812 hst12->SetFillColor(kBlue);
2813 hst12->SetLineColor(kBlue);
2814
2815 THStack st1("st1", "st1");
2816 st1.Add(hst11);
2817 st1.Add(hst12);
2818
2819 cst1->cd(1); st1.Draw();
2820 cst1->cd(2); st1.Draw("hist");
2821}
2822End_Macro
2823
2824\anchor HP27
2825### Drawing of 3D implicit functions
2826
2827
28283D implicit functions (`TF3`) can be drawn as iso-surfaces.
2829The implicit function f(x,y,z) = 0 is drawn in cartesian coordinates.
2830In the following example the options "FB" and "BB" suppress the
2831"Front Box" and "Back Box" around the plot.
2832
2833Begin_Macro(source)
2834{
2835 auto c2 = new TCanvas("c2","c2",600,400);
2836 auto f3 = new TF3("f3","sin(x*x+y*y+z*z-36)",-2,2,-2,2,-2,2);
2837 f3->SetClippingBoxOn(0,0,0);
2838 f3->SetFillColor(30);
2839 f3->SetLineColor(15);
2840 f3->Draw("FBBB");
2841}
2842End_Macro
2843
2844
2845\anchor HP28
2846### Associated functions drawing
2847
2848
2849An associated function is created by `TH1::Fit`. More than on fitted
2850function can be associated with one histogram (see `TH1::Fit`).
2851
2852A `TF1` object `f1` can be added to the list of associated
2853functions of an histogram `h` without calling `TH1::Fit`
2854simply doing:
2855
2856 h->GetListOfFunctions()->Add(f1);
2857
2858or
2859
2860 h->GetListOfFunctions()->Add(f1,someoption);
2861
2862To retrieve a function by name from this list, do:
2863
2864 TF1 *f1 = (TF1*)h->GetListOfFunctions()->FindObject(name);
2865
2866or
2867
2868 TF1 *f1 = h->GetFunction(name);
2869
2870Associated functions are automatically painted when an histogram is drawn.
2871To avoid the painting of the associated functions the option `HIST`
2872should be added to the list of the options used to paint the histogram.
2873
2874
2875\anchor HP29
2876### Drawing using OpenGL
2877
2878
2879The class `TGLHistPainter` allows to paint data set using the OpenGL 3D
2880graphics library. The plotting options start with `GL` keyword.
2881In addition, in order to inform canvases that OpenGL should be used to render
28823D representations, the following option should be set:
2883
2884 gStyle->SetCanvasPreferGL(true);
2885
2886
2887\anchor HP29a
2888#### General information: plot types and supported options
2889
2890The following types of plots are provided:
2891
2892For lego plots the supported options are:
2893
2894| Option | Description |
2895|----------|-------------------------------------------------------------------|
2896| "GLLEGO" | Draw a lego plot. It works also for `TH2Poly`.|
2897| "GLLEGO2"| Bins with color levels.|
2898| "GLLEGO3"| Cylindrical bars.|
2899
2900
2901
2902Lego painter in cartesian supports logarithmic scales for X, Y, Z.
2903In polar only Z axis can be logarithmic, in cylindrical only Y.
2904
2905For surface plots (`TF2` and `TH2`) the supported options are:
2906
2907| Option | Description |
2908|-----------|------------------------------------------------------------------|
2909| "GLSURF" | Draw a surface.|
2910| "GLSURF1" | Surface with color levels|
2911| "GLSURF2" | The same as "GLSURF1" but without polygon outlines.|
2912| "GLSURF3" | Color level projection on top of plot (works only in cartesian coordinate system).|
2913| "GLSURF4" | Same as "GLSURF" but without polygon outlines.|
2914
2915
2916
2917The surface painting in cartesian coordinates supports logarithmic scales along
2918X, Y, Z axis. In polar coordinates only the Z axis can be logarithmic,
2919in cylindrical coordinates only the Y axis.
2920
2921Additional options to SURF and LEGO - Coordinate systems:
2922
2923| Option | Description |
2924|----------|-------------------------------------------------------------------|
2925| " " | Default, cartesian coordinates system.|
2926| "POL" | Polar coordinates system.|
2927| "CYL" | Cylindrical coordinates system.|
2928| "SPH" | Spherical coordinates system.|
2929
2930
2931
2932\anchor HP290
2933#### TH3 as color boxes
2934
2935The supported option is:
2936
2937| Option | Description |
2938|----------|-------------------------------------------------------------------|
2939| "GLCOL" | H3 is drawn using semi-transparent colored boxes. See glvox1.C .|
2940
2941
2942
2943\anchor HP29b
2944#### TH3 as boxes (spheres)
2945
2946The supported options are:
2947
2948| Option | Description |
2949|----------|-------------------------------------------------------------------|
2950| "GLBOX" | TH3 as a set of boxes, size of box is proportional to bin content.|
2951| "GLBOX1" | The same as "glbox", but spheres are drawn instead of boxes.|
2952
2953
2954
2955\anchor HP29c
2956#### TH3 as iso-surface(s)
2957
2958The supported option is:
2959
2960| Option | Description |
2961|----------|-------------------------------------------------------------------|
2962| "GLISO" | TH3 is drawn using iso-surfaces.|
2963
2964
2965
2966\anchor HP29d
2967#### TF3 (implicit function)
2968
2969The supported option is:
2970
2971| Option | Description |
2972|----------|-------------------------------------------------------------------|
2973| "GL" | Draw a TF3.|
2974
2975
2976
2977\anchor HP29e
2978#### Parametric surfaces
2979
2980glparametric.C shows how to create parametric equations and visualize the surface.
2981
2982\anchor HP29f
2983#### Interaction with the plots
2984
2985All the interactions are implemented via standard methods
2986`DistancetoPrimitive()` and `ExecuteEvent()`. That's why all the
2987interactions with the OpenGL plots are possible only when the mouse cursor is
2988in the plot's area (the plot's area is the part of a the pad occupied by
2989gl-produced picture). If the mouse cursor is not above gl-picture, the standard
2990pad interaction is performed.
2991
2992\anchor HP29g
2993#### Selectable parts
2994
2995Different parts of the plot can be selected:
2996
2997- xoz, yoz, xoy back planes: When such a plane selected, it's highlighted in green
2998 if the dynamic slicing by this plane is supported, and it's highlighted in red,
2999 if the dynamic slicing is not supported.
3000- The plot itself:
3001 On surfaces, the selected surface is outlined in red. (TF3 and
3002 ISO are not outlined). On lego plots, the selected bin is
3003 highlighted. The bin number and content are displayed in pad's
3004 status bar. In box plots, the box or sphere is highlighted and
3005 the bin info is displayed in pad's status bar.
3006
3007
3008\anchor HP29h
3009#### Rotation and zooming
3010
3011
3012- Rotation:
3013 When the plot is selected, it can be rotated by pressing and
3014 holding the left mouse button and move the cursor.
3015- Zoom/Unzoom:
3016 Mouse wheel or 'j', 'J', 'k', 'K' keys.
3017
3018
3019\anchor HP29i
3020#### Panning
3021
3022The selected plot can be moved in a pad's area by pressing and
3023holding the left mouse button and the shift key.
3024
3025\anchor HP29j
3026#### Box cut
3027
3028Surface, iso, box, TF3 and parametric painters support box cut by
3029pressing the 'c' or 'C' key when the mouse cursor is in a plot's
3030area. That will display a transparent box, cutting away part of the
3031surface (or boxes) in order to show internal part of plot. This box
3032can be moved inside the plot's area (the full size of the box is
3033equal to the plot's surrounding box) by selecting one of the box
3034cut axes and pressing the left mouse button to move it.
3035
3036\anchor HP29k
3037#### Plot specific interactions (dynamic slicing etc.)
3038
3039Currently, all gl-plots support some form of slicing. When back plane
3040is selected (and if it's highlighted in green) you can press and hold
3041left mouse button and shift key and move this back plane inside
3042plot's area, creating the slice. During this "slicing" plot becomes
3043semi-transparent. To remove all slices (and projected curves for
3044surfaces) double click with left mouse button in a plot's area.
3045
3046\anchor HP29l
3047#### Surface with option "GLSURF"
3048
3049The surface profile is displayed on the slicing plane.
3050The profile projection is drawn on the back plane
3051by pressing `'p'` or `'P'` key.
3052
3053\anchor HP29m
3054#### TF3
3055
3056The contour plot is drawn on the slicing plane. For TF3 the color
3057scheme can be changed by pressing 's' or 'S'.
3058
3059\anchor HP29n
3060#### Box
3061
3062The contour plot corresponding to slice plane position is drawn in real time.
3063
3064\anchor HP29o
3065#### Iso
3066
3067Slicing is similar to "GLBOX" option.
3068
3069\anchor HP29p
3070#### Parametric plot
3071
3072No slicing. Additional keys: 's' or 'S' to change color scheme -
3073about 20 color schemes supported ('s' for "scheme"); 'l' or 'L' to
3074increase number of polygons ('l' for "level" of details), 'w' or 'W'
3075to show outlines ('w' for "wireframe").
3076
3077\anchor HP30
3078#### Highlight mode for histogram
3079
3080\since **ROOT version 6.15/01**
3081
3082\image html hlHisto3_top.gif "Highlight mode"
3083
3084Highlight mode is implemented for `TH1` (and for `TGraph`) class. When
3085highlight mode is on, mouse movement over the bin will be represented
3086graphically. Bin will be highlighted as "bin box" (presented by box
3087object). Moreover, any highlight (change of bin) emits signal
3088`TCanvas::Highlighted()` which allows the user to react and call their own
3089function. For a better understanding see also the tutorial `hist043` to `hist046`
3090located in `$ROOTSYS/tutorials/hist/`.
3091
3092Highlight mode is switched on/off by `TH1::SetHighlight()` function
3093or interactively from `TH1` context menu. `TH1::IsHighlight()` to verify
3094whether the highlight mode enabled or disabled, default it is disabled.
3095
3096~~~ {.cpp}
3097 root [0] .x $ROOTSYS/tutorials/hsimple.C
3098 root [1] hpx->SetHighlight(kTRUE) // or interactively from TH1 context menu
3099 root [2] hpx->IsHighlight()
3100 (bool) true
3101~~~
3102
3103\image html hlsimple_nofun.gif "Highlight mode for histogram"
3104
3105\anchor HP30a
3106#### Highlight mode and user function
3107
3108The user can use (connect) `TCanvas::Highlighted()` signal, which is always
3109emitted if there is a highlight bin and call user function via signal
3110and slot communication mechanism. `TCanvas::Highlighted()` is similar
3111`TCanvas::Picked()`
3112
3113- when selected object (histogram as a whole) is different from previous
3114then emit `Picked()` signal
3115- when selected (highlighted) bin from histogram is different from previous
3116then emit `Highlighted()` signal
3117
3118Any user function (or functions) has to be defined
3119`UserFunction(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)`.
3120In example (see below) has name `PrintInfo()`. All parameters of user
3121function are taken from
3122
3123 void TCanvas::Highlighted(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)
3124
3125- `pad` is pointer to pad with highlighted histogram
3126- `obj` is pointer to highlighted histogram
3127- `x` is highlighted x bin for 1D histogram
3128- `y` is highlighted y bin for 2D histogram (for 1D histogram not in use)
3129
3130Example how to create a connection from any `TCanvas` object to a user
3131`UserFunction()` slot (see also `TQObject::Connect()` for additional info)
3132
3133 TQObject::Connect("TCanvas", "Highlighted(TVirtualPad*,TObject*,Int_t,Int_t)",
3134 0, 0, "UserFunction(TVirtualPad*,TObject*,Int_t,Int_t)");
3135
3136or use non-static "simplified" function
3137`TCanvas::HighlightConnect(const char *slot)`
3138
3139 c1->HighlightConnect("UserFunction(TVirtualPad*,TObject*,Int_t,Int_t)");
3140
3141NOTE the signal and slot string must have a form
3142"(TVirtualPad*,TObject*,Int_t,Int_t)"
3143
3144 root [0] .x $ROOTSYS/tutorials/hsimple.C
3145 root [1] hpx->SetHighlight(kTRUE)
3146 root [2] .x hlprint.C
3147
3148file `hlprint.C`
3149~~~ {.cpp}
3150void PrintInfo(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)
3151{
3152 auto h = (TH1F *)obj;
3153 if (!h->IsHighlight()) // after highlight disabled
3154 h->SetTitle("highlight disable");
3155 else
3156 h->SetTitle(TString::Format("bin[%03d] (%5.2f) content %g", x,
3157 h->GetBinCenter(x), h->GetBinContent(x)));
3158 pad->Update();
3159}
3160
3161void hlprint()
3162{
3163 if (!gPad) return;
3164 gPad->GetCanvas()->HighlightConnect("PrintInfo(TVirtualPad*,TObject*,Int_t,Int_t)");
3165}
3166~~~
3167
3168\image html hlsimple.gif "Highlight mode and simple user function"
3169
3170For more complex demo please see for example tree200_temperature.C file.
3171
3172*/
3173
3175
3178
3179const Int_t kNMAX = 2000;
3180
3181const Int_t kMAXCONTOUR = 104;
3183
3184static std::unique_ptr<TBox> gXHighlightBox, gYHighlightBox; // highlight X and Y box
3185
3207
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());
8730 stats->SetTextFont(gStyle->GetStatFont());
8731 if (gStyle->GetStatFont()%10 > 2)
8733 stats->SetFitFormat(gStyle->GetFitFormat());
8735 stats->SetName("stats");
8736
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());
8937 stats->SetName("stats");
8938
8940 stats->SetTextAlign(12);
8941 stats->SetTextFont(gStyle->GetStatFont());
8942 if (gStyle->GetStatFont()%10 > 2)
8944 stats->SetFitFormat(gStyle->GetFitFormat());
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());
9150 stats->SetName("stats");
9151
9153 stats->SetTextAlign(12);
9154 stats->SetTextFont(gStyle->GetStatFont());
9155 stats->SetFitFormat(gStyle->GetFitFormat());
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
9902
9903 // Paint the TGraph bins.
9904 if (poly->IsA() == TGraph::Class()) {
9905 TGraph *g = (TGraph*)poly;
9906 auto origin = g->GetFillColor();
9907 g->SetFillColor(rootColor);
9908 g->TAttFill::Modify();
9909 g->Paint("F");
9910 g->SetFillColor(origin);
9911 }
9912
9913 // Paint the TMultiGraph bins.
9914 if (poly->IsA() == TMultiGraph::Class()) {
9917 while (auto g = (TGraph*) nextg()) {
9918 auto origin = g->GetFillColor();
9919 g->SetFillColor(rootColor);
9920 g->TAttFill::Modify();
9921 g->Paint("F");
9922 g->SetFillColor(origin);
9923 }
9924 }
9925 }
9927}
9928
9929////////////////////////////////////////////////////////////////////////////////
9930/// [Control function to draw a TH2Poly as a scatter plot.](\ref HP20a)
9931
9933{
9934
9935 //Do not highlight the histogram, if its part was selected.
9936 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
9937 return;
9938
9939 Int_t k, loop, marker=0;
9940 Double_t z, xk,xstep, yk, ystep, xp, yp;
9941 Double_t scale = 1;
9942 Double_t zmin = fH->GetMinimum();
9943 Double_t zmax = fH->GetMaximum();
9944 if (Hoption.Logz) {
9945 if (zmax > 0) {
9946 if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
9947 zmin = TMath::Log10(zmin);
9948 zmax = TMath::Log10(zmax);
9949 } else {
9950 return;
9951 }
9952 }
9953 Double_t dz = zmax - zmin;
9954 scale = (kNMAX-1)/dz;
9955
9956
9957 // use an independent instance of a random generator
9958 // instead of gRandom to avoid conflicts and
9959 // to get same random numbers when drawing the same histogram
9961
9962 TH2PolyBin *b;
9963
9964 TIter next(((TH2Poly*)fH)->GetBins());
9965 TObject *obj, *poly;
9966
9967 Double_t maxarea = 0, a;
9968 while ((obj=next())) {
9969 b = (TH2PolyBin*)obj;
9970 a = b->GetArea();
9971 if (a>maxarea) maxarea = a;
9972 }
9973
9974 next.Reset();
9975
9976 while ((obj=next())) {
9977 b = (TH2PolyBin*)obj;
9978 poly = b->GetPolygon();
9979 z = b->GetContent();
9980 if (z < zmin) z = zmin;
9981 if (z > zmax) z = zmax;
9982 if (Hoption.Logz) {
9983 if (z > 0) z = TMath::Log10(z) - zmin;
9984 } else {
9985 z -= zmin;
9986 }
9987 k = Int_t((z*scale)*(b->GetArea()/maxarea));
9988 xk = b->GetXMin();
9989 yk = b->GetYMin();
9990 xstep = b->GetXMax()-xk;
9991 ystep = b->GetYMax()-yk;
9992
9993 // Paint the TGraph bins.
9994 if (poly->IsA() == TGraph::Class()) {
9995 TGraph *g = (TGraph*)poly;
9996 if (k <= 0 || z <= 0) continue;
9997 loop = 0;
9998 while (loop<k) {
9999 if (k+marker >= kNMAX) {
10000 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10001 marker=0;
10002 }
10003 xp = (random.Rndm()*xstep) + xk;
10004 yp = (random.Rndm()*ystep) + yk;
10005 if (g->IsInside(xp,yp)) {
10006 fXbuf[marker] = xp;
10007 fYbuf[marker] = yp;
10008 marker++;
10009 loop++;
10010 }
10011 }
10012 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10013 }
10014
10015 // Paint the TMultiGraph bins.
10016 if (poly->IsA() == TMultiGraph::Class()) {
10018 TList *gl = mg->GetListOfGraphs();
10019 if (!gl) return;
10020 if (k <= 0 || z <= 0) continue;
10021 loop = 0;
10022 while (loop<k) {
10023 if (k+marker >= kNMAX) {
10024 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10025 marker=0;
10026 }
10027 xp = (random.Rndm()*xstep) + xk;
10028 yp = (random.Rndm()*ystep) + yk;
10029 if (mg->IsInside(xp,yp)) {
10030 fXbuf[marker] = xp;
10031 fYbuf[marker] = yp;
10032 marker++;
10033 loop++;
10034 }
10035 }
10036 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10037 }
10038 }
10039 PaintTH2PolyBins("l");
10040}
10041
10042////////////////////////////////////////////////////////////////////////////////
10043/// [Control function to draw a TH2Poly as a text plot.](\ref HP20a)
10044
10046{
10047
10048 TLatex text;
10049 text.SetTextFont(gStyle->GetTextFont());
10050 text.SetTextColor(fH->GetMarkerColor());
10051 text.SetTextSize(0.02*fH->GetMarkerSize());
10052
10053 Double_t x, y, z, e, angle = 0;
10054 TString tt, tf;
10055 tf.Form("%s%s","%",gStyle->GetPaintTextFormat());
10056 if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
10057 Int_t opt = (Int_t)Hoption.Text/1000;
10058
10059 text.SetTextAlign(22);
10060 if (Hoption.Text == 1) angle = 0;
10061 text.SetTextAngle(angle);
10062 text.TAttText::Modify();
10063
10064 TH2PolyBin *b;
10065
10066 TIter next(((TH2Poly*)fH)->GetBins());
10067 TObject *obj, *p;
10068
10069 while ((obj=next())) {
10070 b = (TH2PolyBin*)obj;
10071 p = b->GetPolygon();
10072 x = (b->GetXMin()+b->GetXMax())/2;
10073 if (Hoption.Logx) {
10074 if (x > 0) x = TMath::Log10(x);
10075 else continue;
10076 }
10077 y = (b->GetYMin()+b->GetYMax())/2;
10078 if (Hoption.Logy) {
10079 if (y > 0) y = TMath::Log10(y);
10080 else continue;
10081 }
10082 z = b->GetContent();
10083 if (z < fH->GetMinimum() || (z == 0 && !Hoption.MinimumZero)) continue;
10084 if (opt==2) {
10085 e = fH->GetBinError(b->GetBinNumber());
10086 tf.Form("#splitline{%s%s}{#pm %s%s}",
10088 "%",gStyle->GetPaintTextFormat());
10089 tt.Form(tf.Data(),z,e);
10090 } else {
10091 tt.Form(tf.Data(),z);
10092 }
10093 if (opt==3) text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),p->GetName());
10094 else text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),tt.Data());
10095 }
10096
10097 PaintTH2PolyBins("l");
10098}
10099
10100////////////////////////////////////////////////////////////////////////////////
10101/// [Control function to draw a 1D/2D histograms with the bin values.](\ref HP15)
10102
10104{
10105
10106 TLatex text;
10107 text.SetTextFont(((int)gStyle->GetTextFont()/10)*10+2); // font precision must be 2
10108 text.SetTextColor(fH->GetMarkerColor());
10109 text.SetTextSize(0.02*fH->GetMarkerSize());
10110
10111 Double_t x, y, z, e, angle = 0;
10112 TString tt, tf;
10113 tf.Form("%s%s","%",gStyle->GetPaintTextFormat());
10114 if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
10115
10116 // 1D histograms
10117 if (fH->GetDimension() == 1) {
10119 Double_t yt;
10120 TProfile *hp = (TProfile*)fH;
10121 if (Hoption.Text>2000 && fH->InheritsFrom(TProfile::Class())) {
10122 Hoption.Text = Hoption.Text-2000;
10123 getentries = kTRUE;
10124 }
10125 if (Hoption.Text == 1) angle = 90;
10126 text.SetTextAlign(11);
10127 if (angle == 90) text.SetTextAlign(12);
10128 if (angle == 0) text.SetTextAlign(21);
10129 text.TAttText::Modify();
10130 Double_t dt = 0.02*(gPad->GetY2()-gPad->GetY1());
10131 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10132 if (Hoption.Bar) {
10133 x = fH->GetXaxis()->GetBinLowEdge(i)+
10134 fH->GetXaxis()->GetBinWidth(i)*
10135 (fH->GetBarOffset()+0.5*fH->GetBarWidth());
10136 } else {
10137 x = fH->GetXaxis()->GetBinCenter(i);
10138 }
10139 y = fH->GetBinContent(i);
10140 yt = y;
10141 if (Hoption.MinimumZero && y<0) y = 0;
10142 if (getentries) yt = hp->GetBinEntries(i);
10143 if (yt == 0.) continue;
10144 tt.Form(tf.Data(),yt);
10145 if (Hoption.Logx) {
10146 if (x > 0) x = TMath::Log10(x);
10147 else continue;
10148 }
10149 if (Hoption.Logy) {
10150 if (y > 0) y = TMath::Log10(y);
10151 else continue;
10152 }
10153 if (y >= gPad->GetY2()) continue;
10154 if (y <= gPad->GetY1()) continue;
10155 text.PaintLatex(x,y+0.2*dt,angle,0.02*fH->GetMarkerSize(),tt.Data());
10156 }
10157
10158 // 2D histograms
10159 } else {
10160 Double_t zmin = Hparam.zmin;
10161 if (Hoption.Logz) zmin = TMath::Power(10,Hparam.zmin);
10162
10163 text.SetTextAlign(22);
10164 if (Hoption.Text == 1) angle = 0;
10165 text.SetTextAngle(angle);
10166 text.TAttText::Modify();
10167 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
10168 y = fYaxis->GetBinCenter(j);
10169 if (Hoption.Logy) {
10170 if (y > 0) y = TMath::Log10(y);
10171 else continue;
10172 }
10173 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10174 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
10175 x = fXaxis->GetBinCenter(i);
10176 if (Hoption.Logx) {
10177 if (x > 0) x = TMath::Log10(x);
10178 else continue;
10179 }
10180 if (!IsInside(x,y)) continue;
10181 z = fH->GetBinContent(bin);
10182 if (z < zmin || (z == 0 && !Hoption.MinimumZero)) continue;
10183 if (Hoption.Text>2000) {
10184 e = fH->GetBinError(bin);
10185 tf.Form("#splitline{%s%s}{#pm %s%s}",
10187 "%",gStyle->GetPaintTextFormat());
10188 tt.Form(tf.Data(),z,e);
10189 } else {
10190 tt.Form(tf.Data(),z);
10191 }
10192 text.PaintLatex(x,y+fH->GetBarOffset()*fYaxis->GetBinWidth(j),
10193 angle,0.02*fH->GetMarkerSize(),tt.Data());
10194 }
10195 }
10196 }
10197}
10198
10199////////////////////////////////////////////////////////////////////////////////
10200/// [Control function to draw a 3D implicit functions.](\ref HP27)
10201
10203{
10204
10205 Int_t irep;
10206
10207 TAxis *xaxis = fH->GetXaxis();
10208 TAxis *yaxis = fH->GetYaxis();
10209 TAxis *zaxis = fH->GetZaxis();
10210
10211 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
10212 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
10213 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
10214 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
10215 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
10216 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
10217
10218 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
10219
10220 TView *view = gPad ? gPad->GetView() : nullptr;
10221 if (!view) {
10222 Error("PaintTF3", "no TView in current pad");
10223 return;
10224 }
10225 Double_t thedeg = 90 - gPad->GetTheta();
10226 Double_t phideg = -90 - gPad->GetPhi();
10227 Double_t psideg = view->GetPsi();
10228 view->SetView(phideg, thedeg, psideg, irep);
10229
10230 fLego->InitMoveScreen(-1.1,1.1);
10231
10232 if (Hoption.BackBox) {
10233 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
10235 fLego->BackBox(90);
10236 }
10237
10239
10240 fLego->ImplicitFunction(fCurrentF3, fXbuf.data(), fYbuf.data(), fH->GetNbinsX(),
10241 fH->GetNbinsY(),
10242 fH->GetNbinsZ(), "BF");
10243
10244 if (Hoption.FrontBox) {
10245 fLego->InitMoveScreen(-1.1,1.1);
10247 fLego->FrontBox(90);
10248 }
10249 if (!Hoption.Axis && !Hoption.Same) {
10250 TGaxis axis;
10251 PaintLegoAxis(&axis, 90);
10252 }
10253
10254 PaintTitle();
10255
10256 fLego.reset();
10257}
10258
10259/////////////////////////////////////////////////////////////new TGaxis///////////////////
10260/// Draw the histogram title
10261///
10262/// The title is drawn according to the title alignment returned by
10263/// `GetTitleAlign()`. It is a 2 digits integer): hv
10264///
10265/// where `h` is the horizontal alignment and `v` is the
10266/// vertical alignment.
10267///
10268/// - `h` can get the values 1 2 3 for left, center, and right
10269/// - `v` can get the values 1 2 3 for bottom, middle and top
10270///
10271/// for instance the default alignment is: 13 (left top)
10272
10274{
10275 // probably best place for calls PaintHighlightBin
10276 // calls after paint histo (1D or 2D) and before paint title and stats
10277 if (!gPad->GetView()) PaintHighlightBin();
10278
10279 if (Hoption.Same) return;
10280 if (fH->TestBit(TH1::kNoTitle)) return;
10281 Int_t nt = strlen(fH->GetTitle());
10282 TPaveText *title = nullptr;
10283 TObject *obj;
10284 TIter next(gPad->GetListOfPrimitives());
10285 while ((obj = next())) {
10286 if (!obj->InheritsFrom(TPaveText::Class())) continue;
10287 title = (TPaveText*)obj;
10288 if (strcmp(title->GetName(),"title")) {title = nullptr; continue;}
10289 break;
10290 }
10291 if (nt == 0 || gStyle->GetOptTitle() <= 0) {
10292 if (title) delete title;
10293 return;
10294 }
10297
10298 if (ht <= 0) {
10299 if (gStyle->GetTitleFont("")%10 == 3) {
10300 Double_t hw = TMath::Max((Double_t)gPad->XtoPixel(gPad->GetX2()),
10301 (Double_t)gPad->YtoPixel(gPad->GetY1()));
10302 ht = 1.1*(gStyle->GetTitleSize("")/hw);
10303 } else {
10304 ht = 1.1*gStyle->GetTitleFontSize();
10305 }
10306 }
10307 if (ht <= 0) ht = 0.05;
10308 if (wt <= 0) {
10309 TLatex l;
10310 l.SetTextSize(ht);
10311 l.SetTitle(fH->GetTitle());
10312 // adjustment in case the title has several lines (#splitline)
10313 ht = TMath::Max(ht, 1.2*l.GetYsize()/(gPad->GetY2() - gPad->GetY1()));
10314 Double_t wndc = l.GetXsize()/(gPad->GetX2() - gPad->GetX1());
10315 wt = TMath::Min(0.7, 0.02+wndc);
10316 }
10317 if (title) {
10318 TText *t0 = (TText*)title->GetLine(0);
10319 if (t0) {
10320 if (!strcmp(t0->GetTitle(),fH->GetTitle())) return;
10321 t0->SetTitle(fH->GetTitle());
10322 if (wt > 0) title->SetX2NDC(title->GetX1NDC()+wt);
10323 }
10324 return;
10325 }
10326
10328 if (talh < 1) talh = 1; else if (talh > 3) talh = 3;
10330 if (talv < 1) talv = 1; else if (talv > 3) talv = 3;
10332 xpos = gStyle->GetTitleX();
10333 ypos = gStyle->GetTitleY();
10334 if (talh == 2) xpos = xpos-wt/2.;
10335 if (talh == 3) xpos = xpos-wt;
10336 if (talv == 2) ypos = ypos+ht/2.;
10337 if (talv == 1) ypos = ypos+ht;
10338
10339 TPaveText *ptitle = new TPaveText(xpos, ypos-ht, xpos+wt, ypos,"blNDC");
10340
10341 // box with the histogram title
10342 ptitle->SetFillColor(gStyle->GetTitleFillColor());
10343 ptitle->SetFillStyle(gStyle->GetTitleStyle());
10344 ptitle->SetName("title");
10345 ptitle->SetBorderSize(gStyle->GetTitleBorderSize());
10346 ptitle->SetTextColor(gStyle->GetTitleTextColor());
10347 ptitle->SetTextFont(gStyle->GetTitleFont(""));
10348 if (gStyle->GetTitleFont("")%10 > 2)
10349 ptitle->SetTextSize(gStyle->GetTitleFontSize());
10350 ptitle->AddText(fH->GetTitle());
10351 ptitle->SetBit(kCanDelete);
10352 ptitle->Draw();
10353 ptitle->Paint("blNDC");
10354
10355 if(!gPad->IsEditable()) delete ptitle;
10356}
10357
10358////////////////////////////////////////////////////////////////////////////////
10359/// Process message `mess`.
10360
10361void THistPainter::ProcessMessage(const char *mess, const TObject *obj)
10362{
10363 if (!strcmp(mess,"SetF3")) {
10364 fCurrentF3 = (TF3 *)obj;
10365 }
10366}
10367
10368////////////////////////////////////////////////////////////////////////////////
10369/// Static function.
10370///
10371/// Convert Right Ascension, Declination to X,Y using an AITOFF projection.
10372/// This procedure can be used to create an all-sky map in Galactic
10373/// coordinates with an equal-area Aitoff projection. Output map
10374/// coordinates are zero longitude centered.
10375/// Also called Hammer-Aitoff projection (first presented by Ernst von Hammer in 1892)
10376///
10377/// source: GMT
10378///
10379/// code from Ernst-Jan Buis
10380
10382{
10383
10384 Double_t x, y;
10385
10387 Double_t delta = b*TMath::DegToRad();
10388 Double_t r2 = TMath::Sqrt(2.);
10389 Double_t f = 2*r2/TMath::Pi();
10390 Double_t cdec = TMath::Cos(delta);
10393 y = TMath::Sin(delta)*r2/denom;
10394 x *= TMath::RadToDeg()/f;
10395 y *= TMath::RadToDeg()/f;
10396 // x *= -1.; // for a skymap swap left<->right
10397 Al = x;
10398 Ab = y;
10399
10400 return 0;
10401}
10402
10403////////////////////////////////////////////////////////////////////////////////
10404/// Static function
10405///
10406/// Probably the most famous of the various map projections, the Mercator projection
10407/// takes its name from Mercator who presented it in 1569. It is a cylindrical, conformal projection
10408/// with no distortion along the equator.
10409/// The Mercator projection has been used extensively for world maps in which the distortion towards
10410/// the polar regions grows rather large, thus incorrectly giving the impression that, for example,
10411/// Greenland is larger than South America. In reality, the latter is about eight times the size of
10412/// Greenland. Also, the Former Soviet Union looks much bigger than Africa or South America. One may wonder
10413/// whether this illusion has had any influence on U.S. foreign policy.' (Source: GMT)
10414/// code from Ernst-Jan Buis
10415
10417{
10418
10419 Al = l;
10421 Ab = TMath::Log(aid);
10422 return 0;
10423}
10424
10425////////////////////////////////////////////////////////////////////////////////
10426/// Static function code for sinusoidal projection
10427/// from Ernst-Jan Buis
10428/// Source https://en.wikipedia.org/wiki/Sinusoidal_projection
10429
10431{
10432
10433 Al = l*cos(b*TMath::DegToRad());
10434 Ab = b;
10435 return 0;
10436}
10437
10438////////////////////////////////////////////////////////////////////////////////
10439/// Static function code for parabolic projection
10440/// from Ernst-Jan Buis
10441
10443{
10444
10445 Al = l*(2.*TMath::Cos(2*b*TMath::DegToRad()/3) - 1);
10446 Ab = 180*TMath::Sin(b*TMath::DegToRad()/3);
10447 return 0;
10448}
10449
10450////////////////////////////////////////////////////////////////////////////////
10451/// Static function.
10452///
10453/// Convert Right Ascension, Declination to X,Y using an MOLLWEIDE projection.
10454/// This procedure can be used to create an all-sky map in Galactic
10455/// coordinates with an equal-area Mollweide projection. Output map
10456/// coordinates are zero longitude centered.
10457/// It is also known as the Babinet projection, homalographic projection, homolographic projection, and elliptical projection.
10458/// Source: https://en.wikipedia.org/wiki/Mollweide_projection
10459///
10460/// code from Marco Meyer-Conde
10461
10463{
10464
10465 Double_t theta0 = b * TMath::DegToRad(), theta = theta0;
10466
10467 for (int i = 0; i < 100; i++) {
10468 Double_t num = 2 * theta + TMath::Sin(2 * theta) - TMath::Pi() * TMath::Sin(theta0);
10469 Double_t den = 4 * TMath::Power(TMath::Cos(theta), 2);
10470
10471 if (den < 1e-20) {
10472 theta = theta0;
10473 break;
10474 }
10475
10476 theta -= num / den;
10477
10478 if (TMath::Abs(num / den) < 1e-4) break;
10479 }
10480
10481 Al = l * TMath::Cos(theta);
10482 Ab = 90 * TMath::Sin(theta);
10483
10484 return 0;
10485}
10486
10487////////////////////////////////////////////////////////////////////////////////
10488/// Recompute the histogram range following graphics operations.
10489
10491{
10492
10493 if (Hoption.Same) return;
10494
10495 // Compute x,y range
10497 xmax = Hparam.xmax,
10498 ymin = Hparam.ymin,
10499 ymax = Hparam.ymax,
10500 xscale = 1;
10501
10502 std::function<Int_t(Double_t,Double_t,Double_t&,Double_t&)> func;
10503
10504 if (Hoption.Proj == 1) {
10505 func = ProjectAitoff2xy;
10506 xscale = 0.9999;
10507 } else if (Hoption.Proj == 2) {
10508 if (Hparam.ymin <= -90 || Hparam.ymax >= 90) {
10509 Warning("Mercator Projection", "Latitude out of range %f or %f", Hparam.ymin, Hparam.ymax);
10510 Hoption.Proj = 0;
10511 } else {
10514 }
10515 } else if (Hoption.Proj == 3) {
10516 func = ProjectSinusoidal2xy;
10517 } else if (Hoption.Proj == 4) {
10518 func = ProjectParabolic2xy;
10519 } else if (Hoption.Proj == 5) {
10520 func = ProjectMollweide2xy;
10521 }
10522
10523 if (func) {
10525
10529 func(Hparam.xmax, Hparam.ymin, xmax, ymin);
10530
10531 if (xmin > xmin_aid) xmin = xmin_aid;
10532 if (ymin > ymin_aid) ymin = ymin_aid;
10533 if (xmax < xmax_aid) xmax = xmax_aid;
10534 if (ymax < ymax_aid) ymax = ymax_aid;
10535 if (Hparam.ymin < 0 && Hparam.ymax > 0) {
10536 // there is an 'equator', check its range in the plot..
10537 func(Hparam.xmin*xscale, 0, xmin_aid, ymin_aid);
10538 func(Hparam.xmax*xscale, 0, xmax_aid, ymin_aid);
10539 if (xmin > xmin_aid) xmin = xmin_aid;
10540 if (xmax < xmax_aid) xmax = xmax_aid;
10541 }
10542 if (Hparam.xmin < 0 && Hparam.xmax > 0) {
10543 func(0, Hparam.ymin, xmin_aid, ymin_aid);
10544 func(0, Hparam.ymax, xmax_aid, ymax_aid);
10545 if (ymin > ymin_aid) ymin = ymin_aid;
10546 if (ymax < ymax_aid) ymax = ymax_aid;
10547 }
10548 }
10549
10550 Hparam.xmin = xmin;
10551 Hparam.xmax = xmax;
10552 Hparam.ymin = ymin;
10553 Hparam.ymax = ymax;
10554
10555 Double_t dx = xmax-xmin;
10556 Double_t dy = ymax-ymin;
10557 Double_t dxr = dx/(1 - gPad->GetLeftMargin() - gPad->GetRightMargin());
10558 Double_t dyr = dy/(1 - gPad->GetBottomMargin() - gPad->GetTopMargin());
10559
10560 // Range() could change the size of the pad pixmap and therefore should
10561 // be called before the other paint routines
10562 gPad->Range(xmin - dxr*gPad->GetLeftMargin(),
10563 ymin - dyr*gPad->GetBottomMargin(),
10564 xmax + dxr*gPad->GetRightMargin(),
10565 ymax + dyr*gPad->GetTopMargin());
10566 gPad->RangeAxis(xmin, ymin, xmax, ymax);
10567}
10568
10569////////////////////////////////////////////////////////////////////////////////
10570/// Set current histogram to `h`
10571
10573{
10574
10575 if (h == nullptr) return;
10576 fH = h;
10577 fXaxis = h->GetXaxis();
10578 fYaxis = h->GetYaxis();
10579 fZaxis = h->GetZaxis();
10581}
10582
10583////////////////////////////////////////////////////////////////////////////////
10584/// Initialize various options to draw 2D histograms.
10585
10587{
10588
10589 static const char *where = "TableInit";
10590
10591 Int_t first, last;
10593 Double_t zmin, zmax;
10594 Int_t maximum = 0;
10595 Int_t minimum = 0;
10596 if (fH->GetMaximumStored() != -1111) maximum = 1;
10597 if (fH->GetMinimumStored() != -1111) minimum = 1;
10598
10599 // ----------------- Compute X axis parameters
10600 first = fXaxis->GetFirst();
10601 last = fXaxis->GetLast();
10602 Hparam.xlast = last;
10603 Hparam.xfirst = first;
10608
10609 // if log scale in X, replace xmin,max by the log
10610 if (Hoption.Logx) {
10611 // find the first edge of a bin that is > 0
10612 if (Hparam.xlowedge <=0 ) {
10615 }
10616 if (Hparam.xmin <=0 || Hparam.xmax <=0) {
10617 Error(where, "cannot set X axis to log scale");
10618 return 0;
10619 }
10621 if (Hparam.xfirst < first) Hparam.xfirst = first;
10623 if (Hparam.xlast > last) Hparam.xlast = last;
10626 }
10627
10628 // ----------------- Compute Y axis parameters
10629 first = fYaxis->GetFirst();
10630 last = fYaxis->GetLast();
10631 Hparam.ylast = last;
10632 Hparam.yfirst = first;
10635 if (!Hparam.ybinsize) Hparam.ybinsize = 1;
10638
10639 // if log scale in Y, replace ymin,max by the log
10640 if (Hoption.Logy) {
10641 if (Hparam.ylowedge <=0 ) {
10644 }
10645 if (Hparam.ymin <=0 || Hparam.ymax <=0) {
10646 Error(where, "cannot set Y axis to log scale");
10647 return 0;
10648 }
10650 if (Hparam.yfirst < first) Hparam.yfirst = first;
10652 if (Hparam.ylast > last) Hparam.ylast = last;
10655 }
10656
10657
10658 // ----------------- Compute Z axis parameters
10659 Double_t bigp = TMath::Power(10,32);
10660 zmax = -bigp;
10661 zmin = bigp;
10662 Double_t c1, e1;
10663 Double_t allchan = 0;
10664 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
10665 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10666 c1 = fH->GetBinContent(i,j);
10667 zmax = TMath::Max(zmax,c1);
10668 if (Hoption.Error) {
10669 e1 = fH->GetBinError(i,j);
10670 zmax = TMath::Max(zmax,c1+e1);
10671 }
10672 zmin = TMath::Min(zmin,c1);
10673 allchan += c1;
10674 }
10675 }
10676
10677 // Take into account maximum , minimum
10678
10679 if (maximum) zmax = fH->GetMaximumStored();
10680 if (minimum) zmin = fH->GetMinimumStored();
10681 if (Hoption.Logz && zmax < 0) {
10682 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10683 return 0;
10684 } else if (Hoption.Logz && zmin>=0 && zmax==0) { // empty histogram in log scale
10685 zmin = 0.01;
10686 zmax = 10.;
10687 }
10688 if (zmin >= zmax) {
10689 if (Hoption.Logz) {
10690 if (zmax > 0) zmin = 0.001*zmax;
10691 else {
10692 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10693 return 0;
10694 }
10695 }
10696 }
10697
10698 // take into account normalization factor
10699 Hparam.allchan = allchan;
10700 Double_t factor = allchan;
10701 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
10702 if (allchan) factor /= allchan;
10703 if (factor == 0) factor = 1;
10704 Hparam.factor = factor;
10705 zmax = factor*zmax;
10706 zmin = factor*zmin;
10707 c1 = zmax;
10708 if (TMath::Abs(zmin) > TMath::Abs(c1)) c1 = zmin;
10709
10710 // For log scales, histogram coordinates are log10(ymin) and
10711 // log10(ymax). Final adjustment (if not option "Same")
10712 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
10713 // Maximum and Minimum are not defined.
10714 if (Hoption.Logz) {
10715 if (zmin <= 0) {
10716 zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
10717 fH->SetMinimum(zmin);
10718 }
10719 zmin = TMath::Log10(zmin);
10720 if (!minimum) zmin += TMath::Log10(0.5);
10721 zmax = TMath::Log10(zmax);
10722 if (!maximum) zmax += TMath::Log10(2*(0.9/0.95));
10723 goto LZMIN;
10724 }
10725
10726 // final adjustment of YMAXI for linear scale (if not option "Same"):
10727 // decrease histogram height to MAX% of allowed height if HMAXIM
10728 // has not been called.
10729 // MAX% is the value in percent which has been set in HPLSET
10730 // (default is 90%).
10731 if (!maximum) {
10732 zmax += yMARGIN*(zmax-zmin);
10733 }
10734
10735 // final adjustment of ymin for linear scale.
10736 // if minimum is not set , then ymin is set to zero if >0
10737 // or to ymin - yMARGIN if <0.
10738 if (!minimum) {
10739 if (Hoption.MinimumZero) {
10740 if (zmin >= 0) zmin = 0;
10741 else zmin -= yMARGIN*(zmax-zmin);
10742 } else {
10743 Double_t dzmin = yMARGIN*(zmax-zmin);
10744 if (zmin >= 0 && (zmin-dzmin <= 0)) zmin = 0;
10745 else zmin -= dzmin;
10746 }
10747 }
10748
10749LZMIN:
10750 Hparam.zmin = zmin;
10751 Hparam.zmax = zmax;
10752
10753 // Set bar offset and width
10756
10757 return 1;
10758}
10759
10760////////////////////////////////////////////////////////////////////////////////
10761/// This function returns the best format to print the error value (e)
10762/// knowing the parameter value (v) and the format (f) used to print it.
10763
10765{
10766
10767 static TString ef;
10768 TString tf, tv;
10769
10770 // print v with the format f in tv.
10771 tf.Form("%s%s","%",f);
10772 tv.Form(tf.Data(),v);
10773
10774 // Analyse tv.
10775 int ie = tv.Index("e");
10776 int iE = tv.Index("E");
10777 int id = tv.Index(".");
10778
10779 // v has been printed with the exponent notation.
10780 // There is 2 cases, the exponent is positive or negative
10781 if (ie >= 0 || iE >= 0) {
10782 if (tv.Index("+") >= 0) {
10783 if (e < 1) {
10784 ef.Form("%s.1f","%");
10785 } else {
10786 if (ie >= 0) {
10787 ef.Form("%s.%de","%",ie-id-1);
10788 } else {
10789 ef.Form("%s.%dE","%",iE-id-1);
10790 }
10791 }
10792 } else {
10793 if (ie >= 0) {
10794 ef.Form("%s.%de","%",ie-id-1);
10795 } else {
10796 ef.Form("%s.%dE","%",iE-id-1);
10797 }
10798 }
10799
10800 // There is not '.' in tv. e will be printed with one decimal digit.
10801 } else if (id < 0) {
10802 ef.Form("%s.1f","%");
10803
10804 // There is a '.' in tv and no exponent notation. e's decimal part will
10805 // have the same number of digits as v's one.
10806 } else {
10807 ef.Form("%s.%df","%",tv.Length()-id-1);
10808 }
10809
10810 return ef.Data();
10811}
10812
10813////////////////////////////////////////////////////////////////////////////////
10814/// Set projection.
10815
10817{
10818 if (fShowProjection2) {
10819 auto name2 = TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2);
10820 auto c2 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name2.Data()));
10821 if (c2) c2->Close();
10822 fShowProjection2 = 0;
10823 }
10824 if (fShowProjection) {
10825 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10826 auto c1 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name1.Data()));
10827 if (c1) c1->Close();
10828 fShowProjection = 0;
10829 }
10830
10831 if (nbins <= 0) return;
10832
10833 TString opt = option;
10834 opt.ToLower();
10835 Int_t projection = 0;
10836 if (opt.Contains("x")) projection = 1;
10837 if (opt.Contains("y")) projection = 2;
10838 if (opt.Contains("z")) projection = 3;
10839 if (opt.Contains("xy")) projection = 4;
10840 if (opt.Contains("yx")) projection = 5;
10841 if (opt.Contains("xz")) projection = 6;
10842 if (opt.Contains("zx")) projection = 7;
10843 if (opt.Contains("yz")) projection = 8;
10844 if (opt.Contains("zy")) projection = 9;
10845 if (projection < 4) fShowOption = option+1;
10846 else fShowOption = option+2;
10847 fShowProjection = projection+100*nbins;
10848 fShowProjection2 = 0;
10849 gROOT->MakeDefCanvas();
10850 gPad->SetName(TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection).Data());
10851 gPad->SetGrid();
10852}
10853
10855{
10856 if (fShowProjection2) {
10857 auto name2 = TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2);
10858 auto c2 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name2.Data()));
10859 if (c2) c2->Close();
10860 fShowProjection2 = 0;
10861 }
10862 if (fShowProjection) {
10863 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10864 auto c1 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name1.Data()));
10865 if (c1) c1->Close();
10866 fShowProjection = 0;
10867 }
10868
10869 if ((nbinsX <= 0) || (nbinsY <= 0)) return;
10870
10871
10872 TString opt = option;
10873 opt.ToLower();
10874 Int_t projection = 0;
10875 if (opt.Contains("x")) projection = 1;
10876 if (opt.Contains("y")) projection = 2;
10877 if (opt.Contains("z")) projection = 3;
10878 if (opt.Contains("xy")) projection = 4;
10879 if (opt.Contains("yx")) projection = 5;
10880 if (opt.Contains("xz")) projection = 6;
10881 if (opt.Contains("zx")) projection = 7;
10882 if (opt.Contains("yz")) projection = 8;
10883 if (opt.Contains("zy")) projection = 9;
10884 if (projection < 4) fShowOption = option+1;
10885 else fShowOption = option+2;
10888 gROOT->MakeDefCanvas();
10889 gPad->SetName(TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection).Data());
10890 gPad->SetGrid();
10891 gROOT->MakeDefCanvas();
10892 gPad->SetName(TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2).Data());
10893 gPad->SetGrid();
10894}
10895
10896
10897////////////////////////////////////////////////////////////////////////////////
10898/// Show projection onto X.
10899
10901{
10902
10903 Int_t nbins = (Int_t)fShowProjection/100;
10904 gPad->SetDoubleBuffer(0); // turn off double buffer mode
10905 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
10906
10907 // Erase old position and draw a line at current position
10908 static int pyold1 = 0;
10909 static int pyold2 = 0;
10910 float uxmin = gPad->GetUxmin();
10911 float uxmax = gPad->GetUxmax();
10912 int pxmin = gPad->XtoAbsPixel(uxmin);
10913 int pxmax = gPad->XtoAbsPixel(uxmax);
10914 Float_t upy = gPad->AbsPixeltoY(py);
10915 Float_t y = gPad->PadtoY(upy);
10916 Int_t biny1 = fH->GetYaxis()->FindBin(y);
10917 Int_t biny2 = TMath::Min(biny1+nbins-1, fH->GetYaxis()->GetNbins());
10918 Int_t py1 = gPad->YtoAbsPixel(gPad->GetLogy() ? TMath::Log10(fH->GetYaxis()->GetBinLowEdge(biny1)) : fH->GetYaxis()->GetBinLowEdge(biny1));
10919 Int_t py2 = gPad->YtoAbsPixel(gPad->GetLogy() ? TMath::Log10(fH->GetYaxis()->GetBinUpEdge(biny2)) : fH->GetYaxis()->GetBinUpEdge(biny2));
10920
10922 gVirtualX->DrawBox(pxmin,py1,pxmax,py2,TVirtualX::kFilled);
10923 pyold1 = py1;
10924 pyold2 = py2;
10925
10926 // Create or set the new canvas proj x
10928 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10929 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(name1.Data());
10930 if (c) {
10931 c->Clear();
10932 } else {
10933 fShowProjection = 0;
10934 fShowProjection2 = 0;
10935 pyold1 = 0;
10936 pyold2 = 0;
10937 return;
10938 }
10939 c->cd();
10940 c->SetLogy(ctxt.GetSaved()->GetLogz());
10941 c->SetLogx(ctxt.GetSaved()->GetLogx());
10942
10943 // Draw slice corresponding to mouse position
10944 TString prjName = TString::Format("slice_px_of_%s",fH->GetName());
10945 TH1D *hp = ((TH2*)fH)->ProjectionX(prjName, biny1, biny2);
10946 if (hp) {
10947 hp->SetFillColor(38);
10948 // apply a patch from Oliver Freyermuth to set the title in the projection
10949 // using the range of the projected Y values
10950 if (biny1 == biny2) {
10953 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
10955 if (fH->GetYaxis()->GetLabels() != nullptr) {
10956 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf] %s", biny1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetYaxis()->GetBinLabel(biny1)));
10957 } else {
10958 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf]", biny1, valuePrecision, valueFrom, valuePrecision, valueTo));
10959 }
10960 } else {
10963 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
10964 // biny1 is used here to get equal precision no matter how large the binrange is,
10965 // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
10967 if (fH->GetYaxis()->GetLabels() != nullptr) {
10968 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)));
10969 } else {
10970 hp->SetTitle(TString::Format("ProjectionX of biny=[%d,%d] [y=%.*lf..%.*lf]", biny1, biny2, valuePrecision, valueFrom, valuePrecision, valueTo));
10971 }
10972 }
10973 hp->SetXTitle(fH->GetXaxis()->GetTitle());
10974 hp->SetYTitle(((TH2*)fH)->GetZaxis()->GetTitle() ? ((TH2*)fH)->GetZaxis()->GetTitle() : "Number of Entries");
10975 hp->Draw();
10976 c->Update();
10977 }
10978}
10979
10980////////////////////////////////////////////////////////////////////////////////
10981/// Show projection onto Y.
10982
10984{
10985
10986 Int_t nbins = (Int_t)fShowProjection/100;
10987 if (fShowProjection2)
10988 nbins = (Int_t)fShowProjection2/100;
10989 gPad->SetDoubleBuffer(0); // turn off double buffer mode
10990 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
10991
10992 // Erase old position and draw a line at current position
10993 static int pxold1 = 0;
10994 static int pxold2 = 0;
10995 float uymin = gPad->GetUymin();
10996 float uymax = gPad->GetUymax();
10997 int pymin = gPad->YtoAbsPixel(uymin);
10998 int pymax = gPad->YtoAbsPixel(uymax);
10999 Float_t upx = gPad->AbsPixeltoX(px);
11000 Float_t x = gPad->PadtoX(upx);
11001 Int_t binx1 = fH->GetXaxis()->FindBin(x);
11002 Int_t binx2 = TMath::Min(binx1+nbins-1, fH->GetXaxis()->GetNbins());
11003 Int_t px1 = gPad->XtoAbsPixel(gPad->GetLogx() ? TMath::Log10(fH->GetXaxis()->GetBinLowEdge(binx1)) : fH->GetXaxis()->GetBinLowEdge(binx1));
11004 Int_t px2 = gPad->XtoAbsPixel(gPad->GetLogx() ? TMath::Log10(fH->GetXaxis()->GetBinUpEdge(binx2)) : fH->GetXaxis()->GetBinUpEdge(binx2));
11005
11007 gVirtualX->DrawBox(px1,pymin,px2,pymax,TVirtualX::kFilled);
11008 pxold1 = px1;
11009 pxold2 = px2;
11010
11011 // Create or set the new canvas proj y
11013
11014 TString name2 = fShowProjection2 ? TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2)
11015 : TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
11016
11017 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(name2.Data());
11018 if (c) {
11019 c->Clear();
11020 } else {
11021 fShowProjection = 0;
11022 fShowProjection2 = 0;
11023 pxold1 = 0;
11024 pxold2 = 0;
11025 return;
11026 }
11027 c->cd();
11028 c->SetLogy(ctxt.GetSaved()->GetLogz());
11029 c->SetLogx(ctxt.GetSaved()->GetLogy());
11030
11031 // Draw slice corresponding to mouse position
11032 TString prjName = TString::Format("slice_py_of_%s",fH->GetName());
11033 TH1D *hp = ((TH2*)fH)->ProjectionY(prjName, binx1, binx2);
11034 if (hp) {
11035 hp->SetFillColor(38);
11036 // apply a patch from Oliver Freyermuth to set the title in the projection
11037 // using the range of the projected X values
11038 if (binx1 == binx2) {
11041 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11043 if (fH->GetXaxis()->GetLabels() != nullptr) {
11044 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf] [%s]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetXaxis()->GetBinLabel(binx1)));
11045 } else {
11046 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo));
11047 }
11048 } else {
11051 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11052 // binx1 is used here to get equal precision no matter how large the binrange is,
11053 // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
11055 if (fH->GetXaxis()->GetLabels() != nullptr) {
11056 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)));
11057 } else {
11058 hp->SetTitle(TString::Format("ProjectionY of binx=[%d,%d] [x=%.*lf..%.*lf]", binx1, binx2, valuePrecision, valueFrom, valuePrecision, valueTo));
11059 }
11060 }
11061 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11062 hp->SetYTitle(((TH2*)fH)->GetZaxis()->GetTitle() ? ((TH2*)fH)->GetZaxis()->GetTitle() : "Number of Entries");
11063 hp->Draw(fShowProjection2 ? "hbar" : "");
11064 c->Update();
11065 }
11066}
11067
11068////////////////////////////////////////////////////////////////////////////////
11069/// Show projection (specified by `fShowProjection`) of a `TH3`.
11070/// The drawing option for the projection is in `fShowOption`.
11071///
11072/// First implementation; R.Brun
11073///
11074/// Full implementation: Tim Tran (timtran@jlab.org) April 2006
11075
11077{
11078
11079 Int_t nbins=(Int_t)fShowProjection/100; //decode nbins
11080 if (fH->GetDimension() < 3) {
11081 if (fShowProjection2 % 100 == 1) {
11082 ShowProjectionY(px, py);
11083 }
11084 if (fShowProjection % 100 == 1) {
11085 ShowProjectionX(px, py);
11086 return;
11087 }
11088 if (fShowProjection % 100 == 2) {
11089 ShowProjectionY(px, py);
11090 return;
11091 }
11092 }
11093
11094 gPad->SetDoubleBuffer(0); // turn off double buffer mode
11095 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
11096
11097 // Erase old position and draw a line at current position
11098 TView *view = gPad->GetView();
11099 if (!view) return;
11100 TH3 *h3 = (TH3*)fH;
11101 TAxis *xaxis = h3->GetXaxis();
11102 TAxis *yaxis = h3->GetYaxis();
11103 TAxis *zaxis = h3->GetZaxis();
11104 Double_t u[3],xx[3];
11105
11106 static TPoint line1[2];//store end points of a line, initialised 0 by default
11107 static TPoint line2[2];// second line when slice thickness > 1 bin thickness
11108 static TPoint line3[2];
11109 static TPoint line4[2];
11110 static TPoint endface1[5];
11111 static TPoint endface2[5];
11112 static TPoint rect1[5];//store vertices of the polyline (rectangle), initialsed 0 by default
11113 static TPoint rect2[5];// second rectangle when slice thickness > 1 bin thickness
11114
11115 Double_t uxmin = gPad->GetUxmin();
11116 Double_t uxmax = gPad->GetUxmax();
11117 Double_t uymin = gPad->GetUymin();
11118 Double_t uymax = gPad->GetUymax();
11119
11120 int pxmin = gPad->XtoAbsPixel(uxmin);
11121 int pxmax = gPad->XtoAbsPixel(uxmax);
11122 if (pxmin==pxmax) return;
11123 int pymin = gPad->YtoAbsPixel(uymin);
11124 int pymax = gPad->YtoAbsPixel(uymax);
11125 if (pymin==pymax) return;
11128 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(TString::Format("c_%zx_projection_%d",
11129 (size_t)fH, fShowProjection).Data());
11130 if (!c) {
11131 fShowProjection = 0;
11132 return;
11133 }
11134
11136
11137 switch ((Int_t)fShowProjection%100) {
11138 case 1:
11139 // "x"
11140 {
11141 Int_t firstY = yaxis->GetFirst();
11142 Int_t lastY = yaxis->GetLast();
11144 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11145 yaxis->SetRange(biny,biny2);
11146 Int_t firstZ = zaxis->GetFirst();
11147 Int_t lastZ = zaxis->GetLast();
11149 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11150 zaxis->SetRange(binz,binz2);
11151 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11152 if (nbins>1 && line1[0].GetX()) {
11153 gVirtualX->DrawPolyLine(2,line2);
11154 gVirtualX->DrawPolyLine(2,line3);
11155 gVirtualX->DrawPolyLine(2,line4);
11156 gVirtualX->DrawPolyLine(5,endface1);
11157 gVirtualX->DrawPolyLine(5,endface2);
11158 }
11159 xx[0] = xaxis->GetXmin();
11160 xx[2] = zaxis->GetBinCenter(binz);
11161 xx[1] = yaxis->GetBinCenter(biny);
11162 view->WCtoNDC(xx,u);
11163 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11164 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11165 xx[0] = xaxis->GetXmax();
11166 view->WCtoNDC(xx,u);
11167 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11168 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11169 gVirtualX->DrawPolyLine(2,line1);
11170 if (nbins>1) {
11171 xx[0] = xaxis->GetXmin();
11172 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11173 xx[1] = yaxis->GetBinCenter(biny);
11174 view->WCtoNDC(xx,u);
11175 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11176 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11177 xx[0] = xaxis->GetXmax();
11178 view->WCtoNDC(xx,u);
11179 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11180 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11181
11182 xx[0] = xaxis->GetXmin();
11183 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11184 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11185 view->WCtoNDC(xx,u);
11186 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11187 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11188 xx[0] = xaxis->GetXmax();
11189 view->WCtoNDC(xx,u);
11190 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11191 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11192
11193 xx[0] = xaxis->GetXmin();
11194 xx[2] = zaxis->GetBinCenter(binz);
11195 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11196 view->WCtoNDC(xx,u);
11197 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11198 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11199 xx[0] = xaxis->GetXmax();
11200 view->WCtoNDC(xx,u);
11201 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11202 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11203
11204 endface1[0].SetX(line1[0].GetX());
11205 endface1[0].SetY(line1[0].GetY());
11206 endface1[1].SetX(line2[0].GetX());
11207 endface1[1].SetY(line2[0].GetY());
11208 endface1[2].SetX(line3[0].GetX());
11209 endface1[2].SetY(line3[0].GetY());
11210 endface1[3].SetX(line4[0].GetX());
11211 endface1[3].SetY(line4[0].GetY());
11212 endface1[4].SetX(line1[0].GetX());
11213 endface1[4].SetY(line1[0].GetY());
11214
11215 endface2[0].SetX(line1[1].GetX());
11216 endface2[0].SetY(line1[1].GetY());
11217 endface2[1].SetX(line2[1].GetX());
11218 endface2[1].SetY(line2[1].GetY());
11219 endface2[2].SetX(line3[1].GetX());
11220 endface2[2].SetY(line3[1].GetY());
11221 endface2[3].SetX(line4[1].GetX());
11222 endface2[3].SetY(line4[1].GetY());
11223 endface2[4].SetX(line1[1].GetX());
11224 endface2[4].SetY(line1[1].GetY());
11225
11226 gVirtualX->DrawPolyLine(2,line2);
11227 gVirtualX->DrawPolyLine(2,line3);
11228 gVirtualX->DrawPolyLine(2,line4);
11229 gVirtualX->DrawPolyLine(5,endface1);
11230 gVirtualX->DrawPolyLine(5,endface2);
11231 }
11232 c->Clear();
11233 c->cd();
11234 TH1 *hp = h3->Project3D("x");
11235 yaxis->SetRange(firstY,lastY);
11236 zaxis->SetRange(firstZ,lastZ);
11237 if (hp) {
11238 hp->SetFillColor(38);
11239 if (nbins == 1)
11240 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny),
11241 binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
11242 else {
11243 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),
11244 binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
11245 }
11246 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11247 hp->SetYTitle("Number of Entries");
11248 hp->Draw(fShowOption.Data());
11249 }
11250 }
11251 break;
11252
11253 case 2:
11254 // "y"
11255 {
11256 Int_t firstX = xaxis->GetFirst();
11257 Int_t lastX = xaxis->GetLast();
11259 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11260 xaxis->SetRange(binx,binx2);
11261 Int_t firstZ = zaxis->GetFirst();
11262 Int_t lastZ = zaxis->GetLast();
11264 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11265 zaxis->SetRange(binz,binz2);
11266 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11267 if (nbins>1 && line1[0].GetX()) {
11268 gVirtualX->DrawPolyLine(2,line2);
11269 gVirtualX->DrawPolyLine(2,line3);
11270 gVirtualX->DrawPolyLine(2,line4);
11271 gVirtualX->DrawPolyLine(5,endface1);
11272 gVirtualX->DrawPolyLine(5,endface2);
11273 }
11274 xx[0]=xaxis->GetBinCenter(binx);
11275 xx[2] = zaxis->GetBinCenter(binz);
11276 xx[1] = yaxis->GetXmin();
11277 view->WCtoNDC(xx,u);
11278 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11279 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11280 xx[1] = yaxis->GetXmax();
11281 view->WCtoNDC(xx,u);
11282 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11283 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11284 gVirtualX->DrawPolyLine(2,line1);
11285 if (nbins>1) {
11286 xx[1] = yaxis->GetXmin();
11287 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11288 xx[0] = xaxis->GetBinCenter(binx);
11289 view->WCtoNDC(xx,u);
11290 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11291 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11292 xx[1] = yaxis->GetXmax();
11293 view->WCtoNDC(xx,u);
11294 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11295 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11296
11297 xx[1] = yaxis->GetXmin();
11298 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11299 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11300 view->WCtoNDC(xx,u);
11301 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11302 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11303 xx[1] = yaxis->GetXmax();
11304 view->WCtoNDC(xx,u);
11305 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11306 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11307
11308 xx[1] = yaxis->GetXmin();
11309 xx[2] = zaxis->GetBinCenter(binz);
11310 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11311 view->WCtoNDC(xx,u);
11312 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11313 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11314 xx[1] = yaxis->GetXmax();
11315 view->WCtoNDC(xx,u);
11316 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11317 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11318
11319 endface1[0].SetX(line1[0].GetX());
11320 endface1[0].SetY(line1[0].GetY());
11321 endface1[1].SetX(line2[0].GetX());
11322 endface1[1].SetY(line2[0].GetY());
11323 endface1[2].SetX(line3[0].GetX());
11324 endface1[2].SetY(line3[0].GetY());
11325 endface1[3].SetX(line4[0].GetX());
11326 endface1[3].SetY(line4[0].GetY());
11327 endface1[4].SetX(line1[0].GetX());
11328 endface1[4].SetY(line1[0].GetY());
11329
11330 endface2[0].SetX(line1[1].GetX());
11331 endface2[0].SetY(line1[1].GetY());
11332 endface2[1].SetX(line2[1].GetX());
11333 endface2[1].SetY(line2[1].GetY());
11334 endface2[2].SetX(line3[1].GetX());
11335 endface2[2].SetY(line3[1].GetY());
11336 endface2[3].SetX(line4[1].GetX());
11337 endface2[3].SetY(line4[1].GetY());
11338 endface2[4].SetX(line1[1].GetX());
11339 endface2[4].SetY(line1[1].GetY());
11340
11341 gVirtualX->DrawPolyLine(2,line2);
11342 gVirtualX->DrawPolyLine(2,line3);
11343 gVirtualX->DrawPolyLine(2,line4);
11344 gVirtualX->DrawPolyLine(5,endface1);
11345 gVirtualX->DrawPolyLine(5,endface2);
11346 }
11347 c->Clear();
11348 c->cd();
11349 TH1 *hp = h3->Project3D("y");
11350 xaxis->SetRange(firstX,lastX);
11351 zaxis->SetRange(firstZ,lastZ);
11352 if (hp) {
11353 hp->SetFillColor(38);
11354 if (nbins == 1)
11355 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
11356 binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
11357 else
11358 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),
11359 binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
11360 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11361 hp->SetYTitle("Number of Entries");
11362 hp->Draw(fShowOption.Data());
11363 }
11364 }
11365 break;
11366
11367 case 3:
11368 // "z"
11369 {
11370 Int_t firstX = xaxis->GetFirst();
11371 Int_t lastX = xaxis->GetLast();
11373 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11374 xaxis->SetRange(binx,binx2);
11375 Int_t firstY = yaxis->GetFirst();
11376 Int_t lastY = yaxis->GetLast();
11378 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11379 yaxis->SetRange(biny,biny2);
11380 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11381 if (nbins>1 && line1[0].GetX()) {
11382 gVirtualX->DrawPolyLine(2,line2);
11383 gVirtualX->DrawPolyLine(2,line3);
11384 gVirtualX->DrawPolyLine(2,line4);
11385 gVirtualX->DrawPolyLine(5,endface1);
11386 gVirtualX->DrawPolyLine(5,endface2);
11387 }
11388 xx[0] = xaxis->GetBinCenter(binx);
11389 xx[1] = yaxis->GetBinCenter(biny);
11390 xx[2] = zaxis->GetXmin();
11391 view->WCtoNDC(xx,u);
11392 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11393 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11394 xx[2] = zaxis->GetXmax();
11395 view->WCtoNDC(xx,u);
11396 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11397 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11398 gVirtualX->DrawPolyLine(2,line1);
11399 if (nbins>1) {
11400 xx[2] = zaxis->GetXmin();
11401 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11402 xx[0] = xaxis->GetBinCenter(binx);
11403 view->WCtoNDC(xx,u);
11404 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11405 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11406 xx[2] = zaxis->GetXmax();
11407 view->WCtoNDC(xx,u);
11408 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11409 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11410
11411 xx[2] = zaxis->GetXmin();
11412 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11413 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11414 view->WCtoNDC(xx,u);
11415 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11416 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11417 xx[2] = zaxis->GetXmax();
11418 view->WCtoNDC(xx,u);
11419 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11420 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11421
11422 xx[2] = zaxis->GetXmin();
11423 xx[1] = yaxis->GetBinCenter(biny);
11424 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11425 view->WCtoNDC(xx,u);
11426 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11427 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11428 xx[2] = zaxis->GetXmax();
11429 view->WCtoNDC(xx,u);
11430 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11431 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11432
11433 endface1[0].SetX(line1[0].GetX());
11434 endface1[0].SetY(line1[0].GetY());
11435 endface1[1].SetX(line2[0].GetX());
11436 endface1[1].SetY(line2[0].GetY());
11437 endface1[2].SetX(line3[0].GetX());
11438 endface1[2].SetY(line3[0].GetY());
11439 endface1[3].SetX(line4[0].GetX());
11440 endface1[3].SetY(line4[0].GetY());
11441 endface1[4].SetX(line1[0].GetX());
11442 endface1[4].SetY(line1[0].GetY());
11443
11444 endface2[0].SetX(line1[1].GetX());
11445 endface2[0].SetY(line1[1].GetY());
11446 endface2[1].SetX(line2[1].GetX());
11447 endface2[1].SetY(line2[1].GetY());
11448 endface2[2].SetX(line3[1].GetX());
11449 endface2[2].SetY(line3[1].GetY());
11450 endface2[3].SetX(line4[1].GetX());
11451 endface2[3].SetY(line4[1].GetY());
11452 endface2[4].SetX(line1[1].GetX());
11453 endface2[4].SetY(line1[1].GetY());
11454
11455 gVirtualX->DrawPolyLine(2,line2);
11456 gVirtualX->DrawPolyLine(2,line3);
11457 gVirtualX->DrawPolyLine(2,line4);
11458 gVirtualX->DrawPolyLine(5,endface1);
11459 gVirtualX->DrawPolyLine(5,endface2);
11460 }
11461 c->Clear();
11462 c->cd();
11463 TH1 *hp = h3->Project3D("z");
11464 xaxis->SetRange(firstX,lastX);
11465 yaxis->SetRange(firstY,lastY);
11466 if (hp) {
11467 hp->SetFillColor(38);
11468 if (nbins == 1)
11469 hp->SetTitle(TString::Format("ProjectionZ of binx=%d [x=%.1f..%.1f] biny=%d [y=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
11470 biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny)));
11471 else
11472 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),
11473 biny, biny2, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny2) ) );
11474 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11475 hp->SetYTitle("Number of Entries");
11476 hp->Draw(fShowOption.Data());
11477 }
11478 }
11479 break;
11480
11481 case 4:
11482 // "xy"
11483 {
11484 Int_t first = zaxis->GetFirst();
11485 Int_t last = zaxis->GetLast();
11486 Int_t binz = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11487 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11488 zaxis->SetRange(binz,binz2);
11489 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11490 if (nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11491 xx[0] = xaxis->GetXmin();
11492 xx[1] = yaxis->GetXmax();
11493 xx[2] = zaxis->GetBinCenter(binz);
11494 view->WCtoNDC(xx,u);
11495 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11496 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11497 rect1[4].SetX(rect1[0].GetX());
11498 rect1[4].SetY(rect1[0].GetY());
11499 xx[0] = xaxis->GetXmax();
11500 view->WCtoNDC(xx,u);
11501 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11502 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11503 xx[1] = yaxis->GetXmin();
11504 view->WCtoNDC(xx,u);
11505 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11506 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11507 xx[0] = xaxis->GetXmin();
11508 view->WCtoNDC(xx,u);
11509 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11510 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11511 gVirtualX->DrawPolyLine(5,rect1);
11512 if (nbins>1) {
11513 xx[0] = xaxis->GetXmin();
11514 xx[1] = yaxis->GetXmax();
11515 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11516 view->WCtoNDC(xx,u);
11517 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11518 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11519 rect2[4].SetX(rect2[0].GetX());
11520 rect2[4].SetY(rect2[0].GetY());
11521 xx[0] = xaxis->GetXmax();
11522 view->WCtoNDC(xx,u);
11523 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11524 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11525 xx[1] = yaxis->GetXmin();
11526 view->WCtoNDC(xx,u);
11527 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11528 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11529 xx[0] = xaxis->GetXmin();
11530 view->WCtoNDC(xx,u);
11531 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11532 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11533 gVirtualX->DrawPolyLine(5,rect2);
11534 }
11535
11536 c->Clear();
11537 c->cd();
11538 TH2 *hp = (TH2*)h3->Project3D("xy");
11539 zaxis->SetRange(first,last);
11540 if (hp) {
11541 hp->SetFillColor(38);
11542 if (nbins==1)hp->SetTitle(TString::Format("ProjectionXY of binz=%d [z=%.1f..%.f]", binz,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz)));
11543 else hp->SetTitle(TString::Format("ProjectionXY, binz=[%d,%d] [z=%.1f..%.1f]", binz,binz2,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz2)));
11544 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11545 hp->SetYTitle(fH->GetXaxis()->GetTitle());
11546 hp->SetZTitle("Number of Entries");
11547 hp->Draw(fShowOption.Data());
11548 }
11549 }
11550 break;
11551
11552 case 5:
11553 // "yx"
11554 {
11555 Int_t first = zaxis->GetFirst();
11556 Int_t last = zaxis->GetLast();
11557 Int_t binz = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11558 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11559 zaxis->SetRange(binz,binz2);
11560 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11561 if (nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11562 xx[0] = xaxis->GetXmin();
11563 xx[1] = yaxis->GetXmax();
11564 xx[2] = zaxis->GetBinCenter(binz);
11565 view->WCtoNDC(xx,u);
11566 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11567 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11568 rect1[4].SetX(rect1[0].GetX());
11569 rect1[4].SetY(rect1[0].GetY());
11570 xx[0] = xaxis->GetXmax();
11571 view->WCtoNDC(xx,u);
11572 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11573 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11574 xx[1] = yaxis->GetXmin();
11575 view->WCtoNDC(xx,u);
11576 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11577 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11578 xx[0] = xaxis->GetXmin();
11579 view->WCtoNDC(xx,u);
11580 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11581 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11582 gVirtualX->DrawPolyLine(5,rect1);
11583 if (nbins>1) {
11584 xx[0] = xaxis->GetXmin();
11585 xx[1] = yaxis->GetXmax();
11586 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11587 view->WCtoNDC(xx,u);
11588 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11589 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11590 rect2[4].SetX(rect2[0].GetX());
11591 rect2[4].SetY(rect2[0].GetY());
11592 xx[0] = xaxis->GetXmax();
11593 view->WCtoNDC(xx,u);
11594 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11595 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11596 xx[1] = yaxis->GetXmin();
11597 view->WCtoNDC(xx,u);
11598 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11599 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11600 xx[0] = xaxis->GetXmin();
11601 view->WCtoNDC(xx,u);
11602 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11603 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11604 gVirtualX->DrawPolyLine(5,rect2);
11605 }
11606 c->Clear();
11607 c->cd();
11608 TH2 *hp = (TH2*)h3->Project3D("yx");
11609 zaxis->SetRange(first,last);
11610 if (hp) {
11611 hp->SetFillColor(38);
11612 if (nbins==1)hp->SetTitle(TString::Format("ProjectionYX of binz=%d [z=%.1f..%.f]", binz,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz)));
11613 else hp->SetTitle(TString::Format("ProjectionYX, binz=[%d,%d] [z=%.1f..%.1f]", binz,binz2,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz2)));
11614 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11615 hp->SetYTitle(fH->GetYaxis()->GetTitle());
11616 hp->SetZTitle("Number of Entries");
11617 hp->Draw(fShowOption.Data());
11618 }
11619 }
11620 break;
11621
11622 case 6:
11623 // "xz"
11624 {
11625 Int_t first = yaxis->GetFirst();
11626 Int_t last = yaxis->GetLast();
11627 Int_t biny = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11628 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11629 yaxis->SetRange(biny,biny2);
11630 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11631 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11632 xx[0] = xaxis->GetXmin();
11633 xx[2] = zaxis->GetXmax();
11634 xx[1] = yaxis->GetBinCenter(biny);
11635 view->WCtoNDC(xx,u);
11636 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11637 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11638 rect1[4].SetX(rect1[0].GetX());
11639 rect1[4].SetY(rect1[0].GetY());
11640 xx[0] = xaxis->GetXmax();
11641 view->WCtoNDC(xx,u);
11642 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11643 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11644 xx[2] = zaxis->GetXmin();
11645 view->WCtoNDC(xx,u);
11646 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11647 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11648 xx[0] = xaxis->GetXmin();
11649 view->WCtoNDC(xx,u);
11650 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11651 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11652 gVirtualX->DrawPolyLine(5,rect1);
11653 if (nbins>1) {
11654 xx[0] = xaxis->GetXmin();
11655 xx[2] = zaxis->GetXmax();
11656 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11657 view->WCtoNDC(xx,u);
11658 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11659 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11660 rect2[4].SetX(rect2[0].GetX());
11661 rect2[4].SetY(rect2[0].GetY());
11662 xx[0] = xaxis->GetXmax();
11663 view->WCtoNDC(xx,u);
11664 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11665 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11666 xx[2] = zaxis->GetXmin();
11667 view->WCtoNDC(xx,u);
11668 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11669 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11670 xx[0] = xaxis->GetXmin();
11671 view->WCtoNDC(xx,u);
11672 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11673 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11674 gVirtualX->DrawPolyLine(5,rect2);
11675 }
11676 c->Clear();
11677 c->cd();
11678 TH2 *hp = (TH2*)h3->Project3D("xz");
11679 yaxis->SetRange(first,last);
11680 if (hp) {
11681 hp->SetFillColor(38);
11682 if (nbins==1)hp->SetTitle(TString::Format("ProjectionXZ of biny=%d [y=%.1f..%.f]", biny,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny)));
11683 else hp->SetTitle(TString::Format("ProjectionXZ, biny=[%d,%d] [y=%.1f..%.1f]", biny,biny2,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny2)));
11684 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11685 hp->SetYTitle(fH->GetXaxis()->GetTitle());
11686 hp->SetZTitle("Number of Entries");
11687 hp->Draw(fShowOption.Data());
11688 }
11689 }
11690 break;
11691
11692 case 7:
11693 // "zx"
11694 {
11695 Int_t first = yaxis->GetFirst();
11696 Int_t last = yaxis->GetLast();
11697 Int_t biny = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11698 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11699 yaxis->SetRange(biny,biny2);
11700 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11701 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11702 xx[0] = xaxis->GetXmin();
11703 xx[2] = zaxis->GetXmax();
11704 xx[1] = yaxis->GetBinCenter(biny);
11705 view->WCtoNDC(xx,u);
11706 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11707 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11708 rect1[4].SetX(rect1[0].GetX());
11709 rect1[4].SetY(rect1[0].GetY());
11710 xx[0] = xaxis->GetXmax();
11711 view->WCtoNDC(xx,u);
11712 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11713 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11714 xx[2] = zaxis->GetXmin();
11715 view->WCtoNDC(xx,u);
11716 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11717 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11718 xx[0] = xaxis->GetXmin();
11719 view->WCtoNDC(xx,u);
11720 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11721 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11722 gVirtualX->DrawPolyLine(5,rect1);
11723 if (nbins>1) {
11724 xx[0] = xaxis->GetXmin();
11725 xx[2] = zaxis->GetXmax();
11726 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11727 view->WCtoNDC(xx,u);
11728 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11729 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11730 rect2[4].SetX(rect2[0].GetX());
11731 rect2[4].SetY(rect2[0].GetY());
11732 xx[0] = xaxis->GetXmax();
11733 view->WCtoNDC(xx,u);
11734 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11735 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11736 xx[2] = zaxis->GetXmin();
11737 view->WCtoNDC(xx,u);
11738 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11739 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11740 xx[0] = xaxis->GetXmin();
11741 view->WCtoNDC(xx,u);
11742 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11743 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11744 gVirtualX->DrawPolyLine(5,rect2);
11745 }
11746 c->Clear();
11747 c->cd();
11748 TH2 *hp = (TH2*)h3->Project3D("zx");
11749 yaxis->SetRange(first,last);
11750 if (hp) {
11751 hp->SetFillColor(38);
11752 if (nbins==1)hp->SetTitle(TString::Format("ProjectionZX of biny=%d [y=%.1f..%.f]", biny,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny)));
11753 else hp->SetTitle(TString::Format("ProjectionZX, biny=[%d,%d] [y=%.1f..%.1f]", biny,biny2,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny2)));
11754 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11755 hp->SetYTitle(fH->GetZaxis()->GetTitle());
11756 hp->SetZTitle("Number of Entries");
11757 hp->Draw(fShowOption.Data());
11758 }
11759 }
11760 break;
11761
11762 case 8:
11763 // "yz"
11764 {
11765 Int_t first = xaxis->GetFirst();
11766 Int_t last = xaxis->GetLast();
11767 Int_t binx = first + Int_t((last-first)*(px-pxmin)/(pxmax-pxmin));
11768 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11769 xaxis->SetRange(binx,binx2);
11770 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11771 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11772 xx[2] = zaxis->GetXmin();
11773 xx[1] = yaxis->GetXmax();
11774 xx[0] = xaxis->GetBinCenter(binx);
11775 view->WCtoNDC(xx,u);
11776 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11777 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11778 rect1[4].SetX(rect1[0].GetX());
11779 rect1[4].SetY(rect1[0].GetY());
11780 xx[2] = zaxis->GetXmax();
11781 view->WCtoNDC(xx,u);
11782 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11783 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11784 xx[1] = yaxis->GetXmin();
11785 view->WCtoNDC(xx,u);
11786 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11787 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11788 xx[2] = zaxis->GetXmin();
11789 view->WCtoNDC(xx,u);
11790 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11791 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11792 gVirtualX->DrawPolyLine(5,rect1);
11793 if (nbins>1) {
11794 xx[2] = zaxis->GetXmin();
11795 xx[1] = yaxis->GetXmax();
11796 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11797 view->WCtoNDC(xx,u);
11798 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11799 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11800 rect2[4].SetX(rect2[0].GetX());
11801 rect2[4].SetY(rect2[0].GetY());
11802 xx[2] = zaxis->GetXmax();
11803 view->WCtoNDC(xx,u);
11804 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11805 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11806 xx[1] = yaxis->GetXmin();
11807 view->WCtoNDC(xx,u);
11808 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11809 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11810 xx[2] = zaxis->GetXmin();
11811 view->WCtoNDC(xx,u);
11812 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11813 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11814 gVirtualX->DrawPolyLine(5,rect2);
11815 }
11816 c->Clear();
11817 c->cd();
11818 TH2 *hp = (TH2*)h3->Project3D("yz");
11819 xaxis->SetRange(first,last);
11820 if (hp) {
11821 hp->SetFillColor(38);
11822 if (nbins==1)hp->SetTitle(TString::Format("ProjectionYZ of binx=%d [x=%.1f..%.f]", binx,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx)));
11823 else hp->SetTitle(TString::Format("ProjectionYZ, binx=[%d,%d] [x=%.1f..%.1f]", binx,binx2,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx2)));
11824 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11825 hp->SetYTitle(fH->GetYaxis()->GetTitle());
11826 hp->SetZTitle("Number of Entries");
11827 hp->Draw(fShowOption.Data());
11828 }
11829 }
11830 break;
11831
11832 case 9:
11833 // "zy"
11834 {
11835 Int_t first = xaxis->GetFirst();
11836 Int_t last = xaxis->GetLast();
11837 Int_t binx = first + Int_t((last-first)*(px-pxmin)/(pxmax-pxmin));
11838 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11839 xaxis->SetRange(binx,binx2);
11840 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11841 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11842 xx[2] = zaxis->GetXmin();
11843 xx[1] = yaxis->GetXmax();
11844 xx[0] = xaxis->GetBinCenter(binx);
11845 view->WCtoNDC(xx,u);
11846 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11847 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11848 rect1[4].SetX(rect1[0].GetX());
11849 rect1[4].SetY(rect1[0].GetY());
11850 xx[2] = zaxis->GetXmax();
11851 view->WCtoNDC(xx,u);
11852 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11853 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11854 xx[1] = yaxis->GetXmin();
11855 view->WCtoNDC(xx,u);
11856 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11857 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11858 xx[2] = zaxis->GetXmin();
11859 view->WCtoNDC(xx,u);
11860 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11861 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11862 gVirtualX->DrawPolyLine(5,rect1);
11863 if (nbins>1) {
11864 xx[2] = zaxis->GetXmin();
11865 xx[1] = yaxis->GetXmax();
11866 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11867 view->WCtoNDC(xx,u);
11868 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11869 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11870 rect2[4].SetX(rect2[0].GetX());
11871 rect2[4].SetY(rect2[0].GetY());
11872 xx[2] = zaxis->GetXmax();
11873 view->WCtoNDC(xx,u);
11874 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11875 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11876 xx[1] = yaxis->GetXmin();
11877 view->WCtoNDC(xx,u);
11878 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11879 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11880 xx[2] = zaxis->GetXmin();
11881 view->WCtoNDC(xx,u);
11882 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11883 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11884 gVirtualX->DrawPolyLine(5,rect2);
11885 }
11886 c->Clear();
11887 c->cd();
11888 TH2 *hp = (TH2*)h3->Project3D("zy");
11889 xaxis->SetRange(first,last);
11890 if (hp) {
11891 hp->SetFillColor(38);
11892 if (nbins==1)hp->SetTitle(TString::Format("ProjectionZY of binx=%d [x=%.1f..%.f]", binx,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx)));
11893 else hp->SetTitle(TString::Format("ProjectionZY, binx=[%d,%d] [x=%.1f..%.1f]", binx,binx2,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx2)));
11894 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11895 hp->SetYTitle(fH->GetZaxis()->GetTitle());
11896 hp->SetZTitle("Number of Entries");
11897 hp->Draw(fShowOption.Data());
11898 }
11899 }
11900 break;
11901 }
11902 c->Update();
11903}
@ kMouseMotion
Definition Buttons.h:23
@ kWheelUp
Definition Buttons.h:18
@ kButton1Motion
Definition Buttons.h:20
@ kButton1Up
Definition Buttons.h:19
@ kWheelDown
Definition Buttons.h:18
@ kButton1Down
Definition Buttons.h:17
@ kButton1Locate
Definition Buttons.h:22
@ kArrowVer
Definition GuiTypes.h:374
@ kPointer
Definition GuiTypes.h:375
Handle_t Window_t
Window handle.
Definition GuiTypes.h:29
#define d(i)
Definition RSha256.hxx:102
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
#define c(i)
Definition RSha256.hxx:101
#define g(i)
Definition RSha256.hxx:105
#define a(i)
Definition RSha256.hxx:99
#define h(i)
Definition RSha256.hxx:106
#define e(i)
Definition RSha256.hxx:103
short Style_t
Style number (short)
Definition RtypesCore.h:96
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:59
short Color_t
Color number (short)
Definition RtypesCore.h:99
unsigned int UInt_t
Unsigned integer 4 bytes (unsigned int)
Definition RtypesCore.h:60
short Width_t
Line width (short)
Definition RtypesCore.h:98
float Float_t
Float 4 bytes (float)
Definition RtypesCore.h:71
short Short_t
Signed Short integer 2 bytes (short)
Definition RtypesCore.h:53
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
double Double_t
Double 8 bytes.
Definition RtypesCore.h:73
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
const char Option_t
Option string (const char)
Definition RtypesCore.h:80
#define BIT(n)
Definition Rtypes.h:91
@ kBlack
Definition Rtypes.h:66
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
R__EXTERN TEnv * gEnv
Definition TEnv.h:170
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t option
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void pixel
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t wmin
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize wid
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t np
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize id
Option_t Option_t TPoint TPoint const char x2
Option_t Option_t TPoint TPoint const char x1
Option_t Option_t TPoint TPoint angle
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void xpos
Option_t Option_t TPoint TPoint const char mode
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char backcolor
Option_t Option_t TPoint TPoint const char y2
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void ypos
Option_t Option_t width
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize fs
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t wmax
Option_t Option_t TPoint TPoint const char text
Option_t Option_t TPoint TPoint const char y1
R__EXTERN TH1 * gCurrentHist
R__EXTERN Hoption_t Hoption
float xmin
int ncx
float ymin
int ncy
float xmax
float ymax
static TString gStringStdDevZ
static TString gStringStdDevX
static TString gStringIntegralBinWidth
const UInt_t kCannotRotate
static TString gStringStdDev
const Int_t kNMAX
Hparam_t Hparam
const Int_t kMAXCONTOUR
static TString gStringOverflow
static TString gStringUnderflow
static TString gStringSkewnessY
static TString gStringMean
static TString gStringKurtosis
Hoption_t Hoption
static TString gStringMeanX
static TString gStringEntries
static TString gStringIntegral
static TString gStringKurtosisY
static TString gStringStdDevY
static TString gStringMeanY
static TString gStringSkewnessX
static TString gStringKurtosisX
static std::unique_ptr< TBox > gXHighlightBox
static std::unique_ptr< TBox > gYHighlightBox
static TString gStringSkewnessZ
TH1 * gCurrentHist
static TString gStringMeanZ
static TString gStringSkewness
static TString gStringKurtosisZ
const Int_t kMaxCuts
const Int_t kCYLINDRICAL
const Int_t kSPHERICAL
const Int_t kRAPIDITY
#define gROOT
Definition TROOT.h:414
R__EXTERN TStyle * gStyle
Definition TStyle.h:442
R__EXTERN TSystem * gSystem
Definition TSystem.h:572
const Int_t kCARTESIAN
Definition TView3D.cxx:32
const Int_t kPOLAR
Definition TView3D.cxx:33
#define gPad
#define gVirtualX
Definition TVirtualX.h:337
polygon * polys
Definition X3DBuffer.c:24
Draw all kinds of Arrows.
Definition TArrow.h:29
virtual Int_t GetNdivisions() const
Definition TAttAxis.h:37
virtual Float_t GetLabelOffset() const
Definition TAttAxis.h:41
virtual Float_t GetLabelSize() const
Definition TAttAxis.h:42
virtual Float_t GetTickLength() const
Definition TAttAxis.h:46
virtual Float_t GetTitleOffset() const
Definition TAttAxis.h:44
virtual Color_t GetFillColor() const
Return the fill area color.
Definition TAttFill.h:31
virtual Style_t GetFillStyle() const
Return the fill area style.
Definition TAttFill.h:32
virtual void SetFillColor(Color_t fcolor)
Set the fill area color.
Definition TAttFill.h:38
virtual void SetFillStyle(Style_t fstyle)
Set the fill area style.
Definition TAttFill.h:40
virtual Color_t GetLineColor() const
Return the line color.
Definition TAttLine.h:35
virtual void SetLineStyle(Style_t lstyle)
Set the line style.
Definition TAttLine.h:44
virtual Width_t GetLineWidth() const
Return the line width.
Definition TAttLine.h:37
virtual void SetLineWidth(Width_t lwidth)
Set the line width.
Definition TAttLine.h:45
virtual void SetLineColor(Color_t lcolor)
Set the line color.
Definition TAttLine.h:42
virtual Style_t GetLineStyle() const
Return the line style.
Definition TAttLine.h:36
virtual Style_t GetMarkerStyle() const
Return the marker style.
Definition TAttMarker.h:33
virtual void SetMarkerColor(Color_t mcolor=1)
Set the marker color.
Definition TAttMarker.h:39
virtual Color_t GetMarkerColor() const
Return the marker color.
Definition TAttMarker.h:32
virtual Size_t GetMarkerSize() const
Return the marker size.
Definition TAttMarker.h:34
virtual void SetMarkerStyle(Style_t mstyle=1)
Set the marker style.
Definition TAttMarker.h:41
virtual void SetMarkerSize(Size_t msize=1)
Set the marker size.
Definition TAttMarker.h:46
static Style_t GetMarkerStyleBase(Style_t style)
Internal helper function that returns the corresponding marker style with line width 1 for the given ...
virtual void SetTextAlign(Short_t align=11)
Set the text alignment.
Definition TAttText.h:44
virtual Font_t GetTextFont() const
Return the text font.
Definition TAttText.h:37
virtual void SetTextAngle(Float_t tangle=0)
Set the text angle.
Definition TAttText.h:45
virtual void SetTextColor(Color_t tcolor=1)
Set the text color.
Definition TAttText.h:46
virtual void SetTextFont(Font_t tfont=62)
Set the text font.
Definition TAttText.h:48
virtual void SetTextSize(Float_t tsize=1)
Set the text size.
Definition TAttText.h:49
Class to manage histogram axis.
Definition TAxis.h:32
virtual Bool_t GetTimeDisplay() const
Definition TAxis.h:133
Bool_t IsAlphanumeric() const
Definition TAxis.h:90
const char * GetTitle() const override
Returns title of object.
Definition TAxis.h:137
virtual Double_t GetBinCenter(Int_t bin) const
Return center of bin.
Definition TAxis.cxx: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:293
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:422
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:1090
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:2473
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition TClass.cxx:2973
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
The color creation and management class.
Definition TColor.h:22
static void RGBtoHLS(Float_t r, Float_t g, Float_t b, Float_t &h, Float_t &l, Float_t &s)
Definition TColor.h:83
static Int_t GetColor(const char *hexcolor)
Static method returning color number for color specified by hex color string of form: "#rrggbb",...
Definition TColor.cxx:1926
static Int_t GetColorBright(Int_t color)
Static function: Returns the bright color number corresponding to n If the TColor object does not exi...
Definition TColor.cxx:2095
static Int_t GetColorDark(Int_t color)
Static function: Returns the dark color number corresponding to n If the TColor object does not exist...
Definition TColor.cxx:2138
static void HLStoRGB(Float_t h, Float_t l, Float_t s, Float_t &r, Float_t &g, Float_t &b)
Definition TColor.h:78
To draw a Crown.
Definition TCrown.h:19
Graphical cut class.
Definition TCutG.h:20
static TClass * Class()
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition TEnv.cxx:503
1-Dim function class
Definition TF1.h:182
virtual Double_t GetXmax() const
Definition TF1.h:525
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:1939
virtual void GetParLimits(Int_t ipar, Double_t &parmin, Double_t &parmax) const
Return limits for parameter ipar.
Definition TF1.cxx:1990
virtual Double_t GetParError(Int_t ipar) const
Return value of parameter number ipar.
Definition TF1.cxx:1980
static TClass * Class()
Double_t GetChisquare() const
Return the Chisquare after fitting. See ROOT::Fit::FitResult::Chi2()
Definition TF1.h:409
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:3449
virtual Double_t GetMaximumStored() const
Definition TF1.h:438
virtual Int_t GetNpar() const
Definition TF1.h:446
virtual Int_t GetNumberFreeParameters() const
Return the number of free parameters.
Definition TF1.cxx:1950
@ kNotDraw
Definition TF1.h:297
virtual void SetMinimum(Double_t minimum=-1111)
Set the minimum value along Y for this function In case the function is already drawn,...
Definition TF1.cxx:3462
virtual const char * GetParName(Int_t ipar) const
Definition TF1.h:494
virtual Double_t Eval(Double_t x, Double_t y=0, Double_t z=0, Double_t t=0) const
Evaluate this function.
Definition TF1.cxx:1446
virtual Double_t GetXmin() const
Definition TF1.h:521
virtual Double_t GetParameter(Int_t ipar) const
Definition TF1.h:477
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:805
void SetRange(Double_t xmin, Double_t xmax) override
Initialize the upper and lower bounds to draw the function.
Definition TF2.h:133
static TClass * Class()
TF3 defines a 3D Function with Parameters.
Definition TF3.h:28
The axis painter class.
Definition TGaxis.h:26
void SetTimeFormat(const char *tformat)
Change the format used for time plotting.
Definition TGaxis.cxx:2945
virtual void PaintAxis(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax, Double_t &wmin, Double_t &wmax, Int_t &ndiv, Option_t *chopt="", Double_t gridlength=0, Bool_t drawGridOnly=kFALSE)
Control function to draw an axis.
Definition TGaxis.cxx:1007
void SetTitleOffset(Float_t titleoffset=1)
Definition TGaxis.h:130
virtual void SetTitle(const char *title="")
Change the title of the axis.
Definition TGaxis.cxx:2918
void SetLabelOffset(Float_t labeloffset)
Definition TGaxis.h:108
virtual void ImportAxisAttributes(TAxis *axis)
Internal method to import TAxis attributes to this TGaxis.
Definition TGaxis.cxx:954
void SetTickSize(Float_t ticksize)
Definition TGaxis.h:124
void SetLabelSize(Float_t labelsize)
Definition TGaxis.h:109
void SetOption(Option_t *option="")
To set axis options.
Definition TGaxis.cxx:2910
Graphics object made of three arrays X, Y and Z with the same number of points each.
Definition TGraph2D.h:41
static TClass * Class()
TGraphDelaunay2D generates a Delaunay triangulation of a TGraph2D.
TGraphDelaunay generates a Delaunay triangulation of a TGraph2D.
A TGraph is an object made of two arrays X and Y with npoints each.
Definition TGraph.h:41
static TClass * Class()
@ kClipFrame
Clip to the frame boundary.
Definition TGraph.h:75
void PaintGraph(Int_t npoints, const Double_t *x, const Double_t *y, Option_t *chopt)
Draw the (x,y) as a graph.
Definition TGraph.cxx:2016
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:2025
1-D histogram with a double per channel (see TH1 documentation)
Definition TH1.h:926
1-D histogram with a float per channel (see TH1 documentation)
Definition TH1.h:878
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:109
TAxis * GetZaxis()
Definition TH1.h:573
virtual EBinErrorOpt GetBinErrorOption() const
Definition TH1.h:517
virtual Float_t GetBarWidth() const
Definition TH1.h:501
virtual Double_t GetMinimumStored() const
Definition TH1.h:537
virtual Float_t GetBarOffset() const
Definition TH1.h:500
static TClass * Class()
virtual Double_t GetStdDev(Int_t axis=1) const
Returns the Standard Deviation (Sigma).
Definition TH1.cxx:7658
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:9120
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:7586
virtual Double_t GetSkewness(Int_t axis=1) const
Definition TH1.cxx:7722
virtual Double_t GetContourLevelPad(Int_t level) const
Return the value of contour number "level" in Pad coordinates.
Definition TH1.cxx:8496
virtual Int_t GetDimension() const
Definition TH1.h:527
static void AddDirectory(Bool_t add=kTRUE)
Sets the flag controlling the automatic add of histograms in memory.
Definition TH1.cxx:1263
@ kNoTitle
Don't draw the histogram title.
Definition TH1.h:408
@ kUserContour
User specified contour levels.
Definition TH1.h:404
@ kNoStats
Don't draw stats box.
Definition TH1.h:403
TAxis * GetXaxis()
Definition TH1.h:571
virtual Double_t GetSumOfWeights() const
Return the sum of weights across all bins excluding under/overflows.
Definition TH1.h:559
virtual Int_t GetBin(Int_t binx, Int_t biny=0, Int_t binz=0) const
Return Global bin number corresponding to binx,y,z.
Definition TH1.cxx:4979
virtual Double_t GetMaximum(Double_t maxval=FLT_MAX) const
Return maximum value smaller than maxval of bins in the range, unless the value has been overridden b...
Definition TH1.cxx:8605
virtual Int_t GetNbinsX() const
Definition TH1.h:541
virtual void SetMaximum(Double_t maximum=-1111)
Definition TH1.h:652
TAxis * GetYaxis()
Definition TH1.h:572
virtual Double_t GetBinErrorLow(Int_t bin) const
Return lower error associated to bin number bin.
Definition TH1.cxx:9136
virtual void SetMinimum(Double_t minimum=-1111)
Definition TH1.h:653
virtual Double_t Integral(Option_t *option="") const
Return integral of bin contents.
Definition TH1.cxx:7997
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:9279
virtual Double_t GetBinLowEdge(Int_t bin) const
Return bin lower edge for 1D histogram.
Definition TH1.cxx:9209
virtual Double_t GetEntries() const
Return the current number of entries.
Definition TH1.cxx:4416
TList * GetListOfFunctions() const
Definition TH1.h:488
virtual Double_t GetMeanError(Int_t axis=1) const
Return standard error of mean of this histogram along the X axis.
Definition TH1.cxx:7626
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:8791
@ kNormal
Errors with Normal (Wald) approximation: errorUp=errorLow= sqrt(N)
Definition TH1.h:115
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition TH1.cxx:5081
virtual Int_t GetContour(Double_t *levels=nullptr)
Return contour values into array levels if pointer levels is non zero.
Definition TH1.cxx:8467
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:9220
virtual void SetContour(Int_t nlevels, const Double_t *levels=nullptr)
Set the number and values of contour levels.
Definition TH1.cxx:8543
virtual Double_t GetBinErrorUp(Int_t bin) const
Return upper error associated to bin number bin.
Definition TH1.cxx:9167
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:7706
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:8695
static Bool_t AddDirectoryStatus()
Static function: cannot be inlined on Windows/NT.
Definition TH1.cxx:741
virtual void LabelsDeflate(Option_t *axis="X")
Reduce the number of bins for the axis passed in the option to the number of bins having a label.
Definition TH1.cxx:5265
virtual Int_t BufferEmpty(Int_t action=0)
Fill histogram with all entries in the buffer.
Definition TH1.cxx:1383
virtual Double_t GetKurtosis(Int_t axis=1) const
Definition TH1.cxx:7795
2-D histogram with a double per channel (see TH1 documentation)
Definition TH2.h:400
2-D histogram with a float per channel (see TH1 documentation)
Definition TH2.h:345
Helper class to represent a bin in the TH2Poly histogram.
Definition TH2Poly.h:25
2D Histogram with Polygonal Bins
Definition TH2Poly.h:66
static TClass * Class()
Service class for 2-D histogram classes.
Definition TH2.h:30
static TClass * Class()
The 3-D histogram classes derived from the 1-D histogram classes.
Definition TH3.h:45
static TClass * Class()
The Histogram stack class.
Definition THStack.h:40
static TClass * Class()
The histogram painter class.
static Int_t ProjectSinusoidal2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function code for sinusoidal projection from Ernst-Jan Buis Source https://en....
void Paint(Option_t *option="") override
Control routine to paint any kind of histograms
TAxis * fYaxis
Pointer to Y axis.
std::unique_ptr< TPainter3dAlgorithms > fLego
Pointer to a TPainter3dAlgorithms object.
std::vector< Double_t > fXbuf
X buffer coordinates.
Int_t fXHighlightBin
X highlight bin.
TF3 * fCurrentF3
Current TF3 function.
virtual void PaintErrors(Option_t *option)
Draw 1D histograms error bars.
~THistPainter() override
destructor.
Int_t fShowProjection2
True if a second projection must be drawn (when calling SetShowProjectionXY on a TH2)
virtual void PaintTF3()
Control function to draw a 3D implicit functions.
virtual Int_t TableInit()
Initialize various options to draw 2D histograms.
virtual void PaintTH2PolyScatterPlot(Option_t *option)
Control function to draw a TH2Poly as a scatter plot.
static Int_t ProjectMollweide2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
static Int_t ProjectAitoff2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
virtual void PaintText(Option_t *option)
Control function to draw a 1D/2D histograms with the bin values.
Int_t DistancetoPrimitive(Int_t px, Int_t py) override
Compute the distance from the point px,py to a line.
virtual void PaintAxis(Bool_t drawGridOnly=kFALSE)
Draw axis (2D case) of an histogram.
virtual void PaintColorLevelsFast(Option_t *option)
[Rendering scheme for the COL2 and COLZ2 options] (HP14)
virtual Int_t PaintInit()
Compute histogram parameters used by the drawing routines.
virtual void Paint2DErrors(Option_t *option)
Draw 2D histograms errors.
Int_t fYHighlightBin
Y highlight bin.
virtual void PaintCandlePlot(Option_t *option)
Control function to draw a 2D histogram as a candle (box) plot or violin plot
virtual void PaintScatterPlot(Option_t *option)
Control function to draw a 2D histogram as a scatter plot.
void SetShowProjectionXY(const char *option, Int_t nbinsY, Int_t nbinsX) override
virtual void PaintLego(Option_t *option)
Control function to draw a 2D histogram as a lego plot.
virtual void PaintH3(Option_t *option="")
Control function to draw a 3D histograms.
Int_t fNcuts
Number of graphical cuts.
TString fShowOption
Option to draw the projection.
virtual void PaintHighlightBin(Option_t *option="")
Paint highlight bin as TBox object.
virtual void PaintTH2PolyBins(Option_t *option)
Control function to draw a TH2Poly bins' contours.
virtual Int_t PaintContourLine(Double_t elev1, Int_t icont1, Double_t x1, Double_t y1, Double_t elev2, Int_t icont2, Double_t x2, Double_t y2, Double_t *xarr, Double_t *yarr, Int_t *itarr, Double_t *levels)
Fill the matrix xarr and yarr for Contour Plot.
Int_t fShowProjection
True if a projection must be drawn.
virtual void PaintLegoAxis(TGaxis *axis, Double_t ang)
Draw the axis for legos and surface plots.
virtual void PaintTriangles(Option_t *option)
Control function to draw a table using Delaunay triangles.
virtual void HighlightBin(Int_t px, Int_t py)
Check on highlight bin.
virtual void PaintH3Box(Int_t iopt)
Control function to draw a 3D histogram with boxes.
Int_t MakeCuts(char *cutsopt) override
Decode string choptin and fill Graphical cuts structure.
TList * fFunctions
Pointer to histogram list of functions.
void DrawPanel() override
Display a panel with all histogram drawing options.
std::unique_ptr< TPie > fPie
Pointer to a TPie in case of option PIE.
static void PaintSpecialObjects(const TObject *obj, Option_t *option)
Static function to paint special objects like vectors and matrices.
virtual void PaintTitle()
new TGaxis/////////////////// Draw the histogram title
virtual void PaintTH2PolyColorLevels(Option_t *option)
Control function to draw a TH2Poly as a color plot.
virtual std::vector< THistRenderingRegion > ComputeRenderingRegions(TAxis *pAxis, Int_t nPixels, bool isLog)
Returns the rendering regions for an axis to use in the COL2 option.
virtual void ShowProjectionX(Int_t px, Int_t py)
Show projection onto X.
virtual void PaintPalette()
Paint the color palette on the right side of the pad.
TAxis * fXaxis
Pointer to X axis.
virtual void PaintStat2(Int_t dostat, TF1 *fit)
Draw the statistics box for 2D histograms.
virtual void PaintArrows(Option_t *option)
Control function to draw a table as an arrow plot
virtual void RecalculateRange()
Recompute the histogram range following graphics operations.
void PaintStat(Int_t dostat, TF1 *fit) override
Draw the statistics box for 1D and profile histograms.
static Int_t ProjectParabolic2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function code for parabolic projection from Ernst-Jan Buis.
std::unique_ptr< TGraph2DPainter > fGraph2DPainter
Pointer to a TGraph2DPainter object.
virtual void PaintBarH(Option_t *option)
Draw a bar char in a rotated pad (X vertical, Y horizontal)
virtual void PaintStat3(Int_t dostat, TF1 *fit)
Draw the statistics box for 3D histograms.
virtual void PaintSurface(Option_t *option)
Control function to draw a 2D histogram as a surface plot.
TList * fStack
Pointer to stack of histograms (if any)
THistPainter()
Default constructor.
TH1 * fH
Pointer to histogram to paint.
virtual void PaintTH2PolyText(Option_t *option)
Control function to draw a TH2Poly as a text plot.
virtual void ShowProjection3(Int_t px, Int_t py)
Show projection (specified by fShowProjection) of a TH3.
TAxis * fZaxis
Pointer to Z axis.
void SetHistogram(TH1 *h) override
Set current histogram to h
virtual void PaintFunction(Option_t *option)
[Paint functions associated to an histogram.](HP28")
virtual void PaintBar(Option_t *option)
Draw a bar-chart in a normal pad.
static Int_t ProjectMercator2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
virtual void PaintBoxes(Option_t *option)
Control function to draw a 2D histogram as a box plot
virtual Int_t MakeChopt(Option_t *option)
Decode string choptin and fill Hoption structure.
char * GetObjectInfo(Int_t px, Int_t py) const override
Display the histogram info (bin number, contents, integral up to bin corresponding to cursor position...
TList * GetContourList(Double_t contour) const override
Get a contour (as a list of TGraphs) using the Delaunay triangulation.
void ProcessMessage(const char *mess, const TObject *obj) override
Process message mess.
void SetShowProjection(const char *option, Int_t nbins) override
Set projection.
virtual void ShowProjectionY(Int_t px, Int_t py)
Show projection onto Y.
static const char * GetBestFormat(Double_t v, Double_t e, const char *f)
This function returns the best format to print the error value (e) knowing the parameter value (v) an...
virtual void PaintContour(Option_t *option)
Control function to draw a 2D histogram as a contour plot.
TCutG * fCuts[kMaxCuts]
Pointers to graphical cuts.
virtual void PaintTable(Option_t *option)
Control function to draw 2D/3D histograms (tables).
void ExecuteEvent(Int_t event, Int_t px, Int_t py) override
Execute the actions corresponding to event.
virtual Int_t PaintInitH()
Compute histogram parameters used by the drawing routines for a rotated pad.
virtual void PaintFrame()
Calculate range and clear pad (canvas).
Int_t fCutsOpt[kMaxCuts]
Sign of each cut.
virtual void PaintH3Iso()
Control function to draw a 3D histogram with Iso Surfaces.
std::vector< Double_t > fYbuf
Y buffer coordinates.
virtual void PaintH3BoxRaster()
Control function to draw a 3D histogram with boxes.
virtual void PaintHist(Option_t *option)
Control routine to draw 1D histograms
void SetHighlight() override
Set highlight (enable/disable) mode for fH.
virtual void DefineColorLevels(Int_t ndivz)
Define the color levels used to paint legos, surfaces etc..
TString fObjectInfo
virtual void PaintColorLevels(Option_t *option)
Control function to draw a 2D histogram as a color plot.
Bool_t IsInside(Int_t x, Int_t y) override
Return kTRUE if the cell ix, iy is inside one of the graphical cuts.
A class to define a conversion from pixel values to pixel color.
Definition TAttImage.h:33
static TImagePalette * CreateCOLPalette(Int_t nContours)
Factory method to creates an image palette for histogram plotting.
An abstract interface to image processing library.
Definition TImage.h:29
static TImage * Create()
Create an image.
Definition TImage.cxx:34
void Reset()
To draw Mathematical Formula.
Definition TLatex.h:20
A doubly linked list.
Definition TList.h:38
TObject * FindObject(const char *name) const override
Find an object in this list using its name.
Definition TList.cxx:708
void Add(TObject *obj) override
Definition TList.h:81
TObject * Remove(TObject *obj) override
Remove object from the list.
Definition TList.cxx:952
TObject * First() const override
Return the first object in the list. Returns 0 when list is empty.
Definition TList.cxx:789
virtual TObjLink * FirstLink() const
Definition TList.h:107
TObject * At(Int_t idx) const override
Returns the object at position idx. Returns 0 if idx is out of range.
Definition TList.cxx:487
void AddFirst(TObject *obj) override
Add object at the beginning of the list.
Definition TList.cxx:97
TMatrixTBase.
static TClass * Class()
A TMultiGraph is a collection of TGraph (or derived) objects.
Definition TMultiGraph.h:34
TList * GetListOfGraphs() const
Definition TMultiGraph.h:67
static TClass * Class()
virtual Int_t IsInside(Double_t x, Double_t y) const
Return 1 if the point (x,y) is inside one of the graphs 0 otherwise.
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:50
An array of TObjects.
Definition TObjArray.h:31
Mother of all ROOT objects.
Definition TObject.h:41
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:457
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:202
virtual Option_t * GetDrawOption() const
Get option used by the graphics system to draw this object.
Definition TObject.cxx:441
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1074
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:881
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:1088
virtual const char * GetTitle() const
Returns title of object.
Definition TObject.cxx:501
void ResetBit(UInt_t f)
Definition TObject.h:201
@ kCannotPick
if object in a pad cannot be picked
Definition TObject.h:73
@ kCanDelete
if object in a list can be deleted
Definition TObject.h:68
@ kMustCleanup
if object destructor must call RecursiveRemove()
Definition TObject.h:70
void DrawFaceMove3(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 3rd variant for "MOVING SCREEN" algorithm (draw level lines only)
void DrawLevelLines(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw level lines without hidden line removal.
void SurfaceFunction(Int_t ia, Int_t ib, Double_t *f, Double_t *t)
Service function for Surfaces.
void DrawFaceMode1(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *t)
Draw face - 1st variant (2 colors: 1st for external surface, 2nd for internal)
void GouraudFunction(Int_t ia, Int_t ib, Double_t *f, Double_t *t)
Find part of surface with luminosity in the corners.
void DrawFaceMove1(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 1st variant for "MOVING SCREEN" algorithm (draw face with level lines)
void DrawFaceRaster2(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 2nd variant for "RASTER SCREEN" algorithm (draw face for stacked lego plot)
void LegoFunction(Int_t ia, Int_t ib, Int_t &nv, Double_t *ab, Double_t *vv, Double_t *t)
Service function for Legos.
void DrawFaceMove2(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 2nd variant for "MOVING SCREEN" algorithm (draw face for stacked lego plot)
void DrawFaceRaster1(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 1st variant for "RASTER SCREEN" algorithm (draw face with level lines)
void DrawFaceMode3(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *t)
Draw face - 3rd option (draw face for stacked lego plot)
void DrawFaceMode2(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *t)
Draw face - 2nd option (fill in correspondence with function levels)
The palette painting class.
The histogram statistics painter class.
Definition TPaveStats.h:18
Int_t GetOptStat() const
Return the stat option.
virtual void SetStatFormat(const char *format="6.4g")
Change (i.e. set) the format for printing statistics.
void SetOptStat(Int_t stat=1)
Set the stat option.
virtual const char * GetFitFormat() const
Definition TPaveStats.h:35
virtual void SetFitFormat(const char *format="5.4g")
Change (i.e. set) the format for printing fit parameters in statistics box.
Int_t GetOptFit() const
Return the fit option.
void SetParent(TObject *obj) override
Definition TPaveStats.h:53
void SetOptFit(Int_t fit=1)
Set the fit option.
virtual const char * GetStatFormat() const
Definition TPaveStats.h:36
void Paint(Option_t *option="") override
Paint the pave stat.
static TClass * Class()
A Pave (see TPave) with text, lines or/and boxes inside.
Definition TPaveText.h:21
virtual TText * AddText(Double_t x1, Double_t y1, const char *label)
Add a new Text line to this pavetext at given coordinates.
static TClass * Class()
void Clear(Option_t *option="") override
Clear all lines in this pavetext.
virtual TText * GetLine(Int_t number) const
Get Pointer to line number in this pavetext.
const char * GetName() const override
Returns name of object.
Definition TPave.h:58
virtual void SetName(const char *name="")
Definition TPave.h:81
virtual void SetBorderSize(Int_t bordersize=4)
Sets the border size of the TPave box and shadow.
Definition TPave.h:79
Option_t * GetOption() const override
Definition TPave.h:59
Double_t GetX1NDC() const
Definition TPave.h:61
virtual void SetX2NDC(Double_t x2)
Definition TPave.h:85
void SetX(SCoord_t x)
Definition TPoint.h:48
void SetY(SCoord_t y)
Definition TPoint.h:49
Profile2D histograms are used to display the mean value of Z and its error for each cell in X,...
Definition TProfile2D.h:27
static TClass * Class()
Profile Histogram.
Definition TProfile.h:32
static TClass * Class()
Random number generator class based on the maximally equidistributed combined Tausworthe generator by...
Definition TRandom2.h:27
Sequenceable collection abstract base class.
Basic string class.
Definition TString.h:138
void ToLower()
Change string to lower-case.
Definition TString.cxx:1189
const char * Data() const
Definition TString.h:384
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2384
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2362
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:641
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:660
Int_t GetOptStat() const
Definition TStyle.h:247
Color_t GetStatTextColor() const
Definition TStyle.h:260
Float_t GetTitleX() const
Definition TStyle.h:282
Int_t GetOptTitle() const
Definition TStyle.h:248
Float_t GetStatFontSize() const
Definition TStyle.h:263
Float_t GetBarOffset() const
Definition TStyle.h:184
Float_t GetStatX() const
Definition TStyle.h:266
Float_t GetTitleSize(Option_t *axis="X") const
Return title size.
Definition TStyle.cxx:1241
Float_t GetTitleY() const
Definition TStyle.h:283
Style_t GetTitleFont(Option_t *axis="X") const
Return title font.
Definition TStyle.cxx:1217
Bool_t GetHistMinimumZero() const
Definition TStyle.h:239
Float_t GetStatY() const
Definition TStyle.h:267
Color_t GetTitleFillColor() const
Definition TStyle.h:273
Style_t GetTitleStyle() const
Definition TStyle.h:275
Color_t GetStatColor() const
Definition TStyle.h:259
Float_t GetBarWidth() const
Definition TStyle.h:185
void SetDrawBorder(Int_t drawborder=1)
Definition TStyle.h:346
Float_t GetStatH() const
Definition TStyle.h:269
Width_t GetTitleBorderSize() const
Definition TStyle.h:277
Int_t GetColorPalette(Int_t i) const
Return color number i in current palette.
Definition TStyle.cxx:1102
Float_t GetErrorX() const
Definition TStyle.h:188
Double_t GetHistTopMargin() const
Definition TStyle.h:240
void SetBarOffset(Float_t baroff=0.5)
Definition TStyle.h:339
Float_t GetEndErrorSize() const
Definition TStyle.h:187
Int_t GetDrawBorder() const
Definition TStyle.h:186
Width_t GetStatBorderSize() const
Definition TStyle.h:261
Color_t GetTitleTextColor() const
Definition TStyle.h:274
void SetBarWidth(Float_t barwidth=0.5)
Definition TStyle.h:340
Float_t GetTitleH() const
Definition TStyle.h:285
Style_t GetStatStyle() const
Definition TStyle.h:264
Float_t GetStatW() const
Definition TStyle.h:268
const char * GetFitFormat() const
Definition TStyle.h:201
const char * GetStatFormat() const
Definition TStyle.h:265
Int_t GetNumberOfColors() const
Return number of colors in the color palette.
Definition TStyle.cxx:1176
Int_t GetOptFit() const
Definition TStyle.h:246
Int_t GetNumberContours() const
Definition TStyle.h:243
const char * GetPaintTextFormat() const
Definition TStyle.h:252
Style_t GetStatFont() const
Definition TStyle.h:262
Float_t GetTitleFontSize() const
Definition TStyle.h:276
Int_t GetTitleAlign() const
Definition TStyle.h:272
Float_t GetTitleW() const
Definition TStyle.h:284
virtual int Load(const char *module, const char *entry="", Bool_t system=kFALSE)
Load a shared library.
Definition TSystem.cxx:1868
Base class for several text objects.
Definition TText.h:22
TVectorT.
Definition TVectorT.h:29
static TClass * Class()
See TView3D.
Definition TView.h:25
virtual Double_t GetPsi()=0
virtual Double_t * GetRmax()=0
virtual void SetAxisNDC(const Double_t *x1, const Double_t *x2, const Double_t *y1, const Double_t *y2, const Double_t *z1, const Double_t *z2)=0
virtual Double_t * GetRmin()=0
virtual void WCtoNDC(const Float_t *pw, Float_t *pn)=0
virtual void SetOutlineToCube()=0
virtual Int_t GetDistancetoAxis(Int_t axis, Int_t px, Int_t py, Double_t &ratio)=0
virtual Double_t * GetTnorm()=0
virtual void ExecuteRotateView(Int_t event, Int_t px, Int_t py)=0
virtual TSeqCollection * GetOutline()=0
virtual void PadRange(Int_t rback)=0
virtual void SetRange(const Double_t *min, const Double_t *max)=0
virtual void FindNormal(Double_t x, Double_t y, Double_t z, Double_t &zn)=0
virtual void AxisVertex(Double_t ang, Double_t *av, Int_t &ix1, Int_t &ix2, Int_t &iy1, Int_t &iy2, Int_t &iz1, Int_t &iz2)=0
virtual void SetView(Double_t longitude, Double_t latitude, Double_t psi, Int_t &irep)=0
Abstract base class used by ROOT graphics editor.
static TVirtualPadEditor * GetPadEditor(Bool_t load=kTRUE)
Returns the pad editor dialog. Static method.
small helper class to store/restore gPad context in TPad methods
Definition TVirtualPad.h:61
TVirtualPad is an abstract base class for the Pad and Canvas classes.
Definition TVirtualPad.h:51
TLine * line
void box(Int_t pat, Double_t x1, Double_t y1, Double_t x2, Double_t y2)
Definition fillpatterns.C:1
Double_t y[n]
Definition legend1.C:17
return c1
Definition legend1.C:41
Double_t x[n]
Definition legend1.C:17
Double_t ey[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
Double_t ex[n]
Definition legend1.C:17
TH1F * h1
Definition legend1.C:5
TF1 * f1
Definition legend1.C:11
return c2
Definition legend2.C:14
Int_t Nint(T x)
Round to nearest integer. Rounds half integers to the nearest even integer.
Definition TMath.h:704
Short_t Max(Short_t a, Short_t b)
Returns the largest of a and b.
Definition TMathBase.h:249
Double_t Prob(Double_t chi2, Int_t ndf)
Computation of the probability for a certain Chi-squared (chi2) and number of degrees of freedom (ndf...
Definition TMath.cxx:637
Double_t ATan(Double_t)
Returns the principal value of the arc tangent of x, expressed in radians.
Definition TMath.h:651
constexpr Double_t PiOver2()
Definition TMath.h:54
Double_t Log(Double_t x)
Returns the natural logarithm of x.
Definition TMath.h:767
constexpr Double_t DegToRad()
Conversion from degree to radian: .
Definition TMath.h:82
Double_t Sqrt(Double_t x)
Returns the square root of x.
Definition TMath.h:673
LongDouble_t Power(LongDouble_t x, LongDouble_t y)
Returns x raised to the power y.
Definition TMath.h:732
Short_t Min(Short_t a, Short_t b)
Returns the smallest of a and b.
Definition TMathBase.h:197
Double_t Cos(Double_t)
Returns the cosine of an angle of x radians.
Definition TMath.h:605
constexpr Double_t Pi()
Definition TMath.h:40
Bool_t AreEqualRel(Double_t af, Double_t bf, Double_t relPrec)
Comparing floating points.
Definition TMath.h:429
Double_t Sin(Double_t)
Returns the sine of an angle of x radians.
Definition TMath.h:599
Double_t Tan(Double_t)
Returns the tangent of an angle of x radians.
Definition TMath.h:611
Long64_t BinarySearch(Long64_t n, const T *array, T value)
Binary search in an array of n values to locate value.
Definition TMathBase.h:329
constexpr Double_t RadToDeg()
Conversion from radian to degree: .
Definition TMath.h:75
Double_t Log10(Double_t x)
Returns the common (base-10) logarithm of x.
Definition TMath.h:773
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:122
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