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](\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\anchor HP01b
247#### Options supported for 1D histograms
248
249| Option | Description |
250|----------|-------------------------------------------------------------------|
251| " " | Default. |
252| "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.|
253| "][" | When this option is selected the first and last vertical lines of the histogram are not drawn.|
254| "B" | Bar chart option.|
255| "BAR" | Like option "B", but bars can be drawn with a 3D effect.|
256| "HBAR" | Like option "BAR", but bars are drawn horizontally.|
257| "C" | Draw a smooth Curve through the histogram bins.|
258| "E0" | Draw error bars. Markers are drawn for bins with 0 contents. Combined with E1 or E2 it avoids error bars clipping|
259| "E1" | Draw error bars with perpendicular lines at the edges.|
260| "E2" | Draw error bars with rectangles.|
261| "E3" | Draw a fill area through the end points of the vertical error bars.|
262| "E4" | Draw a smoothed filled area through the end points of the error bars.|
263| "E5" | Like E3 but ignore the bins with 0 contents.|
264| "E6" | Like E4 but ignore the bins with 0 contents.|
265| "X0" | When used with one of the "E" option, it suppress the error bar along X as `gStyle->SetErrorX(0)` would do.|
266| "L" | Draw a line through the bin contents.|
267| "P" | Draw current marker at each bin except empty bins.|
268| "P*" | Draw a star marker at each bin except empty bins.|
269| "P0" | Draw current marker at each bin including empty bins.|
270| "PIE" | Draw histogram as a Pie Chart.|
271| "*H" | Draw histogram with a * at each bin.|
272| "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.|
273
274
275\anchor HP01c
276#### Options supported for 2D histograms
277
278| Option | Description |
279|--------------|------------------------------------------------------------------|
280| " " | Default (color plot).|
281| "ARR" | Arrow mode. Shows gradient between adjacent cells.|
282| "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. |
283| "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.|
284| "COL" | A box is drawn for each cell with a color scale varying with contents. All the none empty bins 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).|
285| "COLZ" | Same as "COL". In addition the color palette is also drawn.|
286| "COL2" | Alternative rendering algorithm to "COL". Can significantly improve rendering performance for large, non-sparse 2-D histograms.|
287| "COLZ2" | Same as "COL2". In addition the color palette is also drawn.|
288| "Z CJUST" | In combination with colored options "COL","CONT0" etc: Justify labels in the color palette at color boundaries. For more details see `TPaletteAxis`|
289| "CANDLE" | Draw a candle plot along X axis.|
290| "CANDLEX" | Same as "CANDLE".|
291| "CANDLEY" | Draw a candle plot along Y axis.|
292| "CANDLEXn" | Draw a candle plot along X axis. Different candle-styles with n from 1 to 6.|
293| "CANDLEYn" | Draw a candle plot along Y axis. Different candle-styles with n from 1 to 6.|
294| "VIOLIN" | Draw a violin plot along X axis.|
295| "VIOLINX" | Same as "VIOLIN".|
296| "VIOLINY" | Draw a violin plot along Y axis.|
297| "VIOLINXn" | Draw a violin plot along X axis. Different violin-styles with n being 1 or 2.|
298| "VIOLINYn" | Draw a violin plot along Y axis. Different violin-styles with n being 1 or 2.|
299| "CONT" | Draw a contour plot (same as CONT0).|
300| "CONT0" | Draw a contour plot using surface colors to distinguish contours.|
301| "CONT1" | Draw a contour plot using line styles to distinguish contours.|
302| "CONT2" | Draw a contour plot using the same line style for all contours.|
303| "CONT3" | Draw a contour plot using fill area colors.|
304| "CONT4" | Draw a contour plot using surface colors (SURF option at theta = 0).|
305| "LIST" | Generate a list of TGraph objects for each contour.|
306| "SAME0" | Same as "SAME" but do not use the z-axis range of the first plot. |
307| "SAMES0" | Same as "SAMES" but do not use the z-axis range of the first plot. |
308| "CYL" | Use Cylindrical coordinates. The X coordinate is mapped on the angle and the Y coordinate on the cylinder length.|
309| "POL" | Use Polar coordinates. The X coordinate is mapped on the angle and the Y coordinate on the radius.|
310| "SPH" | Use Spherical coordinates. The X coordinate is mapped on the latitude and the Y coordinate on the longitude.|
311| "PSR" | Use PseudoRapidity/Phi coordinates. The X coordinate is mapped on Phi.|
312| "SURF" | Draw a surface plot with hidden line removal.|
313| "SURF1" | Draw a surface plot with hidden surface removal.|
314| "SURF2" | Draw a surface plot using colors to show the cell contents.|
315| "SURF3" | Same as SURF with in addition a contour view drawn on the top.|
316| "SURF4" | Draw a surface using Gouraud shading.|
317| "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.|
318| "AITOFF" | Draw a contour via an AITOFF projection.|
319| "MERCATOR" | Draw a contour via an Mercator projection.|
320| "SINUSOIDAL" | Draw a contour via an Sinusoidal projection.|
321| "PARABOLIC" | Draw a contour via an Parabolic projection.|
322| "MOLLWEIDE" | Draw a contour via an Mollweide projection.|
323| "LEGO9" | Draw the 3D axis only. Mainly needed for internal use |
324| "FB" | With LEGO or SURFACE, suppress the Front-Box.|
325| "BB" | With LEGO or SURFACE, suppress the Back-Box.|
326| "A" | With LEGO or SURFACE, suppress the axis.|
327| "SCAT" | Draw a scatter-plot (deprecated option).|
328| "[cutg]" | Draw only the sub-range selected by the TCutG named "cutg".|
329
330
331\anchor HP01d
332#### Options supported for 3D histograms
333
334| Option | Description |
335|----------|-------------------------------------------------------------------|
336| " " | Default (color plot).|
337| "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)`.|
338| "BOX" | Draw a for each cell with volume proportional to the content's absolute value. An hidden line removal algorithm is used|
339| "BOX1" | Same as BOX but an hidden surface removal algorithm is used|
340| "BOX2" | The boxes' colors are picked in the current palette according to the bins' contents|
341| "BOX2Z" | Same as "BOX2". In addition the color palette is also drawn.|
342| "BOX3" | Same as BOX1, but the border lines of each lego-bar are not drawn.|
343| "LEGO" | Same as `BOX`.|
344
345
346\anchor HP01e
347#### Options supported for histograms' stacks (`THStack`)
348
349| Option | Description |
350|------------|-----------------------------------------------------------------|
351| " " | Default, the histograms are drawn on top of each other (as lego plots for 2D histograms).|
352| "NOSTACK" | Histograms in the stack are all paint in the same pad as if the option `SAME` had been specified.|
353| "NOSTACKB" | Histograms are drawn next to each other as bar charts.|
354| "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.|
355| "PFC" | Palette Fill Color: stack's fill color is taken in the current palette. |
356| "PLC" | Palette Line Color: stack's line color is taken in the current palette. |
357| "PMC" | Palette Marker Color: stack's marker color is taken in the current palette. |
358
359
360
361\anchor HP02
362### Setting the Style
363
364
365Histograms use the current style (`gStyle`). When one changes the current
366style and would like to propagate the changes to the histogram,
367`TH1::UseCurrentStyle` should be called. Call `UseCurrentStyle` on
368each histogram is needed.
369
370To force all the histogram to use the current style use:
371
372 gROOT->ForceStyle();
373
374All the histograms read after this call will use the current style.
375
376
377\anchor HP03
378### Setting line, fill, marker, and text attributes
379
380
381The histogram classes inherit from the attribute classes:
382`TAttLine`, `TAttFill` and `TAttMarker`.
383See the description of these classes for the list of options.
384
385
386\anchor HP04
387### Setting Tick marks on the histogram axis
388
389
390The `TPad::SetTicks` method specifies the type of tick marks on the axis.
391If ` tx = gPad->GetTickx()` and `ty = gPad->GetTicky()` then:
392
393 tx = 1; tick marks on top side are drawn (inside)
394 tx = 2; tick marks and labels on top side are drawn
395 ty = 1; tick marks on right side are drawn (inside)
396 ty = 2; tick marks and labels on right side are drawn
397
398By default only the left Y axis and X bottom axis are drawn
399(`tx = ty = 0`)
400
401`TPad::SetTicks(tx,ty)` allows to set these options.
402See also The `TAxis` functions to set specific axis attributes.
403
404In case multiple color filled histograms are drawn on the same pad, the fill
405area may hide the axis tick marks. One can force a redraw of the axis over all
406the histograms by calling:
407
408 gPad->RedrawAxis();
409
410
411\anchor HP05
412### Giving titles to the X, Y and Z axis
413
414
415 h->GetXaxis()->SetTitle("X axis title");
416 h->GetYaxis()->SetTitle("Y axis title");
417
418The histogram title and the axis titles can be any `TLatex` string.
419The titles are part of the persistent histogram.
420
421
422\anchor HP060
423### The option "SAME"
424
425
426By default, when an histogram is drawn, the current pad is cleared before
427drawing. In order to keep the previous drawing and draw on top of it the
428option `SAME` should be use. The histogram drawn with the option
429`SAME` uses the coordinates system available in the current pad.
430
431This option can be used alone or combined with any valid drawing option but
432some combinations must be use with care.
433
434\anchor HP060a
435#### Limitations
436
437- It does not work when combined with the `LEGO` and `SURF` options unless the
438 histogram plotted with the option `SAME` has exactly the same
439 ranges on the X, Y and Z axis as the currently drawn histogram. To superimpose
440 lego plots [histograms' stacks](\ref HP26) should be used.
441
442
443\anchor HP061
444### Colors automatically picked in palette
445
446\since **ROOT version 6.09/01**
447
448When several histograms are painted in the same canvas thanks to the option "SAME"
449or via a `THStack` it might be useful to have an easy and automatic way to choose
450their color. The simplest way is to pick colors in the current active color
451palette. Palette coloring for histogram is activated thanks to the options `PFC`
452(Palette Fill Color), `PLC` (Palette Line Color) and `PMC` (Palette Marker Color).
453When one of these options is given to `TH1::Draw` the histogram get its color
454from the current color palette defined by `gStyle->SetPalette(...)`. The color
455is determined according to the number of objects having palette coloring in
456the current pad.
457
458Begin_Macro(source)
459../../../tutorials/hist/histpalettecolor.C
460End_Macro
461
462Begin_Macro(source)
463../../../tutorials/hist/thstackpalettecolor.C
464End_Macro
465
466Begin_Macro(source)
467../../../tutorials/hist/thstack2palettecolor.C
468End_Macro
469
470\anchor HP06
471### Superimposing two histograms with different scales in the same pad
472
473
474The following example creates two histograms, the second histogram is the bins
475integral of the first one. It shows a procedure to draw the two histograms in
476the same pad and it draws the scale of the second histogram using a new vertical
477axis on the right side. See also the tutorial `transpad.C` for a variant
478of this example.
479
480Begin_Macro(source)
481{
482 auto c1 = new TCanvas("c1","c1",600,400);
483 // create/fill draw h1
484 gStyle->SetOptStat(kFALSE);
485 auto h1 = new TH1F("h1","Superimposing two histograms with different scales",100,-3,3);
486 Int_t i;
487 for (i=0;i<10000;i++) h1->Fill(gRandom->Gaus(0,1));
488 h1->Draw();
489 c1->Update();
490
491 // create hint1 filled with the bins integral of h1
492 auto hint1 = new TH1F("hint1","h1 bins integral",100,-3,3);
493 float sum = 0.f;
494 for (i=1;i<=100;i++) {
495 sum += h1->GetBinContent(i);
496 hint1->SetBinContent(i,sum);
497 }
498
499 // scale hint1 to the pad coordinates
500 float rightmax = 1.1*hint1->GetMaximum();
501 float scale = gPad->GetUymax()/rightmax;
502 hint1->SetLineColor(kRed);
503 hint1->Scale(scale);
504 hint1->Draw("same");
505
506 // draw an axis on the right side
507 auto axis = new TGaxis(gPad->GetUxmax(),gPad->GetUymin(),
508 gPad->GetUxmax(), gPad->GetUymax(),0,rightmax,510,"+L");
509 axis->SetLineColor(kRed);
510 axis->SetTextColor(kRed);
511 axis->Draw();
512}
513End_Macro
514
515
516\anchor HP07
517### Statistics Display
518
519
520The type of information shown in the histogram statistics box can be selected
521with:
522
523 gStyle->SetOptStat(mode);
524
525The `mode` has up to nine digits that can be set to on (1 or 2), off (0).
526
527 mode = ksiourmen (default = 000001111)
528 k = 1; kurtosis printed
529 k = 2; kurtosis and kurtosis error printed
530 s = 1; skewness printed
531 s = 2; skewness and skewness error printed
532 i = 1; integral of bins printed
533 i = 2; integral of bins with option "width" printed
534 o = 1; number of overflows printed
535 u = 1; number of underflows printed
536 r = 1; standard deviation printed
537 r = 2; standard deviation and standard deviation error printed
538 m = 1; mean value printed
539 m = 2; mean and mean error values printed
540 e = 1; number of entries printed
541 n = 1; name of histogram is printed
542
543For example:
544
545 gStyle->SetOptStat(11);
546
547displays only the name of histogram and the number of entries, whereas:
548
549 gStyle->SetOptStat(1101);
550
551displays the name of histogram, mean value and standard deviation.
552
553<b>WARNING 1:</b> never do:
554
555 gStyle->SetOptStat(0001111);
556
557but instead do:
558
559 gStyle->SetOptStat(1111);
560
561because `0001111` will be taken as an octal number!
562
563<b>WARNING 2:</b> for backward compatibility with older versions
564
565 gStyle->SetOptStat(1);
566
567is taken as:
568
569 gStyle->SetOptStat(1111)
570
571To print only the name of the histogram do:
572
573 gStyle->SetOptStat(1000000001);
574
575<b>NOTE</b> that in case of 2D histograms, when selecting only underflow
576(10000) or overflow (100000), the statistics box will show all combinations
577of underflow/overflows and not just one single number.
578
579The parameter mode can be any combination of the letters `kKsSiIourRmMen`
580
581 k : kurtosis printed
582 K : kurtosis and kurtosis error printed
583 s : skewness printed
584 S : skewness and skewness error printed
585 i : integral of bins printed
586 I : integral of bins with option "width" printed
587 o : number of overflows printed
588 u : number of underflows printed
589 r : standard deviation printed
590 R : standard deviation and standard deviation error printed
591 m : mean value printed
592 M : mean value mean error values printed
593 e : number of entries printed
594 n : name of histogram is printed
595
596For example, to print only name of histogram and number of entries do:
597
598 gStyle->SetOptStat("ne");
599
600To print only the name of the histogram do:
601
602 gStyle->SetOptStat("n");
603
604The default value is:
605
606 gStyle->SetOptStat("nemr");
607
608When a histogram is painted, a `TPaveStats` object is created and added
609to the list of functions of the histogram. If a `TPaveStats` object
610already exists in the histogram list of functions, the existing object is just
611updated with the current histogram parameters.
612
613Once a histogram is painted, the statistics box can be accessed using
614`h->FindObject("stats")`. In the command line it is enough to do:
615
616 Root > h->Draw()
617 Root > TPaveStats *st = (TPaveStats*)h->FindObject("stats")
618
619because after `h->Draw()` the histogram is automatically painted. But
620in a script file the painting should be forced using `gPad->Update()`
621in order to make sure the statistics box is created:
622
623 h->Draw();
624 gPad->Update();
625 TPaveStats *st = (TPaveStats*)h->FindObject("stats");
626
627Without `gPad->Update()` the line `h->FindObject("stats")` returns a null pointer.
628
629When a histogram is drawn with the option `SAME`, the statistics box
630is not drawn. To force the statistics box drawing with the option
631`SAME`, the option `SAMES` must be used.
632If the new statistics box hides the previous statistics box, one can change
633its position with these lines (`h` being the pointer to the histogram):
634
635 Root > TPaveStats *st = (TPaveStats*)h->FindObject("stats")
636 Root > st->SetX1NDC(newx1); //new x start position
637 Root > st->SetX2NDC(newx2); //new x end position
638
639To change the type of information for an histogram with an existing
640`TPaveStats` one should do:
641
642 st->SetOptStat(mode);
643
644Where `mode` has the same meaning than when calling `gStyle->SetOptStat(mode)`
645(see above).
646
647One can delete the statistics box for a histogram `TH1* h` with:
648
649 h->SetStats(0)
650
651and activate it again with:
652
653 h->SetStats(1).
654
655Labels used in the statistics box ("Mean", "Std Dev", ...) can be changed from
656`$ROOTSYS/etc/system.rootrc` or `.rootrc` (look for the string `Hist.Stats.`).
657
658
659\anchor HP08
660### Fit Statistics
661
662
663The type of information about fit parameters printed in the histogram statistics
664box can be selected via the parameter mode. The parameter mode can be
665`= pcev` (default `= 0111`)
666
667 p = 1; print Probability
668 c = 1; print Chisquare/Number of degrees of freedom
669 e = 1; print errors (if e=1, v must be 1)
670 v = 1; print name/values of parameters
671
672Example:
673
674 gStyle->SetOptFit(1011);
675
676print fit probability, parameter names/values and errors.
677
6781. When `v = 1` is specified, only the non-fixed parameters are shown.
6792. When `v = 2` all parameters are shown.
680
681Note: `gStyle->SetOptFit(1)` means "default value", so it is equivalent
682to `gStyle->SetOptFit(111)`
683
684
685\anchor HP09
686### The error bars options
687
688
689| Option | Description |
690|----------|-------------------------------------------------------------------|
691| "E" | Default. Shows only the error bars, not a marker.|
692| "E1" | Small lines are drawn at the end of the error bars.|
693| "E2" | Error rectangles are drawn.|
694| "E3" | A filled area is drawn through the end points of the vertical error bars.|
695| "E4" | A smoothed filled area is drawn through the end points of the vertical error bars.|
696| "E0" | Draw error bars. Markers are drawn for bins with 0 contents. Combined with E1 or E2 it avoids error bars clipping|
697| "E5" | Like E3 but ignore the bins with 0 contents.|
698| "E6" | Like E4 but ignore the bins with 0 contents.|
699| "X0" | When used with one of the "E" option, it suppress the error bar along X as `gStyle->SetErrorX(0)` would do.|
700
701Begin_Macro(source)
702{
703 auto c1 = new TCanvas("c1","c1",600,400);
704 auto he = new TH1F("he","Distribution drawn with error bars (option E1) ",100,-3,3);
705 for (int i=0; i<10000; i++) he->Fill(gRandom->Gaus(0,1));
706 gStyle->SetEndErrorSize(3);
707 gStyle->SetErrorX(1.);
708 he->SetMarkerStyle(20);
709 he->Draw("E1");
710}
711End_Macro
712
713The options "E3" and "E4" draw an error band through the end points of the
714vertical error bars. With "E4" the error band is smoothed. Because of the
715smoothing algorithm used some artefacts may appear at the end of the band
716like in the following example. In such cases "E3" should be used instead
717of "E4".
718
719Begin_Macro(source)
720{
721 auto ce4 = new TCanvas("ce4","ce4",600,400);
722 ce4->Divide(2,1);
723 auto he4 = new TH1F("he4","Distribution drawn with option E4",100,-3,3);
724 Int_t i;
725 for (i=0;i<10000;i++) he4->Fill(gRandom->Gaus(0,1));
726 he4->SetFillColor(kRed);
727 he4->GetXaxis()->SetRange(40,48);
728 ce4->cd(1);
729 he4->Draw("E4");
730 ce4->cd(2);
731 auto he3 = (TH1F*)he4->DrawClone("E3");
732 he3->SetTitle("Distribution drawn option E3");
733}
734End_Macro
735
7362D histograms can be drawn with error bars as shown is the following example:
737
738Begin_Macro(source)
739{
740 auto c2e = new TCanvas("c2e","c2e",600,400);
741 auto h2e = new TH2F("h2e","TH2 drawn with option E",40,-4,4,40,-20,20);
742 float px, py;
743 for (Int_t i = 0; i < 25000; i++) {
744 gRandom->Rannor(px,py);
745 h2e->Fill(px,5*py);
746 }
747 h2e->Draw("E");
748}
749End_Macro
750
751
752\anchor HP100
753### The bar chart option
754
755
756The option "B" allows to draw simple vertical bar charts.
757The bar width is controlled with `TH1::SetBarWidth()`,
758and the bar offset within the bin, with `TH1::SetBarOffset()`.
759These two settings are useful to draw several histograms on the
760same plot as shown in the following example:
761
762Begin_Macro(source)
763{
764 int i;
765 const Int_t nx = 8;
766 string os_X[nx] = {"8","32","128","512","2048","8192","32768","131072"};
767 float d_35_0[nx] = {0.75, -3.30, -0.92, 0.10, 0.08, -1.69, -1.29, -2.37};
768 float d_35_1[nx] = {1.01, -3.02, -0.65, 0.37, 0.34, -1.42, -1.02, -2.10};
769
770 auto cb = new TCanvas("cb","cb",600,400);
771 cb->SetGrid();
772
773 gStyle->SetHistMinimumZero();
774
775 auto h1b = new TH1F("h1b","Option B example",nx,0,nx);
776 h1b->SetFillColor(4);
777 h1b->SetBarWidth(0.4);
778 h1b->SetBarOffset(0.1);
779 h1b->SetStats(0);
780 h1b->SetMinimum(-5);
781 h1b->SetMaximum(5);
782
783 for (i=1; i<=nx; i++) {
784 h1b->SetBinContent(i, d_35_0[i-1]);
785 h1b->GetXaxis()->SetBinLabel(i,os_X[i-1].c_str());
786 }
787
788 h1b->Draw("b");
789
790 auto h2b = new TH1F("h2b","h2b",nx,0,nx);
791 h2b->SetFillColor(38);
792 h2b->SetBarWidth(0.4);
793 h2b->SetBarOffset(0.5);
794 h2b->SetStats(0);
795 for (i=1;i<=nx;i++) h2b->SetBinContent(i, d_35_1[i-1]);
796
797 h2b->Draw("b same");
798}
799End_Macro
800
801
802\anchor HP10
803### The "BAR" and "HBAR" options
804
805
806When the option `bar` or `hbar` is specified, a bar chart is drawn. A vertical
807bar-chart is drawn with the options `bar`, `bar0`, `bar1`, `bar2`, `bar3`, `bar4`.
808An horizontal bar-chart is drawn with the options `hbar`, `hbar0`, `hbar1`,
809`hbar2`, `hbar3`, `hbar4` (hbars.C).
810
811- The bar is filled with the histogram fill color.
812- The left side of the bar is drawn with a light fill color.
813- The right side of the bar is drawn with a dark fill color.
814- The percentage of the bar drawn with either the light or dark color is:
815 - 0% for option "(h)bar" or "(h)bar0"
816 - 10% for option "(h)bar1"
817 - 20% for option "(h)bar2"
818 - 30% for option "(h)bar3"
819 - 40% for option "(h)bar4"
820
821When an histogram has errors the option ["HIST"](\ref OPTHIST) together with the `(h)bar` option.
822
823Begin_Macro(source)
824../../../tutorials/hist/hbars.C
825End_Macro
826
827To control the bar width (default is the bin width) `TH1::SetBarWidth()`
828should be used.
829
830To control the bar offset (default is 0) `TH1::SetBarOffset()` should
831be used.
832
833These two parameters are useful when several histograms are plotted using
834the option `SAME`. They allow to plot the histograms next to each other.
835
836
837\anchor HP11
838### The SCATter plot option
839
840\attention
841Use of option `SCAT` has been deprecated. It was the default drawing option for 2D and
8423D histograms. The new default option is `COL` (heat-map).
843
844
845For each cell (i,j) a number of points proportional to the cell content is
846drawn. A maximum of `kNMAX` points per cell is drawn. If the maximum is above
847`kNMAX` contents are normalized to `kNMAX` (`kNMAX=2000`).
848If option is of the form `scat=ff`, (eg `scat=1.8`,
849`scat=1e-3`), then `ff` is used as a scale factor to compute the
850number of dots. `scat=1` is the default.
851
852By default the scatter plot is painted with a "dot marker" which not scalable
853(see the `TAttMarker` documentation). To change the marker size, a scalable marker
854type should be used. For instance a circle (marker style 20).
855
856Begin_Macro(source)
857{
858 auto c1 = new TCanvas("c1","c1",600,400);
859 auto hscat = new TH2F("hscat","Option SCATter example (default for 2D histograms) ",40,-4,4,40,-20,20);
860 float px, py;
861 for (Int_t i = 0; i < 25000; i++) {
862 gRandom->Rannor(px,py);
863 hscat->Fill(px,5*py);
864 hscat->Fill(3+0.5*px,2*py-10.);
865 }
866 hscat->Draw("scat=0.5");
867}
868End_Macro
869
870
871\anchor HP12
872### The ARRow option
873
874
875Shows gradient between adjacent cells. For each cell (i,j) an arrow is drawn
876The orientation of the arrow follows the cell gradient.
877
878Begin_Macro(source)
879{
880 auto c1 = new TCanvas("c1","c1",600,400);
881 auto harr = new TH2F("harr","Option ARRow example",20,-4,4,20,-20,20);
882 harr->SetLineColor(kRed);
883 float px, py;
884 for (Int_t i = 0; i < 25000; i++) {
885 gRandom->Rannor(px,py);
886 harr->Fill(px,5*py);
887 harr->Fill(3+0.5*px,2*py-10.,0.1);
888 }
889 harr->Draw("ARR");
890}
891End_Macro
892
893\since **ROOT version 6.17/01**
894
895The option `ARR` can be combined with the option `COL` or `COLZ`.
896
897Begin_Macro(source)
898{
899 auto c1 = new TCanvas("c1","c1",600,400);
900 auto harr = new TH2F("harr","Option ARR + COLZ example",20,-4,4,20,-20,20);
901 harr->SetStats(0);
902 float px, py;
903 for (Int_t i = 0; i < 25000; i++) {
904 gRandom->Rannor(px,py);
905 harr->Fill(px,5*py);
906 harr->Fill(3+0.5*px,2*py-10.,0.1);
907 }
908 harr->Draw("ARR COLZ");
909}
910End_Macro
911
912
913\anchor HP13
914### The BOX option
915
916
917For each cell (i,j) a box is drawn. The size (surface) of the box is
918proportional to the absolute value of the cell content.
919The cells with a negative content are drawn with a `X` on top of the box.
920
921Begin_Macro(source)
922{
923 auto c1 = new TCanvas("c1","c1",600,400);
924 auto hbox = new TH2F("hbox","Option BOX example",3,0,3,3,0,3);
925 hbox->SetFillColor(42);
926 hbox->Fill(0.5, 0.5, 1.);
927 hbox->Fill(0.5, 1.5, 4.);
928 hbox->Fill(0.5, 2.5, 3.);
929 hbox->Fill(1.5, 0.5, 2.);
930 hbox->Fill(1.5, 1.5, 12.);
931 hbox->Fill(1.5, 2.5, -6.);
932 hbox->Fill(2.5, 0.5, -4.);
933 hbox->Fill(2.5, 1.5, 6.);
934 hbox->Fill(2.5, 2.5, 0.5);
935 hbox->Draw("BOX");
936}
937End_Macro
938
939With option `BOX1` a button is drawn for each cell with surface
940proportional to content's absolute value. A sunken button is drawn for
941negative values a raised one for positive.
942
943Begin_Macro(source)
944{
945 auto c1 = new TCanvas("c1","c1",600,400);
946 auto hbox1 = new TH2F("hbox1","Option BOX1 example",3,0,3,3,0,3);
947 hbox1->SetFillColor(42);
948 hbox1->Fill(0.5, 0.5, 1.);
949 hbox1->Fill(0.5, 1.5, 4.);
950 hbox1->Fill(0.5, 2.5, 3.);
951 hbox1->Fill(1.5, 0.5, 2.);
952 hbox1->Fill(1.5, 1.5, 12.);
953 hbox1->Fill(1.5, 2.5, -6.);
954 hbox1->Fill(2.5, 0.5, -4.);
955 hbox1->Fill(2.5, 1.5, 6.);
956 hbox1->Fill(2.5, 2.5, 0.5);
957 hbox1->Draw("BOX1");
958}
959End_Macro
960
961When the option `SAME` (or "SAMES") is used with the option `BOX`,
962the boxes' sizes are computing taking the previous plots into account. The range
963along the Z axis is imposed by the first plot (the one without option
964`SAME`); therefore the order in which the plots are done is relevant.
965
966Begin_Macro(source)
967{
968 auto c1 = new TCanvas("c1","c1",600,400);
969 auto hb1 = new TH2F("hb1","Example of BOX plots with option SAME ",40,-3,3,40,-3,3);
970 auto hb2 = new TH2F("hb2","hb2",40,-3,3,40,-3,3);
971 auto hb3 = new TH2F("hb3","hb3",40,-3,3,40,-3,3);
972 auto hb4 = new TH2F("hb4","hb4",40,-3,3,40,-3,3);
973 for (Int_t i=0;i<1000;i++) {
974 double x,y;
975 gRandom->Rannor(x,y);
976 if (x>0 && y>0) hb1->Fill(x,y,4);
977 if (x<0 && y<0) hb2->Fill(x,y,3);
978 if (x>0 && y<0) hb3->Fill(x,y,2);
979 if (x<0 && y>0) hb4->Fill(x,y,1);
980 }
981 hb1->SetFillColor(1);
982 hb2->SetFillColor(2);
983 hb3->SetFillColor(3);
984 hb4->SetFillColor(4);
985 hb1->Draw("box");
986 hb2->Draw("box same");
987 hb3->Draw("box same");
988 hb4->Draw("box same");
989}
990End_Macro
991
992\since **ROOT version 6.17/01:**
993
994Sometimes the change of the range of the Z axis is unwanted, in which case, one
995can use `SAME0` (or `SAMES0`) option to opt out of this change.
996
997Begin_Macro(source)
998{
999 auto h2 = new TH2F("h2"," ",10,0,10,10,20,30);
1000 auto hf = (TH2F*)h2->Clone("hf");
1001 h2->SetBit(TH1::kNoStats);
1002 hf->SetBit(TH1::kNoStats);
1003 h2->Fill(5,22);
1004 h2->Fill(5,23);
1005 h2->Fill(6,22);
1006 h2->Fill(6,23);
1007 hf->Fill(6,23);
1008 hf->Fill(6,23);
1009 hf->Fill(6,23);
1010 hf->Fill(6,23);
1011 hf->Fill(5,23);
1012
1013 auto hf_copy1 = hf->Clone("hf_copy1");
1014 TLatex lt;
1015
1016 auto cx = new TCanvas(); cx->Divide(2,1);
1017
1018 cx->cd(1);
1019 h2->Draw("box");
1020 hf->Draw("text colz same");
1021 lt.DrawLatexNDC(0.3,0.5,"SAME");
1022
1023 cx->cd(2);
1024 h2->Draw("box");
1025 hf_copy1->Draw("text colz same0");
1026 lt.DrawLatexNDC(0.3,0.5,"SAME0");
1027}
1028End_Macro
1029
1030
1031\anchor HP14
1032### The COLor option (default for 2D histograms)
1033
1034The magnitude of individual cell (i,j) is represented as a color picked in the current color palette.
1035This data visualization technique is often called a heat map (or heat-map).
1036
1037The color table used is defined in the current style.
1038
1039If the histogram's minimum and maximum are the same (flat histogram), the
1040mapping on colors is not possible, therefore nothing is painted. To paint a
1041flat histogram it is enough to set the histogram minimum
1042(`TH1::SetMinimum()`) different from the bins' content.
1043
1044The default number of color levels used to paint the cells is 20.
1045It can be changed with `TH1::SetContour()` or
1046`TStyle::SetNumberContours()`. The higher this number is, the smoother
1047is the color change between cells.
1048
1049The color palette in TStyle can be modified via `gStyle->SetPalette()`.
1050
1051All the non-empty bins are painted. Empty bins are not painted unless
1052some bins have a negative content because in that case the null bins
1053might be not empty.
1054
1055`TProfile2D` histograms are handled differently because, for this type of 2D
1056histograms, it is possible to know if an empty bin has been filled or not. So even
1057if all the bins' contents are positive some empty bins might be painted. And vice versa,
1058if some bins have a negative content some empty bins might be not painted.
1059
1060Combined with the option `COL`, the option `Z` allows to
1061display the color palette defined by `gStyle->SetPalette()`.
1062
1063In the following example, the histogram has only positive bins; the empty
1064bins (containing 0) are not drawn.
1065
1066Begin_Macro(source)
1067{
1068 auto c1 = new TCanvas("c1","c1",600,400);
1069 auto hcol1 = new TH2F("hcol1","Option COLor example ",40,-4,4,40,-20,20);
1070 float px, py;
1071 for (Int_t i = 0; i < 25000; i++) {
1072 gRandom->Rannor(px,py);
1073 hcol1->Fill(px,5*py);
1074 }
1075 hcol1->Draw("COLZ");
1076}
1077End_Macro
1078
1079In the first plot of following example, the histogram has some negative bins;
1080the empty bins (containing 0) are drawn. In some cases one wants to not draw
1081empty bins (containing 0) of histograms having a negative minimum. The option
1082`1`, used to produce the second plot in the following picture, allows to do that.
1083
1084Begin_Macro(source)
1085{
1086 auto c1 = new TCanvas("c1","c1",600,600);
1087 c1->Divide(1,2);
1088 auto hcol23 = new TH2F("hcol23","Option COLZ example ",40,-4,4,40,-20,20);
1089 auto hcol24 = new TH2F("hcol24","Option COLZ1 example ",40,-4,4,40,-20,20);
1090 float px, py;
1091 for (Int_t i = 0; i < 25000; i++) {
1092 gRandom->Rannor(px,py);
1093 hcol23->Fill(px,5*py);
1094 hcol24->Fill(px,5*py);
1095 }
1096 hcol23->Fill(0.,0.,-200.);
1097 hcol24->Fill(0.,0.,-200.);
1098 c1->cd(1); hcol23->Draw("COLZ");
1099 c1->cd(2); hcol24->Draw("COLZ1");
1100}
1101End_Macro
1102
1103When the maximum of the histogram is set to a smaller value than the real maximum,
1104 the bins having a content between the new maximum and the real maximum are
1105painted with the color corresponding to the new maximum.
1106
1107When the minimum of the histogram is set to a greater value than the real minimum,
1108 the bins having a value between the real minimum and the new minimum are not drawn
1109 unless the option `0` is set.
1110
1111The following example illustrates the option `0` combined with the option `COL`.
1112
1113Begin_Macro(source)
1114{
1115 auto c1 = new TCanvas("c1","c1",600,600);
1116 c1->Divide(1,2);
1117 auto hcol21 = new TH2F("hcol21","Option COLZ",40,-4,4,40,-20,20);
1118 auto hcol22 = new TH2F("hcol22","Option COLZ0",40,-4,4,40,-20,20);
1119 float px, py;
1120 for (Int_t i = 0; i < 25000; i++) {
1121 gRandom->Rannor(px,py);
1122 hcol21->Fill(px,5*py);
1123 hcol22->Fill(px,5*py);
1124 }
1125 hcol21->SetBit(TH1::kNoStats);
1126 hcol22->SetBit(TH1::kNoStats);
1127 c1->cd(1); hcol21->Draw("COLZ");
1128 c1->cd(2); hcol22->Draw("COLZ0");
1129 hcol22->SetMaximum(100);
1130 hcol22->SetMinimum(40);
1131}
1132End_Macro
1133
1134\since **ROOT version 6.09/01:**
1135
1136When the option SAME (or "SAMES") is used with the option COL, the boxes' color
1137are computing taking the previous plots into account. The range along the Z axis
1138is imposed by the first plot (the one without option SAME); therefore the order
1139in which the plots are done is relevant. Same as [in the `BOX` option](\ref HP13), one can use
1140`SAME0` (or `SAMES0`) to opt out of this imposition.
1141
1142Begin_Macro(source)
1143{
1144 auto c = new TCanvas("c","Example of col plots with option SAME",200,10,700,500);
1145 auto h1 = new TH2F("h1","h1",40,-3,3,40,-3,3);
1146 auto h2 = new TH2F("h2","h2",40,-3,3,40,-3,3);
1147 auto h3 = new TH2F("h3","h3",40,-3,3,40,-3,3);
1148 auto h4 = new TH2F("h4","h4",40,-3,3,40,-3,3);
1149 h1->SetBit(TH1::kNoStats);
1150 for (Int_t i=0;i<5000;i++) {
1151 double x,y;
1152 gRandom->Rannor(x,y);
1153 if(x>0 && y>0) h1->Fill(x,y,4);
1154 if(x<0 && y<0) h2->Fill(x,y,3);
1155 if(x>0 && y<0) h3->Fill(x,y,2);
1156 if(x<0 && y>0) h4->Fill(x,y,1);
1157 }
1158 h1->Draw("colz");
1159 h2->Draw("col same");
1160 h3->Draw("col same");
1161 h4->Draw("col same");
1162}
1163End_Macro
1164
1165The option `COL` can be combined with the option `POL`:
1166
1167Begin_Macro(source)
1168{
1169 auto c1 = new TCanvas("c1","c1",600,400);
1170 auto hcol1 = new TH2F("hcol1","Option COLor combined with POL",40,-4,4,40,-4,4);
1171 float px, py;
1172 for (Int_t i = 0; i < 25000; i++) {
1173 gRandom->Rannor(px,py);
1174 hcol1->Fill(px,py);
1175 }
1176 hcol1->Draw("COLZPOL");
1177}
1178End_Macro
1179
1180\since **ROOT version 6.07/03:**
1181
1182A second rendering technique is also available with the COL2 and COLZ2 options.
1183
1184These options provide potential performance improvements compared to the standard
1185COL option. The performance comparison of the COL2 to the COL option depends on
1186the histogram and the size of the rendering region in the current pad. In general,
1187a small (approx. less than 100 bins per axis), sparsely populated TH2 will render
1188faster with the COL option.
1189
1190However, for larger histograms (approx. more than 100 bins per axis)
1191that are not sparse, the COL2 option will provide up to 20 times performance improvements.
1192For example, a 1000x1000 bin TH2 that is not sparse will render an order of magnitude
1193faster with the COL2 option.
1194
1195The COL2 option will also scale its performance based on the size of the
1196pixmap the histogram image is being rendered into. It also is much better optimized for
1197sessions where the user is forwarding X11 windows through an `ssh` connection.
1198
1199For the most part, the COL2 and COLZ2 options are a drop in replacement to the COL
1200and COLZ options. There is one major difference and that concerns the treatment of
1201bins with zero content. The COL2 and COLZ2 options color these bins the color of zero.
1202
1203COL2 option renders the histogram as a bitmap. Therefore it cannot be saved in vector
1204graphics file format like PostScript or PDF (an empty image will be generated). It can
1205be saved only in bitmap files like PNG format for instance.
1206
1207
1208\anchor HP140
1209### The CANDLE and VIOLIN options
1210
1211The mechanism behind Candle plots and Violin plots is very similar. Because of this they are
1212implemented in the same class TCandle. The keywords CANDLE or VIOLIN will initiate the drawing of
1213the corresponding plots. Followed by the keyword the user can select a plot direction (X or V for
1214vertical projections, or Y or H for horizontal projections) and/or predefined definitions
1215(1-6 for candles, 1-2 for violins). The order doesn't matter. Default is X and 1.
1216
1217Instead of using the predefined representations, the candle and violin parameters can be
1218changed individually. In that case the option have the following form:
1219
1220 CANDLEX(<option-string>)
1221 CANDLEY(<option-string>)
1222 VIOLINX(<option-string>)
1223 VIOLINY(<option-string>).
1224
1225All zeros at the beginning of `option-string` can be omitted.
1226
1227`option-string` consists eight values, defined as follow:
1228
1229 "CANDLEX(zhpawMmb)"
1230
1231Where:
1232
1233 - `b = 0`; no box drawn
1234 - `b = 1`; the box is drawn. As the candle-plot is also called a box-plot it
1235 makes sense in the very most cases to always draw the box
1236 - `b = 2`; draw a filled box with border
1237
1238 - `m = 0`; no median drawn
1239 - `m = 1`; median is drawn as a line
1240 - `m = 2`; median is drawn with errors (notches)
1241 - `m = 3`; median is drawn as a circle
1242
1243 - `M = 0`; no mean drawn
1244 - `M = 1`; mean is drawn as a dashed line
1245 - `M = 3`; mean is drawn as a circle
1246
1247 - `w = 0`; no whisker drawn
1248 - `w = 1`; whisker is drawn to end of distribution.
1249 - `w = 2`; whisker is drawn to max 1.5*iqr
1250
1251 - `a = 0`; no anchor drawn
1252 - `a = 1`; the anchors are drawn
1253
1254 - `p = 0`; no points drawn
1255 - `p = 1`; only outliers are drawn
1256 - `p = 2`; all datapoints are drawn
1257 - `p = 3`: all datapoints are drawn scattered
1258
1259 - `h = 0`; no histogram is drawn
1260 - `h = 1`; histogram at the left or bottom side is drawn
1261 - `h = 2`; histogram at the right or top side is drawn
1262 - `h = 3`; histogram at left and right or top and bottom (violin-style) is drawn
1263
1264 - `z = 0`; no zero indicator line is drawn
1265 - `z = 1`; zero indicator line is drawn.
1266
1267As one can see all individual options for both candle and violin plots can be accessed by this
1268mechanism. In deed the keywords CANDLE(<option-string>) and VIOLIN(<option-string>) have the same
1269meaning. So you can parametrise an option-string for a candle plot and use the keywords VIOLIN and
1270vice versa, if you wish.
1271
1272Using a logarithmic x- or y-axis is possible for candle and violin charts.
1273
1274\since **ROOT version 6.11/01**
1275
1276a logarithmic z-axis is possible, too but will only affect violin charts of course.
1277
1278\anchor HP140a
1279#### The CANDLE option
1280
1281<a href="http://en.wikipedia.org/wiki/Box_plot">A Candle plot</a> (also known as
1282a "box plot" or "whisker plot") was invented in 1977 by John Tukey. It is a convenient
1283way to describe graphically a data distribution (D) with only five numbers:
1284
1285 1. The minimum value of the distribution D (bottom or left whisker).
1286 2. The lower quartile (Q1): 25% of the data points in D are less than Q1 (bottom of the box).
1287 3. The median (M): 50% of the data points in D are less than M.
1288 4. The upper quartile (Q3): 75% of the data points in D are less than Q3 (top of the box).
1289 5. The maximum value of the distribution D (top or right whisker).
1290
1291In this implementation a TH2 is considered as a collection of TH1 along
1292X (option `CANDLE` or `CANDLEX`) or Y (option `CANDLEY`).
1293Each TH1 is represented as one candle.
1294
1295Begin_Macro(source)
1296../../../tutorials/hist/candleplotwhiskers.C
1297End_Macro
1298
1299The candle reduces the information coming from a whole distribution into few values.
1300Independently from the number of entries or the significance of the underlying distribution
1301a candle will always look like a candle. So candle plots should be used carefully in
1302particular with unknown distributions. The definition of a candle is based on
1303__unbinned data__. Here, candles are created from binned data. Because of this, the
1304deviation is connected to the bin width used. The calculation of the quantiles
1305normally done on unbinned data also. Because data are binned, this will
1306only work the best possible way within the resolution of one bin
1307
1308Because of all these facts one should take care that:
1309
1310 - there are enough points per candle
1311 - the bin width is small enough (more bins will increase the maximum
1312 available resolution of the quantiles although there will be some
1313 bins with no entries)
1314 - never make a candle-plot if the underlying distribution is double-distributed
1315 - only create candles of distributions that are more-or-less gaussian (the
1316 MPV should be not too far away from the mean).
1317
1318#### What a candle is made of
1319
1320\since **ROOT version 6.07/05**
1321
1322##### The box
1323The box displays the position of the inter-quantile-range of the underlying
1324distribution. The box contains 25% of the distribution below the median
1325and 25% of the distribution above the median. If the underlying distribution is large
1326enough and gaussian shaped the end-points of the box represent \f$ 0.6745\times\sigma \f$
1327(Where \f$ \sigma \f$ is the standard deviation of the gaussian). The width and
1328the position of the box can be modified by SetBarWidth() and SetBarOffset().
1329The +-25% quantiles are calculated by the GetQuantiles() methods.
1330
1331\since **ROOT version 6.11/01**
1332
1333Using the static function TCandle::SetBoxRange(double) the box definition will be
1334overwritten. E.g. using a box range of 0.68 will redefine the area of the lower box edge
1335to the upper box edge in order to cover 68% of the distribution illustrated by that candle.
1336The static function will affect all candle-charts in the running program.
1337Default is 0.5.
1338
1339Using the static function TCandle::SetScaledCandle(bool) the width of the box (and the
1340whole candle) can be influenced. Deactivated, the width is constant (to be set by
1341SetBarWidth() ). Activated, the width of the boxes will be scaled to each other based on the
1342amount of data in the corresponding candle, the maximum width can be influenced by
1343SetBarWidth(). The static function will affect all candle-charts in the running program.
1344Default is false. Scaling between multiple candle-charts (using "same" or THStack) is not
1345supported, yet
1346
1347##### The Median
1348For a sorted list of numbers, the median is the value in the middle of the list.
1349E.g. if a sorted list is made of five numbers "1,2,3,6,7" 3 will be the median
1350because it is in the middle of the list. If the number of entries is even the
1351average of the two values in the middle will be used. As histograms are binned
1352data, the situation is a bit more complex. The following example shows this:
1353
1354~~~ {.cpp}
1355void quantiles() {
1356 auto h = new TH1I("h","h",10,0,10);
1357 //h->Fill(3);
1358 //h->Fill(3);
1359 h->Fill(4);
1360 h->Draw();
1361 double p = 0.;
1362 double q = 0.;
1363 h->GetQuantiles(1,&q,&p);
1364
1365 cout << "Median is: " << q << std::endl;
1366}
1367~~~
1368
1369Here the bin-width is 1.0. If the two Fill(3) are commented out, as there are currently,
1370the example will return a calculated median of 4.5, because that's the bin center
1371of the bin in which the value 4.0 has been dropped. If the two Fill(3) are not
1372commented out, it will return 3.75, because the algorithm tries to evenly distribute
1373the individual values of a bin with bin content > 0. It means the sorted list
1374would be "3.25, 3.75, 4.5".
1375
1376The consequence is a median of 3.75. This shows how important it is to use a
1377small enough bin-width when using candle-plots on binned data.
1378If the distribution is large enough and gaussian shaped the median will be exactly
1379equal to the mean.
1380The median can be shown as a line or as a circle or not shown at all.
1381
1382In order to show the significance of the median notched candle plots apply a "notch" or
1383narrowing of the box around the median. The significance is defined by
1384\f$ 1.57\times\frac{iqr}{N} \f$ and will be represented as the size of the notch
1385(where iqr is the size of the box and N is the number of entries of the whole
1386distribution). Candle plots like these are usually called "notched candle plots".
1387
1388In case the significance of the median is greater that the size of the box, the
1389box will have an unnatural shape. Usually it means the chart has not enough data,
1390or that representing this uncertainty is not useful
1391
1392##### The Mean
1393The mean can be drawn as a dashed line or as a circle or not drawn at all.
1394The mean is the arithmetic average of the values in the distribution.
1395It is calculated using GetMean(). Because histograms are
1396binned data, the mean value can differ from a calculation on the raw-data.
1397If the distribution is large enough and gaussian shaped the mean will be
1398exactly the median.
1399
1400##### The Whiskers
1401The whiskers represent the part of the distribution not covered by the box.
1402The upper 25% and the lower 25% of the distribution are located within the whiskers.
1403Two representations are available.
1404
1405 - A simple one (using w=1) defining the lower whisker from the lowest data value
1406 to the bottom of the box, and the upper whisker from the top of the box to the
1407 highest data value. In this representation the whisker-lines are dashed.
1408 - A more complex one having a further restriction. The whiskers are still connected
1409 to the box but their length cannot exceed \f$ 1.5\times iqr \f$. So it might
1410 be that the outermost part of the underlying distribution will not be covered
1411 by the whiskers. Usually these missing parts will be represented by the outliers
1412 (see points). Of course the upper and the lower whisker may differ in length.
1413 In this representation the whiskers are drawn as solid lines.
1414
1415\since **ROOT version 6.11/01**
1416
1417Using the static function TCandle::SetWhiskerRange(double) the whisker definition w=1
1418will be overwritten. E.g. using a whisker-range of 0.95 and w=1 will redefine the area of
1419the lower whisker to the upper whisker in order to cover 95% of the distribution inside
1420that candle. The static function will affect all candle-charts in the running program.
1421Default is 1.
1422
1423If the distribution is large enough and gaussian shaped, the maximum length of
1424the whisker will be located at \f$ \pm 2.698 \sigma \f$ (when using the
14251.5*iqr-definition (w=2), where \f$ \sigma \f$ is the standard deviation
1426(see picture above). In that case 99.3% of the total distribution will be covered
1427by the box and the whiskers, whereas 0.7% are represented by the outliers.
1428
1429##### The Anchors
1430The anchors have no special meaning in terms of statistical calculation. They mark
1431the end of the whiskers and they have the width of the box. Both representation
1432with and without anchors are common.
1433
1434##### The Points
1435Depending on the configuration the points can have different meanings:
1436 - If p=1 the points represent the outliers. If they are shown, it means
1437 some parts of the underlying distribution are not covered by the whiskers.
1438 This can only occur when the whiskers are set to option w=2. Here the whiskers
1439 can have a maximum length of \f$ 1.5 \times iqr \f$. So any points outside the
1440 whiskers will be drawn as outliers. The outliers will be represented by crosses.
1441 - If p=2 all points in the distribution will be painted as crosses. This is
1442 useful for small datasets only (up to 10 or 20 points per candle).
1443 The outliers are shown along the candle. Because the underlying distribution
1444 is binned, is frequently occurs that a bin contains more than one value.
1445 Because of this the points will be randomly scattered within their bin along
1446 the candle axis. If the bin content for a bin is exactly 1 (usually
1447 this happens for the outliers) if will be drawn in the middle of the bin along
1448 the candle axis. As the maximum number of points per candle is limited by kNMax/2
1449 on very large datasets scaling will be performed automatically. In that case one
1450 would loose all outliers because they have usually a bin content of 1 (and a
1451 bin content between 0 and 1 after the scaling). Because of this all bin contents
1452 between 0 and 1 - after the scaling - will be forced to be 1.
1453 - As the drawing of all values on large datasets can lead to big amounts of crosses,
1454 one can show all values as a scatter plot instead by choosing p=3. The points will be
1455 drawn as dots and will be scattered within the width of the candle. The color
1456 of the points will be the color of the candle-chart.
1457
1458##### Other Options
1459Is is possible to combine all options of candle and violin plots with each other. E.g. a box-plot
1460with a histogram.
1461
1462#### How to use the candle-plots drawing option
1463
1464There are six predefined candle-plot representations:
1465
1466 - "CANDLEX1": Standard candle (whiskers cover the whole distribution)
1467 - "CANDLEX2": Standard candle with better whisker definition + outliers.
1468 It is a good compromise
1469 - "CANDLEX3": Like candle2 but with a mean as a circle.
1470 It is easier to distinguish mean and median
1471 - "CANDLEX4": Like candle3 but showing the uncertainty of the median as well
1472 (notched candle plots).
1473 For bigger datasets per candle
1474 - "CANDLEX5": Like candle2 but showing all data points.
1475 For very small datasets
1476 - "CANDLEX6": Like candle2 but showing all datapoints scattered.
1477 For huge datasets
1478
1479
1480The following picture shows how the six predefined representations look.
1481
1482Begin_Macro
1483{
1484 auto c1 = new TCanvas("c1","c1",700,800);
1485 c1->Divide(2,3);
1486 gStyle->SetOptStat(kFALSE);
1487
1488 auto hcandle = new TH2F("hcandle"," ",10,-4,4,40,-20,20);
1489 float px, py;
1490 for (Int_t i = 0; i < 15000; i++) {
1491 gRandom->Rannor(px,py);
1492 hcandle->Fill(px,5*py);
1493 }
1494 hcandle->SetMarkerSize(0.5);
1495
1496 TH2F *h2;
1497 for (Int_t i=1; i<7; i++) {
1498 c1->cd(i);
1499 h2 = (TH2F*)hcandle->DrawClone(Form("CANDLE%d",i));
1500 h2->SetTitle(Form("CANDLE%d",i));
1501 }
1502}
1503End_Macro
1504
1505
1506#### Example 1
1507Box and improved whisker, no mean, no median, no anchor no outliers
1508
1509 h1->Draw("CANDLEX(2001)");
1510
1511#### Example 2
1512A Candle-definition like "CANDLEX2" (New standard candle with better whisker definition + outliers)
1513
1514 h1->Draw("CANDLEX(112111)");
1515
1516#### Example 3
1517The following example shows how several candle plots can be super-imposed using
1518the option SAME. Note that the bar-width and bar-offset are active on candle plots.
1519Also the color, the line width, the size of the points and so on can be changed by the
1520standard attribute setting methods such as SetLineColor() SetLineWidth().
1521
1522Begin_Macro(source)
1523../../../tutorials/hist/candleplot.C
1524End_Macro
1525
1526\anchor HP140b
1527#### The VIOLIN option
1528
1529<a href="http://en.wikipedia.org/wiki/Violin_plot">A violin plot</a> is a candle plot
1530that also encodes the pdf information at each point.
1531
1532
1533Quartiles and mean are also represented at each point, with a marker
1534and two lines.
1535
1536In this implementation a TH2 is considered as a collection of TH1 along
1537X (option `VIOLIN` or `VIOLINX`) or Y (option `VIOLINY`).
1538
1539#### What a violin is made of
1540
1541\since **ROOT version 6.09/02**
1542
1543##### The histogram
1544The histogram is typically drawn to both directions with respect to the middle-line of the
1545corresponding bin. This can be achieved by using h=3. It is possible to draw a histogram only to
1546one side (h=1, or h=2).
1547The maximum number of bins in the histogram is limited to 500, if the number of bins in the used
1548histogram is higher it will be rebinned automatically. The maximum height of the histogram can
1549be modified by using SetBarWidth() and the position can be changed with SetBarOffset().
1550A solid fill style is recommended.
1551
1552\since **ROOT version 6.11/01**
1553
1554Using the static function TCandle::SetScaledViolin(bool) the height of the histogram or the
1555violin can be influenced. Activated, the height of the bins of the individual violins will be
1556scaled with respect to each other, the maximum height can be influenced by SetBarWidth().
1557Deactivated, the height of the bin with the maximum content of each individual violin is
1558set to a constant value using SetBarWidth(). The static function will affect all violin-charts
1559in the running program. Default is true. Scaling between multiple violin-charts
1560(using "same" or THStack) is not supported, yet.
1561
1562##### The zero indicator line
1563Typical for violin charts is a line in the background over the whole histogram indicating
1564the bins with zero entries. The zero indicator line can be activated with z=1. The line color
1565will always be the same as the fill-color of the histogram.
1566
1567##### The Mean
1568The Mean is illustrated with the same mechanism as used for candle plots. Usually a circle is used.
1569
1570##### Whiskers
1571The whiskers are illustrated by the same mechanism as used for candle plots. There is only one
1572difference. When using the simple whisker definition (w=1) and the zero indicator line (z=1), then
1573the whiskers will be forced to be solid (usually hashed)
1574
1575##### Points
1576The points are illustrated by the same mechanism as used for candle plots. E.g. VIOLIN2 uses
1577better whisker definition (w=2) and outliers (p=1).
1578
1579##### Other options
1580It is possible to combine all options of candle or violin plots with each other. E.g. a violin plot
1581including a box-plot.
1582
1583#### How to use the violin-plots drawing option
1584
1585There are two predefined violin-plot representations:
1586 - "VIOLINX1": Standard violin (histogram, mean, whisker over full distribution,
1587 zero indicator line)
1588 - "VIOLINX2": Line VIOLINX1 both with better whisker definition + outliers.
1589
1590A solid fill style is recommended for this plot (as opposed to a hollow or
1591hashed style).
1592
1593Begin_Macro(source)
1594{
1595 auto c1 = new TCanvas("c1","c1",600,400);
1596 Int_t nx(6), ny(40);
1597 double xmin(0.0), xmax(+6.0), ymin(0.0), ymax(+4.0);
1598 auto hviolin = new TH2F("hviolin", "Option VIOLIN example", nx, xmin, xmax, ny, ymin, ymax);
1599 TF1 f1("f1", "gaus", +0,0 +4.0);
1600 double x,y;
1601 for (Int_t iBin=1; iBin<hviolin->GetNbinsX(); ++iBin) {
1602 double xc = hviolin->GetXaxis()->GetBinCenter(iBin);
1603 f1.SetParameters(1, 2.0+TMath::Sin(1.0+xc), 0.2+0.1*(xc-xmin)/xmax);
1604 for(Int_t i=0; i<10000; ++i){
1605 x = xc;
1606 y = f1.GetRandom();
1607 hviolin->Fill(x, y);
1608 }
1609 }
1610 hviolin->SetFillColor(kGray);
1611 hviolin->SetMarkerStyle(20);
1612 hviolin->SetMarkerSize(0.5);
1613 hviolin->Draw("VIOLIN");
1614 c1->Update();
1615}
1616End_Macro
1617
1618The next example illustrates a time development of a certain value:
1619
1620Begin_Macro(source)
1621../../../tutorials/hist/candledecay.C
1622End_Macro
1623
1624
1625\anchor HP15
1626### The TEXT and TEXTnn Option
1627
1628
1629For each bin the content is printed. The text attributes are:
1630
1631- text font = current TStyle font (`gStyle->SetTextFont()`).
1632- text size = 0.02*padheight*markersize (if `h` is the histogram drawn
1633 with the option `TEXT` the marker size can be changed with
1634 `h->SetMarkerSize(markersize)`).
1635- text color = marker color.
1636
1637By default the format `g` is used. This format can be redefined
1638by calling `gStyle->SetPaintTextFormat()`.
1639
1640It is also possible to use `TEXTnn` in order to draw the text with
1641the angle `nn` (`0 < nn <= 90`).
1642
1643For 2D histograms the text is plotted in the center of each non empty cells.
1644It is possible to plot empty cells by calling `gStyle->SetHistMinimumZero()`
1645or providing MIN0 draw option. For 1D histogram the text is plotted at a y
1646position equal to the bin content.
1647
1648For 2D histograms when the option "E" (errors) is combined with the option
1649text ("TEXTE"), the error for each bin is also printed.
1650
1651Begin_Macro(source)
1652{
1653 auto c01 = new TCanvas("c01","c01",700,400);
1654 c01->Divide(2,1);
1655 auto htext1 = new TH1F("htext1","Option TEXT on 1D histograms ",10,-4,4);
1656 auto htext2 = new TH2F("htext2","Option TEXT on 2D histograms ",10,-4,4,10,-20,20);
1657 float px, py;
1658 for (Int_t i = 0; i < 25000; i++) {
1659 gRandom->Rannor(px,py);
1660 htext1->Fill(px,0.1);
1661 htext2->Fill(px,5*py,0.1);
1662 }
1663 gStyle->SetPaintTextFormat("4.1f m");
1664 htext2->SetMarkerSize(1.8);
1665 c01->cd(1);
1666 htext2->Draw("TEXT45");
1667 c01->cd(2);
1668 htext1->Draw();
1669 htext1->Draw("HIST TEXT0 SAME");
1670}
1671End_Macro
1672
1673\since **ROOT version 6.07/07:**
1674
1675In case several histograms are drawn on top ot each other (using option `SAME`),
1676the text can be shifted using `SetBarOffset()`. It specifies an offset for the
1677text position in each cell, in percentage of the bin width.
1678
1679Begin_Macro(source)
1680{
1681 auto c03 = new TCanvas("c03","c03",700,400);
1682 gStyle->SetOptStat(0);
1683 auto htext3 = new TH2F("htext3","Several 2D histograms drawn with option TEXT",10,-4,4,10,-20,20);
1684 auto htext4 = new TH2F("htext4","htext4",10,-4,4,10,-20,20);
1685 auto htext5 = new TH2F("htext5","htext5",10,-4,4,10,-20,20);
1686 float px, py;
1687 for (Int_t i = 0; i < 25000; i++) {
1688 gRandom->Rannor(px,py);
1689 htext3->Fill(4*px,20*py,0.1);
1690 htext4->Fill(4*px,20*py,0.5);
1691 htext5->Fill(4*px,20*py,1.0);
1692 }
1693 htext4->SetMarkerSize(1.8);
1694 htext5->SetMarkerSize(1.8);
1695 htext5->SetMarkerColor(kRed);
1696 htext4->SetBarOffset(0.2);
1697 htext4->Draw("COL TEXT SAME");
1698 htext5->SetBarOffset(-0.2);
1699 htext5->Draw("TEXT SAME");
1700}
1701End_Macro
1702
1703In the case of profile histograms it is possible to print the number
1704of entries instead of the bin content. It is enough to combine the
1705option "E" (for entries) with the option "TEXT".
1706
1707Begin_Macro(source)
1708{
1709 auto c02 = new TCanvas("c02","c02",700,400);
1710 c02->Divide(2,1);
1711 gStyle->SetPaintTextFormat("g");
1712
1713 auto profile = new TProfile("profile","profile",10,0,10);
1714 profile->SetMarkerSize(2.2);
1715 profile->Fill(0.5,1);
1716 profile->Fill(1.5,2);
1717 profile->Fill(2.5,3);
1718 profile->Fill(3.5,4);
1719 profile->Fill(4.5,5);
1720 profile->Fill(5.5,5);
1721 profile->Fill(6.5,4);
1722 profile->Fill(7.5,3);
1723 profile->Fill(8.5,2);
1724 profile->Fill(9.5,1);
1725 c02->cd(1); profile->Draw("HIST TEXT0");
1726 c02->cd(2); profile->Draw("HIST TEXT0E");
1727}
1728End_Macro
1729
1730\anchor HP16
1731### The CONTour options
1732
1733
1734The following contour options are supported:
1735
1736| Option | Description |
1737|----------|-----------------------------------------------------------------------------|
1738| "CONT" | Draw a contour plot (same as CONT0). |
1739| "CONT0" | Draw a contour plot using surface colors to distinguish contours. |
1740| "CONT1" | Draw a contour plot using the line colors to distinguish contours. |
1741| "CONT2" | Draw a contour plot using the line styles (1 to 5) to distinguish contours. |
1742| "CONT3" | Draw a contour plot using the same line style for all contours. |
1743| "CONT4" | Draw a contour plot using surface colors (`SURF` option at theta = 0). |
1744
1745
1746The following example shows a 2D histogram plotted with the option
1747`CONTZ`. The option `CONT` draws a contour plot using surface
1748colors to distinguish contours. Combined with the option `CONT` (or
1749`CONT0`), the option `Z` allows to display the color palette
1750defined by `gStyle->SetPalette()`.
1751
1752Begin_Macro(source)
1753{
1754 auto c1 = new TCanvas("c1","c1",600,400);
1755 auto hcontz = new TH2F("hcontz","Option CONTZ example ",40,-4,4,40,-20,20);
1756 float px, py;
1757 for (Int_t i = 0; i < 25000; i++) {
1758 gRandom->Rannor(px,py);
1759 hcontz->Fill(px-1,5*py);
1760 hcontz->Fill(2+0.5*px,2*py-10.,0.1);
1761 }
1762 hcontz->Draw("CONTZ");
1763}
1764End_Macro
1765
1766The following example shows a 2D histogram plotted with the option
1767`CONT1Z`. The option `CONT1` draws a contour plot using the
1768line colors to distinguish contours. Combined with the option `CONT1`,
1769the option `Z` allows to display the color palette defined by
1770`gStyle->SetPalette()`.
1771
1772Begin_Macro(source)
1773{
1774 auto c1 = new TCanvas("c1","c1",600,400);
1775 auto hcont1 = new TH2F("hcont1","Option CONT1Z example ",40,-4,4,40,-20,20);
1776 float px, py;
1777 for (Int_t i = 0; i < 25000; i++) {
1778 gRandom->Rannor(px,py);
1779 hcont1->Fill(px-1,5*py);
1780 hcont1->Fill(2+0.5*px,2*py-10.,0.1);
1781 }
1782 hcont1->Draw("CONT1Z");
1783}
1784End_Macro
1785
1786The following example shows a 2D histogram plotted with the option
1787`CONT2`. The option `CONT2` draws a contour plot using the
1788line styles (1 to 5) to distinguish contours.
1789
1790Begin_Macro(source)
1791{
1792 auto c1 = new TCanvas("c1","c1",600,400);
1793 auto hcont2 = new TH2F("hcont2","Option CONT2 example ",40,-4,4,40,-20,20);
1794 float px, py;
1795 for (Int_t i = 0; i < 25000; i++) {
1796 gRandom->Rannor(px,py);
1797 hcont2->Fill(px-1,5*py);
1798 hcont2->Fill(2+0.5*px,2*py-10.,0.1);
1799 }
1800 hcont2->Draw("CONT2");
1801}
1802End_Macro
1803
1804The following example shows a 2D histogram plotted with the option
1805`CONT3`. The option `CONT3` draws contour plot using the same line style for
1806all contours.
1807
1808Begin_Macro(source)
1809{
1810 auto c1 = new TCanvas("c1","c1",600,400);
1811 auto hcont3 = new TH2F("hcont3","Option CONT3 example ",40,-4,4,40,-20,20);
1812 float px, py;
1813 for (Int_t i = 0; i < 25000; i++) {
1814 gRandom->Rannor(px,py);
1815 hcont3->Fill(px-1,5*py);
1816 hcont3->Fill(2+0.5*px,2*py-10.,0.1);
1817 }
1818 hcont3->SetLineStyle(kDotted);
1819 hcont3->Draw("CONT3");
1820}
1821End_Macro
1822
1823The following example shows a 2D histogram plotted with the option
1824`CONT4`. The option `CONT4` draws a contour plot using surface
1825colors to distinguish contours (`SURF` option at theta = 0). Combined
1826with the option `CONT` (or `CONT0`), the option `Z`
1827allows to display the color palette defined by `gStyle->SetPalette()`.
1828
1829Begin_Macro(source)
1830{
1831 auto c1 = new TCanvas("c1","c1",600,400);
1832 auto hcont4 = new TH2F("hcont4","Option CONT4Z example ",40,-4,4,40,-20,20);
1833 float px, py;
1834 for (Int_t i = 0; i < 25000; i++) {
1835 gRandom->Rannor(px,py);
1836 hcont4->Fill(px-1,5*py);
1837 hcont4->Fill(2+0.5*px,2*py-10.,0.1);
1838 }
1839 hcont4->Draw("CONT4Z");
1840}
1841End_Macro
1842
1843The default number of contour levels is 20 equidistant levels and can be changed
1844with `TH1::SetContour()` or `TStyle::SetNumberContours()`.
1845
1846\anchor HP16a
1847#### The LIST option
1848
1849When option `LIST` is specified together with option
1850`CONT`, the points used to draw the contours are saved in
1851`TGraph` objects:
1852
1853 h->Draw("CONT LIST");
1854 gPad->Update();
1855
1856The contour are saved in `TGraph` objects once the pad is painted.
1857Therefore to use this functionality in a macro, `gPad->Update()`
1858should be performed after the histogram drawing. Once the list is
1859built, the contours are accessible in the following way:
1860
1861 TObjArray *contours = (TObjArray*)gROOT->GetListOfSpecials()->FindObject("contours");
1862 Int_t ncontours = contours->GetSize();
1863 TList *list = (TList*)contours->At(i);
1864
1865Where `i` is a contour number, and list contains a list of
1866`TGraph` objects.
1867For one given contour, more than one disjoint polyline may be generated.
1868The number of TGraphs per contour is given by:
1869
1870 list->GetSize();
1871
1872To access the first graph in the list one should do:
1873
1874 TGraph *gr1 = (TGraph*)list->First();
1875
1876
1877The following example (ContourList.C) shows how to use this functionality.
1878
1879Begin_Macro(source)
1880../../../tutorials/hist/ContourList.C
1881End_Macro
1882
1883\anchor HP16b
1884#### The AITOFF, MERCATOR, SINUSOIDAL and PARABOLIC options
1885
1886The following options select the `CONT4` option and are useful for
1887sky maps or exposure maps (earth.C).
1888
1889| Option | Description |
1890|--------------|---------------------------------------------------------------|
1891| "AITOFF" | Draw a contour via an AITOFF projection.|
1892| "MERCATOR" | Draw a contour via an Mercator projection.|
1893| "SINUSOIDAL" | Draw a contour via an Sinusoidal projection.|
1894| "PARABOLIC" | Draw a contour via an Parabolic projection.|
1895
1896Begin_Macro(source)
1897../../../tutorials/graphics/earth.C
1898End_Macro
1899
1900
1901\anchor HP17
1902### The LEGO options
1903
1904
1905In a lego plot the cell contents are drawn as 3-d boxes. The height of each box
1906is proportional to the cell content. The lego aspect is control with the
1907following options:
1908
1909| Option | Description |
1910|----------|-------------------------------------------------------------------|
1911| "LEGO" | Draw a lego plot using the hidden lines removal technique.|
1912| "LEGO1" | Draw a lego plot using the hidden surface removal technique.|
1913| "LEGO2" | Draw a lego plot using colors to show the cell contents.|
1914| "LEGO3" | Draw a lego plot with hidden surface removal, like LEGO1 but the border lines of each lego-bar are not drawn.|
1915| "LEGO4" | Draw a lego plot with hidden surface removal, like LEGO1 but without the shadow effect on each lego-bar.|
1916| "0" | When used with any LEGO option, the empty bins are not drawn.|
1917
1918
1919See the limitations with [the option "SAME"](\ref HP060a).
1920
1921Line attributes can be used in lego plots to change the edges' style.
1922
1923The following example shows a 2D histogram plotted with the option
1924`LEGO`. The option `LEGO` draws a lego plot using the hidden
1925lines removal technique.
1926
1927Begin_Macro(source)
1928{
1929 auto c2 = new TCanvas("c2","c2",600,400);
1930 auto hlego = new TH2F("hlego","Option LEGO example ",40,-4,4,40,-20,20);
1931 float px, py;
1932 for (Int_t i = 0; i < 25000; i++) {
1933 gRandom->Rannor(px,py);
1934 hlego->Fill(px-1,5*py);
1935 hlego->Fill(2+0.5*px,2*py-10.,0.1);
1936 }
1937 hlego->Draw("LEGO");
1938}
1939End_Macro
1940
1941The following example shows a 2D histogram plotted with the option
1942`LEGO1`. The option `LEGO1` draws a lego plot using the
1943hidden surface removal technique. Combined with any `LEGOn` option, the
1944option `0` allows to not drawn the empty bins.
1945
1946Begin_Macro(source)
1947{
1948 auto c2 = new TCanvas("c2","c2",600,400);
1949 auto hlego1 = new TH2F("hlego1","Option LEGO1 example (with option 0) ",40,-4,4,40,-20,20);
1950 float px, py;
1951 for (Int_t i = 0; i < 25000; i++) {
1952 gRandom->Rannor(px,py);
1953 hlego1->Fill(px-1,5*py);
1954 hlego1->Fill(2+0.5*px,2*py-10.,0.1);
1955 }
1956 hlego1->SetFillColor(kYellow);
1957 hlego1->Draw("LEGO1 0");
1958}
1959End_Macro
1960
1961The following example shows a 2D histogram plotted with the option
1962`LEGO3`. Like the option `LEGO1`, the option `LEGO3`
1963draws a lego plot using the hidden surface removal technique but doesn't draw
1964the border lines of each individual lego-bar. This is very useful for histograms
1965having many bins. With such histograms the option `LEGO1` gives a black
1966image because of the border lines. This option also works with stacked legos.
1967
1968Begin_Macro(source)
1969{
1970 auto c2 = new TCanvas("c2","c2",600,400);
1971 auto hlego3 = new TH2F("hlego3","Option LEGO3 example",40,-4,4,40,-20,20);
1972 float px, py;
1973 for (Int_t i = 0; i < 25000; i++) {
1974 gRandom->Rannor(px,py);
1975 hlego3->Fill(px-1,5*py);
1976 hlego3->Fill(2+0.5*px,2*py-10.,0.1);
1977 }
1978 hlego3->SetFillColor(kRed);
1979 hlego3->Draw("LEGO3");
1980}
1981End_Macro
1982
1983The following example shows a 2D histogram plotted with the option
1984`LEGO2`. The option `LEGO2` draws a lego plot using colors to
1985show the cell contents. Combined with the option `LEGO2`, the option
1986`Z` allows to display the color palette defined by
1987`gStyle->SetPalette()`.
1988
1989Begin_Macro(source)
1990{
1991 auto c2 = new TCanvas("c2","c2",600,400);
1992 auto hlego2 = new TH2F("hlego2","Option LEGO2Z example ",40,-4,4,40,-20,20);
1993 float px, py;
1994 for (Int_t i = 0; i < 25000; i++) {
1995 gRandom->Rannor(px,py);
1996 hlego2->Fill(px-1,5*py);
1997 hlego2->Fill(2+0.5*px,2*py-10.,0.1);
1998 }
1999 hlego2->Draw("LEGO2Z");
2000}
2001End_Macro
2002
2003
2004
2005\anchor HP18
2006### The "SURFace" options
2007
2008
2009In a surface plot, cell contents are represented as a mesh.
2010The height of the mesh is proportional to the cell content.
2011
2012| Option | Description |
2013|----------|-------------------------------------------------------------------|
2014| "SURF" | Draw a surface plot using the hidden line removal technique.|
2015| "SURF1" | Draw a surface plot using the hidden surface removal technique.|
2016| "SURF2" | Draw a surface plot using colors to show the cell contents.|
2017| "SURF3" | Same as `SURF` with an additional filled contour plot on top.|
2018| "SURF4" | Draw a surface using the Gouraud shading technique.|
2019| "SURF5" | Used with one of the options CYL, PSR and CYL this option allows to draw a filled contour plot.|
2020| "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.|
2021| "SURF7" | Same as `SURF2` with an additional line contour plot on top.|
2022
2023
2024
2025See the limitations with [the option "SAME"](\ref HP060a).
2026
2027The following example shows a 2D histogram plotted with the option
2028`SURF`. The option `SURF` draws a lego plot using the hidden
2029lines removal technique.
2030
2031Begin_Macro(source)
2032{
2033 auto c2 = new TCanvas("c2","c2",600,400);
2034 auto hsurf = new TH2F("hsurf","Option SURF example ",30,-4,4,30,-20,20);
2035 float px, py;
2036 for (Int_t i = 0; i < 25000; i++) {
2037 gRandom->Rannor(px,py);
2038 hsurf->Fill(px-1,5*py);
2039 hsurf->Fill(2+0.5*px,2*py-10.,0.1);
2040 }
2041 hsurf->Draw("SURF");
2042}
2043End_Macro
2044
2045The following example shows a 2D histogram plotted with the option
2046`SURF1`. The option `SURF1` draws a surface plot using the
2047hidden surface removal technique. Combined with the option `SURF1`,
2048the option `Z` allows to display the color palette defined by
2049`gStyle->SetPalette()`.
2050
2051Begin_Macro(source)
2052{
2053 auto c2 = new TCanvas("c2","c2",600,400);
2054 auto hsurf1 = new TH2F("hsurf1","Option SURF1 example ",30,-4,4,30,-20,20);
2055 float px, py;
2056 for (Int_t i = 0; i < 25000; i++) {
2057 gRandom->Rannor(px,py);
2058 hsurf1->Fill(px-1,5*py);
2059 hsurf1->Fill(2+0.5*px,2*py-10.,0.1);
2060 }
2061 hsurf1->Draw("SURF1");
2062}
2063End_Macro
2064
2065The following example shows a 2D histogram plotted with the option
2066`SURF2`. The option `SURF2` draws a surface plot using colors
2067to show the cell contents. Combined with the option `SURF2`, the option
2068`Z` allows to display the color palette defined by
2069`gStyle->SetPalette()`.
2070
2071Begin_Macro(source)
2072{
2073 auto c2 = new TCanvas("c2","c2",600,400);
2074 auto hsurf2 = new TH2F("hsurf2","Option SURF2 example ",30,-4,4,30,-20,20);
2075 float px, py;
2076 for (Int_t i = 0; i < 25000; i++) {
2077 gRandom->Rannor(px,py);
2078 hsurf2->Fill(px-1,5*py);
2079 hsurf2->Fill(2+0.5*px,2*py-10.,0.1);
2080 }
2081 hsurf2->Draw("SURF2");
2082}
2083End_Macro
2084
2085The following example shows a 2D histogram plotted with the option
2086`SURF3`. The option `SURF3` draws a surface plot using the
2087hidden line removal technique with, in addition, a filled contour view drawn on the
2088top. Combined with the option `SURF3`, the option `Z` allows
2089to display the color palette defined by `gStyle->SetPalette()`.
2090
2091Begin_Macro(source)
2092{
2093 auto c2 = new TCanvas("c2","c2",600,400);
2094 auto hsurf3 = new TH2F("hsurf3","Option SURF3 example ",30,-4,4,30,-20,20);
2095 float px, py;
2096 for (Int_t i = 0; i < 25000; i++) {
2097 gRandom->Rannor(px,py);
2098 hsurf3->Fill(px-1,5*py);
2099 hsurf3->Fill(2+0.5*px,2*py-10.,0.1);
2100 }
2101 hsurf3->Draw("SURF3");
2102}
2103End_Macro
2104
2105The following example shows a 2D histogram plotted with the option
2106`SURF4`. The option `SURF4` draws a surface using the Gouraud
2107shading technique.
2108
2109Begin_Macro(source)
2110{
2111 auto c2 = new TCanvas("c2","c2",600,400);
2112 auto hsurf4 = new TH2F("hsurf4","Option SURF4 example ",30,-4,4,30,-20,20);
2113 float px, py;
2114 for (Int_t i = 0; i < 25000; i++) {
2115 gRandom->Rannor(px,py);
2116 hsurf4->Fill(px-1,5*py);
2117 hsurf4->Fill(2+0.5*px,2*py-10.,0.1);
2118 }
2119 hsurf4->SetFillColor(kOrange);
2120 hsurf4->Draw("SURF4");
2121}
2122End_Macro
2123
2124The following example shows a 2D histogram plotted with the option
2125`SURF5 CYL`. Combined with the option `SURF5`, the option
2126`Z` allows to display the color palette defined by `gStyle->SetPalette()`.
2127
2128Begin_Macro(source)
2129{
2130 auto c2 = new TCanvas("c2","c2",600,400);
2131 auto hsurf5 = new TH2F("hsurf4","Option SURF5 example ",30,-4,4,30,-20,20);
2132 float px, py;
2133 for (Int_t i = 0; i < 25000; i++) {
2134 gRandom->Rannor(px,py);
2135 hsurf5->Fill(px-1,5*py);
2136 hsurf5->Fill(2+0.5*px,2*py-10.,0.1);
2137 }
2138 hsurf5->Draw("SURF5 CYL");
2139}
2140End_Macro
2141
2142The following example shows a 2D histogram plotted with the option
2143`SURF7`. The option `SURF7` draws a surface plot using the
2144hidden surfaces removal technique with, in addition, a line contour view drawn on the
2145top. Combined with the option `SURF7`, the option `Z` allows
2146to display the color palette defined by `gStyle->SetPalette()`.
2147
2148Begin_Macro(source)
2149{
2150 auto c2 = new TCanvas("c2","c2",600,400);
2151 auto hsurf7 = new TH2F("hsurf3","Option SURF7 example ",30,-4,4,30,-20,20);
2152 float px, py;
2153 for (Int_t i = 0; i < 25000; i++) {
2154 gRandom->Rannor(px,py);
2155 hsurf7->Fill(px-1,5*py);
2156 hsurf7->Fill(2+0.5*px,2*py-10.,0.1);
2157 }
2158 hsurf7->Draw("SURF7");
2159}
2160End_Macro
2161
2162As shown in the following example, when a contour plot is painted on top of a
2163surface plot using the option `SAME`, the contours appear in 3D on the
2164surface.
2165
2166Begin_Macro(source)
2167{
2168 auto c20=new TCanvas("c20","c20",600,400);
2169 int NBins = 50;
2170 double d = 2;
2171 auto hsc = new TH2F("hsc", "Surface and contour with option SAME ", NBins, -d, d, NBins, -d, d);
2172 for (int bx = 1; bx <= NBins; ++bx) {
2173 for (int by = 1; by <= NBins; ++by) {
2174 double x = hsc->GetXaxis()->GetBinCenter(bx);
2175 double y = hsc->GetYaxis()->GetBinCenter(by);
2176 hsc->SetBinContent(bx, by, exp(-x*x)*exp(-y*y));
2177 }
2178 }
2179 hsc->Draw("surf2");
2180 hsc->Draw("CONT1 SAME");
2181}
2182End_Macro
2183
2184
2185\anchor HP19
2186### Cylindrical, Polar, Spherical and PseudoRapidity/Phi options
2187
2188
2189Legos and surfaces plots are represented by default in Cartesian coordinates.
2190Combined with any `LEGOn` or `SURFn` options the following
2191options allow to draw a lego or a surface in other coordinates systems.
2192
2193| Option | Description |
2194|----------|-------------------------------------------------------------------|
2195| "CYL" | Use Cylindrical coordinates. The X coordinate is mapped on the angle and the Y coordinate on the cylinder length.|
2196| "POL" | Use Polar coordinates. The X coordinate is mapped on the angle and the Y coordinate on the radius.|
2197| "SPH" | Use Spherical coordinates. The X coordinate is mapped on the latitude and the Y coordinate on the longitude.|
2198| "PSR" | Use PseudoRapidity/Phi coordinates. The X coordinate is mapped on Phi.|
2199
2200
2201
2202<b>WARNING:</b> Axis are not drawn with these options.
2203
2204The following example shows the same histogram as a lego plot is the four
2205different coordinates systems.
2206
2207Begin_Macro(source)
2208{
2209 auto c3 = new TCanvas("c3","c3",600,400);
2210 c3->Divide(2,2);
2211 auto hlcc = new TH2F("hlcc","Cylindrical coordinates",20,-4,4,20,-20,20);
2212 float px, py;
2213 for (Int_t i = 0; i < 25000; i++) {
2214 gRandom->Rannor(px,py);
2215 hlcc->Fill(px-1,5*py);
2216 hlcc->Fill(2+0.5*px,2*py-10.,0.1);
2217 }
2218 hlcc->SetFillColor(kYellow);
2219 c3->cd(1); hlcc->Draw("LEGO1 CYL");
2220 c3->cd(2); auto hlpc = (TH2F*) hlcc->DrawClone("LEGO1 POL");
2221 hlpc->SetTitle("Polar coordinates");
2222 c3->cd(3); auto hlsc = (TH2F*) hlcc->DrawClone("LEGO1 SPH");
2223 hlsc->SetTitle("Spherical coordinates");
2224 c3->cd(4); auto hlprpc = (TH2F*) hlcc->DrawClone("LEGO1 PSR");
2225 hlprpc->SetTitle("PseudoRapidity/Phi coordinates");
2226}
2227End_Macro
2228
2229The following example shows the same histogram as a surface plot is the four different coordinates systems.
2230
2231Begin_Macro(source)
2232{
2233 auto c4 = new TCanvas("c4","c4",600,400);
2234 c4->Divide(2,2);
2235 auto hscc = new TH2F("hscc","Cylindrical coordinates",20,-4,4,20,-20,20);
2236 float px, py;
2237 for (Int_t i = 0; i < 25000; i++) {
2238 gRandom->Rannor(px,py);
2239 hscc->Fill(px-1,5*py);
2240 hscc->Fill(2+0.5*px,2*py-10.,0.1);
2241 }
2242 c4->cd(1); hscc->Draw("SURF1 CYL");
2243 c4->cd(2); auto hspc = (TH2F*) hscc->DrawClone("SURF1 POL");
2244 hspc->SetTitle("Polar coordinates");
2245 c4->cd(3); auto hssc = (TH2F*) hscc->DrawClone("SURF1 SPH");
2246 hssc->SetTitle("Spherical coordinates");
2247 c4->cd(4); auto hsprpc = (TH2F*) hscc->DrawClone("SURF1 PSR");
2248 hsprpc->SetTitle("PseudoRapidity/Phi coordinates");
2249}
2250End_Macro
2251
2252
2253\anchor HP20
2254### Base line for bar-charts and lego plots
2255
2256
2257By default the base line used to draw the boxes for bar-charts and lego plots is
2258the histogram minimum. It is possible to force this base line to be 0, using MIN0 draw
2259option or with the command:
2260
2261 gStyle->SetHistMinimumZero();
2262
2263Begin_Macro(source)
2264{
2265 auto c5 = new TCanvas("c5","c5",700,400);
2266 c5->Divide(2,1);
2267 auto hz1 = new TH1F("hz1","Bar-chart drawn from 0",20,-3,3);
2268 auto hz2 = new TH2F("hz2","Lego plot drawn from 0",20,-3,3,20,-3,3);
2269 Int_t i;
2270 double x,y;
2271 hz1->SetFillColor(kBlue);
2272 hz2->SetFillColor(kBlue);
2273 for (i=0;i<10000;i++) {
2274 x = gRandom->Gaus(0,1);
2275 y = gRandom->Gaus(0,1);
2276 if (x>0) {
2277 hz1->Fill(x,1);
2278 hz2->Fill(x,y,1);
2279 } else {
2280 hz1->Fill(x,-1);
2281 hz2->Fill(x,y,-2);
2282 }
2283 }
2284 c5->cd(1); hz1->Draw("bar2 min0");
2285 c5->cd(2); hz2->Draw("lego1 min0");
2286}
2287End_Macro
2288
2289This option also works for horizontal plots. The example given in the section
2290["The bar chart option"](\ref HP100) appears as follow:
2291
2292Begin_Macro(source)
2293{
2294 int i;
2295 const Int_t nx = 8;
2296 string os_X[nx] = {"8","32","128","512","2048","8192","32768","131072"};
2297 float d_35_0[nx] = {0.75, -3.30, -0.92, 0.10, 0.08, -1.69, -1.29, -2.37};
2298 float d_35_1[nx] = {1.01, -3.02, -0.65, 0.37, 0.34, -1.42, -1.02, -2.10};
2299
2300 auto cbh = new TCanvas("cbh","cbh",400,600);
2301 cbh->SetGrid();
2302
2303 auto h1bh = new TH1F("h1bh","Option HBAR centered on 0",nx,0,nx);
2304 h1bh->SetFillColor(4);
2305 h1bh->SetBarWidth(0.4);
2306 h1bh->SetBarOffset(0.1);
2307 h1bh->SetStats(0);
2308 h1bh->SetMinimum(-5);
2309 h1bh->SetMaximum(5);
2310
2311 for (i=1; i<=nx; i++) {
2312 h1bh->Fill(os_X[i-1].c_str(), d_35_0[i-1]);
2313 h1bh->GetXaxis()->SetBinLabel(i,os_X[i-1].c_str());
2314 }
2315
2316 h1bh->Draw("hbar min0");
2317
2318 auto h2bh = new TH1F("h2bh","h2bh",nx,0,nx);
2319 h2bh->SetFillColor(38);
2320 h2bh->SetBarWidth(0.4);
2321 h2bh->SetBarOffset(0.5);
2322 h2bh->SetStats(0);
2323 for (i=1;i<=nx;i++) h2bh->Fill(os_X[i-1].c_str(), d_35_1[i-1]);
2324
2325 h2bh->Draw("hbar min0 same");
2326}
2327End_Macro
2328
2329
2330\anchor HP20a
2331### TH2Poly Drawing
2332
2333
2334The following options are supported:
2335
2336| Option | Description |
2337|----------|-------------------------------------------------------------------|
2338| "SCAT" | Draw a scatter plot (deprecated).|
2339| "COL" | Draw a color plot. All the bins are painted even the empty bins (default).|
2340| "COLZ" | Same as "COL". In addition the color palette is also drawn.|
2341| "0" | When used with any COL options, the empty bins are not drawn.|
2342| "TEXT" | Draw bin contents as text (format set via `gStyle->SetPaintTextFormat`).|
2343| "TEXTN" | Draw bin names as text.|
2344| "TEXTnn" | Draw bin contents as text at angle nn (0 < nn <= 90).|
2345| "L" | Draw the bins boundaries as lines. The lines attributes are the TGraphs ones.|
2346| "P" | Draw the bins boundaries as markers. The markers attributes are the TGraphs ones.|
2347| "F" | Draw the bins boundaries as filled polygons. The filled polygons attributes are the TGraphs ones.|
2348
2349
2350
2351`TH2Poly` can be drawn as a color plot (option COL). `TH2Poly` bins can have any
2352shapes. The bins are defined as graphs. The following macro is a very simple
2353example showing how to book a TH2Poly and draw it.
2354
2355Begin_Macro(source)
2356{
2357 auto ch2p1 = new TCanvas("ch2p1","ch2p1",600,400);
2358 auto h2p = new TH2Poly();
2359 h2p->SetName("h2poly_name");
2360 h2p->SetTitle("h2poly_title");
2361 double px1[] = {0, 5, 6};
2362 double py1[] = {0, 0, 5};
2363 double px2[] = {0, -1, -1, 0};
2364 double py2[] = {0, 0, -1, 3};
2365 double px3[] = {4, 3, 0, 1, 2.4};
2366 double py3[] = {4, 3.7, 1, 3.7, 2.5};
2367 h2p->AddBin(3, px1, py1);
2368 h2p->AddBin(4, px2, py2);
2369 h2p->AddBin(5, px3, py3);
2370 h2p->Fill(0.1, 0.01, 3);
2371 h2p->Fill(-0.5, -0.5, 7);
2372 h2p->Fill(-0.7, -0.5, 1);
2373 h2p->Fill(1, 3, 1.5);
2374 double fx[] = {0.1, -0.5, -0.7, 1};
2375 double fy[] = {0.01, -0.5, -0.5, 3};
2376 double fw[] = {3, 1, 1, 1.5};
2377 h2p->FillN(4, fx, fy, fw);
2378 h2p->Draw("col");
2379}
2380End_Macro
2381
2382Rectangular bins are a frequent case. The special version of
2383the `AddBin` method allows to define them more easily like
2384shown in the following example (th2polyBoxes.C).
2385
2386Begin_Macro(source)
2387../../../tutorials/hist/th2polyBoxes.C
2388End_Macro
2389
2390One `TH2Poly` bin can be a list of polygons. Such bins are defined
2391by calling `AddBin` with a `TMultiGraph`. The following example
2392shows a such case:
2393
2394Begin_Macro(source)
2395{
2396 auto ch2p2 = new TCanvas("ch2p2","ch2p2",600,400);
2397
2398 Int_t i, bin;
2399 const Int_t nx = 48;
2400 const char *states [nx] = {
2401 "alabama", "arizona", "arkansas", "california",
2402 "colorado", "connecticut", "delaware", "florida",
2403 "georgia", "idaho", "illinois", "indiana",
2404 "iowa", "kansas", "kentucky", "louisiana",
2405 "maine", "maryland", "massachusetts", "michigan",
2406 "minnesota", "mississippi", "missouri", "montana",
2407 "nebraska", "nevada", "new_hampshire", "new_jersey",
2408 "new_mexico", "new_york", "north_carolina", "north_dakota",
2409 "ohio", "oklahoma", "oregon", "pennsylvania",
2410 "rhode_island", "south_carolina", "south_dakota", "tennessee",
2411 "texas", "utah", "vermont", "virginia",
2412 "washington", "west_virginia", "wisconsin", "wyoming"
2413 };
2414 Double_t pop[nx] = {
2415 4708708, 6595778, 2889450, 36961664, 5024748, 3518288, 885122, 18537969,
2416 9829211, 1545801, 12910409, 6423113, 3007856, 2818747, 4314113, 4492076,
2417 1318301, 5699478, 6593587, 9969727, 5266214, 2951996, 5987580, 974989,
2418 1796619, 2643085, 1324575, 8707739, 2009671, 19541453, 9380884, 646844,
2419 11542645, 3687050, 3825657, 12604767, 1053209, 4561242, 812383, 6296254,
2420 24782302, 2784572, 621760, 7882590, 6664195, 1819777, 5654774, 544270
2421 };
2422
2423 Double_t lon1 = -130;
2424 Double_t lon2 = -65;
2425 Double_t lat1 = 24;
2426 Double_t lat2 = 50;
2427 auto p = new TH2Poly("USA","USA Population",lon1,lon2,lat1,lat2);
2428
2429 TFile::SetCacheFileDir(".");
2430 auto f = TFile::Open("http://root.cern/files/usa.root", "CACHEREAD");
2431
2432 TMultiGraph *mg;
2433 TKey *key;
2434 TIter nextkey(gDirectory->GetListOfKeys());
2435 while ((key = (TKey*)nextkey())) {
2436 TObject *obj = key->ReadObj();
2437 if (obj->InheritsFrom("TMultiGraph")) {
2438 mg = (TMultiGraph*)obj;
2439 bin = p->AddBin(mg);
2440 }
2441 }
2442
2443 for (i=0; i<nx; i++) p->Fill(states[i], pop[i]);
2444
2445 gStyle->SetOptStat(11);
2446 p->Draw("COLZ L");
2447}
2448End_Macro
2449
2450`TH2Poly` histograms can also be plotted using the GL interface using
2451the option "GLLEGO".
2452
2453\since **ROOT version 6.09/01**
2454
2455In some cases it can be useful to not draw the empty bins. the option "0"
2456combined with the option "COL" et COLZ allows to do that.
2457
2458Begin_Macro(source)
2459{
2460 auto chc = new TCanvas("chc","chc",600,400);
2461
2462 auto hc = new TH2Poly();
2463 hc->Honeycomb(0,0,.1,25,25);
2464 hc->SetName("hc");
2465 hc->SetTitle("Option COLZ 0");
2466 TRandom ran;
2467 for (int i = 0; i<300; i++) hc->Fill(ran.Gaus(2.,1), ran.Gaus(2.,1));
2468 hc->Draw("colz 0");
2469}
2470End_Macro
2471
2472\anchor HP21
2473### The SPEC option
2474
2475
2476This option allows to use the `TSpectrum2Painter` tools. See the full
2477documentation in `TSpectrum2Painter::PaintSpectrum`.
2478
2479
2480\anchor HP22
2481### Option "Z" : Adding the color palette on the right side of the pad
2482
2483
2484When this option is specified, a color palette with an axis indicating the value
2485of the corresponding color is drawn on the right side of the picture. In case,
2486not enough space is left, one can increase the size of the right margin by
2487calling `TPad::SetRightMargin()`. The attributes used to display the
2488palette axis values are taken from the Z axis of the object. For example, to
2489set the labels size on the palette axis do:
2490
2491 hist->GetZaxis()->SetLabelSize().
2492
2493<b>WARNING:</b> The palette axis is always drawn vertically.
2494
2495
2496\anchor HP23
2497### Setting the color palette
2498
2499
2500To change the color palette `TStyle::SetPalette` should be used, eg:
2501
2502 gStyle->SetPalette(ncolors,colors);
2503
2504For example the option `COL` draws a 2D histogram with cells
2505represented by a box filled with a color index which is a function
2506of the cell content.
2507If the cell content is N, the color index used will be the color number
2508in `colors[N]`, etc. If the maximum cell content is greater than
2509`ncolors`, all cell contents are scaled to `ncolors`.
2510
2511If ` ncolors <= 0`, a default palette (see below) of 50 colors is
2512defined. This palette is recommended for pads, labels ...
2513
2514`if ncolors == 1 && colors == 0`, then a Pretty Palette with a
2515Spectrum Violet->Red is created with 50 colors. That's the default rain bow
2516palette.
2517
2518Other pre-defined palettes with 255 colors are available when `colors == 0`.
2519The following value of `ncolors` give access to:
2520
2521
2522 if ncolors = 51 and colors=0, a Deep Sea palette is used.
2523 if ncolors = 52 and colors=0, a Grey Scale palette is used.
2524 if ncolors = 53 and colors=0, a Dark Body Radiator palette is used.
2525 if ncolors = 54 and colors=0, a two-color hue palette palette is used.(dark blue through neutral gray to bright yellow)
2526 if ncolors = 55 and colors=0, a Rain Bow palette is used.
2527 if ncolors = 56 and colors=0, an inverted Dark Body Radiator palette is used.
2528
2529
2530If `ncolors > 0 && colors == 0`, the default palette is used with a maximum of ncolors.
2531
2532The default palette defines:
2533
2534- index 0 to 9 : shades of grey
2535- index 10 to 19 : shades of brown
2536- index 20 to 29 : shades of blue
2537- index 30 to 39 : shades of red
2538- index 40 to 49 : basic colors
2539
2540The color numbers specified in the palette can be viewed by selecting
2541the item `colors` in the `VIEW` menu of the canvas tool bar.
2542The red, green, and blue components of a color can be changed thanks to
2543`TColor::SetRGB()`.
2544
2545\since **ROOT version 6.19/01**
2546
2547As default labels and ticks are drawn by `TGAxis` at equidistant (lin or log)
2548points as controlled by SetNdivisions.
2549If option "CJUST" is given labels and ticks are justified at the
2550color boundaries defined by the contour levels.
2551For more details see `TPaletteAxis`
2552
2553\anchor HP24
2554### Drawing a sub-range of a 2D histogram; the [cutg] option
2555
2556
2557Using a `TCutG` object, it is possible to draw a sub-range of a 2D
2558histogram. One must create a graphical cut (mouse or C++) and specify the name
2559of the cut between `[]` in the `Draw()` option.
2560For example (fit2a.C), with a `TCutG` named `cutg`, one can call:
2561
2562 myhist->Draw("surf1 [cutg]");
2563
2564To invert the cut, it is enough to put a `-` in front of its name:
2565
2566 myhist->Draw("surf1 [-cutg]");
2567
2568It is possible to apply several cuts (`,` means logical AND):
2569
2570 myhist->Draw("surf1 [cutg1,cutg2]");
2571
2572Begin_Macro(source)
2573../../../tutorials/fit/fit2a.C
2574End_Macro
2575
2576\anchor HP25
2577### Drawing options for 3D histograms
2578
2579
2580| Option | Description |
2581|----------|-------------------------------------------------------------------|
2582| "SCAT" | Draw a scatter plot (deprecated).|
2583| "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)`|
2584| "BOX" | Draw a for each cell with volume proportional to the content's absolute value. An hidden line removal algorithm is used|
2585| "BOX1" | Same as BOX but an hidden surface removal algorithm is used|
2586| "BOX2" | Same as "COL". The boxes' colors are picked in the current palette according to the bins' contents (default)|
2587| "BOX2Z" | Same as "BOX2". In addition the color palette is also drawn.|
2588| "BOX3" | Same as BOX1, but the border lines of each lego-bar are not drawn.|
2589
2590Note that instead of `BOX` one can also use `LEGO`.
2591
2592By default, 3D histograms are drawn as a colored box plots.
2593
2594The following example shows a 3D histogram plotted as a scatter plot.
2595
2596Begin_Macro(source)
2597{
2598 auto c06 = new TCanvas("c06","c06",600,400);
2599 gStyle->SetOptStat(kFALSE);
2600 auto h3scat = new TH3F("h3scat","Option SCAT",15,-2,2,15,-2,2,15,0,4);
2601 double x, y, z;
2602 for (Int_t i=0;i<10000;i++) {
2603 gRandom->Rannor(x, y);
2604 z = x*x + y*y;
2605 h3scat->Fill(x,y,z);
2606 }
2607 h3scat->Draw();
2608}
2609End_Macro
2610
2611The following example shows a 3D histogram plotted with the option `BOX`.
2612
2613Begin_Macro(source)
2614{
2615 auto c16 = new TCanvas("c16","c16",600,400);
2616 gStyle->SetOptStat(kFALSE);
2617 auto h3box = new TH3F("h3box","Option BOX",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 h3box->Fill(x,y,z);
2623 }
2624 h3box->Draw("BOX");
2625}
2626End_Macro
2627
2628The following example shows a 3D histogram plotted with the option `BOX1`.
2629
2630Begin_Macro(source)
2631{
2632 auto c36 = new TCanvas("c36","c36",600,400);
2633 gStyle->SetOptStat(kFALSE);
2634 auto h3box = new TH3F("h3box","Option BOX1",10,-2.,2.,10,-2.,2.,10,-0.5,2.);
2635 double x, y, z;
2636 for (Int_t i=0;i<10000;i++) {
2637 gRandom->Rannor(x, y);
2638 z = abs(sin(x)/x + cos(y)*y);
2639 h3box->Fill(x,y,z);
2640 }
2641 h3box->SetFillColor(9);
2642 h3box->Draw("BOX1");
2643}
2644End_Macro
2645
2646The following example shows a 3D histogram plotted with the option `BOX2`.
2647
2648Begin_Macro(source)
2649{
2650 auto c56 = new TCanvas("c56","c56",600,400);
2651 gStyle->SetOptStat(kFALSE);
2652 auto h3box = new TH3F("h3box","Option BOX2 (default)",10,-2.,2.,10,-2.,2.,10,-0.5,2.);
2653 double x, y, z;
2654 for (Int_t i=0;i<10000;i++) {
2655 gRandom->Rannor(x, y);
2656 z = abs(sin(x)/x + cos(y)*y);
2657 h3box->Fill(x,y,z);
2658 }
2659 h3box->Draw("BOX2 Z");
2660}
2661End_Macro
2662
2663The following example shows a 3D histogram plotted with the option `BOX3`.
2664
2665Begin_Macro(source)
2666{
2667 auto c46 = new TCanvas("c46","c46",600,400);
2668 c46->SetFillColor(38);
2669 gStyle->SetOptStat(kFALSE);
2670 auto h3box = new TH3F("h3box","Option BOX3",15,-2,2,15,-2,2,15,0,4);
2671 double x, y, z;
2672 for (Int_t i=0;i<10000;i++) {
2673 gRandom->Rannor(x, y);
2674 z = x*x + y*y;
2675 h3box->Fill(x,y,z);
2676 }
2677 h3box->Draw("BOX3");
2678}
2679End_Macro
2680
2681For all the `BOX` options each bin is drawn as a 3D box with a volume proportional
2682to the absolute value of the bin content. The bins with a negative content are
2683drawn with a X on each face of the box as shown in the following example:
2684
2685Begin_Macro(source)
2686{
2687 auto c = new TCanvas("c","c",600,400);
2688 gStyle->SetOptStat(kFALSE);
2689 auto h3box = new TH3F("h3box","Option BOX1 with negative bins",3, 0., 4., 3, 0.,4., 3, 0., 4.);
2690 h3box->Fill(0., 2., 2., 10.);
2691 h3box->Fill(2., 2., 2., 5.);
2692 h3box->Fill(2., 2., .5, 2.);
2693 h3box->Fill(2., 2., 3., -1.);
2694 h3box->Fill(3., 2., 2., -10.);
2695 h3box->SetFillColor(8);
2696 h3box->Draw("box1");
2697}
2698End_Macro
2699
2700The following example shows a 3D histogram plotted with the option `ISO`.
2701
2702Begin_Macro(source)
2703{
2704 auto c26 = new TCanvas("c26","c26",600,400);
2705 gStyle->SetOptStat(kFALSE);
2706 auto h3iso = new TH3F("h3iso","Option ISO",15,-2,2,15,-2,2,15,0,4);
2707 double x, y, z;
2708 for (Int_t i=0;i<10000;i++) {
2709 gRandom->Rannor(x, y);
2710 z = x*x + y*y;
2711 h3iso->Fill(x,y,z);
2712 }
2713 h3iso->SetFillColor(kCyan);
2714 h3iso->Draw("ISO");
2715}
2716End_Macro
2717
2718
2719\anchor HP26
2720### Drawing option for histograms' stacks
2721
2722
2723Stacks of histograms are managed with the `THStack`. A `THStack`
2724is a collection of `TH1` (or derived) objects. For painting only the
2725`THStack` containing `TH1` only or
2726`THStack` containing `TH2` only will be considered.
2727
2728By default, histograms are shown stacked:
2729
27301. The first histogram is paint.
27312. The sum of the first and second, etc...
2732
2733If the option `NOSTACK` is specified, the histograms are all paint in
2734the same pad as if the option `SAME` had been specified. This allows to
2735compute X and Y scales common to all the histograms, like
2736`TMultiGraph` does for graphs.
2737
2738If the option `PADS` is specified, the current pad/canvas is
2739subdivided into a number of pads equal to the number of histograms and each
2740histogram is paint into a separate pad.
2741
2742The following example shows various types of stacks (hstack.C).
2743
2744Begin_Macro(source)
2745../../../tutorials/hist/hstack.C
2746End_Macro
2747
2748The option `nostackb` allows to draw the histograms next to each
2749other as bar charts:
2750
2751Begin_Macro(source)
2752{
2753 auto cst0 = new TCanvas("cst0","cst0",600,400);
2754 auto hs = new THStack("hs","Stacked 1D histograms: option #font[82]{\"nostackb\"}");
2755
2756 auto h1 = new TH1F("h1","h1",10,-4,4);
2757 h1->FillRandom("gaus",20000);
2758 h1->SetFillColor(kRed);
2759 hs->Add(h1);
2760
2761 auto h2 = new TH1F("h2","h2",10,-4,4);
2762 h2->FillRandom("gaus",15000);
2763 h2->SetFillColor(kBlue);
2764 hs->Add(h2);
2765
2766 auto h3 = new TH1F("h3","h3",10,-4,4);
2767 h3->FillRandom("gaus",10000);
2768 h3->SetFillColor(kGreen);
2769 hs->Add(h3);
2770
2771 hs->Draw("nostackb");
2772 hs->GetXaxis()->SetNdivisions(-10);
2773 cst0->SetGridx();
2774}
2775End_Macro
2776
2777If at least one of the histograms in the stack has errors, the whole stack is
2778visualized by default with error bars. To visualize it without errors the
2779option `HIST` should be used.
2780
2781Begin_Macro(source)
2782{
2783 auto cst1 = new TCanvas("cst1","cst1",700,400);
2784 cst1->Divide(2,1);
2785
2786 auto hst11 = new TH1F("hst11", "", 20, -10, 10);
2787 hst11->Sumw2();
2788 hst11->FillRandom("gaus", 1000);
2789 hst11->SetFillColor(kViolet);
2790 hst11->SetLineColor(kViolet);
2791
2792 auto hst12 = new TH1F("hst12", "", 20, -10, 10);
2793 hst12->FillRandom("gaus", 500);
2794 hst12->SetFillColor(kBlue);
2795 hst12->SetLineColor(kBlue);
2796
2797 THStack st1("st1", "st1");
2798 st1.Add(hst11);
2799 st1.Add(hst12);
2800
2801 cst1->cd(1); st1.Draw();
2802 cst1->cd(2); st1.Draw("hist");
2803}
2804End_Macro
2805
2806\anchor HP27
2807### Drawing of 3D implicit functions
2808
2809
28103D implicit functions (`TF3`) can be drawn as iso-surfaces.
2811The implicit function f(x,y,z) = 0 is drawn in cartesian coordinates.
2812In the following example the options "FB" and "BB" suppress the
2813"Front Box" and "Back Box" around the plot.
2814
2815Begin_Macro(source)
2816{
2817 auto c2 = new TCanvas("c2","c2",600,400);
2818 auto f3 = new TF3("f3","sin(x*x+y*y+z*z-36)",-2,2,-2,2,-2,2);
2819 f3->SetClippingBoxOn(0,0,0);
2820 f3->SetFillColor(30);
2821 f3->SetLineColor(15);
2822 f3->Draw("FBBB");
2823}
2824End_Macro
2825
2826
2827\anchor HP28
2828### Associated functions drawing
2829
2830
2831An associated function is created by `TH1::Fit`. More than on fitted
2832function can be associated with one histogram (see `TH1::Fit`).
2833
2834A `TF1` object `f1` can be added to the list of associated
2835functions of an histogram `h` without calling `TH1::Fit`
2836simply doing:
2837
2838 h->GetListOfFunctions()->Add(f1);
2839
2840or
2841
2842 h->GetListOfFunctions()->Add(f1,someoption);
2843
2844To retrieve a function by name from this list, do:
2845
2846 TF1 *f1 = (TF1*)h->GetListOfFunctions()->FindObject(name);
2847
2848or
2849
2850 TF1 *f1 = h->GetFunction(name);
2851
2852Associated functions are automatically painted when an histogram is drawn.
2853To avoid the painting of the associated functions the option `HIST`
2854should be added to the list of the options used to paint the histogram.
2855
2856
2857\anchor HP29
2858### Drawing using OpenGL
2859
2860
2861The class `TGLHistPainter` allows to paint data set using the OpenGL 3D
2862graphics library. The plotting options start with `GL` keyword.
2863In addition, in order to inform canvases that OpenGL should be used to render
28643D representations, the following option should be set:
2865
2866 gStyle->SetCanvasPreferGL(true);
2867
2868
2869\anchor HP29a
2870#### General information: plot types and supported options
2871
2872The following types of plots are provided:
2873
2874For lego plots the supported options are:
2875
2876| Option | Description |
2877|----------|-------------------------------------------------------------------|
2878| "GLLEGO" | Draw a lego plot. It works also for `TH2Poly`.|
2879| "GLLEGO2"| Bins with color levels.|
2880| "GLLEGO3"| Cylindrical bars.|
2881
2882
2883
2884Lego painter in cartesian supports logarithmic scales for X, Y, Z.
2885In polar only Z axis can be logarithmic, in cylindrical only Y.
2886
2887For surface plots (`TF2` and `TH2`) the supported options are:
2888
2889| Option | Description |
2890|-----------|------------------------------------------------------------------|
2891| "GLSURF" | Draw a surface.|
2892| "GLSURF1" | Surface with color levels|
2893| "GLSURF2" | The same as "GLSURF1" but without polygon outlines.|
2894| "GLSURF3" | Color level projection on top of plot (works only in cartesian coordinate system).|
2895| "GLSURF4" | Same as "GLSURF" but without polygon outlines.|
2896
2897
2898
2899The surface painting in cartesian coordinates supports logarithmic scales along
2900X, Y, Z axis. In polar coordinates only the Z axis can be logarithmic,
2901in cylindrical coordinates only the Y axis.
2902
2903Additional options to SURF and LEGO - Coordinate systems:
2904
2905| Option | Description |
2906|----------|-------------------------------------------------------------------|
2907| " " | Default, cartesian coordinates system.|
2908| "POL" | Polar coordinates system.|
2909| "CYL" | Cylindrical coordinates system.|
2910| "SPH" | Spherical coordinates system.|
2911
2912
2913
2914\anchor HP290
2915#### TH3 as color boxes
2916
2917The supported option is:
2918
2919| Option | Description |
2920|----------|-------------------------------------------------------------------|
2921| "GLCOL" | H3 is drawn using semi-transparent colored boxes. See `$ROOTSYS/tutorials/gl/glvox1.C`.|
2922
2923
2924
2925\anchor HP29b
2926#### TH3 as boxes (spheres)
2927
2928The supported options are:
2929
2930| Option | Description |
2931|----------|-------------------------------------------------------------------|
2932| "GLBOX" | TH3 as a set of boxes, size of box is proportional to bin content.|
2933| "GLBOX1" | The same as "glbox", but spheres are drawn instead of boxes.|
2934
2935
2936
2937\anchor HP29c
2938#### TH3 as iso-surface(s)
2939
2940The supported option is:
2941
2942| Option | Description |
2943|----------|-------------------------------------------------------------------|
2944| "GLISO" | TH3 is drawn using iso-surfaces.|
2945
2946
2947
2948\anchor HP29d
2949#### TF3 (implicit function)
2950
2951The supported option is:
2952
2953| Option | Description |
2954|----------|-------------------------------------------------------------------|
2955| "GL" | Draw a TF3.|
2956
2957
2958
2959\anchor HP29e
2960#### Parametric surfaces
2961
2962`$ROOTSYS/tutorials/gl/glparametric.C` shows how to create parametric
2963equations and visualize the surface.
2964
2965\anchor HP29f
2966#### Interaction with the plots
2967
2968All the interactions are implemented via standard methods
2969`DistancetoPrimitive()` and `ExecuteEvent()`. That's why all the
2970interactions with the OpenGL plots are possible only when the mouse cursor is
2971in the plot's area (the plot's area is the part of a the pad occupied by
2972gl-produced picture). If the mouse cursor is not above gl-picture, the standard
2973pad interaction is performed.
2974
2975\anchor HP29g
2976#### Selectable parts
2977
2978Different parts of the plot can be selected:
2979
2980- xoz, yoz, xoy back planes: When such a plane selected, it's highlighted in green
2981 if the dynamic slicing by this plane is supported, and it's highlighted in red,
2982 if the dynamic slicing is not supported.
2983- The plot itself:
2984 On surfaces, the selected surface is outlined in red. (TF3 and
2985 ISO are not outlined). On lego plots, the selected bin is
2986 highlighted. The bin number and content are displayed in pad's
2987 status bar. In box plots, the box or sphere is highlighted and
2988 the bin info is displayed in pad's status bar.
2989
2990
2991\anchor HP29h
2992#### Rotation and zooming
2993
2994
2995- Rotation:
2996 When the plot is selected, it can be rotated by pressing and
2997 holding the left mouse button and move the cursor.
2998- Zoom/Unzoom:
2999 Mouse wheel or 'j', 'J', 'k', 'K' keys.
3000
3001
3002\anchor HP29i
3003#### Panning
3004
3005The selected plot can be moved in a pad's area by pressing and
3006holding the left mouse button and the shift key.
3007
3008\anchor HP29j
3009#### Box cut
3010
3011Surface, iso, box, TF3 and parametric painters support box cut by
3012pressing the 'c' or 'C' key when the mouse cursor is in a plot's
3013area. That will display a transparent box, cutting away part of the
3014surface (or boxes) in order to show internal part of plot. This box
3015can be moved inside the plot's area (the full size of the box is
3016equal to the plot's surrounding box) by selecting one of the box
3017cut axes and pressing the left mouse button to move it.
3018
3019\anchor HP29k
3020#### Plot specific interactions (dynamic slicing etc.)
3021
3022Currently, all gl-plots support some form of slicing. When back plane
3023is selected (and if it's highlighted in green) you can press and hold
3024left mouse button and shift key and move this back plane inside
3025plot's area, creating the slice. During this "slicing" plot becomes
3026semi-transparent. To remove all slices (and projected curves for
3027surfaces) double click with left mouse button in a plot's area.
3028
3029\anchor HP29l
3030#### Surface with option "GLSURF"
3031
3032The surface profile is displayed on the slicing plane.
3033The profile projection is drawn on the back plane
3034by pressing `'p'` or `'P'` key.
3035
3036\anchor HP29m
3037#### TF3
3038
3039The contour plot is drawn on the slicing plane. For TF3 the color
3040scheme can be changed by pressing 's' or 'S'.
3041
3042\anchor HP29n
3043#### Box
3044
3045The contour plot corresponding to slice plane position is drawn in real time.
3046
3047\anchor HP29o
3048#### Iso
3049
3050Slicing is similar to "GLBOX" option.
3051
3052\anchor HP29p
3053#### Parametric plot
3054
3055No slicing. Additional keys: 's' or 'S' to change color scheme -
3056about 20 color schemes supported ('s' for "scheme"); 'l' or 'L' to
3057increase number of polygons ('l' for "level" of details), 'w' or 'W'
3058to show outlines ('w' for "wireframe").
3059
3060\anchor HP30
3061#### Highlight mode for histogram
3062
3063\since **ROOT version 6.15/01**
3064
3065\image html hlHisto3_top.gif "Highlight mode"
3066
3067Highlight mode is implemented for `TH1` (and for `TGraph`) class. When
3068highlight mode is on, mouse movement over the bin will be represented
3069graphically. Bin will be highlighted as "bin box" (presented by box
3070object). Moreover, any highlight (change of bin) emits signal
3071`TCanvas::Highlighted()` which allows the user to react and call their own
3072function. For a better understanding see also the tutorials
3073`$ROOTSYS/tutorials/hist/hlHisto*.C` files.
3074
3075Highlight mode is switched on/off by `TH1::SetHighlight()` function
3076or interactively from `TH1` context menu. `TH1::IsHighlight()` to verify
3077whether the highlight mode enabled or disabled, default it is disabled.
3078
3079~~~ {.cpp}
3080 root [0] .x $ROOTSYS/tutorials/hsimple.C
3081 root [1] hpx->SetHighlight(kTRUE) // or interactively from TH1 context menu
3082 root [2] hpx->IsHighlight()
3083 (bool) true
3084~~~
3085
3086\image html hlsimple_nofun.gif "Highlight mode for histogram"
3087
3088\anchor HP30a
3089#### Highlight mode and user function
3090
3091The user can use (connect) `TCanvas::Highlighted()` signal, which is always
3092emitted if there is a highlight bin and call user function via signal
3093and slot communication mechanism. `TCanvas::Highlighted()` is similar
3094`TCanvas::Picked()`
3095
3096- when selected object (histogram as a whole) is different from previous
3097then emit `Picked()` signal
3098- when selected (highlighted) bin from histogram is different from previous
3099then emit `Highlighted()` signal
3100
3101Any user function (or functions) has to be defined
3102`UserFunction(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)`.
3103In example (see below) has name `PrintInfo()`. All parameters of user
3104function are taken from
3105
3106 void TCanvas::Highlighted(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)
3107
3108- `pad` is pointer to pad with highlighted histogram
3109- `obj` is pointer to highlighted histogram
3110- `x` is highlighted x bin for 1D histogram
3111- `y` is highlighted y bin for 2D histogram (for 1D histogram not in use)
3112
3113Example how to create a connection from any `TCanvas` object to a user
3114`UserFunction()` slot (see also `TQObject::Connect()` for additional info)
3115
3116 TQObject::Connect("TCanvas", "Highlighted(TVirtualPad*,TObject*,Int_t,Int_t)",
3117 0, 0, "UserFunction(TVirtualPad*,TObject*,Int_t,Int_t)");
3118
3119or use non-static "simplified" function
3120`TCanvas::HighlightConnect(const char *slot)`
3121
3122 c1->HighlightConnect("UserFunction(TVirtualPad*,TObject*,Int_t,Int_t)");
3123
3124NOTE the signal and slot string must have a form
3125"(TVirtualPad*,TObject*,Int_t,Int_t)"
3126
3127 root [0] .x $ROOTSYS/tutorials/hsimple.C
3128 root [1] hpx->SetHighlight(kTRUE)
3129 root [2] .x hlprint.C
3130
3131file `hlprint.C`
3132~~~ {.cpp}
3133void PrintInfo(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)
3134{
3135 auto h = (TH1F *)obj;
3136 if (!h->IsHighlight()) // after highlight disabled
3137 h->SetTitle("highlight disable");
3138 else
3139 h->SetTitle(TString::Format("bin[%03d] (%5.2f) content %g", x,
3140 h->GetBinCenter(x), h->GetBinContent(x)));
3141 pad->Update();
3142}
3143
3144void hlprint()
3145{
3146 if (!gPad) return;
3147 gPad->GetCanvas()->HighlightConnect("PrintInfo(TVirtualPad*,TObject*,Int_t,Int_t)");
3148}
3149~~~
3150
3151\image html hlsimple.gif "Highlight mode and simple user function"
3152
3153For more complex demo please see for example `$ROOTSYS/tutorials/tree/temperature.C` file.
3154
3155*/
3156
3158
3161
3162const Int_t kNMAX = 2000;
3163
3164const Int_t kMAXCONTOUR = 104;
3166
3167static std::unique_ptr<TBox> gXHighlightBox, gYHighlightBox; // highlight X and Y box
3168
3190
3192
3193////////////////////////////////////////////////////////////////////////////////
3194/// Default constructor.
3195
3197{
3198 fH = nullptr;
3199 fXaxis = nullptr;
3200 fYaxis = nullptr;
3201 fZaxis = nullptr;
3202 fFunctions = nullptr;
3203 fNcuts = 0;
3204 fStack = nullptr;
3205 fShowProjection = 0;
3206 fShowProjection2 = 0;
3207 fShowOption = "";
3208 for (int i=0; i<kMaxCuts; i++) {
3209 fCuts[i] = nullptr;
3210 fCutsOpt[i] = 0;
3211 }
3212 fXHighlightBin = -1;
3213 fYHighlightBin = -1;
3214 fCurrentF3 = nullptr;
3215
3216 gStringEntries = gEnv->GetValue("Hist.Stats.Entries", "Entries");
3217 gStringMean = gEnv->GetValue("Hist.Stats.Mean", "Mean");
3218 gStringMeanX = gEnv->GetValue("Hist.Stats.MeanX", "Mean x");
3219 gStringMeanY = gEnv->GetValue("Hist.Stats.MeanY", "Mean y");
3220 gStringMeanZ = gEnv->GetValue("Hist.Stats.MeanZ", "Mean z");
3221 gStringStdDev = gEnv->GetValue("Hist.Stats.StdDev", "Std Dev");
3222 gStringStdDevX = gEnv->GetValue("Hist.Stats.StdDevX", "Std Dev x");
3223 gStringStdDevY = gEnv->GetValue("Hist.Stats.StdDevY", "Std Dev y");
3224 gStringStdDevZ = gEnv->GetValue("Hist.Stats.StdDevZ", "Std Dev z");
3225 gStringUnderflow = gEnv->GetValue("Hist.Stats.Underflow", "Underflow");
3226 gStringOverflow = gEnv->GetValue("Hist.Stats.Overflow", "Overflow");
3227 gStringIntegral = gEnv->GetValue("Hist.Stats.Integral", "Integral");
3228 gStringIntegralBinWidth = gEnv->GetValue("Hist.Stats.IntegralBinWidth", "Integral(w)");
3229 gStringSkewness = gEnv->GetValue("Hist.Stats.Skewness", "Skewness");
3230 gStringSkewnessX = gEnv->GetValue("Hist.Stats.SkewnessX", "Skewness x");
3231 gStringSkewnessY = gEnv->GetValue("Hist.Stats.SkewnessY", "Skewness y");
3232 gStringSkewnessZ = gEnv->GetValue("Hist.Stats.SkewnessZ", "Skewness z");
3233 gStringKurtosis = gEnv->GetValue("Hist.Stats.Kurtosis", "Kurtosis");
3234 gStringKurtosisX = gEnv->GetValue("Hist.Stats.KurtosisX", "Kurtosis x");
3235 gStringKurtosisY = gEnv->GetValue("Hist.Stats.KurtosisY", "Kurtosis y");
3236 gStringKurtosisZ = gEnv->GetValue("Hist.Stats.KurtosisZ", "Kurtosis z");
3237}
3238
3239////////////////////////////////////////////////////////////////////////////////
3240/// destructor.
3241
3243{
3244}
3245
3246////////////////////////////////////////////////////////////////////////////////
3247/// Compute the distance from the point px,py to a line.
3248///
3249/// Compute the closest distance of approach from point px,py to elements of
3250/// an histogram. The distance is computed in pixels units.
3251///
3252/// Algorithm: Currently, this simple model computes the distance from the mouse
3253/// to the histogram contour only.
3254
3256{
3257
3258 Double_t defaultLabelSize = 0.04; // See TAttAxis.h for source of this value
3259
3260 const Int_t big = 9999;
3261 const Int_t kMaxDiff = 7;
3262
3263 if (fPie)
3264 return fPie->DistancetoPrimitive(px, py);
3265
3266 Double_t x = gPad->AbsPixeltoX(px);
3267 Double_t x1 = gPad->AbsPixeltoX(px+1);
3268
3269 Int_t puxmin = gPad->XtoAbsPixel(gPad->GetUxmin());
3270 Int_t puymin = gPad->YtoAbsPixel(gPad->GetUymin());
3271 Int_t puxmax = gPad->XtoAbsPixel(gPad->GetUxmax());
3272 Int_t puymax = gPad->YtoAbsPixel(gPad->GetUymax());
3273 Int_t curdist = big;
3274 Int_t yxaxis, dyaxis,xyaxis, dxaxis;
3275 Bool_t dsame;
3276 TObject *PadPointer = gPad->GetPadPointer();
3277 if (!PadPointer) return 0;
3278 TString doption = PadPointer->GetDrawOption();
3279 Double_t factor = 1;
3280 if (fH->GetNormFactor() != 0) {
3281 factor = fH->GetNormFactor()/fH->GetSumOfWeights();
3282 }
3283 // return if point is not in the histogram area
3284
3285 // If a 3D view exists, check distance to axis
3286 TView *view = gPad->GetView();
3287 Int_t d1,d2,d3;
3288 if (view && Hoption.Contour != 14) {
3289 Double_t ratio;
3290 d3 = view->GetDistancetoAxis(3, px, py, ratio);
3291 if (d3 <= kMaxDiff) {gPad->SetSelected(fZaxis); return 0;}
3292 d1 = view->GetDistancetoAxis(1, px, py, ratio);
3293 if (d1 <= kMaxDiff) {gPad->SetSelected(fXaxis); return 0;}
3294 d2 = view->GetDistancetoAxis(2, px, py, ratio);
3295 if (d2 <= kMaxDiff) {gPad->SetSelected(fYaxis); return 0;}
3296 if ( px > puxmin && px < puxmax && py > puymax && py < puymin) curdist = 1;
3297 goto FUNCTIONS;
3298 }
3299 // check if point is close to an axis
3300 doption.ToLower();
3301 dsame = kFALSE;
3302 if (doption.Contains("same")) dsame = kTRUE;
3303
3304 dyaxis = Int_t(2*(puymin-puymax)*TMath::Max(Double_t(fYaxis->GetLabelSize()), defaultLabelSize));
3305 if (doption.Contains("y+")) {
3306 xyaxis = puxmax + Int_t((puxmax-puxmin)*fYaxis->GetLabelOffset());
3307 if (px <= xyaxis+dyaxis && px >= xyaxis && py >puymax && py < puymin) {
3308 if (!dsame) {
3309 if (gPad->IsVertical()) gPad->SetSelected(fYaxis);
3310 else gPad->SetSelected(fXaxis);
3311 return 0;
3312 }
3313 }
3314 } else {
3315 xyaxis = puxmin - Int_t((puxmax-puxmin)*fYaxis->GetLabelOffset());
3316 if (px >= xyaxis-dyaxis && px <= xyaxis && py >puymax && py < puymin) {
3317 if (!dsame) {
3318 if (gPad->IsVertical()) gPad->SetSelected(fYaxis);
3319 else gPad->SetSelected(fXaxis);
3320 return 0;
3321 }
3322 }
3323 }
3324
3325 dxaxis = Int_t((puymin-puymax)*TMath::Max(Double_t(fXaxis->GetLabelSize()), defaultLabelSize));
3326 if (doption.Contains("x+")) {
3327 yxaxis = puymax - Int_t((puymin-puymax)*fXaxis->GetLabelOffset());
3328 if (py >= yxaxis-dxaxis && py <= yxaxis && px <puxmax && px > puxmin) {
3329 if (!dsame) {
3330 if (gPad->IsVertical()) gPad->SetSelected(fXaxis);
3331 else gPad->SetSelected(fYaxis);
3332 return 0;
3333 }
3334 }
3335 } else {
3336 yxaxis = puymin + Int_t((puymin-puymax)*fXaxis->GetLabelOffset());
3337 if (yxaxis < puymin) yxaxis = puymin;
3338 if (py <= yxaxis+dxaxis && py >= yxaxis && px <puxmax && px > puxmin) {
3339 if (!dsame) {
3340 if (gPad->IsVertical()) gPad->SetSelected(fXaxis);
3341 else gPad->SetSelected(fYaxis);
3342 return 0;
3343 }
3344 }
3345 }
3346
3347 if (fH->IsHighlight()) { // only if highlight is enable
3348 if ((px > puxmin) && (py < puymin) && (px < puxmax) && (py > puymax))
3349 HighlightBin(px, py);
3350 }
3351
3352 // if object is 2D or 3D return this object
3353 if (fH->GetDimension() == 2) {
3354 if (fH->InheritsFrom(TH2Poly::Class())) {
3355 TH2Poly *th2 = (TH2Poly*)fH;
3357 gPad->GetRangeAxis(xmin, ymin, xmax, ymax);
3358 Double_t pxu = gPad->AbsPixeltoX(px);
3359 Double_t pyu = gPad->AbsPixeltoY(py);
3360 if ((pxu>xmax) || (pxu < xmin) || (pyu>ymax) || (pyu < ymin)) {
3361 curdist = big;
3362 goto FUNCTIONS;
3363 } else {
3364 Int_t bin = th2->FindBin(pxu, pyu);
3365 if (bin>0) curdist = 1;
3366 else curdist = big;
3367 goto FUNCTIONS;
3368 }
3369 }
3370 Int_t delta2 = 5; //Give a margin of delta2 pixels to be in the 2-d area
3371 if ( px > puxmin + delta2
3372 && px < puxmax - delta2
3373 && py > puymax + delta2
3374 && py < puymin - delta2) {curdist =1; goto FUNCTIONS;}
3375 }
3376
3377 // point is inside histogram area. Find channel number
3378 if (gPad->IsVertical()) {
3379 Int_t bin = fXaxis->FindFixBin(gPad->PadtoX(x));
3380 Int_t binsup = fXaxis->FindFixBin(gPad->PadtoX(x1));
3381 Double_t binval = factor*fH->GetBinContent(bin);
3382 Int_t pybin = gPad->YtoAbsPixel(gPad->YtoPad(binval));
3383 if (binval == 0 && pybin < puymin) pybin = 10000;
3384 // special case if more than one bin for the pixel
3385 if (binsup-bin>1) {
3386 Double_t binvalmin, binvalmax;
3387 binvalmin=binval;
3388 binvalmax=binval;
3389 for (Int_t ibin=bin+1; ibin<binsup; ibin++) {
3390 Double_t binvaltmp = factor*fH->GetBinContent(ibin);
3391 if (binvalmin>binvaltmp) binvalmin=binvaltmp;
3392 if (binvalmax<binvaltmp) binvalmax=binvaltmp;
3393 }
3394 Int_t pybinmin = gPad->YtoAbsPixel(gPad->YtoPad(binvalmax));
3395 Int_t pybinmax = gPad->YtoAbsPixel(gPad->YtoPad(binvalmin));
3396 if (py<pybinmax+kMaxDiff/2 && py>pybinmin-kMaxDiff/2) pybin = py;
3397 }
3398 if (bin != binsup) { // Mouse on bin border
3399 Double_t binsupval = factor*fH->GetBinContent(binsup);
3400 Int_t pybinsub = gPad->YtoAbsPixel(gPad->YtoPad(binsupval));
3401 if (py <= TMath::Max(pybinsub,pybin) && py >= TMath::Min(pybinsub,pybin) && pybin != 10000) return 0;
3402 }
3403 if (TMath::Abs(py - pybin) <= kMaxDiff) return TMath::Abs(py - pybin);
3404 } else {
3405 Double_t y = gPad->AbsPixeltoY(py);
3406 Double_t y1 = gPad->AbsPixeltoY(py+1);
3407 Int_t bin = fXaxis->FindFixBin(gPad->PadtoY(y));
3408 Int_t binsup = fXaxis->FindFixBin(gPad->PadtoY(y1));
3409 Double_t binval = factor*fH->GetBinContent(bin);
3410 Int_t pxbin = gPad->XtoAbsPixel(gPad->XtoPad(binval));
3411 if (binval == 0 && pxbin > puxmin) pxbin = 10000;
3412 // special case if more than one bin for the pixel
3413 if (binsup-bin>1) {
3414 Double_t binvalmin, binvalmax;
3415 binvalmin=binval;
3416 binvalmax=binval;
3417 for (Int_t ibin=bin+1; ibin<binsup; ibin++) {
3418 Double_t binvaltmp = factor*fH->GetBinContent(ibin);
3419 if (binvalmin>binvaltmp) binvalmin=binvaltmp;
3420 if (binvalmax<binvaltmp) binvalmax=binvaltmp;
3421 }
3422 Int_t pxbinmin = gPad->XtoAbsPixel(gPad->XtoPad(binvalmax));
3423 Int_t pxbinmax = gPad->XtoAbsPixel(gPad->XtoPad(binvalmin));
3424 if (px<pxbinmax+kMaxDiff/2 && px>pxbinmin-kMaxDiff/2) pxbin = px;
3425 }
3426 if (TMath::Abs(px - pxbin) <= kMaxDiff) return TMath::Abs(px - pxbin);
3427 }
3428 // Loop on the list of associated functions and user objects
3429FUNCTIONS:
3430 TObject *f;
3431 TIter next(fFunctions);
3432 while ((f = (TObject*) next())) {
3433 Int_t dist;
3434 if (f->InheritsFrom(TF1::Class())) dist = f->DistancetoPrimitive(-px,py);
3435 else dist = f->DistancetoPrimitive(px,py);
3436 if (dist < kMaxDiff) {gPad->SetSelected(f); return dist;}
3437 }
3438 return curdist;
3439}
3440
3441////////////////////////////////////////////////////////////////////////////////
3442/// Display a panel with all histogram drawing options.
3443
3445{
3446
3447 gCurrentHist = fH;
3448 if (!gPad) {
3449 Error("DrawPanel", "need to draw histogram first");
3450 return;
3451 }
3453 editor->Show();
3454 gROOT->ProcessLine(TString::Format("((TCanvas*)0x%zx)->Selected((TVirtualPad*)0x%zx,(TObject*)0x%zx,1)",
3455 (size_t)gPad->GetCanvas(), (size_t)gPad, (size_t)fH).Data());
3456}
3457
3458////////////////////////////////////////////////////////////////////////////////
3459/// Execute the actions corresponding to `event`.
3460///
3461/// This function is called when a histogram is clicked with the locator at
3462/// the pixel position px,py.
3463
3465{
3466
3467 if (!gPad) return;
3468
3469 static Int_t bin, px1, py1, px2, py2, pyold;
3470 static std::unique_ptr<TBox> zoombox;
3471 Double_t zbx1,zbx2,zby1,zby2;
3472
3473 Int_t bin1, bin2;
3474 Double_t xlow, xup, ylow, binval, x, baroffset, barwidth, binwidth;
3475 Bool_t opaque = gPad->OpaqueMoving();
3476
3477 if (!gPad->IsEditable()) return;
3478
3479 if (fPie) {
3480 fPie->ExecuteEvent(event, px, py);
3481 return;
3482 }
3483 // come here if we have a lego/surface in the pad
3484 TView *view = gPad->GetView();
3485
3486 if (!fShowProjection && view && !view->TestBit(kCannotRotate)) {
3487 view->ExecuteRotateView(event, px, py);
3488 return;
3489 }
3490
3491 TAxis *xaxis = fH->GetXaxis();
3492 TAxis *yaxis = fH->GetYaxis();
3493 Int_t dimension = fH->GetDimension();
3494
3495 // In case of option SAME the axis must be the ones of the first drawn histogram
3496 TString IsSame = fH->GetDrawOption();
3497 IsSame.ToLower();
3498 if (IsSame.Index("same")>=0) {
3499 TH1 *h1;
3500 TIter next(gPad->GetListOfPrimitives());
3501 while ((h1 = (TH1 *)next())) {
3502 if (!h1->InheritsFrom(TH1::Class())) continue;
3503 xaxis = h1->GetXaxis();
3504 yaxis = h1->GetYaxis();
3505 break;
3506 }
3507 }
3508
3509 Double_t factor = 1;
3510 if (fH->GetNormFactor() != 0) {
3511 factor = fH->GetNormFactor()/fH->GetSumOfWeights();
3512 }
3513
3514 switch (event) {
3515
3516 case kButton1Down:
3517
3518 if (!opaque) gVirtualX->SetLineColor(-1);
3519 fH->TAttLine::Modify();
3520
3521 if (opaque && dimension ==2) {
3522 zbx1 = gPad->AbsPixeltoX(px);
3523 zbx2 = gPad->AbsPixeltoX(px);
3524 zby1 = gPad->AbsPixeltoY(py);
3525 zby2 = gPad->AbsPixeltoY(py);
3526 px1 = px;
3527 py1 = py;
3528 if (gPad->GetLogx()) {
3529 zbx1 = TMath::Power(10,zbx1);
3530 zbx2 = TMath::Power(10,zbx2);
3531 }
3532 if (gPad->GetLogy()) {
3533 zby1 = TMath::Power(10,zby1);
3534 zby2 = TMath::Power(10,zby2);
3535 }
3536 if (zoombox) Error("ExecuteEvent", "Last zoom box was not deleted");
3537 zoombox = std::make_unique<TBox>(zbx1, zby1, zbx2, zby2);
3538 Int_t ci = TColor::GetColor("#7d7dff");
3539 TColor *zoomcolor = gROOT->GetColor(ci);
3540 if (!TCanvas::SupportAlpha() || !zoomcolor) zoombox->SetFillStyle(3002);
3541 else zoomcolor->SetAlpha(0.5);
3542 zoombox->SetFillColor(ci);
3543 zoombox->Draw();
3544 gPad->Modified();
3545 gPad->Update();
3546 }
3547 // No break !!!
3548
3549 case kMouseMotion:
3550
3551 if (fShowProjection) {ShowProjection3(px,py); break;}
3552
3553 gPad->SetCursor(kPointer);
3554 if (dimension ==1) {
3555 if (Hoption.Bar) {
3556 baroffset = fH->GetBarOffset();
3557 barwidth = fH->GetBarWidth();
3558 } else {
3559 baroffset = 0;
3560 barwidth = 1;
3561 }
3562 x = gPad->AbsPixeltoX(px);
3563 bin = fXaxis->FindFixBin(gPad->PadtoX(x));
3564 binwidth = fXaxis->GetBinWidth(bin);
3565 xlow = gPad->XtoPad(fXaxis->GetBinLowEdge(bin) + baroffset*binwidth);
3566 xup = gPad->XtoPad(xlow + barwidth*binwidth);
3567 ylow = gPad->GetUymin();
3568 px1 = gPad->XtoAbsPixel(xlow);
3569 px2 = gPad->XtoAbsPixel(xup);
3570 py1 = gPad->YtoAbsPixel(ylow);
3571 py2 = py;
3572 pyold = py;
3573 if (gROOT->GetEditHistograms()) gPad->SetCursor(kArrowVer);
3574 }
3575
3576 break;
3577
3578 case kButton1Motion:
3579
3580 if (dimension ==1) {
3581 if (gROOT->GetEditHistograms()) {
3582 if (!opaque) {
3583 gVirtualX->DrawBox(px1, py1, px2, py2,TVirtualX::kHollow); // Draw the old box
3584 py2 += py - pyold;
3585 gVirtualX->DrawBox(px1, py1, px2, py2,TVirtualX::kHollow); // Draw the new box
3586 pyold = py;
3587 } else {
3588 py2 += py - pyold;
3589 pyold = py;
3590 binval = gPad->PadtoY(gPad->AbsPixeltoY(py2))/factor;
3591 fH->SetBinContent(bin,binval);
3592 gPad->Modified(kTRUE);
3593 }
3594 }
3595 }
3596
3597 if (opaque && dimension ==2) {
3598 if (TMath::Abs(px1-px)>5 && TMath::Abs(py1-py)>5) {
3599 zbx2 = gPad->AbsPixeltoX(px);
3600 zby2 = gPad->AbsPixeltoY(py);
3601 if (gPad->GetLogx()) zbx2 = TMath::Power(10,zbx2);
3602 if (gPad->GetLogy()) zby2 = TMath::Power(10,zby2);
3603 if (zoombox) {
3604 zoombox->SetX2(zbx2);
3605 zoombox->SetY2(zby2);
3606 }
3607 gPad->Modified();
3608 gPad->Update();
3609 }
3610 }
3611
3612 break;
3613
3614 case kWheelUp:
3615
3616 if (dimension ==2) {
3617 bin1 = xaxis->GetFirst()+1;
3618 bin2 = xaxis->GetLast()-1;
3619 bin1 = TMath::Max(bin1, 1);
3620 bin2 = TMath::Min(bin2, xaxis->GetNbins());
3621 if (bin2>bin1) xaxis->SetRange(bin1,bin2);
3622 bin1 = yaxis->GetFirst()+1;
3623 bin2 = yaxis->GetLast()-1;
3624 bin1 = TMath::Max(bin1, 1);
3625 bin2 = TMath::Min(bin2, yaxis->GetNbins());
3626 if (bin2>bin1) yaxis->SetRange(bin1,bin2);
3627 }
3628 gPad->Modified();
3629 gPad->Update();
3630
3631 break;
3632
3633 case kWheelDown:
3634
3635 if (dimension == 2) {
3636 bin1 = xaxis->GetFirst()-1;
3637 bin2 = xaxis->GetLast()+1;
3638 bin1 = TMath::Max(bin1, 1);
3639 bin2 = TMath::Min(bin2, xaxis->GetNbins());
3640 if (bin2>bin1) xaxis->SetRange(bin1,bin2);
3641 bin1 = yaxis->GetFirst()-1;
3642 bin2 = yaxis->GetLast()+1;
3643 bin1 = TMath::Max(bin1, 1);
3644 bin2 = TMath::Min(bin2, yaxis->GetNbins());
3645 if (bin2>bin1) yaxis->SetRange(bin1,bin2);
3646 }
3647 gPad->Modified();
3648 gPad->Update();
3649
3650 break;
3651
3652 case kButton1Up:
3653 if (dimension ==1) {
3654 if (gROOT->GetEditHistograms()) {
3655 binval = gPad->PadtoY(gPad->AbsPixeltoY(py2))/factor;
3656 fH->SetBinContent(bin,binval);
3657 PaintInit(); // recalculate Hparam structure and recalculate range
3658 }
3659
3660 // might resize pad pixmap so should be called before any paint routine
3662 }
3663 if (opaque && dimension ==2) {
3664 if (zoombox) {
3665 Double_t x1 = TMath::Min(zoombox->GetX1(), zoombox->GetX2());
3666 Double_t x2 = TMath::Max(zoombox->GetX1(), zoombox->GetX2());
3667 Double_t y1 = TMath::Min(zoombox->GetY1(), zoombox->GetY2());
3668 Double_t y2 = TMath::Max(zoombox->GetY1(), zoombox->GetY2());
3669 x1 = TMath::Max(x1,xaxis->GetXmin());
3670 x2 = TMath::Min(x2,xaxis->GetXmax());
3671 y1 = TMath::Max(y1,yaxis->GetXmin());
3672 y2 = TMath::Min(y2,yaxis->GetXmax());
3673 if (x1<x2 && y1<y2) {
3674 xaxis->SetRangeUser(x1, x2);
3675 yaxis->SetRangeUser(y1, y2);
3676 }
3677 zoombox.reset();
3678 }
3679 }
3680 gPad->Modified(kTRUE);
3681 if (opaque) gVirtualX->SetLineColor(-1);
3682
3683 break;
3684
3685 case kButton1Locate:
3686
3687 ExecuteEvent(kButton1Down, px, py);
3688
3689 while (true) {
3690 px = py = 0;
3691 event = gVirtualX->RequestLocator(1, 1, px, py);
3692
3694
3695 if (event != -1) { // button is released
3696 ExecuteEvent(kButton1Up, px, py);
3697 return;
3698 }
3699 }
3700 }
3701}
3702
3703////////////////////////////////////////////////////////////////////////////////
3704/// Get a contour (as a list of TGraphs) using the Delaunay triangulation.
3705
3707{
3708 // Check if fH contains a TGraphDelaunay2D
3709 TList *hl = fH->GetListOfFunctions();
3710 TGraphDelaunay2D *dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
3711 // try with the old painter
3712 TGraphDelaunay *dtOld = nullptr;
3713 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
3714
3715 if (!dt && !dtOld) return nullptr;
3716
3717 gCurrentHist = fH;
3718
3719 if (!fGraph2DPainter)
3720 ((THistPainter*)this)->fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
3721
3722 return fGraph2DPainter->GetContourList(contour);
3723}
3724
3725////////////////////////////////////////////////////////////////////////////////
3726/// Display the histogram info (bin number, contents, integral up to bin
3727/// corresponding to cursor position px,py.
3728
3730{
3731
3732 if (!gPad) return (char*)"";
3733
3734 Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
3735 Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
3736 Double_t x1 = gPad->PadtoX(gPad->AbsPixeltoX(px+1));
3737 TString drawOption = fH->GetDrawOption();
3738 drawOption.ToLower();
3739 Double_t xmin, xmax, uxmin,uxmax;
3740 Double_t ymin, ymax, uymin,uymax;
3741 if (fH->GetDimension() == 2) {
3742 if (gPad->GetView() || drawOption.Index("cont") >= 0) {
3743 uxmin=gPad->GetUxmin();
3744 uxmax=gPad->GetUxmax();
3747 x = xmin +(xmax-xmin)*(x-uxmin)/(uxmax-uxmin);
3748 uymin=gPad->GetUymin();
3749 uymax=gPad->GetUymax();
3752 y = ymin +(ymax-ymin)*(y-uymin)/(uymax-uymin);
3753 }
3754 }
3755 Int_t binx,biny,binmin=0,binx1;
3756 if (gPad->IsVertical()) {
3757 binx = fXaxis->FindFixBin(x);
3758 if (drawOption.Index("same") >= 0) {
3759 TH1 *h1;
3760 TIter next(gPad->GetListOfPrimitives());
3761 while ((h1 = (TH1 *)next())) {
3762 if (!h1->InheritsFrom(TH1::Class())) continue;
3763 binmin = h1->GetXaxis()->GetFirst();
3764 break;
3765 }
3766 } else {
3767 binmin = fXaxis->GetFirst();
3768 }
3769 binx1 = fXaxis->FindFixBin(x1);
3770 // special case if more than 1 bin in x per pixel
3771 if (binx1-binx>1 && fH->GetDimension() == 1) {
3772 Double_t binval=fH->GetBinContent(binx);
3773 Int_t binnear=binx;
3774 for (Int_t ibin=binx+1; ibin<binx1; ibin++) {
3775 Double_t binvaltmp = fH->GetBinContent(ibin);
3776 if (TMath::Abs(y-binvaltmp) < TMath::Abs(y-binval)) {
3777 binval=binvaltmp;
3778 binnear=ibin;
3779 }
3780 }
3781 binx = binnear;
3782 }
3783 } else {
3784 x1 = gPad->PadtoY(gPad->AbsPixeltoY(py+1));
3785 binx = fXaxis->FindFixBin(y);
3786 if (drawOption.Index("same") >= 0) {
3787 TH1 *h1;
3788 TIter next(gPad->GetListOfPrimitives());
3789 while ((h1 = (TH1 *)next())) {
3790 if (!h1->InheritsFrom(TH1::Class())) continue;
3791 binmin = h1->GetXaxis()->GetFirst();
3792 break;
3793 }
3794 } else {
3795 binmin = fXaxis->GetFirst();
3796 }
3797 binx1 = fXaxis->FindFixBin(x1);
3798 // special case if more than 1 bin in x per pixel
3799 if (binx1-binx>1 && fH->GetDimension() == 1) {
3800 Double_t binval=fH->GetBinContent(binx);
3801 Int_t binnear=binx;
3802 for (Int_t ibin=binx+1; ibin<binx1; ibin++) {
3803 Double_t binvaltmp = fH->GetBinContent(ibin);
3804 if (TMath::Abs(x-binvaltmp) < TMath::Abs(x-binval)) {
3805 binval=binvaltmp;
3806 binnear=ibin;
3807 }
3808 }
3809 binx = binnear;
3810 }
3811 }
3812 if (fH->GetDimension() == 1) {
3814 TProfile *tp = (TProfile*)fH;
3815 fObjectInfo.Form("(x=%g, y=%g, binx=%d, binc=%g, bine=%g, binn=%d)",
3816 x, y, binx, fH->GetBinContent(binx), fH->GetBinError(binx),
3817 (Int_t) tp->GetBinEntries(binx));
3818 }
3819 else {
3820 Double_t integ = 0;
3821 for (Int_t bin=binmin;bin<=binx;bin++) {integ += fH->GetBinContent(bin);}
3822 fObjectInfo.Form("(x=%g, y=%g, binx=%d, binc=%g, Sum=%g)",
3823 x,y,binx,fH->GetBinContent(binx),integ);
3824 }
3825 } else if (fH->GetDimension() == 2) {
3826 if (fH->InheritsFrom(TH2Poly::Class())) {
3827 TH2Poly *th2 = (TH2Poly*)fH;
3828 biny = th2->FindBin(x,y);
3829 fObjectInfo.Form("%s (x=%g, y=%g, bin=%d, binc=%g)",
3830 th2->GetBinTitle(biny),x,y,biny,th2->GetBinContent(biny));
3831 }
3832 else if (fH->InheritsFrom(TProfile2D::Class())) {
3833 TProfile2D *tp = (TProfile2D*)fH;
3834 biny = fYaxis->FindFixBin(y);
3835 Int_t bin = fH->GetBin(binx,biny);
3836 fObjectInfo.Form("(x=%g, y=%g, binx=%d, biny=%d, binc=%g, bine=%g, binn=%d)",
3837 x, y, binx, biny, fH->GetBinContent(bin),
3838 fH->GetBinError(bin), (Int_t) tp->GetBinEntries(bin));
3839 } else {
3840 biny = fYaxis->FindFixBin(y);
3841 fObjectInfo.Form("(x=%g, y=%g, binx=%d, biny=%d, binc=%g bine=%g)",
3842 x,y,binx,biny,fH->GetBinContent(binx,biny),
3843 fH->GetBinError(binx,biny));
3844 }
3845 } else {
3846 // 3d case: retrieving the x,y,z bin is not yet implemented
3847 // print just the x,y info
3848 fObjectInfo.Form("(x=%g, y=%g)",x,y);
3849 }
3850
3851 return (char *)fObjectInfo.Data();
3852}
3853
3854////////////////////////////////////////////////////////////////////////////////
3855/// Set highlight (enable/disable) mode for fH
3856
3858{
3859 if (fH->IsHighlight()) return;
3860
3861 fXHighlightBin = -1;
3862 fYHighlightBin = -1;
3863 // delete previous highlight box
3864 if (gXHighlightBox) gXHighlightBox.reset();
3865 if (gYHighlightBox) gYHighlightBox.reset();
3866 // emit Highlighted() signal (user can check on disabled)
3867 if (gPad->GetCanvas()) gPad->GetCanvas()->Highlighted(gPad, fH, fXHighlightBin, fYHighlightBin);
3868}
3869
3870////////////////////////////////////////////////////////////////////////////////
3871/// Check on highlight bin
3872
3874{
3875 // call from DistancetoPrimitive (only if highlight is enable)
3876
3877 Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
3878 Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
3879 Int_t binx = fXaxis->FindFixBin(x);
3880 Int_t biny = fYaxis->FindFixBin(y);
3881 if (!gPad->IsVertical()) binx = fXaxis->FindFixBin(y);
3882
3883 Bool_t changedBin = kFALSE;
3884 if (binx != fXHighlightBin) {
3885 fXHighlightBin = binx;
3886 changedBin = kTRUE;
3887 } else if (fH->GetDimension() == 1) return;
3888 if (biny != fYHighlightBin) {
3889 fYHighlightBin = biny;
3890 changedBin = kTRUE;
3891 }
3892 if (!changedBin) return;
3893
3894 // Info("HighlightBin", "histo: %p '%s'\txbin: %d, ybin: %d",
3895 // (void *)fH, fH->GetName(), fXHighlightBin, fYHighlightBin);
3896
3897 // paint highlight bin as box (recursive calls PaintHighlightBin)
3898 gPad->Modified(kTRUE);
3899 gPad->Update();
3900
3901 // emit Highlighted() signal
3902 if (gPad->GetCanvas()) gPad->GetCanvas()->Highlighted(gPad, fH, fXHighlightBin, fYHighlightBin);
3903}
3904
3905////////////////////////////////////////////////////////////////////////////////
3906/// Paint highlight bin as TBox object
3907
3909{
3910 // call from PaintTitle
3911
3912 if (!fH->IsHighlight()) return;
3913
3914 Double_t uxmin = gPad->GetUxmin();
3915 Double_t uxmax = gPad->GetUxmax();
3916 Double_t uymin = gPad->GetUymin();
3917 Double_t uymax = gPad->GetUymax();
3918 if (gPad->GetLogx()) {
3919 uxmin = TMath::Power(10.0, uxmin);
3920 uxmax = TMath::Power(10.0, uxmax);
3921 }
3922 if (gPad->GetLogy()) {
3923 uymin = TMath::Power(10.0, uymin);
3924 uymax = TMath::Power(10.0, uymax);
3925 }
3926
3927 // testing specific possibility (after zoom, draw with "same", log, etc.)
3928 Double_t hcenter;
3929 if (gPad->IsVertical()) {
3931 if ((hcenter < uxmin) || (hcenter > uxmax)) return;
3932 } else {
3934 if ((hcenter < uymin) || (hcenter > uymax)) return;
3935 }
3936 if (fH->GetDimension() == 2) {
3938 if ((hcenter < uymin) || (hcenter > uymax)) return;
3939 }
3940
3941 // paint X highlight bin (for 1D or 2D)
3942 Double_t hbx1, hbx2, hby1, hby2;
3943 if (gPad->IsVertical()) {
3946 hby1 = uymin;
3947 hby2 = uymax;
3948 } else {
3949 hbx1 = uxmin;
3950 hbx2 = uxmax;
3953 }
3954
3955 if (!gXHighlightBox) {
3956 gXHighlightBox = std::make_unique<TBox>(hbx1, hby1, hbx2, hby2);
3957 gXHighlightBox->SetBit(kCannotPick);
3958 gXHighlightBox->SetFillColor(TColor::GetColor("#9797ff"));
3959 if (!TCanvas::SupportAlpha()) gXHighlightBox->SetFillStyle(3001);
3960 else gROOT->GetColor(gXHighlightBox->GetFillColor())->SetAlpha(0.5);
3961 }
3962 gXHighlightBox->SetX1(hbx1);
3963 gXHighlightBox->SetX2(hbx2);
3964 gXHighlightBox->SetY1(hby1);
3965 gXHighlightBox->SetY2(hby2);
3966 gXHighlightBox->Paint();
3967
3968 // Info("PaintHighlightBin", "histo: %p '%s'\txbin: %d, ybin: %d",
3969 // (void *)fH, fH->GetName(), fXHighlightBin, fYHighlightBin);
3970
3971 // paint Y highlight bin (only for 2D)
3972 if (fH->GetDimension() != 2) return;
3973 hbx1 = uxmin;
3974 hbx2 = uxmax;
3977
3978 if (!gYHighlightBox) {
3979 gYHighlightBox = std::make_unique<TBox>(hbx1, hby1, hbx2, hby2);
3980 gYHighlightBox->SetBit(kCannotPick);
3981 gYHighlightBox->SetFillColor(gXHighlightBox->GetFillColor());
3982 gYHighlightBox->SetFillStyle(gXHighlightBox->GetFillStyle());
3983 }
3984 gYHighlightBox->SetX1(hbx1);
3985 gYHighlightBox->SetX2(hbx2);
3986 gYHighlightBox->SetY1(hby1);
3987 gYHighlightBox->SetY2(hby2);
3988 gYHighlightBox->Paint();
3989}
3990
3991////////////////////////////////////////////////////////////////////////////////
3992/// Return `kTRUE` if the cell `ix`, `iy` is inside one of the graphical cuts.
3993
3995{
3996
3997 for (Int_t i=0;i<fNcuts;i++) {
4000 if (fCutsOpt[i] > 0) {
4001 if (!fCuts[i]->IsInside(x,y)) return kFALSE;
4002 } else {
4003 if (fCuts[i]->IsInside(x,y)) return kFALSE;
4004 }
4005 }
4006 return kTRUE;
4007}
4008
4009////////////////////////////////////////////////////////////////////////////////
4010/// Return `kTRUE` if the point `x`, `y` is inside one of the graphical cuts.
4011
4013{
4014
4015 for (Int_t i=0;i<fNcuts;i++) {
4016 if (fCutsOpt[i] > 0) {
4017 if (!fCuts[i]->IsInside(x,y)) return kFALSE;
4018 } else {
4019 if (fCuts[i]->IsInside(x,y)) return kFALSE;
4020 }
4021 }
4022 return kTRUE;
4023}
4024
4025////////////////////////////////////////////////////////////////////////////////
4026/// Decode string `choptin` and fill Hoption structure.
4027
4029{
4030
4031 char *l;
4032 char chopt[128];
4033 Int_t nch = strlen(choptin);
4034 strlcpy(chopt,choptin,128);
4035 Int_t hdim = fH->GetDimension();
4036 Bool_t explicitColor = kFALSE;
4037
4045 Hoption.Candle = 0;
4046
4047 // special 2D options
4048 Hoption.List = 0;
4049 Hoption.Zscale = 0;
4050 Hoption.FrontBox = 1;
4051 Hoption.BackBox = 1;
4053
4054 Hoption.Zero = 0;
4055
4057
4058 //check for graphical cuts
4059 MakeCuts(chopt);
4060
4061 for (Int_t i=0;i<nch;i++) chopt[i] = toupper(chopt[i]);
4062 if (hdim > 1) Hoption.Color = 1; // Default drawing option for 2D and 3D histograms
4063 if (!nch) Hoption.Hist = 1;
4064 if (fFunctions->First()) Hoption.Func = 1;
4065 if (fH->GetSumw2N() && hdim == 1) Hoption.Error = 2;
4066
4067 char *l1 = strstr(chopt,"PFC"); // Automatic Fill Color
4068 char *l2 = strstr(chopt,"PLC"); // Automatic Line Color
4069 char *l3 = strstr(chopt,"PMC"); // Automatic Marker Color
4070 if (l1 || l2 || l3) {
4071 Int_t i = gPad->NextPaletteColor();
4072 if (l1) {memcpy(l1," ",3); fH->SetFillColor(i);}
4073 if (l2) {memcpy(l2," ",3); fH->SetLineColor(i);}
4074 if (l3) {memcpy(l3," ",3); fH->SetMarkerColor(i);}
4075 Hoption.Hist = 1; // Make sure something is drawn in case there is no drawing option specified.
4076 }
4077
4078 l = strstr(chopt,"MIN0");
4079 if (l) {
4080 Hoption.MinimumZero = 1;
4081 memcpy(l," ",4);
4082 }
4083
4084 l = strstr(chopt,"SPEC");
4085 if (l) {
4086 Hoption.Color = 0;
4087 memcpy(l," ",4);
4088 Int_t bs=0;
4089 l = strstr(chopt,"BF(");
4090 if (l) {
4091 if (sscanf(&l[3],"%d",&bs) > 0) {
4092 Int_t i=0;
4093 while (l[i]!=')') {
4094 l[i] = ' ';
4095 i++;
4096 }
4097 l[i] = ' ';
4098 }
4099 }
4100 Hoption.Spec = TMath::Max(1600,bs);
4101 return 1;
4102 }
4103
4104 l = strstr(chopt,"GL");
4105 if (l) {
4106 memcpy(l," ",2);
4107 }
4108 l = strstr(chopt,"X+");
4109 if (l) {
4110 Hoption.AxisPos = 10;
4111 memcpy(l," ",2);
4112 }
4113 l = strstr(chopt,"Y+");
4114 if (l) {
4115 Hoption.AxisPos += 1;
4116 memcpy(l," ",2);
4117 }
4118 if ((Hoption.AxisPos == 10 || Hoption.AxisPos == 1) && (nch == 2)) Hoption.Hist = 1;
4119 if (Hoption.AxisPos == 11 && nch == 4) Hoption.Hist = 1;
4120
4121 l = strstr(chopt,"SAMES");
4122 if (l) {
4123 if (nch == 5) Hoption.Hist = 1;
4124 Hoption.Same = 2;
4125 memcpy(l," ",5);
4126 if (l[5] == '0') { Hoption.Same += 10; l[5] = ' '; }
4127 }
4128 l = strstr(chopt,"SAME");
4129 if (l) {
4130 if (nch == 4) Hoption.Hist = 1;
4131 Hoption.Same = 1;
4132 memcpy(l," ",4);
4133 if (l[4] == '0') { Hoption.Same += 10; l[4] = ' '; }
4134 }
4135
4136 l = strstr(chopt,"SCAT");
4137 if (l) {
4138 Warning("MakeChopt","option SCAT is deprecated.");
4139 Hoption.Scat = 1;
4140 memcpy(l," ",4);
4141 Hoption.Color = 0;
4142 }
4143
4144 l = strstr(chopt,"PIE");
4145 if (l) {
4146 Hoption.Pie = 1;
4147 memcpy(l," ",3);
4148 }
4149
4150
4151 l = strstr(chopt,"CANDLE");
4152 if (l) {
4153 TCandle candle;
4154 Hoption.Candle = candle.ParseOption(l);
4155 Hoption.Color = 0;
4156 }
4157
4158 l = strstr(chopt,"VIOLIN");
4159 if (l) {
4160 TCandle candle;
4161 Hoption.Candle = candle.ParseOption(l);
4162 Hoption.Color = 0;
4163 }
4164
4165 l = strstr(chopt,"LEGO");
4166 if (l) {
4167 Hoption.Color = 0;
4168 Hoption.Lego = 1; memcpy(l," ",4);
4169 if (l[4] == '1') { Hoption.Lego = 11; l[4] = ' '; }
4170 if (l[4] == '2') { Hoption.Lego = 12; l[4] = ' '; }
4171 if (l[4] == '3') { Hoption.Lego = 13; l[4] = ' '; }
4172 if (l[4] == '4') { Hoption.Lego = 14; l[4] = ' '; }
4173 if (l[4] == '9') { Hoption.Lego = 19; l[4] = ' '; }
4174 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4175 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4176 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4177 }
4178
4179 l = strstr(chopt,"SURF");
4180 if (l) {
4181 Hoption.Color = 0;
4182 Hoption.Surf = 1; memcpy(l," ",4);
4183 if (l[4] == '1') { Hoption.Surf = 11; l[4] = ' '; }
4184 if (l[4] == '2') { Hoption.Surf = 12; l[4] = ' '; }
4185 if (l[4] == '3') { Hoption.Surf = 13; l[4] = ' '; }
4186 if (l[4] == '4') { Hoption.Surf = 14; l[4] = ' '; }
4187 if (l[4] == '5') { Hoption.Surf = 15; l[4] = ' '; }
4188 if (l[4] == '6') { Hoption.Surf = 16; l[4] = ' '; }
4189 if (l[4] == '7') { Hoption.Surf = 17; l[4] = ' '; }
4190 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4191 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4192 }
4193
4194 l = strstr(chopt,"TF3");
4195 if (l) {
4196 memcpy(l," ",3);
4197 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4198 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4199 }
4200
4201 l = strstr(chopt,"ISO");
4202 if (l) {
4203 memcpy(l," ",3);
4204 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4205 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4206 Hoption.Color = 0;
4207 }
4208
4209 l = strstr(chopt,"LIST"); if (l) { Hoption.List = 1; memcpy(l," ",4);}
4210
4211 l = strstr(chopt,"CONT");
4212 if (l) {
4213 memcpy(l," ",4);
4214 if (hdim>1) {
4215 Hoption.Color = 0;
4216 Hoption.Contour = 1;
4217 if (l[4] == '1') { Hoption.Contour = 11; l[4] = ' '; }
4218 if (l[4] == '2') { Hoption.Contour = 12; l[4] = ' '; }
4219 if (l[4] == '3') { Hoption.Contour = 13; l[4] = ' '; }
4220 if (l[4] == '4') { Hoption.Contour = 14; l[4] = ' '; }
4221 if (l[4] == '5') { Hoption.Contour = 15; l[4] = ' '; }
4222 } else {
4223 Hoption.Hist = 1;
4224 }
4225 }
4226 l = strstr(chopt,"HBAR");
4227 if (l) {
4228 Hoption.Hist = 0;
4229 Hoption.Bar = 20; memcpy(l," ",4);
4230 if (l[4] == '1') { Hoption.Bar = 21; l[4] = ' '; }
4231 if (l[4] == '2') { Hoption.Bar = 22; l[4] = ' '; }
4232 if (l[4] == '3') { Hoption.Bar = 23; l[4] = ' '; }
4233 if (l[4] == '4') { Hoption.Bar = 24; l[4] = ' '; }
4234 }
4235 l = strstr(chopt,"BAR");
4236 if (l) {
4237 Hoption.Hist = 0;
4238 Hoption.Bar = 10; memcpy(l," ",3);
4239 if (l[3] == '1') { Hoption.Bar = 11; l[3] = ' '; }
4240 if (l[3] == '2') { Hoption.Bar = 12; l[3] = ' '; }
4241 if (l[3] == '3') { Hoption.Bar = 13; l[3] = ' '; }
4242 if (l[3] == '4') { Hoption.Bar = 14; l[3] = ' '; }
4243 }
4244
4245 l = strstr(chopt,"ARR" );
4246 if (l) {
4247 memcpy(l," ", 3);
4248 if (hdim>1) {
4249 Hoption.Arrow = 1;
4250 Hoption.Color = 0;
4251 l = strstr(chopt,"COL"); if (l) { Hoption.Arrow = 2; memcpy(l," ",3); }
4252 l = strstr(chopt,"Z"); if (l) { Hoption.Zscale = 1; memcpy(l," ",1); }
4253 } else {
4254 Hoption.Hist = 1;
4255 }
4256 }
4257 l = strstr(chopt,"BOX" );
4258 if (l) {
4259 memcpy(l," ", 3);
4260 if (hdim>1) {
4261 Hoption.Color = 0;
4262 Hoption.Box = 1;
4263 if (l[3] == '1') { Hoption.Box = 11; l[3] = ' '; }
4264 if (l[3] == '2') { Hoption.Box = 12; l[3] = ' '; }
4265 if (l[3] == '3') { Hoption.Box = 13; l[3] = ' '; }
4266 } else {
4267 Hoption.Hist = 1;
4268 }
4269 }
4270 l = strstr(chopt,"TEXT");
4271 if (l) {
4272 Int_t angle;
4273 if (sscanf(&l[4],"%d",&angle) > 0) {
4274 if (angle < 0) angle=0;
4275 if (angle > 90) angle=90;
4276 Hoption.Text = 1000+angle;
4277 } else {
4278 Hoption.Text = 1;
4279 }
4280 memcpy(l," ", 4);
4281 l = strstr(chopt,"N");
4282 if (l && fH->InheritsFrom(TH2Poly::Class())) Hoption.Text += 3000;
4283 Hoption.Color = 0;
4284 }
4285 l = strstr(chopt,"COLZ");
4286 if (l) {
4287 memcpy(l," ",4);
4288 if (hdim > 1) {
4289 explicitColor = kTRUE;
4290 Hoption.Color = 1;
4291 Hoption.Zscale = 1;
4292 if (l[4] == '2') { Hoption.Color = 3; l[4] = ' '; }
4293 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4294 l = strstr(chopt,"1"); if (l) { Hoption.Color = 2; memcpy(l," ",1); }
4295 } else {
4296 Hoption.Hist = 1;
4297 }
4298 }
4299 l = strstr(chopt,"COL" );
4300 if (l) {
4301 memcpy(l," ", 3);
4302 if (hdim > 1) {
4303 explicitColor = kTRUE;
4304 Hoption.Color = 1;
4305 if (l[3] == '2') { Hoption.Color = 3; l[3] = ' '; }
4306 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4307 l = strstr(chopt,"1"); if (l) { Hoption.Color = 2; memcpy(l," ",1); }
4308 } else {
4309 Hoption.Hist = 1;
4310 }
4311 }
4312 l = strstr(chopt,"FUNC"); if (l) { Hoption.Func = 2; memcpy(l," ",4); Hoption.Hist = 0; }
4313 l = strstr(chopt,"HIST"); if (l) { Hoption.Hist = 2; memcpy(l," ",4); Hoption.Func = 0; Hoption.Error = 0;}
4314 l = strstr(chopt,"AXIS"); if (l) { Hoption.Axis = 1; memcpy(l," ",4); }
4315 l = strstr(chopt,"AXIG"); if (l) { Hoption.Axis = 2; memcpy(l," ",4); }
4316 l = strstr(chopt,"SCAT"); if (l) { Hoption.Scat = 1; memcpy(l," ",4); }
4317 l = strstr(chopt,"POL"); if (l) { Hoption.System = kPOLAR; memcpy(l," ",3); }
4318 l = strstr(chopt,"CYL"); if (l) { Hoption.System = kCYLINDRICAL; memcpy(l," ",3); }
4319 l = strstr(chopt,"SPH"); if (l) { Hoption.System = kSPHERICAL; memcpy(l," ",3); }
4320 l = strstr(chopt,"PSR"); if (l) { Hoption.System = kRAPIDITY; memcpy(l," ",3); }
4321
4322 l = strstr(chopt,"TRI");
4323 if (l) {
4324 if (!explicitColor) Hoption.Color = 0;
4325 Hoption.Tri = 1; memcpy(l," ",3);
4326 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4327 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4328 l = strstr(chopt,"ERR"); if (l) memcpy(l," ",3);
4329 }
4330
4331 l = strstr(chopt,"AITOFF");
4332 if (l) {
4333 Hoption.Proj = 1; memcpy(l," ",6); //Aitoff projection
4334 }
4335 l = strstr(chopt,"MERCATOR");
4336 if (l) {
4337 Hoption.Proj = 2; memcpy(l," ",8); //Mercator projection
4338 }
4339 l = strstr(chopt,"SINUSOIDAL");
4340 if (l) {
4341 Hoption.Proj = 3; memcpy(l," ",10); //Sinusoidal projection
4342 }
4343 l = strstr(chopt,"PARABOLIC");
4344 if (l) {
4345 Hoption.Proj = 4; memcpy(l," ",9); //Parabolic projection
4346 }
4347 l = strstr(chopt,"MOLLWEIDE");
4348 if (l) {
4349 Hoption.Proj = 5; memcpy(l," ",9); //Mollweide projection
4350 }
4351 if (Hoption.Proj > 0) {
4352 if (!explicitColor) Hoption.Color = 0;
4353 Hoption.Contour = 14;
4354 }
4355
4356 if (strstr(chopt,"A")) Hoption.Axis = -1;
4357 if (strstr(chopt,"B")) Hoption.Bar = 1;
4358 if (strstr(chopt,"C") && !strstr(chopt,"CJUST")) { Hoption.Curve =1; Hoption.Hist = -1;}
4359 if (strstr(chopt,"F")) Hoption.Fill =1;
4360 if (strstr(chopt,"][")) {Hoption.Off =1; Hoption.Hist =1;}
4361 if (strstr(chopt,"F2")) Hoption.Fill =2;
4362 if (strstr(chopt,"L")) { Hoption.Line =1; Hoption.Hist = -1;}
4363 if (strstr(chopt,"P")) { Hoption.Mark =1; Hoption.Hist = -1;}
4364 if (strstr(chopt,"Z")) Hoption.Zscale =1;
4365 if (strstr(chopt,"*")) Hoption.Star =1;
4366 if (strstr(chopt,"H")) Hoption.Hist =2;
4367 if (strstr(chopt,"P0")) Hoption.Mark =10;
4368
4369 if (fH->InheritsFrom(TH2Poly::Class())) {
4370 if ((Hoption.Fill+Hoption.Line+Hoption.Mark != 0) && !explicitColor) Hoption.Color = 0;
4371 }
4372
4373 if (strstr(chopt,"E")) {
4374 if (hdim == 1) {
4375 Hoption.Error = 1;
4376 if (strstr(chopt,"E1")) Hoption.Error = 11;
4377 if (strstr(chopt,"E2")) Hoption.Error = 12;
4378 if (strstr(chopt,"E3")) Hoption.Error = 13;
4379 if (strstr(chopt,"E4")) Hoption.Error = 14;
4380 if (strstr(chopt,"E5")) Hoption.Error = 15;
4381 if (strstr(chopt,"E6")) Hoption.Error = 16;
4382 if (strstr(chopt,"E0")) Hoption.Error += 40;
4383 if (strstr(chopt,"X0")) {
4384 if (Hoption.Error == 1) Hoption.Error += 20;
4385 Hoption.Error += 10;
4386 }
4388 Hoption.Text += 2000;
4389 Hoption.Error = 0;
4390 }
4391 } else {
4392 if (Hoption.Error == 0) {
4393 Hoption.Error = 100;
4394 if (!explicitColor) Hoption.Color = 0;
4395 }
4396 if (Hoption.Text) {
4397 Hoption.Text += 2000;
4398 Hoption.Error = 0;
4399 }
4400 }
4401 }
4402
4403 if (Hoption.Surf == 15) {
4405 Hoption.Surf = 13;
4406 Warning("MakeChopt","option SURF5 is not supported in Cartesian and Polar modes");
4407 }
4408 }
4409
4410 // Copy options from current style
4411 Hoption.Logx = gPad->GetLogx();
4412 Hoption.Logy = gPad->GetLogy();
4413 Hoption.Logz = gPad->GetLogz();
4414
4415 // Check options incompatibilities
4416 if (Hoption.Bar == 1) Hoption.Hist = -1;
4417 return 1;
4418}
4419
4420////////////////////////////////////////////////////////////////////////////////
4421/// Decode string `choptin` and fill Graphical cuts structure.
4422
4424{
4425
4426 fNcuts = 0;
4427 char *left = (char*)strchr(choptin,'[');
4428 if (!left) return 0;
4429 char *right = (char*)strchr(choptin,']');
4430 if (!right) return 0;
4431 Int_t nch = right-left;
4432 if (nch < 2) return 0;
4433 char *cuts = left+1;
4434 *right = 0;
4435 char *comma, *minus;
4436 Int_t i;
4437 while (true) {
4438 comma = strchr(cuts,',');
4439 if (comma) *comma = 0;
4440 minus = strchr(cuts,'-');
4441 if (minus) cuts = minus+1;
4442 while (*cuts == ' ') cuts++;
4443 Int_t nc = strlen(cuts);
4444 while (cuts[nc-1] == ' ') {cuts[nc-1] = 0; nc--;}
4445 TIter next(gROOT->GetListOfSpecials());
4446 TCutG *cut=nullptr;
4447 TObject *obj;
4448 while ((obj = next())) {
4449 if (!obj->InheritsFrom(TCutG::Class())) continue;
4450 if (strcmp(obj->GetName(),cuts)) continue;
4451 cut = (TCutG*)obj;
4452 break;
4453 }
4454 if (cut) {
4455 fCuts[fNcuts] = cut;
4456 fCutsOpt[fNcuts] = 1;
4457 if (minus) fCutsOpt[fNcuts] = -1;
4458 fNcuts++;
4459 }
4460 if (!comma) break;
4461 cuts = comma+1;
4462 }
4463 for (i=0;i<=nch;i++) left[i] = ' ';
4464 return fNcuts;
4465}
4466
4467////////////////////////////////////////////////////////////////////////////////
4468/// [Control routine to paint any kind of histograms](\ref HP00)
4469
4471{
4472
4473 if (fH->GetBuffer()) fH->BufferEmpty(-1);
4474
4475 //For iOS: put the histogram on the top of stack of pickable objects.
4476 const TPickerStackGuard topPush(fH);
4477
4478 gPad->SetVertical(kTRUE);
4479
4480 TH1 *oldhist = gCurrentHist;
4481 gCurrentHist = fH;
4482 TH1 *hsave = fH;
4483 Double_t minsav = fH->GetMinimumStored();
4484
4485 if (!MakeChopt(option)) return; //check options and fill Hoption structure
4486
4487 // Paint using TSpectrum2Painter
4488 if (Hoption.Spec) {
4489 if (!TableInit()) return;
4490 if (!TClass::GetClass("TSpectrum2Painter")) gSystem->Load("libSpectrumPainter");
4491 gROOT->ProcessLineFast(TString::Format("TSpectrum2Painter::PaintSpectrum((TH2F*)0x%zx,\"%s\",%d)",
4492 (size_t)fH, option, Hoption.Spec).Data());
4493 return;
4494 }
4495
4496 // Deflate the labels in case of alphanumeric labels
4500
4501 if (Hoption.Pie) {
4502 if (fH->GetDimension() == 1) {
4503 if (!fPie)
4504 fPie = std::make_unique<TPie>(fH);
4505 fPie->Paint(option);
4506 } else {
4507 Error("Paint", "Option PIE is for 1D histograms only");
4508 }
4509 return;
4510 } else {
4511 fPie.reset();
4512 }
4513
4514 fXbuf.resize(kNMAX);
4515 fYbuf.resize(kNMAX);
4516 if (fH->GetDimension() > 2) {
4517 PaintH3(option);
4518 fH->SetMinimum(minsav);
4519 if (Hoption.Func) {
4520 Hoption_t hoptsave = Hoption;
4521 Hparam_t hparsave = Hparam;
4523 SetHistogram(hsave);
4524 Hoption = hoptsave;
4525 Hparam = hparsave;
4526 }
4527 gCurrentHist = oldhist;
4528 fXbuf.clear();
4529 fYbuf.clear();
4530 return;
4531 }
4532 TView *view = gPad->GetView();
4533 if (view) {
4534 if (!Hoption.Lego && !Hoption.Surf && !Hoption.Tri) {
4535 delete view;
4536 gPad->SetView(nullptr);
4537 }
4538 }
4539 if (fH->GetDimension() > 1 || Hoption.Lego || Hoption.Surf) {
4540 // In case of 1D histogram, Z axis becomes Y axis.
4541 Int_t logysav=0, logzsav=0;
4542 if (fH->GetDimension() == 1) {
4543 logysav = Hoption.Logy;
4544 logzsav = Hoption.Logz;
4545 Hoption.Logz = 0;
4546 if (Hoption.Logy) {
4547 Hoption.Logz = 1;
4548 Hoption.Logy = 0;
4549 }
4550 }
4552 if (Hoption.Func) {
4553 Hoption_t hoptsave = Hoption;
4554 Hparam_t hparsave = Hparam;
4556 SetHistogram(hsave);
4557 Hoption = hoptsave;
4558 Hparam = hparsave;
4559 }
4560 fH->SetMinimum(minsav);
4561 gCurrentHist = oldhist;
4562 fXbuf.clear();
4563 fYbuf.clear();
4564 if (fH->GetDimension() == 1) {
4565 Hoption.Logy = logysav;
4566 Hoption.Logz = logzsav;
4567 }
4568 return;
4569 }
4570
4571 if (Hoption.Bar >= 20) {
4573 fXbuf.clear();
4574 fYbuf.clear();
4575 return;
4576 }
4577
4578 gPad->RangeAxisChanged(); //emit RangeAxisChanged() signal to sync axes
4579 // fill Hparam structure with histo parameters
4580 if (!PaintInit()) {
4581 fXbuf.clear();
4582 fYbuf.clear();
4583 return;
4584 }
4585
4586 // Picture surround (if new page) and page number (if requested).
4587 // Histogram surround (if not option "Same").
4588 PaintFrame();
4589
4590 // Paint histogram axis only
4591 Bool_t gridx = gPad->GetGridx();
4592 Bool_t gridy = gPad->GetGridy();
4593 if (Hoption.Axis > 0) {
4594 if (Hoption.Axis > 1) PaintAxis(kTRUE); //axis with grid
4595 else {
4596 if (gridx) gPad->SetGridx(0);
4597 if (gridy) gPad->SetGridy(0);
4599 if (gridx) gPad->SetGridx(1);
4600 if (gridy) gPad->SetGridy(1);
4601 }
4602 if ((Hoption.Same%10) ==1) Hoption.Same += 1;
4603 goto paintstat;
4604 }
4605 if (gridx || gridy) PaintAxis(kTRUE); // Draw the grid only
4606
4607 // test for options BAR or HBAR
4608 if (Hoption.Bar >= 10) {
4610 }
4611
4612 // do not draw histogram if error bars required
4613 if (!Hoption.Error) {
4614 if (Hoption.Hist && Hoption.Bar<10) PaintHist(option);
4615 }
4616
4617 // test for error bars or option E
4618 if (Hoption.Error) {
4620 if (Hoption.Hist == 2) PaintHist(option);
4621 }
4622
4624
4625 // test for associated function
4626 if (Hoption.Func) {
4627 Hoption_t hoptsave = Hoption;
4628 Hparam_t hparsave = Hparam;
4630 SetHistogram(hsave);
4631 Hoption = hoptsave;
4632 Hparam = hparsave;
4633 }
4634
4635 if (gridx) gPad->SetGridx(0);
4636 if (gridy) gPad->SetGridy(0);
4638 if (gridx) gPad->SetGridx(1);
4639 if (gridy) gPad->SetGridy(1);
4640
4641 PaintTitle(); // Draw histogram title
4642
4643 // Draw box with histogram statistics and/or fit parameters
4644paintstat:
4645 if ((Hoption.Same%10) != 1 && !fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
4646 TIter next(fFunctions);
4647 TObject *obj = nullptr;
4648 while ((obj = next())) {
4649 if (obj->InheritsFrom(TF1::Class())) break;
4650 obj = nullptr;
4651 }
4652
4653 //Stat is painted twice (first, it will be in canvas' list of primitives),
4654 //second, it will be here, this is not required on iOS.
4655 //Condition is ALWAYS true on a platform different from iOS.
4656 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode())
4657 PaintStat(gStyle->GetOptStat(),(TF1*)obj);
4658 }
4659 fH->SetMinimum(minsav);
4660 gCurrentHist = oldhist;
4661 fXbuf.clear();
4662 fYbuf.clear();
4663}
4664
4665////////////////////////////////////////////////////////////////////////////////
4666/// [Control function to draw a table as an arrow plot](\ref HP12)
4667
4669{
4670 Double_t xk, xstep, yk, ystep;
4671 Double_t dx, dy, x1, x2, y1, y2, xc, yc, dxn, dyn;
4674 Double_t xrg = gPad->GetUxmin();
4675 Double_t yrg = gPad->GetUymin();
4676 Double_t xln = gPad->GetUxmax() - xrg;
4677 Double_t yln = gPad->GetUymax() - yrg;
4678 Double_t cx = (xln/Double_t(ncx))/2.;
4679 Double_t cy = (yln/Double_t(ncy))/2.;
4680 Double_t dn = 1.E-30;
4681
4682 auto arrow = new TArrow();
4683 arrow->SetAngle(30);
4684 arrow->SetFillStyle(1001);
4685 arrow->SetFillColor(fH->GetLineColor());
4686 arrow->SetLineColor(fH->GetLineColor());
4687 arrow->SetLineWidth(fH->GetLineWidth());
4688
4689 // Initialize the levels on the Z axis
4690 Int_t ncolors=0, ndivz=0;
4691 Double_t scale=0.;
4692 if (Hoption.Arrow>1) {
4693 ncolors = gStyle->GetNumberOfColors();
4694 Int_t ndiv = fH->GetContour();
4695 if (ndiv == 0 ) {
4696 ndiv = gStyle->GetNumberContours();
4697 fH->SetContour(ndiv);
4698 }
4699 ndivz = TMath::Abs(ndiv);
4700 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
4701 scale = ndivz/(fH->GetMaximum()-fH->GetMinimum());
4702 }
4703
4704 for (Int_t id=1;id<=2;id++) {
4705 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
4706 yk = fYaxis->GetBinLowEdge(j);
4707 ystep = fYaxis->GetBinWidth(j);
4708 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
4709 xk = fXaxis->GetBinLowEdge(i);
4710 xstep = fXaxis->GetBinWidth(i);
4711 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
4712 if (i == Hparam.xfirst) {
4713 dx = fH->GetBinContent(i+1, j) - fH->GetBinContent(i, j);
4714 } else if (i == Hparam.xlast) {
4715 dx = fH->GetBinContent(i, j) - fH->GetBinContent(i-1, j);
4716 } else {
4717 dx = 0.5*(fH->GetBinContent(i+1, j) - fH->GetBinContent(i-1, j));
4718 }
4719 if (j == Hparam.yfirst) {
4720 dy = fH->GetBinContent(i, j+1) - fH->GetBinContent(i, j);
4721 } else if (j == Hparam.ylast) {
4722 dy = fH->GetBinContent(i, j) - fH->GetBinContent(i, j-1);
4723 } else {
4724 dy = 0.5*(fH->GetBinContent(i, j+1) - fH->GetBinContent(i, j-1));
4725 }
4726 if (id == 1) {
4727 dn = TMath::Max(dn, TMath::Abs(dx));
4728 dn = TMath::Max(dn, TMath::Abs(dy));
4729 } else if (id == 2) {
4730 xc = xrg + xln*(Double_t(i - Hparam.xfirst+1)-0.5)/Double_t(ncx);
4731 dxn = cx*dx/dn;
4732 x1 = xc - dxn;
4733 x2 = xc + dxn;
4734 yc = yrg + yln*(Double_t(j - Hparam.yfirst+1)-0.5)/Double_t(ncy);
4735 dyn = cy*dy/dn;
4736 y1 = yc - dyn;
4737 y2 = yc + dyn;
4738 if (Hoption.Arrow>1) {
4739 int color = Int_t(0.01+(fH->GetBinContent(i, j)-fH->GetMinimum())*scale);
4740 Int_t theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
4741 if (theColor > ncolors-1) theColor = ncolors-1;
4742 arrow->SetFillColor(gStyle->GetColorPalette(theColor));
4743 arrow->SetLineColor(gStyle->GetColorPalette(theColor));
4744 }
4745 if (TMath::Abs(x2-x1) > 0. || TMath::Abs(y2-y1) > 0.) {
4746 arrow->PaintArrow(x1, y1, x2, y2, 0.015, "|>");
4747 } else {
4748 arrow->PaintArrow(x1, y1, x2, y2, 0.005, "|>");
4749 }
4750 }
4751 }
4752 }
4753 }
4754
4756}
4757
4758////////////////////////////////////////////////////////////////////////////////
4759/// Draw axis (2D case) of an histogram.
4760///
4761/// If `drawGridOnly` is `TRUE`, only the grid is painted (if needed). This allows
4762/// to draw the grid and the axis separately. In `THistPainter::Paint` this
4763/// feature is used to make sure that the grid is drawn in the background and
4764/// the axis tick marks in the foreground of the pad.
4765
4767{
4768
4769 //On iOS, grid should not be pickable and can not be highlighted.
4770 //Condition is never true on a platform different from iOS.
4771 if (drawGridOnly && (gPad->PadInHighlightMode() || gPad->PadInSelectionMode()))
4772 return;
4773
4774 if (Hoption.Axis == -1) return;
4775 if (Hoption.Same && Hoption.Axis <= 0) return;
4776
4777 // Repainting alphanumeric labels axis on a plot done with
4778 // the option HBAR (horizontal) needs some adjustments.
4779 TAxis *xaxis = nullptr;
4780 TAxis *yaxis = nullptr;
4781 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4782 if (fXaxis->GetLabels() || fYaxis->GetLabels()) { // One axis has alphanumeric labels
4783 TIter next(gPad->GetListOfPrimitives());
4784 TObject *obj;
4785 // Check if the first TH1 of THStack in the pad is drawn with the option HBAR
4786 while ((obj = next())) {
4787 if (!obj->InheritsFrom(TH1::Class()) &&
4788 !obj->InheritsFrom(THStack::Class())) continue;
4789 TString opt = obj->GetDrawOption();
4790 opt.ToLower();
4791 // if drawn with HBAR, the axis should be inverted and the pad set to horizontal
4792 if (strstr(opt,"hbar")) {
4793 gPad->SetVertical(kFALSE);
4794 xaxis = fXaxis;
4795 yaxis = fYaxis;
4796 if (!strcmp(xaxis->GetName(),"xaxis")) {
4797 fXaxis = yaxis;
4798 fYaxis = xaxis;
4799 }
4800 }
4801 break;
4802 }
4803 }
4804 }
4805
4806 static char chopt[10] = "";
4807 Double_t gridl = 0;
4808 Int_t ndiv, ndivx, ndivy, nx1, nx2, ndivsave;
4809 Int_t useHparam = 0;
4810 Double_t umin, umax, uminsave, umaxsave;
4811 Short_t xAxisPos = Hoption.AxisPos/10;
4812 Short_t yAxisPos = Hoption.AxisPos - 10*xAxisPos;
4813
4814 Double_t axmin = gPad->GetUxmin();
4815 Double_t axmax = gPad->GetUxmax();
4816 Double_t aymin = gPad->GetUymin();
4817 Double_t aymax = gPad->GetUymax();
4818 char *cw = nullptr;
4819 TGaxis axis;
4820
4821 // In case of option 'cont4' or in case of option 'same' over a 'cont4 plot'
4822 // Hparam must be use for the axis limits.
4823 if (Hoption.Contour == 14) useHparam = 1;
4824 if (Hoption.Same) {
4825 TObject *obj;
4826 TIter next(gPad->GetListOfPrimitives());
4827 while ((obj=next())) {
4828 if (strstr(obj->GetDrawOption(),"cont4")) {
4829 useHparam = 1;
4830 break;
4831 }
4832 }
4833 }
4834
4835 // Paint X axis
4836
4837 //To make X-axis selectable on iOS device.
4838 if (gPad->PadInSelectionMode())
4839 gPad->PushSelectableObject(fXaxis);
4840
4841 //This condition is ALWAYS true, unless it works on iOS (can be false on iOS).
4842 if (gPad->PadInSelectionMode() || !gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && gPad->GetSelected() == fXaxis)) {
4843 ndivx = fXaxis->GetNdivisions();
4844 if (ndivx > 1000) {
4845 nx2 = ndivx/100;
4846 nx1 = TMath::Max(1, ndivx%100);
4847 ndivx = 100*nx2 + Int_t(Float_t(nx1)*gPad->GetAbsWNDC());
4848 }
4849 axis.SetTextAngle(0);
4851
4852 chopt[0] = 0;
4853 strlcat(chopt, "SDH",10);
4854 if (ndivx < 0) strlcat(chopt, "N",10);
4855 if (gPad->GetGridx()) {
4856 gridl = (aymax-aymin)/(gPad->GetY2() - gPad->GetY1());
4857 strlcat(chopt, "W",10);
4858 }
4859
4860 // Define X-Axis limits
4861 if (Hoption.Logx) {
4862 strlcat(chopt, "G",10);
4863 ndiv = TMath::Abs(ndivx);
4864 if (useHparam) {
4865 umin = TMath::Power(10,Hparam.xmin);
4866 umax = TMath::Power(10,Hparam.xmax);
4867 } else {
4868 umin = TMath::Power(10,axmin);
4869 umax = TMath::Power(10,axmax);
4870 }
4871 } else {
4872 ndiv = TMath::Abs(ndivx);
4873 if (useHparam) {
4874 umin = Hparam.xmin;
4875 umax = Hparam.xmax;
4876 } else {
4877 umin = axmin;
4878 umax = axmax;
4879 }
4880 }
4881
4882 // Display axis as time
4883 if (fXaxis->GetTimeDisplay()) {
4884 strlcat(chopt,"t",10);
4885 if (strlen(fXaxis->GetTimeFormatOnly()) == 0) {
4887 }
4888 }
4889
4890 // The main X axis can be on the bottom or on the top of the pad
4891 Double_t xAxisYPos1, xAxisYPos2;
4892 if (xAxisPos == 1) {
4893 // Main X axis top
4894 xAxisYPos1 = aymax;
4895 xAxisYPos2 = aymin;
4896 } else {
4897 // Main X axis bottom
4898 xAxisYPos1 = aymin;
4899 xAxisYPos2 = aymax;
4900 }
4901
4902 // Paint the main X axis (always)
4903 uminsave = umin;
4904 umaxsave = umax;
4905 ndivsave = ndiv;
4906 axis.SetOption(chopt);
4907 if (xAxisPos) {
4908 strlcat(chopt, "-",10);
4909 gridl = -gridl;
4910 }
4911 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4912 axis.SetLabelSize(0.);
4913 axis.SetTitle("");
4914 }
4915 axis.PaintAxis(axmin, xAxisYPos1,
4916 axmax, xAxisYPos1,
4917 umin, umax, ndiv, chopt, gridl, drawGridOnly);
4918
4919 // Paint additional X axis (if needed)
4920 // On iOS, this additional X axis is neither pickable, nor highlighted.
4921 // Additional checks PadInSelectionMode etc. does not effect non-iOS platform.
4922 if (gPad->GetTickx() && !gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
4923 if (xAxisPos) {
4924 cw=strstr(chopt,"-");
4925 *cw='z';
4926 } else {
4927 strlcat(chopt, "-",10);
4928 }
4929 if (gPad->GetTickx() < 2) strlcat(chopt, "U",10);
4930 if ((cw=strstr(chopt,"W"))) *cw='z';
4931 axis.SetTitle("");
4932 axis.PaintAxis(axmin, xAxisYPos2,
4933 axmax, xAxisYPos2,
4934 uminsave, umaxsave, ndivsave, chopt, gridl, drawGridOnly);
4935 }
4936 }//End of "if pad in selection mode etc".
4937
4938 // Paint Y axis
4939 //On iOS, Y axis must pushed into the stack of selectable objects.
4940 if (gPad->PadInSelectionMode())
4941 gPad->PushSelectableObject(fYaxis);
4942
4943 //This conditions is ALWAYS true on a platform, different from iOS (on iOS can be true, can be false).
4944 if (gPad->PadInSelectionMode() || !gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && gPad->GetSelected() == fYaxis)) {
4945 ndivy = fYaxis->GetNdivisions();
4947
4948 chopt[0] = 0;
4949 strlcat(chopt, "SDH",10);
4950 if (ndivy < 0) strlcat(chopt, "N",10);
4951 if (gPad->GetGridy()) {
4952 gridl = (axmax-axmin)/(gPad->GetX2() - gPad->GetX1());
4953 strlcat(chopt, "W",10);
4954 }
4955
4956 // Define Y-Axis limits
4957 if (Hoption.Logy) {
4958 strlcat(chopt, "G",10);
4959 ndiv = TMath::Abs(ndivy);
4960 if (useHparam) {
4961 umin = TMath::Power(10,Hparam.ymin);
4962 umax = TMath::Power(10,Hparam.ymax);
4963 } else {
4964 umin = TMath::Power(10,aymin);
4965 umax = TMath::Power(10,aymax);
4966 }
4967 } else {
4968 ndiv = TMath::Abs(ndivy);
4969 if (useHparam) {
4970 umin = Hparam.ymin;
4971 umax = Hparam.ymax;
4972 } else {
4973 umin = aymin;
4974 umax = aymax;
4975 }
4976 }
4977
4978 // Display axis as time
4979 if (fYaxis->GetTimeDisplay()) {
4980 strlcat(chopt,"t",10);
4981 if (strlen(fYaxis->GetTimeFormatOnly()) == 0) {
4983 }
4984 }
4985
4986 // The main Y axis can be on the left or on the right of the pad
4987 Double_t yAxisXPos1, yAxisXPos2;
4988 if (yAxisPos == 1) {
4989 // Main Y axis left
4990 yAxisXPos1 = axmax;
4991 yAxisXPos2 = axmin;
4992 } else {
4993 // Main Y axis right
4994 yAxisXPos1 = axmin;
4995 yAxisXPos2 = axmax;
4996 }
4997
4998 // Paint the main Y axis (always)
4999 uminsave = umin;
5000 umaxsave = umax;
5001 ndivsave = ndiv;
5002 axis.SetOption(chopt);
5003 if (yAxisPos) {
5004 strlcat(chopt, "+L",10);
5005 gridl = -gridl;
5006 }
5007 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
5008 axis.SetLabelSize(0.);
5009 axis.SetTitle("");
5010 }
5011 axis.PaintAxis(yAxisXPos1, aymin,
5012 yAxisXPos1, aymax,
5013 umin, umax, ndiv, chopt, gridl, drawGridOnly);
5014
5015 // Paint the additional Y axis (if needed)
5016 // Additional checks for pad mode are required on iOS: this "second" axis is
5017 // neither pickable, nor highlighted. Additional checks have no effect on non-iOS platform.
5018 if (gPad->GetTicky() && !gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
5019 if (gPad->GetTicky() < 2) {
5020 strlcat(chopt, "U",10);
5022 } else {
5023 strlcat(chopt, "+L",10);
5024 }
5025 if ((cw=strstr(chopt,"W"))) *cw='z';
5026 axis.SetTitle("");
5027 axis.PaintAxis(yAxisXPos2, aymin,
5028 yAxisXPos2, aymax,
5029 uminsave, umaxsave, ndivsave, chopt, gridl, drawGridOnly);
5030 }
5031 }//End of "if pad is in selection mode etc."
5032
5033 // Reset the axis if they have been inverted in case of option HBAR
5034 if (xaxis) {
5035 fXaxis = xaxis;
5036 fYaxis = yaxis;
5037 }
5038}
5039
5040////////////////////////////////////////////////////////////////////////////////
5041/// [Draw a bar-chart in a normal pad.](\ref HP10)
5042
5044{
5045
5046 Int_t bar = Hoption.Bar - 10;
5047 Double_t xmin,xmax,ymin,ymax,umin,umax,w,y;
5050 TBox box;
5051 Int_t hcolor = fH->GetFillColor();
5052 if (hcolor == gPad->GetFrameFillColor()) ++hcolor;
5053 Int_t hstyle = fH->GetFillStyle();
5054 box.SetFillColor(hcolor);
5055 box.SetFillStyle(hstyle);
5056 box.SetLineStyle(fH->GetLineStyle());
5057 box.SetLineColor(fH->GetLineColor());
5058 box.SetLineWidth(fH->GetLineWidth());
5059 for (Int_t bin=fXaxis->GetFirst();bin<=fXaxis->GetLast();bin++) {
5060 y = fH->GetBinContent(bin);
5061 xmin = gPad->XtoPad(fXaxis->GetBinLowEdge(bin));
5062 xmax = gPad->XtoPad(fXaxis->GetBinUpEdge(bin));
5063 ymin = gPad->GetUymin();
5064 ymax = gPad->YtoPad(y);
5065 if (ymax < gPad->GetUymin()) continue;
5066 if (ymax > gPad->GetUymax()) ymax = gPad->GetUymax();
5067 if (ymin < gPad->GetUymin()) ymin = gPad->GetUymin();
5068 if (Hoption.MinimumZero && ymin < 0)
5069 ymin=TMath::Min(0.,gPad->GetUymax());
5070 w = (xmax-xmin)*width;
5071 xmin += offset*(xmax-xmin);
5072 xmax = xmin + w;
5073 if (bar < 1) {
5074 box.PaintBox(xmin,ymin,xmax,ymax);
5075 } else {
5076 umin = xmin + bar*(xmax-xmin)/10.;
5077 umax = xmax - bar*(xmax-xmin)/10.;
5078 //box.SetFillColor(hcolor+150); //bright
5079 box.SetFillColor(TColor::GetColorBright(hcolor)); //bright
5080 box.PaintBox(xmin,ymin,umin,ymax);
5081 box.SetFillColor(hcolor);
5082 box.PaintBox(umin,ymin,umax,ymax);
5083 box.SetFillColor(TColor::GetColorDark(hcolor)); //dark
5084 box.PaintBox(umax,ymin,xmax,ymax);
5085 }
5086 }
5087}
5088
5089////////////////////////////////////////////////////////////////////////////////
5090/// [Draw a bar char in a rotated pad (X vertical, Y horizontal)](\ref HP10)
5091
5093{
5094
5095 gPad->SetVertical(kFALSE);
5096
5097 PaintInitH();
5098
5099 TAxis *xaxis = fXaxis;
5100 TAxis *yaxis = fYaxis;
5101 if (!strcmp(xaxis->GetName(),"xaxis")) {
5102 fXaxis = yaxis;
5103 fYaxis = xaxis;
5104 }
5105
5106 PaintFrame();
5108
5109 Int_t bar = Hoption.Bar - 20;
5110 Double_t xmin,xmax,ymin,ymax,umin,umax,w;
5113 TBox box;
5114 Int_t hcolor = fH->GetFillColor();
5115 if (hcolor == gPad->GetFrameFillColor()) ++hcolor;
5116 Int_t hstyle = fH->GetFillStyle();
5117 box.SetFillColor(hcolor);
5118 box.SetFillStyle(hstyle);
5119 box.SetLineStyle(fH->GetLineStyle());
5120 box.SetLineColor(fH->GetLineColor());
5121 box.SetLineWidth(fH->GetLineWidth());
5122 for (Int_t bin=fYaxis->GetFirst();bin<=fYaxis->GetLast();bin++) {
5123 ymin = gPad->YtoPad(fYaxis->GetBinLowEdge(bin));
5124 ymax = gPad->YtoPad(fYaxis->GetBinUpEdge(bin));
5125 xmin = gPad->GetUxmin();
5126 xmax = gPad->XtoPad(fH->GetBinContent(bin));
5127 if (xmax < gPad->GetUxmin()) continue;
5128 if (xmax > gPad->GetUxmax()) xmax = gPad->GetUxmax();
5129 if (xmin < gPad->GetUxmin()) xmin = gPad->GetUxmin();
5130 if (Hoption.MinimumZero && xmin < 0)
5131 xmin=TMath::Min(0.,gPad->GetUxmax());
5132 w = (ymax-ymin)*width;
5133 ymin += offset*(ymax-ymin);
5134 ymax = ymin + w;
5135 if (bar < 1) {
5136 box.PaintBox(xmin,ymin,xmax,ymax);
5137 } else {
5138 umin = ymin + bar*(ymax-ymin)/10.;
5139 umax = ymax - bar*(ymax-ymin)/10.;
5140 box.SetFillColor(TColor::GetColorDark(hcolor)); //dark
5141 box.PaintBox(xmin,ymin,xmax,umin);
5142 box.SetFillColor(hcolor);
5143 box.PaintBox(xmin,umin,xmax,umax);
5144 box.SetFillColor(TColor::GetColorBright(hcolor)); //bright
5145 box.PaintBox(xmin,umax,xmax,ymax);
5146 }
5147 }
5148
5149 PaintTitle();
5150
5151 // Draw box with histogram statistics and/or fit parameters
5152 if ((Hoption.Same%10) != 1 && !fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
5153 TIter next(fFunctions);
5154 TObject *obj = nullptr;
5155 while ((obj = next())) {
5156 if (obj->InheritsFrom(TF1::Class())) break;
5157 obj = nullptr;
5158 }
5159 PaintStat(gStyle->GetOptStat(),(TF1*)obj);
5160 }
5161
5162 fXaxis = xaxis;
5163 fYaxis = yaxis;
5164}
5165
5166////////////////////////////////////////////////////////////////////////////////
5167/// [Control function to draw a 2D histogram as a box plot](\ref HP13)
5168
5170{
5171
5172 Style_t fillsav = fH->GetFillStyle();
5173 Style_t colsav = fH->GetFillColor();
5174 if (fH->GetFillColor() == 0) fH->SetFillStyle(0);
5175 if (Hoption.Box == 11) fH->SetFillStyle(1001);
5176 fH->TAttLine::Modify();
5177 fH->TAttFill::Modify();
5178
5179 Double_t z, xk,xstep, yk, ystep, xcent, ycent, xlow, xup, ylow, yup;
5180 Double_t ux1 = gPad->PixeltoX(1);
5181 Double_t ux0 = gPad->PixeltoX(0);
5182 Double_t uy1 = gPad->PixeltoY(1);
5183 Double_t uy0 = gPad->PixeltoY(0);
5184 Double_t dxmin = 0.51*(gPad->PadtoX(ux1)-gPad->PadtoX(ux0));
5185 Double_t dymin = 0.51*(gPad->PadtoY(uy0)-gPad->PadtoY(uy1));
5186
5187 Double_t zmin = TMath::Max(fH->GetMinimum(),0.);
5190 Double_t zminlin = zmin, zmaxlin = zmax;
5191
5192 // In case of option SAME, zmin and zmax values are taken from the
5193 // first plotted 2D histogram.
5194 if (Hoption.Same > 0 && Hoption.Same < 10) {
5195 TH2 *h2;
5196 TIter next(gPad->GetListOfPrimitives());
5197 while ((h2 = (TH2 *)next())) {
5198 if (!h2->InheritsFrom(TH2::Class())) continue;
5199 zmin = TMath::Max(h2->GetMinimum(), 0.);
5200 zmax = TMath::Max(TMath::Abs(h2->GetMaximum()),
5201 TMath::Abs(h2->GetMinimum()));
5202 zminlin = zmin;
5203 zmaxlin = zmax;
5204 if (Hoption.Logz) {
5205 if (zmin <= 0) {
5206 zmin = TMath::Log10(zmax*0.001);
5207 } else {
5208 zmin = TMath::Log10(zmin);
5209 }
5210 zmax = TMath::Log10(zmax);
5211 }
5212 break;
5213 }
5214 } else {
5215 if (Hoption.Logz) {
5216 if (zmin > 0) {
5217 zmin = TMath::Log10(zmin);
5218 zmax = TMath::Log10(zmax);
5219 } else {
5220 return;
5221 }
5222 }
5223 }
5224
5225 Double_t zratio, dz = zmax - zmin;
5226 Bool_t kZminNeg = kFALSE;
5227 if (fH->GetMinimum()<0) kZminNeg = kTRUE;
5228 Bool_t kZNeg = kFALSE;
5229
5230 // Define the dark and light colors the "button style" boxes.
5231 Color_t color = fH->GetFillColor();
5232 Color_t light=0, dark=0;
5233 if (Hoption.Box == 11) {
5234 light = TColor::GetColorBright(color);
5235 dark = TColor::GetColorDark(color);
5236 }
5237
5238 // Loop over all the bins and draw the boxes
5239 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
5240 yk = fYaxis->GetBinLowEdge(j);
5241 ystep = fYaxis->GetBinWidth(j);
5242 ycent = 0.5*ystep;
5243 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
5244 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
5245 xk = fXaxis->GetBinLowEdge(i);
5246 xstep = fXaxis->GetBinWidth(i);
5247 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
5248 xcent = 0.5*xstep;
5249 z = Hparam.factor*fH->GetBinContent(bin);
5250 kZNeg = kFALSE;
5251
5252 if (TMath::Abs(z) < zminlin) continue; // Can be the case with ...
5253 if (TMath::Abs(z) > zmaxlin) z = zmaxlin; // ... option Same
5254 if (kZminNeg && z==0) continue; // Do not draw empty bins if case of histo with negative bins.
5255
5256 if (z < 0) {
5257 if (Hoption.Logz) continue;
5258 z = -z;
5259 kZNeg = kTRUE;
5260 }
5261 if (Hoption.Logz) {
5262 if (z != 0) z = TMath::Log10(z);
5263 else z = zmin;
5264 }
5265
5266 if (dz == 0) continue;
5267 zratio = TMath::Sqrt((z-zmin)/dz);
5268 if (zratio == 0) continue;
5269
5270 xup = xcent*zratio + xk + xcent;
5271 xlow = 2*(xk + xcent) - xup;
5272 if (xup-xlow < dxmin) xup = xlow+dxmin;
5273 if (Hoption.Logx) {
5274 if (xup > 0) xup = TMath::Log10(xup);
5275 else continue;
5276 if (xlow > 0) xlow = TMath::Log10(xlow);
5277 else continue;
5278 }
5279
5280 yup = ycent*zratio + yk + ycent;
5281 ylow = 2*(yk + ycent) - yup;
5282 if (yup-ylow < dymin) yup = ylow+dymin;
5283 if (Hoption.Logy) {
5284 if (yup > 0) yup = TMath::Log10(yup);
5285 else continue;
5286 if (ylow > 0) ylow = TMath::Log10(ylow);
5287 else continue;
5288 }
5289
5290 xlow = TMath::Max(xlow, gPad->GetUxmin());
5291 ylow = TMath::Max(ylow, gPad->GetUymin());
5292 xup = TMath::Min(xup , gPad->GetUxmax());
5293 yup = TMath::Min(yup , gPad->GetUymax());
5294
5295 if (xlow >= xup) continue;
5296 if (ylow >= yup) continue;
5297
5298 if (Hoption.Box == 1) {
5299 fH->SetFillColor(color);
5300 fH->TAttFill::Modify();
5301 gPad->PaintBox(xlow, ylow, xup, yup);
5302 if (kZNeg) {
5303 gPad->PaintLine(xlow, ylow, xup, yup);
5304 gPad->PaintLine(xlow, yup, xup, ylow);
5305 }
5306 } else if (Hoption.Box == 11) {
5307 // Draw the center of the box
5308 fH->SetFillColor(color);
5309 fH->TAttFill::Modify();
5310 gPad->PaintBox(xlow, ylow, xup, yup);
5311
5312 // Draw top&left part of the box
5313 Double_t x[7], y[7];
5314 Double_t bwidth = 0.1;
5315 x[0] = xlow; y[0] = ylow;
5316 x[1] = xlow + bwidth*(xup-xlow); y[1] = ylow + bwidth*(yup-ylow);
5317 x[2] = x[1]; y[2] = yup - bwidth*(yup-ylow);
5318 x[3] = xup - bwidth*(xup-xlow); y[3] = y[2];
5319 x[4] = xup; y[4] = yup;
5320 x[5] = xlow; y[5] = yup;
5321 x[6] = xlow; y[6] = ylow;
5322 if (kZNeg) fH->SetFillColor(dark);
5323 else fH->SetFillColor(light);
5324 fH->TAttFill::Modify();
5325 gPad->PaintFillArea(7, x, y);
5326
5327 // Draw bottom&right part of the box
5328 x[0] = xlow; y[0] = ylow;
5329 x[1] = xlow + bwidth*(xup-xlow); y[1] = ylow + bwidth*(yup-ylow);
5330 x[2] = xup - bwidth*(xup-xlow); y[2] = y[1];
5331 x[3] = x[2]; y[3] = yup - bwidth*(yup-ylow);
5332 x[4] = xup; y[4] = yup;
5333 x[5] = xup; y[5] = ylow;
5334 x[6] = xlow; y[6] = ylow;
5335 if (kZNeg) fH->SetFillColor(light);
5336 else fH->SetFillColor(dark);
5337 fH->TAttFill::Modify();
5338 gPad->PaintFillArea(7, x, y);
5339 }
5340 }
5341 }
5342
5344 fH->SetFillStyle(fillsav);
5345 fH->SetFillColor(colsav);
5346 fH->TAttFill::Modify();
5347}
5348
5349
5350
5351////////////////////////////////////////////////////////////////////////////////
5352/// [Control function to draw a 2D histogram as a candle (box) plot or violin plot](\ref HP14)
5353
5355{
5356 TH1D *hproj = nullptr;
5357 TH2D *h2 = (TH2D*)fH;
5358
5359 TCandle myCandle;
5361 myCandle.SetMarkerColor(fH->GetLineColor());
5362 myCandle.SetLineColor(fH->GetLineColor());
5363 myCandle.SetLineWidth(fH->GetLineWidth());
5364 myCandle.SetFillColor(fH->GetFillColor());
5365 myCandle.SetFillStyle(fH->GetFillStyle());
5366 myCandle.SetMarkerSize(fH->GetMarkerSize());
5367 myCandle.SetMarkerStyle(fH->GetMarkerStyle());
5369
5370 Bool_t swapXY = myCandle.IsHorizontal();
5371 const Double_t standardCandleWidth = 0.66;
5372 const Double_t standardHistoWidth = 0.8;
5373
5374 double allMaxContent = 0, allMaxIntegral = 0;
5375 if (myCandle.IsViolinScaled())
5376 allMaxContent = h2->GetBinContent(h2->GetMaximumBin());
5377
5378 if (!swapXY) { // Vertical candle
5379 //Determining the slice with the maximum integral - if necessary
5380 if (myCandle.IsCandleScaled())
5381 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast; i++) {
5382 hproj = h2->ProjectionY("_px", i, i);
5383 if (hproj->Integral() > allMaxIntegral) allMaxIntegral = hproj->Integral();
5384 }
5385 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast; i++) {
5386 Double_t binPosX = fXaxis->GetBinLowEdge(i);
5387 Double_t binWidth = fXaxis->GetBinWidth(i);
5388 hproj = h2->ProjectionY("_px", i, i);
5389 if (hproj->GetEntries() != 0) {
5390 Double_t candleWidth = fH->GetBarWidth();
5391 Double_t offset = fH->GetBarOffset()*binWidth;
5392 double myMaxContent = hproj->GetBinContent(hproj->GetMaximumBin());
5393 double myIntegral = hproj->Integral();
5394 Double_t histoWidth = candleWidth;
5395 if (candleWidth > 0.999 && candleWidth < 1.001) {
5396 candleWidth = standardCandleWidth;
5397 histoWidth = standardHistoWidth;
5398 }
5399 if (Hoption.Logz && myMaxContent > 0) {
5400 histoWidth *= myMaxContent/TMath::Log10(myMaxContent);
5401 if (myCandle.IsViolinScaled() && myMaxContent > 0 && allMaxContent > 0)
5402 histoWidth *= TMath::Log10(myMaxContent)/TMath::Log10(allMaxContent);
5403 } else if (myCandle.IsViolinScaled() && (allMaxContent > 0))
5404 histoWidth *= myMaxContent/allMaxContent;
5405 if (myCandle.IsCandleScaled() && (allMaxIntegral > 0))
5406 candleWidth *= myIntegral/allMaxIntegral;
5407
5408 myCandle.SetAxisPosition(binPosX+binWidth/2. + offset);
5409 myCandle.SetCandleWidth(candleWidth*binWidth);
5410 myCandle.SetHistoWidth(histoWidth*binWidth);
5411 myCandle.SetHistogram(hproj);
5412 myCandle.Paint();
5413 }
5414 }
5415 } else { // Horizontal candle
5416 //Determining the slice with the maximum integral - if necessary
5417 if (myCandle.IsCandleScaled())
5418 for (Int_t i=Hparam.yfirst; i<=Hparam.ylast; i++) {
5419 hproj = h2->ProjectionX("_py", i, i);
5420 if (hproj->Integral() > allMaxIntegral) allMaxIntegral = hproj->Integral();
5421 }
5422 for (Int_t i=Hparam.yfirst; i<=Hparam.ylast; i++) {
5423 Double_t binPosY = fYaxis->GetBinLowEdge(i);
5424 Double_t binWidth = fYaxis->GetBinWidth(i);
5425 hproj = h2->ProjectionX("_py", i, i);
5426 if (hproj->GetEntries() != 0) {
5427 Double_t candleWidth = fH->GetBarWidth();
5428 Double_t offset = fH->GetBarOffset()*binWidth;
5429 double myMaxContent = hproj->GetBinContent(hproj->GetMaximumBin());
5430 double myIntegral = hproj->Integral();
5431 Double_t histoWidth = candleWidth;
5432 if (candleWidth > 0.999 && candleWidth < 1.001) {
5433 candleWidth = standardCandleWidth;
5434 histoWidth = standardHistoWidth;
5435 }
5436 if (Hoption.Logz && myMaxContent > 0) {
5437 histoWidth *= myMaxContent/TMath::Log10(myMaxContent);
5438 if (myCandle.IsViolinScaled() && myMaxContent > 0 && allMaxContent > 0)
5439 histoWidth *= TMath::Log10(myMaxContent)/TMath::Log10(allMaxContent);
5440 } else if (myCandle.IsViolinScaled() && (allMaxContent > 0))
5441 histoWidth *= myMaxContent/allMaxContent;
5442 if (myCandle.IsCandleScaled() && (allMaxIntegral > 0))
5443 candleWidth *= myIntegral/allMaxIntegral;
5444
5445 myCandle.SetAxisPosition(binPosY+binWidth/2. + offset);
5446 myCandle.SetCandleWidth(candleWidth*binWidth);
5447 myCandle.SetHistoWidth(histoWidth*binWidth);
5448 myCandle.SetHistogram(hproj);
5449 myCandle.Paint();
5450 }
5451 }
5452 }
5453 delete hproj;
5454}
5455
5456
5457
5458////////////////////////////////////////////////////////////////////////////////
5459/// Returns the rendering regions for an axis to use in the COL2 option
5460///
5461/// The algorithm analyses the size of the axis compared to the size of
5462/// the rendering region. It figures out the boundaries to use for each color
5463/// of the rendering region. Only one axis is computed here.
5464///
5465/// This allows for a single computation of the boundaries before iterating
5466/// through all of the bins.
5467///
5468/// \param pAxis the axis to consider
5469/// \param nPixels the number of pixels to render axis into
5470/// \param isLog whether the axis is log scale
5471
5472std::vector<THistRenderingRegion>
5474{
5475 std::vector<THistRenderingRegion> regions;
5476
5477 enum STRATEGY { Bins, Pixels } strategy;
5478
5479 Int_t nBins = (pAxis->GetLast() - pAxis->GetFirst() + 1);
5480
5481 if (nBins >= nPixels) {
5482 // more bins than pixels... we should loop over pixels and sample
5483 strategy = Pixels;
5484 } else {
5485 // fewer bins than pixels... we should loop over bins
5486 strategy = Bins;
5487 }
5488
5489 if (isLog) {
5490
5491 Double_t xMin = pAxis->GetBinLowEdge(pAxis->GetFirst());
5492 Int_t binOffset=0;
5493 while (xMin <= 0 && ((pAxis->GetFirst()+binOffset) != pAxis->GetLast()) ) {
5494 binOffset++;
5495 xMin = pAxis->GetBinLowEdge(pAxis->GetFirst()+binOffset);
5496 }
5497 if (xMin <= 0) {
5498 // this should cause an error if we have
5499 return regions;
5500 }
5501 Double_t xMax = pAxis->GetBinUpEdge(pAxis->GetLast());
5502
5503 if (strategy == Bins) {
5504 // logarithmic plot. we find the pixel for the bin
5505 // pixel = eta * log10(V) - alpha
5506 // where eta = nPixels/(log10(Vmax)-log10(Vmin))
5507 // and alpha = nPixels*log10(Vmin)/(log10(Vmax)-log10(Vmin))
5508 // and V is axis value
5509 Double_t eta = (nPixels-1.0)/(TMath::Log10(xMax) - TMath::Log10(xMin));
5510 Double_t offset = -1.0 * eta * TMath::Log10(xMin);
5511
5512 for (Int_t bin=pAxis->GetFirst()+binOffset; bin<=pAxis->GetLast(); bin++) {
5513
5514 // linear plot. we simply need to find the appropriate bin
5515 // for the
5516 Double_t xLowValue = pAxis->GetBinLowEdge(bin);
5517 Double_t xUpValue = pAxis->GetBinUpEdge(bin);
5518 Int_t xPx0 = eta*TMath::Log10(xLowValue)+ offset;
5519 Int_t xPx1 = eta*TMath::Log10(xUpValue) + offset;
5520 THistRenderingRegion region = {std::make_pair(xPx0, xPx1),
5521 std::make_pair(bin, bin+1)};
5522 regions.push_back(region);
5523 }
5524
5525 } else {
5526
5527 // loop over pixels
5528
5529 Double_t beta = (TMath::Log10(xMax) - TMath::Log10(xMin))/(nPixels-1.0);
5530
5531 for (Int_t pixelIndex=0; pixelIndex<(nPixels-1); pixelIndex++) {
5532 // linear plot
5533 Int_t binLow = pAxis->FindBin(xMin*TMath::Power(10.0, beta*pixelIndex));
5534 Int_t binHigh = pAxis->FindBin(xMin*TMath::Power(10.0, beta*(pixelIndex+1)));
5535 THistRenderingRegion region = { std::make_pair(pixelIndex, pixelIndex+1),
5536 std::make_pair(binLow, binHigh)};
5537 regions.push_back(region);
5538 }
5539 }
5540 } else {
5541 // standard linear plot
5542
5543 if (strategy == Bins) {
5544 // loop over bins
5545 for (Int_t bin=pAxis->GetFirst(); bin<=pAxis->GetLast(); bin++) {
5546
5547 // linear plot. we simply need to find the appropriate bin
5548 // for the
5549 Int_t xPx0 = ((bin - pAxis->GetFirst()) * nPixels)/nBins;
5550 Int_t xPx1 = xPx0 + nPixels/nBins;
5551
5552 // make sure we don't compute beyond our bounds
5553 if (xPx1>= nPixels) xPx1 = nPixels-1;
5554
5555 THistRenderingRegion region = {std::make_pair(xPx0, xPx1),
5556 std::make_pair(bin, bin+1)};
5557 regions.push_back(region);
5558 }
5559 } else {
5560 // loop over pixels
5561 for (Int_t pixelIndex=0; pixelIndex<nPixels-1; pixelIndex++) {
5562 // linear plot
5563 Int_t binLow = (nBins*pixelIndex)/nPixels + pAxis->GetFirst();
5564 Int_t binHigh = binLow + nBins/nPixels;
5565 THistRenderingRegion region = { std::make_pair(pixelIndex, pixelIndex+1),
5566 std::make_pair(binLow, binHigh)};
5567 regions.push_back(region);
5568 }
5569 }
5570 }
5571
5572 return regions;
5573}
5574
5575////////////////////////////////////////////////////////////////////////////////
5576/// [Rendering scheme for the COL2 and COLZ2 options] (\ref HP14)
5577
5579{
5580
5581 if (Hoption.System != kCARTESIAN) {
5582 Error("THistPainter::PaintColorLevelsFast(Option_t*)",
5583 "Only cartesian coordinates supported by 'COL2' option. Using 'COL' option instead.");
5584 PaintColorLevels(nullptr);
5585 return;
5586 }
5587
5588 Double_t z;
5589
5590 // Use existing max or min values. If either is already set
5591 // the appropriate value to use.
5592 Double_t zmin = fH->GetMinimumStored();
5593 Double_t zmax = fH->GetMaximumStored();
5594 Double_t originalZMin = zmin;
5595 Double_t originalZMax = zmax;
5596 if ((zmin == -1111) && (zmax == -1111)) {
5597 fH->GetMinimumAndMaximum(zmin, zmax);
5598 fH->SetMinimum(zmin);
5599 fH->SetMaximum(zmax);
5600 } else if (zmin == -1111) {
5601 zmin = fH->GetMinimum();
5602 fH->SetMinimum(zmin);
5603 } else if (zmax == -1111) {
5604 zmax = fH->GetMaximum();
5605 fH->SetMaximum(zmax);
5606 }
5607
5608 Double_t dz = zmax - zmin;
5609 if (dz <= 0) { // Histogram filled with a constant value
5610 zmax += 0.1*TMath::Abs(zmax);
5611 zmin -= 0.1*TMath::Abs(zmin);
5612 dz = zmax - zmin;
5613 }
5614
5615 if (Hoption.Logz) {
5616 if (zmin > 0) {
5617 zmin = TMath::Log10(zmin);
5618 zmax = TMath::Log10(zmax);
5619 dz = zmax - zmin;
5620 } else {
5621 Error("THistPainter::PaintColorLevelsFast(Option_t*)",
5622 "Cannot plot logz because bin content is less than 0.");
5623 return;
5624 }
5625 }
5626
5627 // Initialize the levels on the Z axis
5628 Int_t ndiv = fH->GetContour();
5629 if (ndiv == 0 ) {
5630 ndiv = gStyle->GetNumberContours();
5631 fH->SetContour(ndiv);
5632 }
5633 std::vector<Double_t> colorBounds(ndiv);
5634 std::vector<Double_t> contours(ndiv, 0);
5635 if (!fH->TestBit(TH1::kUserContour)) {
5636 fH->SetContour(ndiv);
5637 } else {
5638 fH->GetContour(contours.data());
5639 }
5640
5641 Double_t step = 1.0/ndiv;
5642 for (Int_t i=0; i<ndiv; ++i) {
5643 colorBounds[i] = step*i;
5644 }
5645
5646 auto pFrame = gPad->GetFrame();
5647 Int_t px0 = gPad->XtoPixel(pFrame->GetX1());
5648 Int_t px1 = gPad->XtoPixel(pFrame->GetX2());
5649 Int_t py0 = gPad->YtoPixel(pFrame->GetY1());
5650 Int_t py1 = gPad->YtoPixel(pFrame->GetY2());
5651 Int_t nXPixels = px1-px0;
5652 Int_t nYPixels = py0-py1; // y=0 is at the top of the screen
5653
5654 std::vector<Double_t> buffer(nXPixels*nYPixels, 0);
5655
5656 auto xRegions = ComputeRenderingRegions(fXaxis, nXPixels, Hoption.Logx);
5657 auto yRegions = ComputeRenderingRegions(fYaxis, nYPixels, Hoption.Logy);
5658 if (xRegions.empty() || yRegions.empty()) {
5659 Error("THistPainter::PaintColorLevelFast(Option_t*)",
5660 "Encountered error while computing rendering regions.");
5661 return;
5662 }
5663
5664 Bool_t minExists = kFALSE;
5665 Bool_t maxExists = kFALSE;
5666 Double_t minValue = 1.;
5667 Double_t maxValue = 0.;
5668 for (auto& yRegion : yRegions) {
5669 for (auto& xRegion : xRegions ) {
5670
5671 const auto& xBinRange = xRegion.fBinRange;
5672 const auto& yBinRange = yRegion.fBinRange;
5673
5674 // sample the range
5675 z = fH->GetBinContent(xBinRange.second-1, yBinRange.second-1);
5676
5677 if (Hoption.Logz) {
5678 if (z > 0) z = TMath::Log10(z);
5679 else z = zmin;
5680 }
5681
5682 // obey the user's max and min values if they were set
5683 if (z > zmax) z = zmax;
5684 if (z < zmin) z = zmin;
5685
5687 // contours are absolute values
5688 auto index = TMath::BinarySearch(contours.size(), contours.data(), z);
5689 z = colorBounds[index];
5690 } else {
5691 Int_t index = 0;
5692 if (dz != 0) {
5693 index = 0.001 + ((z - zmin)/dz)*ndiv;
5694 }
5695
5696 if (index == static_cast<Int_t>(colorBounds.size())) {
5697 index--;
5698 }
5699
5700 // Do a little bookkeeping to use later for getting libAfterImage to produce
5701 // the correct colors
5702 if (index == 0) {
5703 minExists = kTRUE;
5704 } else if (index == static_cast<Int_t>(colorBounds.size()-1)) {
5705 maxExists = kTRUE;
5706 }
5707
5708 z = colorBounds[index];
5709
5710 if (z < minValue) {
5711 minValue = z;
5712 }
5713 if (z > maxValue) {
5714 maxValue = z;
5715 }
5716 }
5717
5718 // fill in the actual pixels
5719 const auto& xPixelRange = xRegion.fPixelRange;
5720 const auto& yPixelRange = yRegion.fPixelRange;
5721 for (Int_t xPx = xPixelRange.first; xPx <= xPixelRange.second; ++xPx) {
5722 for (Int_t yPx = yPixelRange.first; yPx <= yPixelRange.second; ++yPx) {
5723 Int_t pixel = yPx*nXPixels + xPx;
5724 buffer[pixel] = z;
5725 }
5726 }
5727 } // end px loop
5728 } // end py loop
5729
5730 // This is a bit of a hack to ensure that we span the entire color range and
5731 // don't screw up the colors for a sparse histogram. No one will notice that I set a
5732 // single pixel on the edge of the image to a different color. This is even more
5733 // true because the chosen pixels will be covered by the axis.
5734 if (minValue != maxValue) {
5735 if ( !minExists) {
5736 buffer.front() = 0;
5737 }
5738
5739 if ( !maxExists) {
5740 buffer[buffer.size()-nXPixels] = 0.95;
5741 }
5742 }
5743
5744 // Generate the TImage
5746 TImage* pImage = TImage::Create();
5748 pImage->SetImage(buffer.data(), nXPixels, nYPixels, pPalette);
5749 delete pPalette;
5750
5751 Window_t wid = static_cast<Window_t>(gVirtualX->GetWindowID(gPad->GetPixmapID()));
5752 pImage->PaintImage(wid, px0, py1, 0, 0, nXPixels, nYPixels);
5753 delete pImage;
5754
5756
5757 // Reset the maximum and minimum values to their original values
5758 // when this function was called. If we don't do this, an initial
5759 // value of -1111 will be replaced with the true max or min values.
5760 fH->SetMinimum(originalZMin);
5761 fH->SetMaximum(originalZMax);
5762}
5763
5764////////////////////////////////////////////////////////////////////////////////
5765/// [Control function to draw a 2D histogram as a color plot.](\ref HP14)
5766
5768{
5769 Double_t z, zc, xk, xstep, yk, ystep, xlow, xup, ylow, yup;
5770
5771 Double_t zmin = fH->GetMinimum();
5772 Double_t zmax = fH->GetMaximum();
5773
5774 Double_t dz = zmax - zmin;
5775 if (dz <= 0) { // Histogram filled with a constant value
5776 zmax += 0.1*TMath::Abs(zmax);
5777 zmin -= 0.1*TMath::Abs(zmin);
5778 dz = zmax - zmin;
5779 }
5780
5781 // In case of option SAME, zmin and zmax values are taken from the
5782 // first plotted 2D histogram.
5783 if (Hoption.Same > 0 && Hoption.Same < 10) {
5784 TH2 *h2;
5785 TIter next(gPad->GetListOfPrimitives());
5786 while ((h2 = (TH2 *)next())) {
5787 if (!h2->InheritsFrom(TH2::Class())) continue;
5788 zmin = h2->GetMinimum();
5789 zmax = h2->GetMaximum();
5790 fH->SetMinimum(zmin);
5791 fH->SetMaximum(zmax);
5792 if (Hoption.Logz) {
5793 if (zmin <= 0) {
5794 zmin = TMath::Log10(zmax*0.001);
5795 } else {
5796 zmin = TMath::Log10(zmin);
5797 }
5798 zmax = TMath::Log10(zmax);
5799 }
5800 dz = zmax - zmin;
5801 break;
5802 }
5803 } else {
5804 if (Hoption.Logz) {
5805 if (zmin > 0) {
5806 zmin = TMath::Log10(zmin);
5807 zmax = TMath::Log10(zmax);
5808 dz = zmax - zmin;
5809 } else {
5810 return;
5811 }
5812 }
5813 }
5814
5815 Style_t fillsav = fH->GetFillStyle();
5816 Style_t colsav = fH->GetFillColor();
5817 fH->SetFillStyle(1001);
5818 fH->TAttFill::Modify();
5819
5820 // Initialize the levels on the Z axis
5821 Int_t ncolors = gStyle->GetNumberOfColors();
5822 Int_t ndiv = fH->GetContour();
5823 if (ndiv == 0 ) {
5824 ndiv = gStyle->GetNumberContours();
5825 fH->SetContour(ndiv);
5826 }
5827 Int_t ndivz = TMath::Abs(ndiv);
5828 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
5829 Double_t scale = (dz ? ndivz / dz : 1.0);
5830
5831 Int_t color;
5832 TProfile2D* prof2d = dynamic_cast<TProfile2D*>(fH);
5833 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
5834 yk = fYaxis->GetBinLowEdge(j);
5835 ystep = fYaxis->GetBinWidth(j);
5836 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
5837 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
5838 xk = fXaxis->GetBinLowEdge(i);
5839 xstep = fXaxis->GetBinWidth(i);
5840 if (Hoption.System == kPOLAR && xk<0) xk= 2*TMath::Pi()+xk;
5841 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
5842 z = fH->GetBinContent(bin);
5843 // if fH is a profile histogram do not draw empty bins
5844 if (prof2d) {
5845 const Double_t binEntries = prof2d->GetBinEntries(bin);
5846 if (binEntries == 0)
5847 continue;
5848 } else {
5849 // don't draw the empty bins for non-profile histograms
5850 // with positive content
5851 if (z == 0) {
5852 if (zmin >= 0 || Hoption.Logz) continue;
5853 if (Hoption.Color == 2) continue;
5854 }
5855 }
5856
5857 if (Hoption.Logz) {
5858 if (z > 0) z = TMath::Log10(z);
5859 else z = zmin;
5860 }
5861 if (z < zmin && !Hoption.Zero) continue;
5862 xup = xk + xstep;
5863 xlow = xk;
5864 if (Hoption.Logx) {
5865 if (xup > 0) xup = TMath::Log10(xup);
5866 else continue;
5867 if (xlow > 0) xlow = TMath::Log10(xlow);
5868 else continue;
5869 }
5870 yup = yk + ystep;
5871 ylow = yk;
5872 if (Hoption.System != kPOLAR) {
5873 if (Hoption.Logy) {
5874 if (yup > 0) yup = TMath::Log10(yup);
5875 else continue;
5876 if (ylow > 0) ylow = TMath::Log10(ylow);
5877 else continue;
5878 }
5879 if (xup < gPad->GetUxmin()) continue;
5880 if (yup < gPad->GetUymin()) continue;
5881 if (xlow > gPad->GetUxmax()) continue;
5882 if (ylow > gPad->GetUymax()) continue;
5883 if (xlow < gPad->GetUxmin()) xlow = gPad->GetUxmin();
5884 if (ylow < gPad->GetUymin()) ylow = gPad->GetUymin();
5885 if (xup > gPad->GetUxmax()) xup = gPad->GetUxmax();
5886 if (yup > gPad->GetUymax()) yup = gPad->GetUymax();
5887 }
5888
5890 zc = fH->GetContourLevelPad(0);
5891 if (z < zc) continue;
5892 color = -1;
5893 for (Int_t k=0; k<ndiv; k++) {
5894 zc = fH->GetContourLevelPad(k);
5895 if (z < zc) {
5896 continue;
5897 } else {
5898 color++;
5899 }
5900 }
5901 } else {
5902 color = Int_t(0.01+(z-zmin)*scale);
5903 }
5904
5905 Int_t theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
5906 if (theColor > ncolors-1) theColor = ncolors-1;
5908 fH->TAttFill::Modify();
5909 if (Hoption.System != kPOLAR) {
5910 gPad->PaintBox(xlow, ylow, xup, yup);
5911 } else {
5912 TCrown crown(0,0,ylow,yup,xlow*TMath::RadToDeg(),xup*TMath::RadToDeg());
5913 crown.SetFillColor(gStyle->GetColorPalette(theColor));
5914 crown.SetLineColor(fH->GetLineColor());
5915 crown.SetLineWidth(fH->GetLineWidth());
5916 crown.SetLineStyle(fH->GetLineStyle());
5917 crown.Paint();
5918 }
5919 }
5920 }
5921
5923
5924 fH->SetFillStyle(fillsav);
5925 fH->SetFillColor(colsav);
5926 fH->TAttFill::Modify();
5927
5928}
5929
5930////////////////////////////////////////////////////////////////////////////////
5931/// [Control function to draw a 2D histogram as a contour plot.](\ref HP16)
5932
5934{
5935
5936 Int_t i, j, count, ncontour, icol, n, lj, m, ix, jx, ljfill;
5937 Int_t itars, mode, ir[4];
5938 Double_t xsave, ysave, thesave,phisave,x[4], y[4], zc[4];
5939
5940 if (Hoption.Contour == 14) {
5941 Hoption.Surf = 12;
5942 Hoption.Axis = 1;
5943 thesave = gPad->GetTheta();
5944 phisave = gPad->GetPhi();
5945 gPad->SetPhi(0.);
5946 gPad->SetTheta(90.);
5948 gPad->SetPhi(phisave);
5949 gPad->SetTheta(thesave);
5950 TView *view = gPad->GetView();
5951 if (view) view->SetBit(kCannotRotate); //tested in ExecuteEvent
5952 PaintAxis();
5953 return;
5954 }
5955
5956 if (Hoption.Same) {
5957 // If the contour is painted on a 3d plot, the contour lines are
5958 // paint in 3d too.
5959 TObject *obj;
5960 TIter next(gPad->GetListOfPrimitives());
5961 while ((obj=next())) {
5962 if (strstr(obj->GetDrawOption(),"surf") ||
5963 strstr(obj->GetDrawOption(),"lego") ||
5964 strstr(obj->GetDrawOption(),"tri")) {
5965 Hoption.Surf = 16;
5967 return;
5968 }
5969 }
5970 }
5971
5972 if (Hoption.Contour == 15) {
5973 TGraphDelaunay2D *dt = nullptr;
5974 TGraphDelaunay *dtOld = nullptr;
5975 TList *hl = fH->GetListOfFunctions();
5976 dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
5977 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
5978 if (!dt && !dtOld) return;
5979 if (!fGraph2DPainter)
5980 fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
5981 fGraph2DPainter->Paint(option);
5982 return;
5983 }
5984
5985 gPad->SetBit(TGraph::kClipFrame);
5986
5987 std::vector<Double_t> levels(2*kMAXCONTOUR);
5988 std::vector<Double_t> xarr(2*kMAXCONTOUR);
5989 std::vector<Double_t> yarr(2*kMAXCONTOUR);
5990 std::vector<Int_t> itarr(2*kMAXCONTOUR);
5991
5992 Int_t npmax = 0;
5993 for (i=0;i<2*kMAXCONTOUR;i++) itarr[i] = 0;
5994
5995 ncontour = fH->GetContour();
5996 if (ncontour == 0) {
5997 ncontour = gStyle->GetNumberContours();
5998 fH->SetContour(ncontour);
5999 }
6000 if (ncontour > kMAXCONTOUR) {
6001 Warning("PaintContour", "maximum number of contours is %d, asked for %d",
6002 kMAXCONTOUR, ncontour);
6003 ncontour = kMAXCONTOUR-1;
6004 }
6005 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ncontour);
6006
6007 for (i=0;i<ncontour;i++) levels[i] = fH->GetContourLevelPad(i);
6008 Int_t linesav = fH->GetLineStyle();
6009 Int_t colorsav = fH->GetLineColor();
6010 Int_t fillsav = fH->GetFillColor();
6011 if (Hoption.Contour == 13) {
6012 fH->TAttLine::Modify();
6013 }
6014
6015 std::vector<std::unique_ptr<TPolyLine>> polys;
6016 TObjArray *contours = nullptr;
6017 TList *list = nullptr;
6018 TGraph *graph = nullptr;
6019 std::vector<Int_t> np;
6020 if (Hoption.Contour == 1) {
6021 np.resize(ncontour);
6022 for (i=0;i<ncontour;i++)
6023 np[i] = 0;
6024 for (i=0;i<ncontour;i++)
6025 polys.emplace_back(std::make_unique<TPolyLine>(100));
6026 if (Hoption.List == 1) {
6027 contours = (TObjArray*)gROOT->GetListOfSpecials()->FindObject("contours");
6028 if (contours) {
6029 gROOT->GetListOfSpecials()->Remove(contours);
6030 count = contours->GetSize();
6031 for (i=0;i<count;i++) {
6032 list = (TList*)contours->At(i);
6033 if (list) list->Delete();
6034 }
6035 contours->Delete();
6036 delete contours;
6037 }
6038 contours = new TObjArray(ncontour);
6039 contours->SetName("contours");
6040 gROOT->GetListOfSpecials()->Add(contours);
6041 for (i=0;i<ncontour;i++) {
6042 list = new TList();
6043 contours->Add(list);
6044 }
6045 }
6046 }
6047 Int_t theColor;
6048 Int_t ncolors = gStyle->GetNumberOfColors();
6049 Int_t ndivz = TMath::Abs(ncontour);
6050
6051 Int_t k,ipoly;
6052 for (j=Hparam.yfirst; j<Hparam.ylast; j++) {
6053 y[0] = fYaxis->GetBinCenter(j);
6054 y[1] = y[0];
6055 y[2] = fYaxis->GetBinCenter(j+1);
6056 y[3] = y[2];
6057 for (i=Hparam.xfirst; i<Hparam.xlast; i++) {
6058 zc[0] = fH->GetBinContent(i, j);
6059 zc[1] = fH->GetBinContent(i+1, j);
6060 zc[2] = fH->GetBinContent(i+1, j+1);
6061 zc[3] = fH->GetBinContent(i, j+1);
6062 if (!IsInside(fXaxis->GetBinCenter(i),fYaxis->GetBinCenter(j))) continue;
6063 if (Hoption.Logz) {
6064 if (zc[0] > 0) zc[0] = TMath::Log10(zc[0]);
6065 else zc[0] = Hparam.zmin;
6066 if (zc[1] > 0) zc[1] = TMath::Log10(zc[1]);
6067 else zc[1] = Hparam.zmin;
6068 if (zc[2] > 0) zc[2] = TMath::Log10(zc[2]);
6069 else zc[2] = Hparam.zmin;
6070 if (zc[3] > 0) zc[3] = TMath::Log10(zc[3]);
6071 else zc[3] = Hparam.zmin;
6072 }
6073 for (k=0;k<4;k++) {
6074 ir[k] = TMath::BinarySearch(ncontour, levels.data(), zc[k]);
6075 }
6076 if (ir[0] != ir[1] || ir[1] != ir[2] || ir[2] != ir[3] || ir[3] != ir[0]) {
6077 x[0] = fXaxis->GetBinCenter(i);
6078 x[3] = x[0];
6079 x[1] = fXaxis->GetBinCenter(i+1);
6080 x[2] = x[1];
6081 if (zc[0] <= zc[1]) n = 0; else n = 1;
6082 if (zc[2] <= zc[3]) m = 2; else m = 3;
6083 if (zc[n] > zc[m]) n = m;
6084 n++;
6085 lj=1;
6086 for (ix=1;ix<=4;ix++) {
6087 m = n%4 + 1;
6088 ljfill = PaintContourLine(zc[n-1],ir[n-1],x[n-1],y[n-1],zc[m-1],
6089 ir[m-1],x[m-1],y[m-1], xarr.data()+lj-1,yarr.data()+lj-1,itarr.data()+lj-1, levels.data());
6090 lj += 2*ljfill;
6091 n = m;
6092 }
6093
6094 if (zc[0] <= zc[1]) n = 0; else n = 1;
6095 if (zc[2] <= zc[3]) m = 2; else m = 3;
6096 if (zc[n] > zc[m]) n = m;
6097 n++;
6098 lj=2;
6099 for (ix=1;ix<=4;ix++) {
6100 if (n == 1) m = 4;
6101 else m = n-1;
6102 ljfill = PaintContourLine(zc[n-1],ir[n-1],x[n-1],y[n-1],zc[m-1],
6103 ir[m-1],x[m-1],y[m-1],xarr.data()+lj-1,yarr.data()+lj-1,itarr.data()+lj-1, levels.data());
6104 lj += 2*ljfill;
6105 n = m;
6106 }
6107
6108 // Re-order endpoints
6109
6110 count = 0;
6111 for (ix=1; ix<=lj-5; ix +=2) {
6112 //count = 0;
6113 while (itarr[ix-1] != itarr[ix]) {
6114 xsave = xarr[ix];
6115 ysave = yarr[ix];
6116 itars = itarr[ix];
6117 for (jx=ix; jx<=lj-5; jx +=2) {
6118 xarr[jx] = xarr[jx+2];
6119 yarr[jx] = yarr[jx+2];
6120 itarr[jx] = itarr[jx+2];
6121 }
6122 xarr[lj-3] = xsave;
6123 yarr[lj-3] = ysave;
6124 itarr[lj-3] = itars;
6125 if (count > 100) break;
6126 count++;
6127 }
6128 }
6129
6130 if (count > 100) continue;
6131 for (ix=1; ix<=lj-2; ix +=2) {
6132 theColor = Int_t((itarr[ix-1]+0.99)*Float_t(ncolors)/Float_t(ndivz));
6133 icol = gStyle->GetColorPalette(theColor);
6134 if (Hoption.Contour == 11) {
6135 fH->SetLineColor(icol);
6136 }
6137 if (Hoption.Contour == 12) {
6138 mode = icol%5;
6139 if (mode == 0) mode = 5;
6141 }
6142 if (Hoption.Contour != 1) {
6143 fH->TAttLine::Modify();
6144 gPad->PaintPolyLine(2,xarr.data()+ix-1,yarr.data()+ix-1);
6145 continue;
6146 }
6147
6148 ipoly = itarr[ix-1];
6149 if (ipoly >=0 && ipoly <ncontour) {
6150 polys[ipoly]->SetPoint(np[ipoly] ,xarr[ix-1],yarr[ix-1]);
6151 polys[ipoly]->SetPoint(np[ipoly]+1,xarr[ix], yarr[ix]);
6152 np[ipoly] += 2;
6153 if (npmax < np[ipoly]) npmax = np[ipoly];
6154 }
6155 }
6156 } // end of if (ir[0]
6157 } //end of for (i
6158 } //end of for (j
6159
6161 std::vector<Double_t> xp, yp;
6162 Int_t nadd,iminus,iplus;
6163 Int_t istart;
6164 Int_t first = ncontour;
6165 std::vector<Int_t> polysort;
6166 Int_t contListNb;
6167 if (Hoption.Contour != 1) goto theEND;
6168
6169 //The 2 points line generated above are now sorted/merged to generate
6170 //a list of consecutive points.
6171 // If the option "List" has been specified, the list of points is saved
6172 // in the form of TGraph objects in the ROOT list of special objects.
6173 xmin = gPad->GetUxmin();
6174 ymin = gPad->GetUymin();
6175 xp.resize(2*npmax);
6176 yp.resize(2*npmax);
6177 polysort.resize(ncontour);
6178 //find first positive contour
6179 for (ipoly=0;ipoly<ncontour;ipoly++) {
6180 if (levels[ipoly] >= 0) {first = ipoly; break;}
6181 }
6182 //store negative contours from 0 to minimum, then all positive contours
6183 k = 0;
6184 for (ipoly=first-1;ipoly>=0;ipoly--) {polysort[k] = ipoly; k++;}
6185 for (ipoly=first;ipoly<ncontour;ipoly++) {polysort[k] = ipoly; k++;}
6186 // we can now draw sorted contours
6187 contListNb = 0;
6188 fH->SetFillStyle(1001);
6189 for (k=0;k<ncontour;k++) {
6190 ipoly = polysort[k];
6191 if (np[ipoly] == 0) continue;
6192 if (Hoption.List) list = (TList*)contours->At(contListNb);
6193 contListNb++;
6194 Double_t *xx = polys[ipoly]->GetX();
6195 Double_t *yy = polys[ipoly]->GetY();
6196 istart = 0;
6197 while (true) {
6198 iminus = npmax;
6199 iplus = iminus+1;
6200 xp[iminus]= xx[istart]; yp[iminus] = yy[istart];
6201 xp[iplus] = xx[istart+1]; yp[iplus] = yy[istart+1];
6202 xx[istart] = xmin; yy[istart] = ymin;
6203 xx[istart+1] = xmin; yy[istart+1] = ymin;
6204 while (true) {
6205 nadd = 0;
6206 for (i=2;i<np[ipoly];i+=2) {
6207 if ((iplus < 2*npmax-1) && (xx[i] == xp[iplus]) && (yy[i] == yp[iplus])) {
6208 iplus++;
6209 xp[iplus] = xx[i+1]; yp[iplus] = yy[i+1];
6210 xx[i] = xmin; yy[i] = ymin;
6211 xx[i+1] = xmin; yy[i+1] = ymin;
6212 nadd++;
6213 }
6214 if ((iminus > 0) && (xx[i+1] == xp[iminus]) && (yy[i+1] == yp[iminus])) {
6215 iminus--;
6216 xp[iminus] = xx[i]; yp[iminus] = yy[i];
6217 xx[i] = xmin; yy[i] = ymin;
6218 xx[i+1] = xmin; yy[i+1] = ymin;
6219 nadd++;
6220 }
6221 }
6222 if (nadd == 0) break;
6223 }
6224 theColor = Int_t((ipoly+0.99)*Float_t(ncolors)/Float_t(ndivz));
6225 icol = gStyle->GetColorPalette(theColor);
6226 if (ndivz > 1) fH->SetFillColor(icol);
6227 fH->TAttFill::Modify();
6228 gPad->PaintFillArea(iplus-iminus+1,xp.data()+iminus,yp.data()+iminus);
6229 if (Hoption.List) {
6230 graph = new TGraph(iplus-iminus+1,xp.data()+iminus,yp.data()+iminus);
6231 graph->SetFillColor(icol);
6232 graph->SetLineWidth(fH->GetLineWidth());
6233 list->Add(graph);
6234 }
6235 //check if more points are left
6236 istart = 0;
6237 for (i=2;i<np[ipoly];i+=2) {
6238 if (xx[i] != xmin && yy[i] != ymin) {
6239 istart = i;
6240 break;
6241 }
6242 }
6243 if (istart == 0) break;
6244 }
6245 }
6246
6247theEND:
6248 gPad->ResetBit(TGraph::kClipFrame);
6250 fH->SetLineStyle(linesav);
6251 fH->SetLineColor(colorsav);
6252 fH->SetFillColor(fillsav);
6253}
6254
6255////////////////////////////////////////////////////////////////////////////////
6256/// Fill the matrix `xarr` and `yarr` for Contour Plot.
6257
6259 Double_t elev2, Int_t icont2, Double_t x2, Double_t y2,
6260 Double_t *xarr, Double_t *yarr, Int_t *itarr, Double_t *levels)
6261{
6262
6263 Bool_t vert;
6264 Double_t tlen, tdif, elev, diff, pdif, xlen;
6265 Int_t n, i, icount;
6266
6267 if (x1 == x2) {
6268 vert = kTRUE;
6269 tlen = y2 - y1;
6270 } else {
6271 vert = kFALSE;
6272 tlen = x2 - x1;
6273 }
6274
6275 n = icont1 +1;
6276 tdif = elev2 - elev1;
6277 i = 0;
6278 icount = 0;
6279 while (n <= icont2 && i <= kMAXCONTOUR/2 -3) {
6280 //elev = fH->GetContourLevel(n);
6281 elev = levels[n];
6282 diff = elev - elev1;
6283 pdif = diff/tdif;
6284 xlen = tlen*pdif;
6285 if (vert) {
6286 if (Hoption.Logx)
6287 xarr[i] = TMath::Log10(x1);
6288 else
6289 xarr[i] = x1;
6290 if (Hoption.Logy)
6291 yarr[i] = TMath::Log10(y1 + xlen);
6292 else
6293 yarr[i] = y1 + xlen;
6294 } else {
6295 if (Hoption.Logx)
6296 xarr[i] = TMath::Log10(x1 + xlen);
6297 else
6298 xarr[i] = x1 + xlen;
6299 if (Hoption.Logy)
6300 yarr[i] = TMath::Log10(y1);
6301 else
6302 yarr[i] = y1;
6303 }
6304 itarr[i] = n;
6305 icount++;
6306 i +=2;
6307 n++;
6308 }
6309 return icount;
6310}
6311
6312////////////////////////////////////////////////////////////////////////////////
6313/// [Draw 1D histograms error bars.](\ref HP09)
6314
6316{
6317
6318 // On iOS, we do not highlight histogram, if it's not picked at the moment
6319 // (but part of histogram (axis or pavestat) was picked, that's why this code
6320 // is called at all. This conditional statement never executes on non-iOS platform.
6321 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH) return;
6322
6323 const Int_t kBASEMARKER=8;
6324 Double_t xp, yp, ex1, ex2, ey1, ey2;
6325 Double_t delta;
6326 Double_t s2x, s2y, bxsize, bysize, symbolsize, xerror, sbasex, sbasey;
6327 Double_t xi1, xi2, xi3, xi4, yi1, yi2, yi3, yi4;
6329 Double_t logxmin = 0;
6330 Double_t logymin = 0;
6331 Double_t offset = 0.;
6332 Double_t width = 0.;
6333 Int_t i, k, npoints, first, last, fixbin;
6334 Int_t if1 = 0;
6335 Int_t if2 = 0;
6336 Int_t drawmarker, errormarker;
6337 Int_t option0, option1, option2, option3, option4, optionE, optionEX0, optionI0;
6338 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};
6339 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};
6340
6341 std::vector<Double_t> xline, yline;
6342 option0 = option1 = option2 = option3 = option4 = optionE = optionEX0 = optionI0 = 0;
6343 if (Hoption.Error >= 40) {Hoption.Error -=40; option0 = 1;}
6344 if (Int_t(Hoption.Error/10) == 2) {optionEX0 = 1; Hoption.Error -= 10;}
6345 if (Hoption.Error == 31) {optionEX0 = 1; Hoption.Error = 1;}
6346 if (Hoption.Error == 11) option1 = 1;
6347 if (Hoption.Error == 12) option2 = 1;
6348 if (Hoption.Error == 13) option3 = 1;
6349 if (Hoption.Error == 14) {option4 = 1; option3 = 1;}
6350 if (Hoption.Error == 15) {optionI0 = 1; option3 = 1;}
6351 if (Hoption.Error == 16) {optionI0 = 1; option4 = 1; option3 = 1;}
6352 if (option2+option3 == 0) optionE = 1;
6353 if (Hoption.Error == 0) optionE = 0;
6354 if (fXaxis->GetXbins()->fN) fixbin = 0;
6355 else fixbin = 1;
6356
6357 offset = fH->GetBarOffset();
6358 width = fH->GetBarWidth();
6359
6361 if (optionEX0) {
6362 xerror = 0;
6363 } else {
6364 xerror = gStyle->GetErrorX();
6365 }
6366 symbolsize = fH->GetMarkerSize();
6367 if (errormarker == 1) symbolsize = 0.01;
6368 sbasex = sbasey = symbolsize*kBASEMARKER;
6369 if (errormarker >= 20 && errormarker <= 49) {
6370 sbasex *= cxx[errormarker-20];
6371 sbasey *= cyy[errormarker-20];
6372 }
6373 // set the graphics attributes
6374
6375 fH->TAttLine::Modify();
6376 fH->TAttFill::Modify();
6377 fH->TAttMarker::Modify();
6378
6379 // set the first and last bin
6380
6381 Double_t factor = Hparam.factor;
6382 first = Hparam.xfirst;
6383 last = Hparam.xlast;
6384 npoints = last - first +1;
6385 xmin = gPad->GetUxmin();
6386 xmax = gPad->GetUxmax();
6387 ymin = gPad->GetUymin();
6388 ymax = gPad->GetUymax();
6389
6390
6391 if (option3) {
6392 xline.resize(2*npoints);
6393 yline.resize(2*npoints);
6394 if ((npoints > 0) && (xline.empty() || yline.empty())) {
6395 Error("PaintErrors", "too many points, out of memory");
6396 return;
6397 }
6398 if1 = 1;
6399 if2 = 2*npoints;
6400 }
6401
6402 // compute the offset of the error bars due to the symbol size
6403 s2x = gPad->PixeltoX(Int_t(0.5*sbasex)) - gPad->PixeltoX(0);
6404 s2y =-gPad->PixeltoY(Int_t(0.5*sbasey)) + gPad->PixeltoY(0);
6405
6406 // compute size of the lines at the end of the error bars
6407 Int_t dxend = Int_t(gStyle->GetEndErrorSize());
6408 bxsize = gPad->PixeltoX(dxend) - gPad->PixeltoX(0);
6409 bysize =-gPad->PixeltoY(dxend) + gPad->PixeltoY(0);
6410
6411
6412 if (fixbin) {
6413 if (Hoption.Logx) xp = TMath::Power(10,Hparam.xmin) + 0.5*Hparam.xbinsize;
6414 else xp = Hparam.xmin + 0.5*Hparam.xbinsize;
6415 } else {
6416 delta = fH->GetBinWidth(first);
6417 xp = fH->GetBinLowEdge(first) + 0.5*delta;
6418 }
6419
6420 // if errormarker = 0 or symbolsize = 0. no symbol is drawn
6421 if (Hoption.Logx) logxmin = TMath::Power(10,Hparam.xmin);
6422 if (Hoption.Logy) logymin = TMath::Power(10,Hparam.ymin);
6423
6424 // ---------------------- Loop over the points---------------------
6425 for (k=first; k<=last; k++) {
6426
6427 // get the data
6428 // xp = X position of the current point
6429 // yp = Y position of the current point
6430 // ex1 = Low X error
6431 // ex2 = Up X error
6432 // ey1 = Low Y error
6433 // ey2 = Up Y error
6434 // (xi,yi) = Error bars coordinates
6435
6436 // apply offset on errors for bar histograms
6437 Double_t xminTmp = gPad->XtoPad(fXaxis->GetBinLowEdge(k));
6438 Double_t xmaxTmp = gPad->XtoPad(fXaxis->GetBinUpEdge(k));
6439 if (Hoption.Logx) {
6440 xminTmp = TMath::Power(10, xminTmp);
6441 xmaxTmp = TMath::Power(10, xmaxTmp);
6442 }
6443 Double_t w = (xmaxTmp-xminTmp)*width;
6444 xminTmp += offset*(xmaxTmp-xminTmp);
6445 xmaxTmp = xminTmp + w;
6446 xp = (xminTmp+xmaxTmp)/2.;
6447
6448 if (Hoption.Logx) {
6449 if (xp <= 0) goto L30;
6450 if (xp < logxmin) goto L30;
6451 if (xp > TMath::Power(10,xmax)) break;
6452 } else {
6453 if (xp < xmin) goto L30;
6454 if (xp > xmax) break;
6455 }
6456 yp = factor*fH->GetBinContent(k);
6457 if (optionI0 && yp==0) goto L30;
6458 if (fixbin) {
6459 ex1 = xerror*Hparam.xbinsize;
6460 } else {
6461 delta = fH->GetBinWidth(k);
6462 ex1 = xerror*delta;
6463 }
6464 if (fH->GetBinErrorOption() == TH1::kNormal) {
6465 ey1 = factor*fH->GetBinError(k);
6466 ey2 = ey1;
6467 } else {
6468 ey1 = factor*fH->GetBinErrorLow(k);
6469 ey2 = factor*fH->GetBinErrorUp(k);
6470 }
6471 ex2 = ex1;
6472
6473 xi4 = xp;
6474 xi3 = xp;
6475 xi2 = xp + ex2;
6476 xi1 = xp - ex1;
6477
6478 yi1 = yp;
6479 yi2 = yp;
6480 yi3 = yp - ey1;
6481 yi4 = yp + ey2;
6482
6483 // take the LOG if necessary
6484 if (Hoption.Logx) {
6485 xi1 = TMath::Log10(TMath::Max(xi1,logxmin));
6486 xi2 = TMath::Log10(TMath::Max(xi2,logxmin));
6487 xi3 = TMath::Log10(TMath::Max(xi3,logxmin));
6488 xi4 = TMath::Log10(TMath::Max(xi4,logxmin));
6489 }
6490 if (Hoption.Logy) {
6491 yi1 = TMath::Log10(TMath::Max(yi1,logymin));
6492 yi2 = TMath::Log10(TMath::Max(yi2,logymin));
6493 yi3 = TMath::Log10(TMath::Max(yi3,logymin));
6494 yi4 = TMath::Log10(TMath::Max(yi4,logymin));
6495 }
6496
6497 // test if error bars are not outside the limits
6498 // otherwise they are truncated
6499
6500 xi1 = TMath::Max(xi1,xmin);
6501 xi2 = TMath::Min(xi2,xmax);
6502 yi3 = TMath::Max(yi3,ymin);
6503 yi4 = TMath::Min(yi4,ymax);
6504
6505 // test if the marker is on the frame limits. If "Yes", the
6506 // marker will not be drawn and the error bars will be readjusted.
6507
6508 drawmarker = kTRUE;
6509 if (!option0 && !option3) {
6510 if (Hoption.Logy && yp < logymin) goto L30;
6511 if (yi1 < ymin || yi1 > ymax) goto L30;
6512 if (Hoption.Error != 0 && yp == 0 && ey1 <= 0) drawmarker = kFALSE;
6513 }
6514 if (!symbolsize || !errormarker) drawmarker = kFALSE;
6515
6516 // draw the error rectangles
6517 if (option2) {
6518 if (yi3 >= ymax) goto L30;
6519 if (yi4 <= ymin) goto L30;
6520 gPad->PaintBox(xi1,yi3,xi2,yi4);
6521 }
6522
6523 // keep points for fill area drawing
6524 if (option3) {
6525 xline[if1-1] = xi3;
6526 xline[if2-1] = xi3;
6527 yline[if1-1] = yi4;
6528 yline[if2-1] = yi3;
6529 if1++;
6530 if2--;
6531 }
6532
6533 // draw the error bars
6534 if (Hoption.Logy && yp < logymin) drawmarker = kFALSE;
6535 if (optionE && drawmarker) {
6536 if ((yi3 < yi1 - s2y) && (yi3 < ymax)) gPad->PaintLine(xi3,yi3,xi4,TMath::Min(yi1 - s2y,ymax));
6537 if ((yi1 + s2y < yi4) && (yi4 > ymin)) gPad->PaintLine(xi3,TMath::Max(yi1 + s2y, ymin),xi4,yi4);
6538 // don't duplicate the horizontal line
6539 if (Hoption.Hist != 2) {
6540 if (yi1<ymax && yi1>ymin) {
6541 if (xi1 < xi3 - s2x) gPad->PaintLine(xi1,yi1,xi3 - s2x,yi2);
6542 if (xi3 + s2x < xi2) gPad->PaintLine(xi3 + s2x,yi1,xi2,yi2);
6543 }
6544 }
6545 }
6546 if (optionE && !drawmarker && (ey1 != 0 || ey2 !=0)) {
6547 if ((yi3 < yi1) && (yi3 < ymax)) gPad->PaintLine(xi3,yi3,xi4,TMath::Min(yi1,ymax));
6548 if ((yi1 < yi4) && (yi4 > ymin)) gPad->PaintLine(xi3,TMath::Max(yi1,ymin),xi4,yi4);
6549 // don't duplicate the horizontal line
6550 if (Hoption.Hist != 2) {
6551 if (yi1<ymax && yi1>ymin) {
6552 if (xi1 < xi3) gPad->PaintLine(xi1,yi1,xi3,yi2);
6553 if (xi3 < xi2) gPad->PaintLine(xi3,yi1,xi2,yi2);
6554 }
6555 }
6556 }
6557
6558 // draw line at the end of the error bars
6559
6560 if (option1 && drawmarker) {
6561
6562 if (yi3 < yi1-s2y && yi3 < ymax && yi3 > ymin) gPad->PaintLine(xi3 - bxsize, yi3 , xi3 + bxsize, yi3);
6563 if (yi4 > yi1+s2y && yi4 < ymax && yi4 > ymin) gPad->PaintLine(xi3 - bxsize, yi4 , xi3 + bxsize, yi4);
6564 if (yi1 <= ymax && yi1 >= ymin) {
6565 if (xi1 < xi3-s2x) gPad->PaintLine(xi1 , yi1 - bysize, xi1 , yi1 + bysize);
6566 if (xi2 > xi3+s2x) gPad->PaintLine(xi2 , yi1 - bysize, xi2 , yi1 + bysize);
6567 }
6568 }
6569
6570 // draw the marker
6571
6572 if (drawmarker) gPad->PaintPolyMarker(1, &xi3, &yi1);
6573
6574L30:
6575 if (fixbin) xp += Hparam.xbinsize;
6576 else {
6577 if (k < last) {
6578 delta = fH->GetBinWidth(k+1);
6579 xp = fH->GetBinLowEdge(k+1) + 0.5*delta;
6580 }
6581 }
6582 } //end of for loop
6583
6584 // draw the filled area
6585
6586 if (option3) {
6587 TGraph graph;
6588 graph.SetLineStyle(fH->GetLineStyle());
6589 graph.SetLineColor(fH->GetLineColor());
6590 graph.SetLineWidth(fH->GetLineWidth());
6591 graph.SetFillStyle(fH->GetFillStyle());
6592 graph.SetFillColor(fH->GetFillColor());
6593 Int_t logx = gPad->GetLogx();
6594 Int_t logy = gPad->GetLogy();
6595 gPad->SetLogx(0);
6596 gPad->SetLogy(0);
6597
6598 // In some cases the number of points in the fill area is smaller than
6599 // 2*npoints. In such cases the array xline and yline must be arranged
6600 // before being plotted. The next loop does that.
6601 if (if2 > npoints) {
6602 for (i=1; i<if1; i++) {
6603 xline[if1-2+i] = xline[if2-1+i];
6604 yline[if1-2+i] = yline[if2-1+i];
6605 }
6606 npoints = if1-1;
6607 }
6608 if (option4) graph.PaintGraph(2*npoints,xline.data(),yline.data(),"FC");
6609 else graph.PaintGraph(2*npoints,xline.data(),yline.data(),"F");
6610 gPad->SetLogx(logx);
6611 gPad->SetLogy(logy);
6612 }
6613}
6614
6615////////////////////////////////////////////////////////////////////////////////
6616/// Draw 2D histograms errors.
6617
6619{
6620
6621 fH->TAttMarker::Modify();
6622 fH->TAttLine::Modify();
6623
6624 // Define the 3D view
6625 fXbuf[0] = Hparam.xmin;
6626 fYbuf[0] = Hparam.xmax;
6627 fXbuf[1] = Hparam.ymin;
6628 fYbuf[1] = Hparam.ymax;
6629 fXbuf[2] = Hparam.zmin;
6630 fYbuf[2] = Hparam.zmax*(1. + gStyle->GetHistTopMargin());
6631 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
6632 TView *view = gPad ? gPad->GetView() : nullptr;
6633 if (!view) {
6634 Error("Paint2DErrors", "no TView in current pad");
6635 return;
6636 }
6637 Double_t thedeg = 90 - gPad->GetTheta();
6638 Double_t phideg = -90 - gPad->GetPhi();
6639 Double_t psideg = view->GetPsi();
6640 Int_t irep;
6641 view->SetView(phideg, thedeg, psideg, irep);
6642
6643 // Set color/style for back box
6644 fLego->SetFillStyle(gPad->GetFrameFillStyle());
6645 fLego->SetFillColor(gPad->GetFrameFillColor());
6646 fLego->TAttFill::Modify();
6647 Int_t backcolor = gPad->GetFrameFillColor();
6648 if (Hoption.System != kCARTESIAN) backcolor = 0;
6649 view->PadRange(backcolor);
6650 fLego->SetFillStyle(fH->GetFillStyle());
6651 fLego->SetFillColor(fH->GetFillColor());
6652 fLego->TAttFill::Modify();
6653
6654 // Paint the Back Box if needed
6655 if (Hoption.BackBox && !Hoption.Same && !Hoption.Lego && !Hoption.Surf) {
6656 fLego->InitMoveScreen(-1.1,1.1);
6657 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
6659 fLego->BackBox(90);
6660 }
6661
6662 // Paint the Errors
6663 Double_t x, ex, x1, x2;
6664 Double_t y, ey, y1, y2;
6665 Double_t z, ez1, ez2, z1, z2;
6666 Double_t temp1[3],temp2[3];
6667 Double_t xyerror;
6668 if (Hoption.Error == 110) {
6669 xyerror = 0;
6670 } else {
6671 xyerror = gStyle->GetErrorX();
6672 }
6673
6674 Double_t xk, xstep, yk, ystep;
6675 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
6676 y = fYaxis->GetBinCenter(j);
6677 ey = fYaxis->GetBinWidth(j)*xyerror;
6678 y1 = y-ey;
6679 y2 = y+ey;
6680 if (Hoption.Logy) {
6681 if (y > 0) y = TMath::Log10(y);
6682 else continue;
6683 if (y1 > 0) y1 = TMath::Log10(y1);
6684 else y1 = Hparam.ymin;
6685 if (y2 > 0) y2 = TMath::Log10(y2);
6686 else y2 = Hparam.ymin;
6687 }
6688 yk = fYaxis->GetBinLowEdge(j);
6689 ystep = fYaxis->GetBinWidth(j);
6690 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
6691 xk = fXaxis->GetBinLowEdge(i);
6692 xstep = fXaxis->GetBinWidth(i);
6693 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
6694 Int_t bin = fH->GetBin(i,j);
6695 x = fXaxis->GetBinCenter(i);
6696 ex = fXaxis->GetBinWidth(i)*xyerror;
6697 x1 = x-ex;
6698 x2 = x+ex;
6699 if (Hoption.Logx) {
6700 if (x > 0) x = TMath::Log10(x);
6701 else continue;
6702 if (x1 > 0) x1 = TMath::Log10(x1);
6703 else x1 = Hparam.xmin;
6704 if (x2 > 0) x2 = TMath::Log10(x2);
6705 else x2 = Hparam.xmin;
6706 }
6707 z = fH->GetBinContent(bin);
6708 if (fH->GetBinErrorOption() == TH1::kNormal) {
6709 ez1 = fH->GetBinError(bin);
6710 ez2 = ez1;
6711 }
6712 else {
6713 ez1 = fH->GetBinErrorLow(bin);
6714 ez2 = fH->GetBinErrorUp(bin);
6715 }
6716 z1 = z - ez1;
6717 z2 = z + ez2;
6718 if (Hoption.Logz) {
6719 if (z > 0) z = TMath::Log10(z);
6720 else z = Hparam.zmin;
6721 if (z1 > 0) z1 = TMath::Log10(z1);
6722 else z1 = Hparam.zmin;
6723 if (z2 > 0) z2 = TMath::Log10(z2);
6724 else z2 = Hparam.zmin;
6725
6726 }
6727 if (z <= Hparam.zmin) continue;
6728 if (z > Hparam.zmax) z = Hparam.zmax;
6729
6730 temp1[0] = x1;
6731 temp1[1] = y;
6732 temp1[2] = z;
6733 temp2[0] = x2;
6734 temp2[1] = y;
6735 temp2[2] = z;
6736 gPad->PaintLine3D(temp1, temp2);
6737 temp1[0] = x;
6738 temp1[1] = y1;
6739 temp1[2] = z;
6740 temp2[0] = x;
6741 temp2[1] = y2;
6742 temp2[2] = z;
6743 gPad->PaintLine3D(temp1, temp2);
6744 temp1[0] = x;
6745 temp1[1] = y;
6746 temp1[2] = z1;
6747 temp2[0] = x;
6748 temp2[1] = y;
6749 temp2[2] = z2;
6750 gPad->PaintLine3D(temp1, temp2);
6751 temp1[0] = x;
6752 temp1[1] = y;
6753 temp1[2] = z;
6754 view->WCtoNDC(temp1, &temp2[0]);
6755 gPad->PaintPolyMarker(1, &temp2[0], &temp2[1]);
6756 }
6757 }
6758
6759 // Paint the Front Box if needed
6760 if (Hoption.FrontBox) {
6761 fLego->InitMoveScreen(-1.1,1.1);
6763 fLego->FrontBox(90);
6764 }
6765
6766 // Paint the Axis if needed
6767 if (!Hoption.Axis && !Hoption.Same && !Hoption.Lego && !Hoption.Surf) {
6768 TGaxis axis;
6769 PaintLegoAxis(&axis, 90);
6770 }
6771
6772 fLego.reset();
6773}
6774
6775////////////////////////////////////////////////////////////////////////////////
6776/// Calculate range and clear pad (canvas).
6777
6779{
6780
6781 if (Hoption.Same) return;
6782
6784
6785 if (Hoption.Lego || Hoption.Surf || Hoption.Tri ||
6786 Hoption.Contour == 14 || Hoption.Error >= 100) {
6787 TObject *frame = gPad->FindObject("TFrame");
6788 if (frame) gPad->GetListOfPrimitives()->Remove(frame);
6789 return;
6790 }
6791
6792 //The next statement is always executed on non-iOS platform,
6793 //on iOS depends on pad mode.
6794 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode())
6795 gPad->PaintPadFrame(Hparam.xmin,Hparam.ymin,Hparam.xmax,Hparam.ymax);
6796}
6797
6798////////////////////////////////////////////////////////////////////////////////
6799/// [Paint functions associated to an histogram.](\ref HP28")
6800
6802{
6803 auto lnk = fFunctions->FirstLink();
6804
6805 while (lnk) {
6806 auto obj = lnk->GetObject();
6807 TVirtualPad::TContext ctxt(true);
6808 if (obj->InheritsFrom(TF2::Class())) {
6809 if (!obj->TestBit(TF2::kNotDraw)) {
6810 if (Hoption.Lego || Hoption.Surf || Hoption.Error >= 100) {
6811 TF2 *f2 = (TF2*)obj;
6812 f2->SetMinimum(fH->GetMinimum());
6813 f2->SetMaximum(fH->GetMaximum());
6814 f2->SetRange(fH->GetXaxis()->GetXmin(), fH->GetYaxis()->GetXmin(), fH->GetXaxis()->GetXmax(), fH->GetYaxis()->GetXmax() );
6815 f2->Paint("surf same");
6816 } else {
6817 obj->Paint("cont3 same");
6818 }
6819 }
6820 } else if (obj->InheritsFrom(TF1::Class())) {
6821 if (!obj->TestBit(TF1::kNotDraw)) obj->Paint("lsame");
6822 } else {
6823 //Let's make this 'function' selectable on iOS device (for example, it can be TPaveStat).
6824 gPad->PushSelectableObject(obj);
6825
6826 //The next statement is ALWAYS executed on non-iOS platform, on iOS it depends on pad's mode
6827 //and picked object.
6828 if (!gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && obj == gPad->GetSelected()))
6829 obj->Paint(lnk->GetOption());
6830 }
6831 lnk = lnk->Next();
6832 }
6833}
6834
6835////////////////////////////////////////////////////////////////////////////////
6836/// [Control routine to draw 1D histograms](\ref HP01b)
6837
6839{
6840
6841 //On iOS: do not highlight hist, if part of it was selected.
6842 //Never executes on non-iOS platform.
6843 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
6844 return;
6845
6846 static char chopth[17];
6847
6848 Int_t htype, oldhtype;
6849 Int_t i, j, first, last, nbins, fixbin;
6850 Double_t c1, yb;
6851 yb = 0;
6852
6853 strlcpy(chopth, " ",17);
6854
6857 Double_t baroffset = fH->GetBarOffset();
6858 Double_t barwidth = fH->GetBarWidth();
6859 Double_t baroffsetsave = gStyle->GetBarOffset();
6860 Double_t barwidthsave = gStyle->GetBarWidth();
6861 gStyle->SetBarOffset(baroffset);
6862 gStyle->SetBarWidth(barwidth);
6863
6864 // Create "LIFE" structure to keep current histogram status
6865
6866 first = Hparam.xfirst;
6867 last = Hparam.xlast;
6868 nbins = last - first + 1;
6869
6870 std::vector<Double_t> keepx, keepy;
6871 if (fXaxis->GetXbins()->fN) fixbin = 0;
6872 else fixbin = 1;
6873 if (fixbin) keepx.resize(2);
6874 else keepx.resize(nbins+1);
6875 keepy.resize(nbins);
6876 Double_t logymin = 0;
6877 if (Hoption.Logy) logymin = TMath::Power(10,ymin);
6878
6879 // Loop on histogram bins
6880
6881 for (j=first; j<=last;j++) {
6883 if (TMath::Abs(ymax-ymin) > 0) {
6884 if (Hoption.Logy) yb = TMath::Log10(TMath::Max(c1,.1*logymin));
6885 else yb = c1;
6886 }
6887 if (!Hoption.Line) {
6888 yb = TMath::Max(yb, ymin);
6889 yb = TMath::Min(yb, ymax);
6890 }
6891 keepy[j-first] = yb;
6892 }
6893
6894 // Draw histogram according to value of FillStyle and FillColor
6895
6896 if (fixbin) { keepx[0] = Hparam.xmin; keepx[1] = Hparam.xmax; }
6897 else {
6898 for (i=0; i<nbins; i++) keepx[i] = fXaxis->GetBinLowEdge(i+first);
6899 keepx[nbins] = fXaxis->GetBinUpEdge(nbins-1+first);
6900 }
6901
6902 // Prepare Fill area (systematic with option "Bar").
6903
6904 oldhtype = fH->GetFillStyle();
6905 htype = oldhtype;
6906 if (Hoption.Bar) {
6907 if (htype == 0 || htype == 1000) htype = 1001;
6908 }
6909
6910 Width_t lw = (Width_t)fH->GetLineWidth();
6911
6912 // Code option for GrapHist
6913
6914 if (Hoption.Line) chopth[0] = 'L';
6915 if (Hoption.Star) chopth[1] = '*';
6916 if (Hoption.Mark) chopth[2] = 'P';
6917 if (Hoption.Mark == 10) chopth[3] = '0';
6919 if (Hoption.Curve) chopth[3] = 'C';
6920 if (Hoption.Hist > 0) chopth[4] = 'H';
6921 else if (Hoption.Bar) chopth[5] = 'B';
6922 if (Hoption.Logy) chopth[6] = '1';
6923 if (fH->GetFillColor() && htype) {
6924 if (Hoption.Hist > 0 || Hoption.Curve || Hoption.Line) {
6925 chopth[7] = 'F';
6926 }
6927 }
6928 }
6929 if (!fixbin && strlen(chopth)) {
6930 chopth[8] = 'N';
6931 }
6932
6933 if (Hoption.Fill == 2) chopth[13] = '2';
6934
6935 // Option LOGX
6936
6937 if (Hoption.Logx) {
6938 chopth[9] = 'G';
6939 chopth[10] = 'X';
6940 if (fixbin) {
6941 keepx[0] = TMath::Power(10,keepx[0]);
6942 keepx[1] = TMath::Power(10,keepx[1]);
6943 }
6944 }
6945
6946 if (Hoption.Off) {
6947 chopth[11] = ']';
6948 chopth[12] = '[';
6949 }
6950
6951 // Draw the histogram
6952
6953 TGraph graph;
6954 graph.SetLineWidth(lw);
6955 graph.SetLineStyle(fH->GetLineStyle());
6956 graph.SetLineColor(fH->GetLineColor());
6957 graph.SetFillStyle(htype);
6958 graph.SetFillColor(fH->GetFillColor());
6959 graph.SetMarkerStyle(fH->GetMarkerStyle());
6960 graph.SetMarkerSize(fH->GetMarkerSize());
6961 graph.SetMarkerColor(fH->GetMarkerColor());
6962 if (!Hoption.Same) graph.ResetBit(TGraph::kClipFrame);
6963
6964 graph.PaintGrapHist(nbins, keepx.data(), keepy.data() ,chopth);
6965
6966 gStyle->SetBarOffset(baroffsetsave);
6967 gStyle->SetBarWidth(barwidthsave);
6968
6969 htype=oldhtype;
6970}
6971
6972////////////////////////////////////////////////////////////////////////////////
6973/// [Control function to draw a 3D histograms.](\ref HP01d)
6974
6976{
6977
6978 TString cmd;
6979 TString opt = option;
6980 opt.ToLower();
6981 Int_t irep;
6982 Float_t NEntries = fH->GetEntries();
6983
6984 if (fCurrentF3 || strstr(opt,"tf3")) {
6985 PaintTF3();
6986 return;
6987 }
6988
6989 if (NEntries > 0) {
6990 if (Hoption.Box || Hoption.Lego || Hoption.Color) {
6991 if (Hoption.Box == 11 || Hoption.Lego == 11) {
6992 PaintH3Box(1);
6993 } else if (Hoption.Box == 12 || Hoption.Lego == 12 || Hoption.Color == 1) {
6994 PaintH3Box(2);
6995 } else if (Hoption.Box == 13 || Hoption.Lego == 13) {
6996 PaintH3Box(3);
6997 } else {
6999 }
7000 return;
7001 }
7002
7003 if (strstr(opt,"iso")) {
7004 PaintH3Iso();
7005 return;
7006 }
7007 }
7008
7009 TView *view = gPad ? gPad->GetView() : nullptr;
7010 if (!view) return;
7011
7012 if (strstr(opt,"fb")) Hoption.FrontBox = 0;
7013 if (strstr(opt,"bb")) Hoption.BackBox = 0;
7014
7015 Double_t thedeg = 90 - gPad->GetTheta();
7016 Double_t phideg = -90 - gPad->GetPhi();
7017 Double_t psideg = view->GetPsi();
7018 view->SetView(phideg, thedeg, psideg, irep);
7019
7020 if(NEntries > 0) { // Paint as 3D scatter plot
7021 cmd.Form("TPolyMarker3D::PaintH3((TH1 *)0x%zx,\"%s\");",(size_t)fH,option);
7022 gROOT->ProcessLine(cmd.Data());
7023 } else {
7024 TAxis* xAxis = fH->GetXaxis();
7025 TAxis* yAxis = fH->GetYaxis();
7026 TAxis* zAxis = fH->GetZaxis();
7027 Double_t xmin = xAxis->GetXmin();
7028 Double_t xmax = xAxis->GetXmax();
7029 Double_t ymin = yAxis->GetXmin();
7030 Double_t ymax = yAxis->GetXmax();
7031 Double_t zmin = zAxis->GetXmin();
7032 Double_t zmax = zAxis->GetXmax();
7033 view->SetRange(xmin, ymin, zmin, xmax, ymax, zmax); // Set the axis limits (Xmin, Ymin, Zmin, Xmax, Ymax, Zmax)
7034 }
7035
7036 if (Hoption.Same) return;
7037
7038 // Draw axis
7039 view->SetOutlineToCube();
7040 TSeqCollection *ol = view->GetOutline();
7041 if (ol && Hoption.BackBox && Hoption.FrontBox) ol->Paint(option);
7043
7044 if (!Hoption.Axis && !Hoption.Same) {
7045 TGaxis axis;
7046 PaintLegoAxis(&axis, 90);
7047 }
7048
7049 // Draw palette. In case of 4D plot with TTree::Draw() the palette should
7050 // be painted with the option colz.
7051 if (fH->GetDrawOption() && strstr(opt,"colz")) {
7052 Int_t ndiv = fH->GetContour();
7053 if (ndiv == 0 ) {
7054 ndiv = gStyle->GetNumberContours();
7055 fH->SetContour(ndiv);
7056 }
7057 PaintPalette();
7058 }
7059
7060 // Draw title
7061 PaintTitle();
7062
7063 //Draw stats and fit results
7064 TF1 *fit = nullptr;
7065 TIter next(fFunctions);
7066 while (auto obj = next()) {
7067 if (obj->InheritsFrom(TF1::Class())) {
7068 fit = (TF1*)obj;
7069 break;
7070 }
7071 }
7072 if ((Hoption.Same%10) != 1) {
7073 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7075 }
7076 }
7077
7078}
7079
7080////////////////////////////////////////////////////////////////////////////////
7081/// Compute histogram parameters used by the drawing routines.
7082
7084{
7085
7086 if (fH->GetDimension() > 1 || Hoption.Lego || Hoption.Surf) return 1;
7087
7088 Int_t i;
7089 static const char *where = "PaintInit";
7090 Double_t yMARGIN = gStyle->GetHistTopMargin();
7091 Int_t maximum = 0;
7092 Int_t minimum = 0;
7093 if (fH->GetMaximumStored() != -1111) maximum = 1;
7094 if (fH->GetMinimumStored() != -1111) minimum = 1;
7095
7096 // Compute X axis parameters
7097
7098 Int_t last = fXaxis->GetLast();
7099 Int_t first = fXaxis->GetFirst();
7102 Hparam.xlast = last;
7103 Hparam.xfirst = first;
7106
7107 // if log scale in X, replace xmin,max by the log
7108 if (Hoption.Logx) {
7109 if (Hparam.xmax<=0) {
7110 Error(where, "cannot set X axis to log scale");
7111 return 0;
7112 }
7113 if (Hparam.xlowedge <=0 ) {
7114 if (Hoption.Same) {
7115 TH1* h1 = nullptr;
7116 TObject *obj;
7117 TIter next(gPad->GetListOfPrimitives());
7118 while ((obj = (TObject *)next())) {
7119 if (obj->InheritsFrom(TH1::Class())) { h1 = (TH1*)(obj) ; break; }
7120 if (obj->InheritsFrom(THStack::Class())) { h1 = ((THStack*)(obj))->GetHistogram() ; break; }
7121 if (obj->InheritsFrom(TGraph::Class())) { h1 = ((TGraph*)(obj))->GetHistogram() ; break; }
7122 if (obj->InheritsFrom(TMultiGraph::Class())) { h1 = ((TMultiGraph*)(obj))->GetHistogram(); break; }
7123 if (obj->InheritsFrom(TGraph2D::Class())) { h1 = ((TGraph2D*)(obj))->GetHistogram(); break; }
7124 if (obj->InheritsFrom(TF1::Class())) { h1 = ((TF1*)(obj))->GetHistogram(); break; }
7125 }
7126 if (h1) {
7128 } else {
7129 Error(where, "undefined user's coordinates. Cannot use option SAME");
7130 return 0;
7131 }
7132 } else {
7133 for (i=first; i<=last; i++) {
7134 Double_t binLow = fXaxis->GetBinLowEdge(i);
7135 if (binLow>0) {
7136 Hparam.xlowedge = binLow;
7137 break;
7138 }
7139 if (binLow == 0 && fH->GetBinContent(i) !=0) {
7140 Hparam.xlowedge = fXaxis->GetBinUpEdge(i)*0.001;
7141 break;
7142 }
7143 }
7144 if (Hparam.xlowedge<=0) {
7145 Error(where, "cannot set X axis to log scale");
7146 return 0;
7147 }
7148 }
7150 }
7155 if (Hparam.xlast > last) Hparam.xlast = last;
7156 if (Hparam.xfirst < first) Hparam.xfirst = first;
7157 }
7158
7159 // Compute Y axis parameters
7160 Double_t bigp = TMath::Power(10,32);
7161 Double_t ymax = -bigp;
7162 Double_t ymin = bigp;
7163 Double_t c1, e1;
7164 Double_t xv[1];
7165 Double_t fval;
7166 TObject *f;
7167 TF1 *f1;
7168 Double_t allchan = 0;
7169 Int_t nonNullErrors = 0;
7170 TIter next(fFunctions);
7171 for (i=first; i<=last;i++) {
7172 c1 = fH->GetBinContent(i);
7174 if (Hoption.Logy) {
7175 if (c1 > 0) ymin = TMath::Min(ymin,c1);
7176 } else {
7178 }
7179 if (Hoption.Error) {
7181 e1 = fH->GetBinError(i);
7182 else
7183 e1 = fH->GetBinErrorUp(i);
7184 if (e1 > 0) nonNullErrors++;
7185 ymax = TMath::Max(ymax,c1+e1);
7187 e1 = fH->GetBinErrorLow(i);
7188
7189 if (Hoption.Logy) {
7190 if (c1-e1>0.01*TMath::Abs(c1)) ymin = TMath::Min(ymin,c1-e1);
7191 } else {
7192 ymin = TMath::Min(ymin,c1-e1);
7193 }
7194 }
7195 if (Hoption.Func) {
7196 xv[0] = fXaxis->GetBinCenter(i);
7197 while ((f = (TObject*) next())) {
7198 if (f->IsA() == TF1::Class()) {
7199 f1 = (TF1*)f;
7200 if (xv[0] < f1->GetXmin() || xv[0] > f1->GetXmax()) continue;
7201 fval = f1->Eval(xv[0],0,0);
7202 if (f1->GetMaximumStored() != -1111) fval = TMath::Min(f1->GetMaximumStored(), fval);
7203 ymax = TMath::Max(ymax,fval);
7204 if (Hoption.Logy) {
7205 if (c1 > 0 && fval > 0.3*c1) ymin = TMath::Min(ymin,fval);
7206 }
7207 }
7208 }
7209 next.Reset();
7210 }
7211 allchan += c1;
7212 }
7213 if (!nonNullErrors) {
7214 if (Hoption.Error) {
7215 if (!Hoption.Mark && !Hoption.Line && !Hoption.Star && !Hoption.Curve) Hoption.Hist = 2;
7216 Hoption.Error=0;
7217 }
7218 }
7219
7220
7221 // Take into account maximum , minimum
7222
7223 if (Hoption.Logy && ymin <= 0) {
7224 if (ymax >= 1) ymin = TMath::Max(.005,ymax*1e-10);
7225 else ymin = 0.001*ymax;
7226 }
7227
7228 Double_t xm = ymin;
7229 if (maximum) ymax = fH->GetMaximumStored();
7230 if (minimum) xm = fH->GetMinimumStored();
7231 if (Hoption.Logy && xm < 0) {
7232 Error(where, "log scale requested with a negative argument (%f)", xm);
7233 return 0;
7234 } else if (Hoption.Logy && xm>=0 && ymax==0) { // empty histogram in log scale
7235 ymin = 0.01;
7236 ymax = 10.;
7237 } else {
7238 ymin = xm;
7239 }
7240
7241 if (ymin >= ymax) {
7242 if (Hoption.Logy) {
7243 if (ymax > 0) ymin = 0.001*ymax;
7244 else {
7245 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", ymax);
7246 return 0;
7247 }
7248 }
7249 else {
7250 if (ymin > 0) {
7251 ymin = 0;
7252 ymax *= 2;
7253 } else if (ymin < 0) {
7254 ymax = 0;
7255 ymin *= 2;
7256 } else {
7257 ymin = 0;
7258 ymax = 1;
7259 }
7260 }
7261 }
7262
7263 // In some cases, mainly because of precision issues, ymin and ymax could almost equal.
7264 if (TMath::AreEqualRel(ymin,ymax,1E-15)) {
7265 ymin = ymin*(1-1E-14);
7266 ymax = ymax*(1+1E-14);
7267 }
7268
7269 // take into account normalization factor
7270 Hparam.allchan = allchan;
7271 Double_t factor = allchan;
7272 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
7273 if (allchan) factor /= allchan;
7274 if (factor == 0) factor = 1;
7275 Hparam.factor = factor;
7276 ymax = factor*ymax;
7277 ymin = factor*ymin;
7278 //just in case the norm factor is negative
7279 // this may happen with a positive norm factor and a negative integral !
7280 if (ymax < ymin) {
7281 Double_t temp = ymax;
7282 ymax = ymin;
7283 ymin = temp;
7284 }
7285
7286 // For log scales, histogram coordinates are LOG10(ymin) and
7287 // LOG10(ymax). Final adjustment (if not option "Same"
7288 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
7289 // Maximum and Minimum are not defined.
7290 if (Hoption.Logy) {
7291 if (ymin <=0 || ymax <=0) {
7292 Error(where, "Cannot set Y axis to log scale");
7293 return 0;
7294 }
7296 if (!minimum) ymin += TMath::Log10(0.5);
7298 if (!maximum) ymax += TMath::Log10(2*(0.9/0.95));
7299 if (!Hoption.Same) {
7300 Hparam.ymin = ymin;
7301 Hparam.ymax = ymax;
7302 }
7303 return 1;
7304 }
7305
7306 // final adjustment of ymin for linear scale.
7307 // if minimum is not set , then ymin is set to zero if >0
7308 // or to ymin - margin if <0.
7309 if (!minimum) {
7310 if (Hoption.MinimumZero) {
7311 if (ymin >= 0) ymin = 0;
7312 else ymin -= yMARGIN*(ymax-ymin);
7313 } else {
7314 Double_t dymin = yMARGIN*(ymax-ymin);
7315 if (ymin >= 0 && (ymin-dymin <= 0)) ymin = 0;
7316 else ymin -= dymin;
7317 }
7318 }
7319
7320 // final adjustment of YMAXI for linear scale (if not option "Same"):
7321 // decrease histogram height to MAX% of allowed height if HMAXIM
7322 // has not been called.
7323 if (!maximum) {
7324 ymax += yMARGIN*(ymax-ymin);
7325 }
7326
7327 Hparam.ymin = ymin;
7328 Hparam.ymax = ymax;
7329 return 1;
7330}
7331
7332////////////////////////////////////////////////////////////////////////////////
7333/// Compute histogram parameters used by the drawing routines for a rotated pad.
7334
7336{
7337
7338 static const char *where = "PaintInitH";
7339 Double_t yMARGIN = gStyle->GetHistTopMargin();
7340 Int_t maximum = 0;
7341 Int_t minimum = 0;
7342 if (fH->GetMaximumStored() != -1111) maximum = 1;
7343 if (fH->GetMinimumStored() != -1111) minimum = 1;
7344
7345 // Compute X axis parameters
7346
7347 Int_t last = fXaxis->GetLast();
7348 Int_t first = fXaxis->GetFirst();
7351 Hparam.xlast = last;
7352 Hparam.xfirst = first;
7355
7356 // if log scale in Y, replace ymin,max by the log
7357 if (Hoption.Logy) {
7358 if (Hparam.xlowedge <=0 ) {
7361 }
7362 if (Hparam.ymin <=0 || Hparam.ymax <=0) {
7363 Error(where, "cannot set Y axis to log scale");
7364 return 0;
7365 }
7370 if (Hparam.xlast > last) Hparam.xlast = last;
7371 }
7372
7373 // Compute Y axis parameters
7374 Double_t bigp = TMath::Power(10,32);
7375 Double_t xmax = -bigp;
7376 Double_t xmin = bigp;
7377 Double_t c1, e1;
7378 Double_t xv[1];
7379 Double_t fval;
7380 Int_t i;
7381 TObject *f;
7382 TF1 *f1;
7383 Double_t allchan = 0;
7384 TIter next(fFunctions);
7385 for (i=first; i<=last;i++) {
7386 c1 = fH->GetBinContent(i);
7389 if (Hoption.Error) {
7390 e1 = fH->GetBinError(i);
7391 xmax = TMath::Max(xmax,c1+e1);
7392 xmin = TMath::Min(xmin,c1-e1);
7393 }
7394 if (Hoption.Func) {
7395 xv[0] = fXaxis->GetBinCenter(i);
7396 while ((f = (TObject*) next())) {
7397 if (f->IsA() == TF1::Class()) {
7398 f1 = (TF1*)f;
7399 if (xv[0] < f1->GetXmin() || xv[0] > f1->GetXmax()) continue;
7400 fval = f1->Eval(xv[0],0,0);
7401 xmax = TMath::Max(xmax,fval);
7402 if (Hoption.Logy) {
7403 if (fval > 0.3*c1) xmin = TMath::Min(xmin,fval);
7404 }
7405 }
7406 }
7407 next.Reset();
7408 }
7409 allchan += c1;
7410 }
7411
7412 // Take into account maximum , minimum
7413
7414 if (Hoption.Logx && xmin <= 0) {
7415 if (xmax >= 1) xmin = TMath::Max(.5,xmax*1e-10);
7416 else xmin = 0.001*xmax;
7417 }
7418 Double_t xm = xmin;
7419 if (maximum) xmax = fH->GetMaximumStored();
7420 if (minimum) xm = fH->GetMinimumStored();
7421 if (Hoption.Logx && xm <= 0) {
7422 Error(where, "log scale requested with zero or negative argument (%f)", xm);
7423 return 0;
7424 }
7425 else xmin = xm;
7426 if (xmin >= xmax) {
7427 if (Hoption.Logx) {
7428 if (xmax > 0) xmin = 0.001*xmax;
7429 else {
7430 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", xmax);
7431 return 0;
7432 }
7433 }
7434 else {
7435 if (xmin > 0) {
7436 xmin = 0;
7437 xmax *= 2;
7438 } else if (xmin < 0) {
7439 xmax = 0;
7440 xmin *= 2;
7441 } else {
7442 xmin = 0;
7443 xmax = 1;
7444 }
7445 }
7446 }
7447
7448 // take into account normalization factor
7449 Hparam.allchan = allchan;
7450 Double_t factor = allchan;
7451 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
7452 if (allchan) factor /= allchan;
7453 if (factor == 0) factor = 1;
7454 Hparam.factor = factor;
7455 xmax = factor*xmax;
7456 xmin = factor*xmin;
7457
7458 // For log scales, histogram coordinates are LOG10(ymin) and
7459 // LOG10(ymax). Final adjustment (if not option "Same"
7460 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
7461 // Maximum and Minimum are not defined.
7462 if (Hoption.Logx) {
7463 if (xmin <=0 || xmax <=0) {
7464 Error(where, "Cannot set Y axis to log scale");
7465 return 0;
7466 }
7468 if (!minimum) xmin += TMath::Log10(0.5);
7470 if (!maximum) xmax += TMath::Log10(2*(0.9/0.95));
7471 if (!Hoption.Same) {
7472 Hparam.xmin = xmin;
7473 Hparam.xmax = xmax;
7474 }
7475 return 1;
7476 }
7477
7478 // final adjustment of ymin for linear scale.
7479 // if minimum is not set , then ymin is set to zero if >0
7480 // or to ymin - margin if <0.
7481 if (!minimum) {
7482 if (xmin >= 0) xmin = 0;
7483 else xmin -= yMARGIN*(xmax-xmin);
7484 }
7485
7486 // final adjustment of YMAXI for linear scale (if not option "Same"):
7487 // decrease histogram height to MAX% of allowed height if HMAXIM
7488 // has not been called.
7489 if (!maximum) {
7490 xmax += yMARGIN*(xmax-xmin);
7491 }
7492 Hparam.xmin = xmin;
7493 Hparam.xmax = xmax;
7494 return 1;
7495}
7496
7497////////////////////////////////////////////////////////////////////////////////
7498/// [Control function to draw a 3D histogram with boxes.](\ref HP25)
7499
7501{
7502 // Predefined box structure
7503 Double_t wxyz[8][3] = { {-1,-1,-1}, {1,-1,-1}, {1,1,-1}, {-1,1,-1},
7504 {-1,-1, 1}, {1,-1, 1}, {1,1, 1}, {-1,1, 1} };
7505 Int_t iface[6][4] = { {0,3,2,1}, {4,5,6,7},
7506 {0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7} };
7507
7508 // Define dimensions of world space
7509 TAxis *xaxis = fH->GetXaxis();
7510 TAxis *yaxis = fH->GetYaxis();
7511 TAxis *zaxis = fH->GetZaxis();
7512
7513 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7514 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7515 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7516 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7517 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7518 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7519
7520 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7521
7522 // Set view
7523 TView *view = gPad ? gPad->GetView() : nullptr;
7524 if (!view) {
7525 Error("PaintH3", "no TView in current pad");
7526 return;
7527 }
7528 Double_t thedeg = 90 - gPad->GetTheta();
7529 Double_t phideg = -90 - gPad->GetPhi();
7530 Double_t psideg = view->GetPsi();
7531 Int_t irep;
7532 view->SetView(phideg, thedeg, psideg, irep);
7533
7534 Int_t backcolor = gPad->GetFrameFillColor();
7535 view->PadRange(backcolor);
7536
7537 // Draw back surfaces of frame box
7538 fLego->InitMoveScreen(-1.1,1.1);
7539 if (Hoption.BackBox) {
7540 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
7542 fLego->BackBox(90);
7543 }
7544
7546
7547 // Define order of drawing
7548 Double_t *tnorm = view->GetTnorm();
7549 if (!tnorm) return;
7550 Int_t incrx = (tnorm[ 8] < 0.) ? -1 : +1;
7551 Int_t incry = (tnorm[ 9] < 0.) ? -1 : +1;
7552 Int_t incrz = (tnorm[10] < 0.) ? -1 : +1;
7553 Int_t ix1 = (incrx == +1) ? xaxis->GetFirst() : xaxis->GetLast();
7554 Int_t iy1 = (incry == +1) ? yaxis->GetFirst() : yaxis->GetLast();
7555 Int_t iz1 = (incrz == +1) ? zaxis->GetFirst() : zaxis->GetLast();
7556 Int_t ix2 = (incrx == +1) ? xaxis->GetLast() : xaxis->GetFirst();
7557 Int_t iy2 = (incry == +1) ? yaxis->GetLast() : yaxis->GetFirst();
7558 Int_t iz2 = (incrz == +1) ? zaxis->GetLast() : zaxis->GetFirst();
7559
7560 // Set graphic attributes (colour, style, etc.)
7561 Style_t fillsav = fH->GetFillStyle();
7562 Style_t colsav = fH->GetFillColor();
7563 Style_t coldark = TColor::GetColorDark(colsav);
7564 Style_t colbright = TColor::GetColorBright(colsav);
7565
7566 fH->SetFillStyle(1001);
7567 fH->TAttFill::Modify();
7568 fH->TAttLine::Modify();
7569 Int_t ncolors = gStyle->GetNumberOfColors();
7570 Int_t theColor;
7571
7572 // Create bin boxes and draw
7576
7577 Double_t pmin[3], pmax[3], sxyz[8][3];
7578 for (Int_t ix = ix1; ix !=ix2+incrx; ix += incrx) {
7579 pmin[0] = xaxis->GetBinLowEdge(ix);
7580 pmax[0] = xaxis->GetBinUpEdge(ix);
7581 for (Int_t iy = iy1; iy != iy2+incry; iy += incry) {
7582 pmin[1] = yaxis->GetBinLowEdge(iy);
7583 pmax[1] = yaxis->GetBinUpEdge(iy);
7584 for (Int_t iz = iz1; iz != iz2+incrz; iz += incrz) {
7585 pmin[2] = zaxis->GetBinLowEdge(iz);
7586 pmax[2] = zaxis->GetBinUpEdge(iz);
7587 Double_t w = fH->GetBinContent(fH->GetBin(ix,iy,iz));
7588 Bool_t neg = kFALSE;
7589 Int_t n = 5;
7590 if (w<0) {
7591 w = -w;
7592 neg = kTRUE;
7593 }
7594 if (w < wmin) continue;
7595 if (w > wmax) w = wmax;
7596 Double_t scale = (TMath::Power((w-wmin)/(wmax-wmin),1./3.))/2.;
7597 if (scale == 0) continue;
7598 for (Int_t i=0; i<3; ++i) {
7599 Double_t c = (pmax[i] + pmin[i])*0.5;
7600 Double_t d = (pmax[i] - pmin[i])*scale;
7601 for (Int_t k=0; k<8; ++k) { // set bin box vertices
7602 sxyz[k][i] = wxyz[k][i]*d + c;
7603 }
7604 }
7605 for (Int_t k=0; k<8; ++k) { // transform to normalized space
7606 view->WCtoNDC(&sxyz[k][0],&sxyz[k][0]);
7607 }
7608 Double_t x[8], y[8]; // draw bin box faces
7609 for (Int_t k=0; k<6; ++k) {
7610 for (Int_t i=0; i<4; ++i) {
7611 Int_t iv = iface[k][i];
7612 x[i] = sxyz[iv][0];
7613 y[i] = sxyz[iv][1];
7614 }
7615 x[4] = x[0] ; y[4] = y[0];
7616 if (neg) {
7617 x[5] = x[2] ; y[5] = y[2];
7618 x[6] = x[3] ; y[6] = y[3];
7619 x[7] = x[1] ; y[7] = y[1];
7620 n = 8;
7621 } else {
7622 n = 5;
7623 }
7624 Double_t z = (x[2]-x[0])*(y[3]-y[1]) - (y[2]-y[0])*(x[3]-x[1]);
7625 if (z <= 0.) continue;
7626 if (iopt == 2) {
7627 theColor = ncolors*((w-wmin)/(wmax-wmin)) -1;
7629 } else {
7630 if (k == 3 || k == 5) {
7631 fH->SetFillColor(coldark);
7632 } else if (k == 0 || k == 1) {
7633 fH->SetFillColor(colbright);
7634 } else {
7635 fH->SetFillColor(colsav);
7636 }
7637 }
7638 fH->TAttFill::Modify();
7639 gPad->PaintFillArea(4, x, y);
7640 if (iopt != 3)gPad->PaintPolyLine(n, x, y);
7641 }
7642 }
7643 }
7644 }
7645
7646 // Draw front surfaces of frame box
7647 if (Hoption.FrontBox) fLego->FrontBox(90);
7648
7649 // Draw axis and title
7650 if (!Hoption.Axis && !Hoption.Same) {
7651 TGaxis axis;
7652 PaintLegoAxis(&axis, 90);
7653 }
7654 PaintTitle();
7655
7656 // Draw palette. if needed.
7657 if (Hoption.Zscale) {
7658 Int_t ndiv = fH->GetContour();
7659 if (ndiv == 0 ) {
7660 ndiv = gStyle->GetNumberContours();
7661 fH->SetContour(ndiv);
7662 }
7663 PaintPalette();
7664 }
7665
7666 //Draw stats and fit results
7667 TF1 *fit = nullptr;
7668 TIter next(fFunctions);
7669 while (auto obj = next()) {
7670 if (obj->InheritsFrom(TF1::Class())) {
7671 fit = (TF1*)obj;
7672 break;
7673 }
7674 }
7675 if ((Hoption.Same%10) != 1) {
7676 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7678 }
7679 }
7680
7681 fLego.reset();
7682
7683 fH->SetFillStyle(fillsav);
7684 fH->SetFillColor(colsav);
7685 fH->TAttFill::Modify();
7686}
7687
7688////////////////////////////////////////////////////////////////////////////////
7689/// [Control function to draw a 3D histogram with boxes.](\ref HP25)
7690
7692{
7693 // Predefined box structure
7694 Double_t wxyz[8][3] = {
7695 {-1,-1,-1}, {1,-1,-1}, {1,1,-1}, {-1,1,-1}, // bottom vertices
7696 {-1,-1, 1}, {1,-1, 1}, {1,1, 1}, {-1,1, 1} // top vertices
7697 };
7698 Int_t iface[6][4] = {
7699 {0,3,2,1}, {4,5,6,7}, // bottom and top faces
7700 {0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7} // side faces
7701 };
7702 Double_t normal[6][3] = {
7703 {0,0,-1}, {0,0,1}, // Z-, Z+
7704 {0,-1,0}, {1,0,0}, {0,1,0}, {-1,0,0} // Y-, X+, Y+, X-
7705 };
7706
7707 // Define dimensions of world space
7708 TAxis *xaxis = fH->GetXaxis();
7709 TAxis *yaxis = fH->GetYaxis();
7710 TAxis *zaxis = fH->GetZaxis();
7711
7712 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7713 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7714 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7715 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7716 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7717 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7718
7719 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7720
7721 // Set view
7722 TView *view = gPad ? gPad->GetView() : nullptr;
7723 if (!view) {
7724 Error("PaintH3", "no TView in current pad");
7725 return;
7726 }
7727 Double_t thedeg = 90 - gPad->GetTheta();
7728 Double_t phideg = -90 - gPad->GetPhi();
7729 Double_t psideg = view->GetPsi();
7730 Int_t irep;
7731 view->SetView(phideg, thedeg, psideg, irep);
7732
7733 Int_t backcolor = gPad->GetFrameFillColor();
7734 view->PadRange(backcolor);
7735
7736 // Draw front surfaces of frame box
7737 if (Hoption.FrontBox) {
7738 fLego->InitMoveScreen(-1.1,1.1);
7740 }
7741
7742 // Initialize hidden line removal algorithm "raster screen"
7743 fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
7744
7745 // Define order of drawing
7746 Double_t *tnorm = view->GetTnorm();
7747 if (!tnorm) return;
7748 Int_t incrx = (tnorm[ 8] < 0.) ? +1 : -1;
7749 Int_t incry = (tnorm[ 9] < 0.) ? +1 : -1;
7750 Int_t incrz = (tnorm[10] < 0.) ? +1 : -1;
7751 Int_t ix1 = (incrx == +1) ? xaxis->GetFirst() : xaxis->GetLast();
7752 Int_t iy1 = (incry == +1) ? yaxis->GetFirst() : yaxis->GetLast();
7753 Int_t iz1 = (incrz == +1) ? zaxis->GetFirst() : zaxis->GetLast();
7754 Int_t ix2 = (incrx == +1) ? xaxis->GetLast() : xaxis->GetFirst();
7755 Int_t iy2 = (incry == +1) ? yaxis->GetLast() : yaxis->GetFirst();
7756 Int_t iz2 = (incrz == +1) ? zaxis->GetLast() : zaxis->GetFirst();
7757
7758 // Set line attributes (colour, style, etc.)
7759 fH->TAttLine::Modify();
7760
7761 // Create bin boxes and draw
7762 const Int_t NTMAX = 100;
7763 Double_t tt[NTMAX][2];
7767 Double_t pmin[3], pmax[3], sxyz[8][3], pp[4][2];
7768 for (Int_t ix = ix1; ix !=ix2+incrx; ix += incrx) {
7769 pmin[0] = xaxis->GetBinLowEdge(ix);
7770 pmax[0] = xaxis->GetBinUpEdge(ix);
7771 for (Int_t iy = iy1; iy != iy2+incry; iy += incry) {
7772 pmin[1] = yaxis->GetBinLowEdge(iy);
7773 pmax[1] = yaxis->GetBinUpEdge(iy);
7774 for (Int_t iz = iz1; iz != iz2+incrz; iz += incrz) {
7775 pmin[2] = zaxis->GetBinLowEdge(iz);
7776 pmax[2] = zaxis->GetBinUpEdge(iz);
7777 Double_t w = fH->GetBinContent(fH->GetBin(ix,iy,iz));
7778 Bool_t neg = kFALSE;
7779 if (w<0) {
7780 w = -w;
7781 neg = kTRUE;
7782 }
7783 if (w < wmin) continue;
7784 if (w > wmax) w = wmax;
7785 Double_t scale = (TMath::Power((w-wmin)/(wmax-wmin),1./3.))/2.;
7786 if (scale == 0) continue;
7787 for (Int_t i=0; i<3; ++i) {
7788 Double_t c = (pmax[i] + pmin[i])*0.5;
7789 Double_t d = (pmax[i] - pmin[i])*scale;
7790 for (Int_t k=0; k<8; ++k) { // set bin box vertices
7791 sxyz[k][i] = wxyz[k][i]*d + c;
7792 }
7793 }
7794 for (Int_t k=0; k<8; ++k) { // transform to normalized space
7795 view->WCtoNDC(&sxyz[k][0],&sxyz[k][0]);
7796 }
7797 for (Int_t k=0; k<6; ++k) { // draw box faces
7798 Double_t zn;
7799 view->FindNormal(normal[k][0], normal[k][1], normal[k][2], zn);
7800 if (zn <= 0) continue;
7801 for (Int_t i=0; i<4; ++i) {
7802 Int_t ip = iface[k][i];
7803 pp[i][0] = sxyz[ip][0];
7804 pp[i][1] = sxyz[ip][1];
7805 }
7806 for (Int_t i=0; i<4; ++i) {
7807 Int_t i1 = i;
7808 Int_t i2 = (i == 3) ? 0 : i + 1;
7809 Int_t nt;
7810 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7811 Double_t xdel = pp[i2][0] - pp[i1][0];
7812 Double_t ydel = pp[i2][1] - pp[i1][1];
7813 Double_t x[2], y[2];
7814 for (Int_t it = 0; it < nt; ++it) {
7815 x[0] = pp[i1][0] + xdel*tt[it][0];
7816 y[0] = pp[i1][1] + ydel*tt[it][0];
7817 x[1] = pp[i1][0] + xdel*tt[it][1];
7818 y[1] = pp[i1][1] + ydel*tt[it][1];
7819 gPad->PaintPolyLine(2, x, y);
7820 }
7821 }
7822 if (neg) {
7823 Int_t i1 = 0;
7824 Int_t i2 = 2;
7825 Int_t nt;
7826 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7827 Double_t xdel = pp[i2][0] - pp[i1][0];
7828 Double_t ydel = pp[i2][1] - pp[i1][1];
7829 Double_t x[2], y[2];
7830 for (Int_t it = 0; it < nt; ++it) {
7831 x[0] = pp[i1][0] + xdel*tt[it][0];
7832 y[0] = pp[i1][1] + ydel*tt[it][0];
7833 x[1] = pp[i1][0] + xdel*tt[it][1];
7834 y[1] = pp[i1][1] + ydel*tt[it][1];
7835 gPad->PaintPolyLine(2, x, y);
7836 }
7837 i1 = 1;
7838 i2 = 3;
7839 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7840 xdel = pp[i2][0] - pp[i1][0];
7841 ydel = pp[i2][1] - pp[i1][1];
7842 for (Int_t it = 0; it < nt; ++it) {
7843 x[0] = pp[i1][0] + xdel*tt[it][0];
7844 y[0] = pp[i1][1] + ydel*tt[it][0];
7845 x[1] = pp[i1][0] + xdel*tt[it][1];
7846 y[1] = pp[i1][1] + ydel*tt[it][1];
7847 gPad->PaintPolyLine(2, x, y);
7848 }
7849 }
7850 fLego->FillPolygonBorder(4, &pp[0][0]); // update raster screen
7851 }
7852 }
7853 }
7854 }
7855
7856 // Draw frame box
7857 if (Hoption.BackBox) {
7858 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
7860 fLego->BackBox(90);
7861 }
7862
7863 if (Hoption.FrontBox) fLego->FrontBox(90);
7864
7865 // Draw axis and title
7866 if (!Hoption.Axis && !Hoption.Same) {
7867 TGaxis axis;
7868 PaintLegoAxis(&axis, 90);
7869 }
7870 PaintTitle();
7871
7872 //Draw stats and fit results
7873 TF1 *fit = nullptr;
7874 TIter next(fFunctions);
7875 while (auto obj = next()) {
7876 if (obj->InheritsFrom(TF1::Class())) {
7877 fit = (TF1*)obj;
7878 break;
7879 }
7880 }
7881 if ((Hoption.Same%10) != 1) {
7882 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7884 }
7885 }
7886
7887 fLego.reset();
7888}
7889
7890////////////////////////////////////////////////////////////////////////////////
7891/// [Control function to draw a 3D histogram with Iso Surfaces.](\ref HP25)
7892
7894{
7895
7896 const Double_t ydiff = 1;
7897 const Double_t yligh1 = 10;
7898 const Double_t qa = 0.15;
7899 const Double_t qd = 0.15;
7900 const Double_t qs = 0.8;
7901 Double_t fmin, fmax;
7902 Int_t i, irep;
7903 Int_t nbcol = 28;
7904 Int_t icol1 = 201;
7905 Int_t ic1 = icol1;
7906 Int_t ic2 = ic1+nbcol;
7907 Int_t ic3 = ic2+nbcol;
7908
7909 TAxis *xaxis = fH->GetXaxis();
7910 TAxis *yaxis = fH->GetYaxis();
7911 TAxis *zaxis = fH->GetZaxis();
7912
7913 Int_t nx = fH->GetNbinsX();
7914 Int_t ny = fH->GetNbinsY();
7915 Int_t nz = fH->GetNbinsZ();
7916
7917 std::vector<Double_t> x(nx);
7918 std::vector<Double_t> y(ny);
7919 std::vector<Double_t> z(nz);
7920
7921 for (i=0; i<nx; i++) x[i] = xaxis->GetBinCenter(i+1);
7922 for (i=0; i<ny; i++) y[i] = yaxis->GetBinCenter(i+1);
7923 for (i=0; i<nz; i++) z[i] = zaxis->GetBinCenter(i+1);
7924
7925 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7926 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7927 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7928 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7929 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7930 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7931
7932 Double_t s[3];
7933 s[0] = fH->GetSumOfWeights()/(fH->GetNbinsX()*fH->GetNbinsY()*fH->GetNbinsZ());
7934 s[1] = 0.5*s[0];
7935 s[2] = 1.5*s[0];
7936
7937 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7938
7939 TView *view = gPad ? gPad->GetView() : nullptr;
7940 if (!view) {
7941 Error("PaintH3Iso", "no TView in current pad");
7942 return;
7943 }
7944 Double_t thedeg = 90 - gPad->GetTheta();
7945 Double_t phideg = -90 - gPad->GetPhi();
7946 Double_t psideg = view->GetPsi();
7947 view->SetView(phideg, thedeg, psideg, irep);
7948
7949 Int_t backcolor = gPad->GetFrameFillColor();
7950 if (Hoption.System != kCARTESIAN) backcolor = 0;
7951 view->PadRange(backcolor);
7952
7953 Double_t dcol = 0.5/Double_t(nbcol);
7954 TColor *colref = gROOT->GetColor(fH->GetFillColor());
7955 if (!colref) {
7956 return;
7957 }
7958 Float_t r, g, b, hue, light, satur;
7959 colref->GetRGB(r,g,b);
7960 TColor::RGBtoHLS(r,g,b,hue,light,satur);
7961 TColor *acol;
7962 for (Int_t col=0;col<nbcol;col++) {
7963 acol = gROOT->GetColor(col+icol1);
7964 TColor::HLStoRGB(hue, .4+col*dcol, satur, r, g, b);
7965 if (acol) acol->SetRGB(r, g, b);
7966 }
7967
7968 fLego->InitMoveScreen(-1.1,1.1);
7969
7970 if (Hoption.BackBox) {
7971 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
7973 fLego->BackBox(90);
7974 }
7975
7976 fLego->LightSource(0, ydiff, 0, 0, 0, irep);
7977 fLego->LightSource(1, yligh1, 1, 1, 1, irep);
7978 fLego->SurfaceProperty(qa, qd, qs, 1, irep);
7979 fmin = ydiff*qa;
7980 fmax = ydiff*qa + (yligh1+0.1)*(qd+qs);
7981 fLego->SetIsoSurfaceParameters(fmin, fmax, nbcol, ic1, ic2, ic3);
7982
7983 fLego->IsoSurface(1, s, nx, ny, nz, x.data(), y.data(), z.data(), "BF");
7984
7985 if (Hoption.FrontBox) {
7986 fLego->InitMoveScreen(-1.1,1.1);
7988 fLego->FrontBox(90);
7989 }
7990 if (!Hoption.Axis && !Hoption.Same) {
7991 TGaxis axis;
7992 PaintLegoAxis(&axis, 90);
7993 }
7994
7995 PaintTitle();
7996
7997 //Draw stats and fit results
7998 TF1 *fit = nullptr;
7999 TIter next(fFunctions);
8000 while (auto obj = next()) {
8001 if (obj->InheritsFrom(TF1::Class())) {
8002 fit = (TF1*)obj;
8003 break;
8004 }
8005 }
8006 if ((Hoption.Same%10) != 1) {
8007 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
8009 }
8010 }
8011
8012 fLego.reset();
8013}
8014
8015////////////////////////////////////////////////////////////////////////////////
8016/// [Control function to draw a 2D histogram as a lego plot.](\ref HP17)
8017
8019{
8020
8021 Int_t raster = 1;
8022 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
8023 Int_t nx = Hparam.xlast - Hparam.xfirst + 1;
8024 Int_t ny = Hparam.ylast - Hparam.yfirst + 1;
8025 Double_t zmin = Hparam.zmin;
8026 Double_t zmax = Hparam.zmax;
8027 Double_t xlab1 = Hparam.xmin;
8028 Double_t xlab2 = Hparam.xmax;
8029 Double_t ylab1 = Hparam.ymin;
8030 Double_t ylab2 = Hparam.ymax;
8031 Double_t dangle = 10*3.141592/180; //Delta angle for Rapidity option
8032 Double_t deltaz = TMath::Abs(zmin);
8033 if (deltaz == 0) deltaz = 1;
8034 if (zmin >= zmax) {
8035 zmin -= 0.5*deltaz;
8036 zmax += 0.5*deltaz;
8037 }
8038 Double_t z1c = zmin;
8039 Double_t z2c = zmin + (zmax-zmin)*(1+gStyle->GetHistTopMargin());
8040
8041 // Compute the lego limits and instantiate a lego object
8042 fXbuf[0] = -1;
8043 fYbuf[0] = 1;
8044 fXbuf[1] = -1;
8045 fYbuf[1] = 1;
8046 if (Hoption.System == kPOLAR) {
8047 fXbuf[2] = z1c;
8048 fYbuf[2] = z2c;
8049 } else if (Hoption.System == kCYLINDRICAL) {
8050 if (Hoption.Logy) {
8051 if (ylab1 > 0) fXbuf[2] = TMath::Log10(ylab1);
8052 else fXbuf[2] = 0;
8053 if (ylab2 > 0) fYbuf[2] = TMath::Log10(ylab2);
8054 else fYbuf[2] = 0;
8055 } else {
8056 fXbuf[2] = ylab1;
8057 fYbuf[2] = ylab2;
8058 }
8059 z1c = 0; z2c = 1;
8060 } else if (Hoption.System == kSPHERICAL) {
8061 fXbuf[2] = -1;
8062 fYbuf[2] = 1;
8063 z1c = 0; z2c = 1;
8064 } else if (Hoption.System == kRAPIDITY) {
8065 fXbuf[2] = -1/TMath::Tan(dangle);
8066 fYbuf[2] = 1/TMath::Tan(dangle);
8067 } else {
8068 fXbuf[0] = xlab1;
8069 fYbuf[0] = xlab2;
8070 fXbuf[1] = ylab1;
8071 fYbuf[1] = ylab2;
8072 fXbuf[2] = z1c;
8073 fYbuf[2] = z2c;
8074 raster = 0;
8075 }
8076
8077 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data(), Hoption.System);
8078
8079 Int_t nids = -1;
8080 TH1 * hid = nullptr;
8081 Color_t colormain = -1, colordark = -1;
8082 Bool_t drawShadowsInLego1 = kTRUE;
8083
8084 // LEGO3 is like LEGO1 except that the black lines around each lego are not drawn.
8085 if (Hoption.Lego == 13) {
8086 Hoption.Lego = 11;
8087 fLego->SetMesh(0);
8088 }
8089 // LEGO4 is like LEGO1 except no shadows are drawn.
8090 if (Hoption.Lego == 14) {
8091 Hoption.Lego = 11;
8092 drawShadowsInLego1 = kFALSE;
8093 }
8094
8095 // Initialize the levels on the Z axis
8096 Int_t ndiv = fH->GetContour();
8097 if (ndiv == 0 ) {
8098 ndiv = gStyle->GetNumberContours();
8099 fH->SetContour(ndiv);
8100 }
8101 Int_t ndivz = TMath::Abs(ndiv);
8102 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
8103
8104 // Initialize colors
8105 if (!fStack) {
8106 fLego->SetEdgeAtt(fH->GetLineColor(),fH->GetLineStyle(),fH->GetLineWidth(),0);
8107 } else {
8108 for (Int_t id=0;id<=fStack->GetSize();id++) {
8109 hid = (TH1*)fStack->At((id==0)?id:id-1);
8110 fLego->SetEdgeAtt(hid->GetLineColor(),hid->GetLineStyle(),hid->GetLineWidth(),id);
8111 }
8112 }
8113
8114 if (Hoption.Lego == 11) {
8115 nids = 1;
8116 if (fStack) nids = fStack->GetSize();
8117 hid = fH;
8118 for (Int_t id=0;id<=nids;id++) {
8119 if (id > 0 && fStack) hid = (TH1*)fStack->At(id-1);
8120 colormain = hid->GetFillColor();
8121 if (colormain == 1) colormain = 17; //avoid drawing with black
8122 if (drawShadowsInLego1) colordark = TColor::GetColorDark(colormain);
8123 else colordark = colormain;
8124 fLego->SetColorMain(colormain,id);
8125 fLego->SetColorDark(colordark,id);
8126 if (id <= 1) fLego->SetColorMain(colormain,-1); // Set Bottom color
8127 if (id == nids) fLego->SetColorMain(colormain,99); // Set Top color
8128 }
8129 }
8130
8131 // Now ready to draw the lego plot
8132 Int_t irep = 0;
8133
8134 TView *view = gPad ? gPad->GetView() : nullptr;
8135 if (!view) {
8136 Error("PaintLego", "no TView in current pad");
8137 return;
8138 }
8139
8140 Double_t thedeg = 90 - gPad->GetTheta();
8141 Double_t phideg = -90 - gPad->GetPhi();
8142 Double_t psideg = view->GetPsi();
8143 view->SetView(phideg, thedeg, psideg, irep);
8144
8145 fLego->SetLineColor(kBlack); // zgrid color for lego1 & lego2
8146 fLego->SetFillStyle(fH->GetFillStyle());
8147
8148 // Set color/style for back box
8149 fLego->SetFillStyle(gPad->GetFrameFillStyle());
8150 fLego->SetFillColor(gPad->GetFrameFillColor());
8151 fLego->TAttFill::Modify();
8152
8153 Int_t backcolor = gPad->GetFrameFillColor();
8154 if (Hoption.System != kCARTESIAN) backcolor = 0;
8155 view->PadRange(backcolor);
8156
8157 fLego->SetFillStyle(fH->GetFillStyle());
8158 fLego->SetFillColor(fH->GetFillColor());
8159 fLego->TAttFill::Modify();
8160
8161 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
8162
8163 if (raster) fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
8164 else fLego->InitMoveScreen(-1.1,1.1);
8165
8166 if (Hoption.Lego == 19) {
8168 if (Hoption.BackBox) fLego->BackBox(90);
8169 if (Hoption.FrontBox) fLego->FrontBox(90);
8170 if (!Hoption.Axis) { TGaxis axis; PaintLegoAxis(&axis, 90); }
8171 return;
8172 }
8173
8174 if (Hoption.Lego == 11 || Hoption.Lego == 12) {
8177 fLego->BackBox(90);
8178 }
8179 }
8180
8181 if (Hoption.Lego == 12) DefineColorLevels(ndivz);
8182
8183 fLego->SetLegoFunction(&TPainter3dAlgorithms::LegoFunction);
8185 if (Hoption.Lego == 11) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode3);
8186 if (Hoption.Lego == 12) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode2);
8187 if (Hoption.System == kPOLAR) {
8188 if (Hoption.Lego == 1) fLego->LegoPolar(1,nx,ny,"FB");
8189 if (Hoption.Lego == 11) fLego->LegoPolar(1,nx,ny,"BF");
8190 if (Hoption.Lego == 12) fLego->LegoPolar(1,nx,ny,"BF");
8191 } else if (Hoption.System == kCYLINDRICAL) {
8192 if (Hoption.Lego == 1) fLego->LegoCylindrical(1,nx,ny,"FB");
8193 if (Hoption.Lego == 11) fLego->LegoCylindrical(1,nx,ny,"BF");
8194 if (Hoption.Lego == 12) fLego->LegoCylindrical(1,nx,ny,"BF");
8195 } else if (Hoption.System == kSPHERICAL) {
8196 if (Hoption.Lego == 1) fLego->LegoSpherical(0,1,nx,ny,"FB");
8197 if (Hoption.Lego == 11) fLego->LegoSpherical(0,1,nx,ny,"BF");
8198 if (Hoption.Lego == 12) fLego->LegoSpherical(0,1,nx,ny,"BF");
8199 } else if (Hoption.System == kRAPIDITY) {
8200 if (Hoption.Lego == 1) fLego->LegoSpherical(1,1,nx,ny,"FB");
8201 if (Hoption.Lego == 11) fLego->LegoSpherical(1,1,nx,ny,"BF");
8202 if (Hoption.Lego == 12) fLego->LegoSpherical(1,1,nx,ny,"BF");
8203 } else {
8204 if (Hoption.Lego == 1) {
8206 fLego->LegoCartesian(90,nx,ny,"FB");}
8207 if (Hoption.Lego == 11) fLego->LegoCartesian(90,nx,ny,"BF");
8208 if (Hoption.Lego == 12) fLego->LegoCartesian(90,nx,ny,"BF");
8209 }
8210
8211 if (Hoption.Lego == 1 || Hoption.Lego == 11) {
8214 fLego->BackBox(90);
8215 }
8216 }
8217 if (Hoption.System == kCARTESIAN) {
8218 fLego->InitMoveScreen(-1.1,1.1);
8220 if (Hoption.FrontBox) fLego->FrontBox(90);
8221 }
8222 if (!Hoption.Axis && !Hoption.Same) {
8223 TGaxis axis;
8224 PaintLegoAxis(&axis, 90);
8225 }
8227 fLego.reset();
8228}
8229
8230////////////////////////////////////////////////////////////////////////////////
8231/// Draw the axis for legos and surface plots.
8232
8234{
8235
8236 static Double_t epsil = 0.001;
8237
8238 Double_t cosa, sina;
8239 Double_t bmin, bmax;
8240 Double_t r[24] /* was [3][8] */;
8241 Int_t ndivx, ndivy, ndivz, i;
8242 Double_t x1[3], x2[3], y1[3], y2[3], z1[3], z2[3], av[24] /* was [3][8] */;
8243 static char chopax[8], chopay[8], chopaz[8];
8244 Int_t ix1, ix2, iy1, iy2, iz1, iz2;
8245 Double_t rad;
8246
8247 TView *view = gPad ? gPad->GetView() : nullptr;
8248 if (!view) {
8249 Error("PaintLegoAxis", "no TView in current pad");
8250 return;
8251 }
8252
8253 // In polar coordinates, draw a short line going from the external circle
8254 // corresponding to r = 1 up to r = 1.1
8255 if (Hoption.System == kPOLAR) {
8256 r[0] = 1;
8257 r[1] = 0;
8258 r[2] = 0;
8259 view->WCtoNDC(r, x1);
8260 r[0] = 1.1;
8261 r[1] = 0;
8262 r[2] = 0;
8263 view->WCtoNDC(r, x2);
8264 gPad->PaintLine(x1[0],x1[1],x2[0],x2[1]);
8265 return;
8266 }
8267
8268 if (Hoption.System != kCARTESIAN) return;
8269
8270 rad = TMath::ATan(1.) * 4. /180.;
8271 cosa = TMath::Cos(ang*rad);
8272 sina = TMath::Sin(ang*rad);
8273
8274 view->AxisVertex(ang, av, ix1, ix2, iy1, iy2, iz1, iz2);
8275 for (i = 1; i <= 8; ++i) {
8276 r[i*3 - 3] = av[i*3 - 3] + av[i*3 - 2]*cosa;
8277 r[i*3 - 2] = av[i*3 - 2]*sina;
8278 r[i*3 - 1] = av[i*3 - 1];
8279 }
8280
8281 view->WCtoNDC(&r[ix1*3 - 3], x1);
8282 view->WCtoNDC(&r[ix2*3 - 3], x2);
8283 view->WCtoNDC(&r[iy1*3 - 3], y1);
8284 view->WCtoNDC(&r[iy2*3 - 3], y2);
8285 view->WCtoNDC(&r[iz1*3 - 3], z1);
8286 view->WCtoNDC(&r[iz2*3 - 3], z2);
8287
8288 view->SetAxisNDC(x1, x2, y1, y2, z1, z2);
8289
8290 Double_t *rmin = view->GetRmin();
8291 Double_t *rmax = view->GetRmax();
8292 if (!rmin || !rmax) return;
8293
8294 // Initialize the axis options
8295 if (x1[0] > x2[0]) strlcpy(chopax, "SDH=+",8);
8296 else strlcpy(chopax, "SDH=-",8);
8297 if (y1[0] > y2[0]) strlcpy(chopay, "SDH=+",8);
8298 else strlcpy(chopay, "SDH=-",8);
8299 if (z2[1] > z1[1]) strlcpy(chopaz, "SDH=+",8);
8300 else strlcpy(chopaz, "SDH=-",8);
8301
8302 // Option LOG is required ?
8303 if (Hoption.Logx) strlcat(chopax,"G",8);
8304 if (Hoption.Logy) strlcat(chopay,"G",8);
8305 if (Hoption.Logz) strlcat(chopaz,"G",8);
8306
8307 // Initialize the number of divisions. If the
8308 // number of divisions is negative, option 'N' is required.
8309 ndivx = fXaxis->GetNdivisions();
8310 ndivy = fYaxis->GetNdivisions();
8311 ndivz = fZaxis->GetNdivisions();
8312 if (ndivx < 0) {
8313 ndivx = TMath::Abs(ndivx);
8314 strlcat(chopax, "N",8);
8315 }
8316 if (ndivy < 0) {
8317 ndivy = TMath::Abs(ndivy);
8318 strlcat(chopay, "N",8);
8319 }
8320 if (ndivz < 0) {
8321 ndivz = TMath::Abs(ndivz);
8322 strlcat(chopaz, "N",8);
8323 }
8324
8325 // Set Axis attributes.
8326 // The variable SCALE rescales the VSIZ
8327 // in order to have the same label size for all angles.
8328
8329 axis->SetLineWidth(1);
8330
8331 // X axis drawing
8332 if (TMath::Abs(x1[0] - x2[0]) >= epsil || TMath::Abs(x1[1] - x2[1]) > epsil) {
8335 if (Hoption.Logx && !fH->InheritsFrom(TH3::Class())) {
8336 bmin = TMath::Power(10, rmin[0]);
8337 bmax = TMath::Power(10, rmax[0]);
8338 } else {
8339 bmin = rmin[0];
8340 bmax = rmax[0];
8341 }
8342 // Option time display is required ?
8343 if (fXaxis->GetTimeDisplay()) {
8344 strlcat(chopax,"t",8);
8345 if (strlen(fXaxis->GetTimeFormatOnly()) == 0) {
8346 axis->SetTimeFormat(fXaxis->ChooseTimeFormat(bmax-bmin));
8347 } else {
8349 }
8350 }
8351 axis->SetOption(chopax);
8352 axis->PaintAxis(x1[0], x1[1], x2[0], x2[1], bmin, bmax, ndivx, chopax);
8353 }
8354
8355 // Y axis drawing
8356 if (TMath::Abs(y1[0] - y2[0]) >= epsil || TMath::Abs(y1[1] - y2[1]) > epsil) {
8359 if (fYaxis->GetTitleOffset() == 0) axis->SetTitleOffset(1.5);
8360
8361 if (fH->GetDimension() < 2) {
8362 strlcpy(chopay, "V=+UN",8);
8363 ndivy = 0;
8364 }
8365 if (TMath::Abs(y1[0] - y2[0]) < epsil) {
8366 y2[0] = y1[0];
8367 }
8368 if (Hoption.Logy && !fH->InheritsFrom(TH3::Class())) {
8369 bmin = TMath::Power(10, rmin[1]);
8370 bmax = TMath::Power(10, rmax[1]);
8371 } else {
8372 bmin = rmin[1];
8373 bmax = rmax[1];
8374 }
8375 // Option time display is required ?
8376 if (fYaxis->GetTimeDisplay()) {
8377 strlcat(chopay,"t",8);
8378 if (strlen(fYaxis->GetTimeFormatOnly()) == 0) {
8379 axis->SetTimeFormat(fYaxis->ChooseTimeFormat(bmax-bmin));
8380 } else {
8382 }
8383 }
8384 axis->SetOption(chopay);
8385 axis->PaintAxis(y1[0], y1[1], y2[0], y2[1], bmin, bmax, ndivy, chopay);
8386 }
8387
8388 // Z axis drawing
8389 if (TMath::Abs(z1[0] - z2[0]) >= 100*epsil || TMath::Abs(z1[1] - z2[1]) > 100*epsil) {
8391 if (Hoption.Logz && !fH->InheritsFrom(TH3::Class())) {
8392 bmin = TMath::Power(10, rmin[2]);
8393 bmax = TMath::Power(10, rmax[2]);
8394 } else {
8395 bmin = rmin[2];
8396 bmax = rmax[2];
8397 }
8398 // Option time display is required ?
8399 if (fZaxis->GetTimeDisplay()) {
8400 strlcat(chopaz,"t",8);
8401 if (strlen(fZaxis->GetTimeFormatOnly()) == 0) {
8402 axis->SetTimeFormat(fZaxis->ChooseTimeFormat(bmax-bmin));
8403 } else {
8405 }
8406 }
8407 axis->SetOption(chopaz);
8408 TString ztit = fZaxis->GetTitle();
8409 if (ztit.Index(";")>0) {
8410 ztit.Remove(ztit.Index(";"),ztit.Length());
8411 axis->SetTitle(ztit.Data());
8412 }
8413 axis->PaintAxis(z1[0], z1[1], z2[0], z2[1], bmin, bmax, ndivz, chopaz);
8414 }
8415
8416 //fH->SetLineStyle(1); /// otherwise fEdgeStyle[i] gets overwritten!
8417}
8418
8419////////////////////////////////////////////////////////////////////////////////
8420/// [Paint the color palette on the right side of the pad.](\ref HP22)
8421
8423{
8424 TPaletteAxis *palette = (TPaletteAxis*)fFunctions->FindObject("palette");
8425 TView *view = gPad ? gPad->GetView() : nullptr;
8426 if (palette) {
8427 if (view) {
8428 if (!palette->TestBit(TPaletteAxis::kHasView)) {
8429 fFunctions->Remove(palette);
8430 delete palette; palette = nullptr;
8431 }
8432 } else {
8433 if (palette->TestBit(TPaletteAxis::kHasView)) {
8434 fFunctions->Remove(palette);
8435 delete palette; palette = nullptr;
8436 }
8437 }
8438 // make sure the histogram member of the palette is setup correctly. It may not be after a Clone()
8439 if (palette && !palette->GetHistogram()) palette->SetHistogram(fH);
8440 }
8441
8442 if (!palette) {
8443 Double_t xup = gPad->GetUxmax();
8444 Double_t x2 = gPad->PadtoX(gPad->GetX2());
8445 Double_t ymin = gPad->PadtoY(gPad->GetUymin());
8446 Double_t ymax = gPad->PadtoY(gPad->GetUymax());
8447 Double_t xr = 0.05*(gPad->GetX2() - gPad->GetX1());
8448 Double_t xmin = gPad->PadtoX(xup +0.1*xr);
8449 Double_t xmax = gPad->PadtoX(xup + xr);
8450 if (xmax > x2) xmax = gPad->PadtoX(gPad->GetX2()-0.01*xr);
8451 palette = new TPaletteAxis(xmin,ymin,xmax,ymax,fH);
8452 fFunctions->AddFirst(palette);
8453 palette->Paint();
8454 }
8455}
8456
8457////////////////////////////////////////////////////////////////////////////////
8458/// [Control function to draw a 2D histogram as a scatter plot.](\ref HP11)
8459
8461{
8462
8463 fH->TAttMarker::Modify();
8464
8465 Int_t k, marker;
8466 Double_t dz, z, xk,xstep, yk, ystep;
8467 Double_t scale = 1;
8468 Bool_t ltest = kFALSE;
8469 Double_t zmax = fH->GetMaximum();
8470 Double_t zmin = fH->GetMinimum();
8471 if (zmin == 0 && zmax == 0) return;
8472 if (zmin == zmax) {
8473 zmax += 0.1*TMath::Abs(zmax);
8474 zmin -= 0.1*TMath::Abs(zmin);
8475 }
8477 if (Hoption.Logz) {
8478 if (zmin > 0) zmin = TMath::Log10(zmin);
8479 else zmin = 0;
8480 if (zmax > 0) zmax = TMath::Log10(zmax);
8481 else zmax = 0;
8482 if (zmin == 0 && zmax == 0) return;
8483 dz = zmax - zmin;
8484 scale = 100/dz;
8485 if (ncells > 10000) scale /= 5;
8486 ltest = kTRUE;
8487 } else {
8488 dz = zmax - zmin;
8489 if (dz >= kNMAX || zmax < 1) {
8490 scale = (kNMAX-1)/dz;
8491 if (ncells > 10000) scale /= 5;
8492 ltest = kTRUE;
8493 }
8494 }
8495 if (fH->GetMinimumStored() == -1111) {
8496 Double_t yMARGIN = gStyle->GetHistTopMargin();
8497 if (Hoption.MinimumZero) {
8498 if (zmin >= 0) zmin = 0;
8499 else zmin -= yMARGIN*(zmax-zmin);
8500 } else {
8501 Double_t dzmin = yMARGIN*(zmax-zmin);
8502 if (zmin >= 0 && (zmin-dzmin <= 0)) zmin = 0;
8503 else zmin -= dzmin;
8504 }
8505 }
8506
8507 TString opt = option;
8508 opt.ToLower();
8509 if (opt.Contains("scat=")) {
8510 char optscat[100];
8511 strlcpy(optscat,opt.Data(),100);
8512 char *oscat = strstr(optscat,"scat=");
8513 char *blank = strstr(oscat," "); if (blank) *blank = 0;
8514 sscanf(oscat+5,"%lg",&scale);
8515 }
8516 // use an independent instance of a random generator
8517 // instead of gRandom to avoid conflicts and
8518 // to get same random numbers when drawing the same histogram
8519 TRandom2 random;
8520 marker=0;
8521 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
8522 yk = fYaxis->GetBinLowEdge(j);
8523 ystep = fYaxis->GetBinWidth(j);
8524 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
8525 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
8526 xk = fXaxis->GetBinLowEdge(i);
8527 xstep = fXaxis->GetBinWidth(i);
8528 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
8529 z = fH->GetBinContent(bin);
8530 if (z < zmin) z = zmin;
8531 if (z > zmax) z = zmax;
8532 if (Hoption.Logz) {
8533 if (z > 0) z = TMath::Log10(z) - zmin;
8534 } else {
8535 z -= zmin;
8536 }
8537 if (z <= 0) continue;
8538 k = Int_t(z*scale);
8539 if (ltest) k++;
8540 if (k > 0) {
8541 for (Int_t loop=0; loop<k; loop++) {
8542 if (k+marker >= kNMAX) {
8543 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
8544 marker=0;
8545 }
8546 fXbuf[marker] = (random.Rndm()*xstep) + xk;
8547 fYbuf[marker] = (random.Rndm()*ystep) + yk;
8548 if (Hoption.Logx) {
8549 if (fXbuf[marker] > 0) fXbuf[marker] = TMath::Log10(fXbuf[marker]);
8550 else break;
8551 }
8552 if (Hoption.Logy) {
8553 if (fYbuf[marker] > 0) fYbuf[marker] = TMath::Log10(fYbuf[marker]);
8554 else break;
8555 }
8556 if (fXbuf[marker] < gPad->GetUxmin()) break;
8557 if (fYbuf[marker] < gPad->GetUymin()) break;
8558 if (fXbuf[marker] > gPad->GetUxmax()) break;
8559 if (fYbuf[marker] > gPad->GetUymax()) break;
8560 marker++;
8561 }
8562 }
8563 }
8564 }
8565 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
8566
8568}
8569
8570////////////////////////////////////////////////////////////////////////////////
8571/// Static function to paint special objects like vectors and matrices.
8572/// This function is called via `gROOT->ProcessLine` to paint these objects
8573/// without having a direct dependency of the graphics or histogramming
8574/// system.
8575
8577{
8578
8579 if (!obj) return;
8582
8583 if (obj->InheritsFrom(TMatrixFBase::Class())) {
8584 // case TMatrixF
8585 TH2F *R__TMatrixFBase = new TH2F((TMatrixFBase &)*obj);
8586 R__TMatrixFBase->SetBit(kCanDelete);
8587 R__TMatrixFBase->Draw(option);
8588
8589 } else if (obj->InheritsFrom(TMatrixDBase::Class())) {
8590 // case TMatrixD
8591 TH2D *R__TMatrixDBase = new TH2D((TMatrixDBase &)*obj);
8592 R__TMatrixDBase->SetBit(kCanDelete);
8593 R__TMatrixDBase->Draw(option);
8594
8595 } else if (obj->InheritsFrom(TVectorF::Class())) {
8596 //case TVectorF
8597 TH1F *R__TVectorF = new TH1F((TVectorF &)*obj);
8598 R__TVectorF->SetBit(kCanDelete);
8599 R__TVectorF->Draw(option);
8600
8601 } else if (obj->InheritsFrom(TVectorD::Class())) {
8602 //case TVectorD
8603 TH1D *R__TVectorD = new TH1D((TVectorD &)*obj);
8604 R__TVectorD->SetBit(kCanDelete);
8605 R__TVectorD->Draw(option);
8606 }
8607
8608 TH1::AddDirectory(status);
8609}
8610
8611////////////////////////////////////////////////////////////////////////////////
8612/// [Draw the statistics box for 1D and profile histograms.](\ref HP07)
8613
8615{
8616 TString tt, tf;
8617 Int_t dofit;
8618 TPaveStats *stats = nullptr;
8619 TIter next(fFunctions);
8620 while (auto obj = next()) {
8621 if (obj->InheritsFrom(TPaveStats::Class())) {
8622 stats = (TPaveStats*)obj;
8623 break;
8624 }
8625 }
8626
8627 if (stats && dostat) {
8628 dofit = stats->GetOptFit();
8629 dostat = stats->GetOptStat();
8630 } else {
8631 dofit = gStyle->GetOptFit();
8632 }
8633 if (!dofit) fit = nullptr;
8634 if (dofit == 1) dofit = 111;
8635 if (dostat == 1) dostat = 1111;
8636 Int_t print_name = dostat%10;
8637 Int_t print_entries = (dostat/10)%10;
8638 Int_t print_mean = (dostat/100)%10;
8639 Int_t print_stddev = (dostat/1000)%10;
8640 Int_t print_under = (dostat/10000)%10;
8641 Int_t print_over = (dostat/100000)%10;
8642 Int_t print_integral= (dostat/1000000)%10;
8643 Int_t print_skew = (dostat/10000000)%10;
8644 Int_t print_kurt = (dostat/100000000)%10;
8645 Int_t nlines = print_name + print_entries + print_mean + print_stddev +
8646 print_under + print_over + print_integral +
8647 print_skew + print_kurt;
8648 Int_t print_fval = dofit%10;
8649 Int_t print_ferrors = (dofit/10)%10;
8650 Int_t print_fchi2 = (dofit/100)%10;
8651 Int_t print_fprob = (dofit/1000)%10;
8652 Int_t nlinesf = print_fval + print_fchi2 + print_fprob;
8653 if (fit) {
8654 if (print_fval < 2) nlinesf += fit->GetNumberFreeParameters();
8655 else nlinesf += fit->GetNpar();
8656 }
8657 if (fH->InheritsFrom(TProfile::Class())) nlinesf += print_mean + print_stddev;
8658
8659 // Pavetext with statistics
8660 Bool_t done = kFALSE;
8661 if (!dostat && !fit) {
8662 if (stats) { fFunctions->Remove(stats); delete stats;}
8663 return;
8664 }
8665 Double_t statw = gStyle->GetStatW();
8666 if (fit) statw = 1.8*gStyle->GetStatW();
8667 Double_t stath = (nlines+nlinesf)*gStyle->GetStatFontSize();
8668 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
8669 stath = 0.25*(nlines+nlinesf)*gStyle->GetStatH();
8670 }
8671 if (stats) {
8672 stats->Clear();
8673 done = kTRUE;
8674 } else {
8675 stats = new TPaveStats(
8676 gStyle->GetStatX()-statw,
8677 gStyle->GetStatY()-stath,
8678 gStyle->GetStatX(),
8679 gStyle->GetStatY(),"brNDC");
8680
8681 stats->SetParent(fH);
8682 stats->SetOptFit(dofit);
8683 stats->SetOptStat(dostat);
8684 stats->SetFillColor(gStyle->GetStatColor());
8685 stats->SetFillStyle(gStyle->GetStatStyle());
8687 stats->SetTextFont(gStyle->GetStatFont());
8688 if (gStyle->GetStatFont()%10 > 2)
8690 stats->SetFitFormat(gStyle->GetFitFormat());
8692 stats->SetName("stats");
8693
8695 stats->SetTextAlign(12);
8696 stats->SetBit(kCanDelete);
8697 stats->SetBit(kMustCleanup);
8698 }
8699 if (print_name) stats->AddText(fH->GetName());
8700 if (print_entries) {
8701 if (fH->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(fH->GetEntries()+0.5));
8702 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(fH->GetEntries()));
8703 stats->AddText(tt.Data());
8704 }
8705 if (print_mean) {
8706 if (print_mean == 1) {
8707 tf.Form("%s = %s%s",gStringMean.Data(),"%",stats->GetStatFormat());
8708 tt.Form(tf.Data(),fH->GetMean(1));
8709 } else {
8710 tf.Form("%s = %s%s #pm %s%s",gStringMean.Data(),"%",stats->GetStatFormat()
8711 ,"%",stats->GetStatFormat());
8712 tt.Form(tf.Data(),fH->GetMean(1),fH->GetMeanError(1));
8713 }
8714 stats->AddText(tt.Data());
8716 if (print_mean == 1) {
8717 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
8718 tt.Form(tf.Data(),fH->GetMean(2));
8719 } else {
8720 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
8721 ,"%",stats->GetStatFormat());
8722 tt.Form(tf.Data(),fH->GetMean(2),fH->GetMeanError(2));
8723 }
8724 stats->AddText(tt.Data());
8725 }
8726 }
8727 if (print_stddev) {
8728 if (print_stddev == 1) {
8729 tf.Form("%s = %s%s",gStringStdDev.Data(),"%",stats->GetStatFormat());
8730 tt.Form(tf.Data(),fH->GetStdDev(1));
8731 } else {
8732 tf.Form("%s = %s%s #pm %s%s",gStringStdDev.Data(),"%",stats->GetStatFormat()
8733 ,"%",stats->GetStatFormat());
8734 tt.Form(tf.Data(),fH->GetStdDev(1),fH->GetStdDevError(1));
8735 }
8736 stats->AddText(tt.Data());
8738 if (print_stddev == 1) {
8739 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
8740 tt.Form(tf.Data(),fH->GetStdDev(2));
8741 } else {
8742 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
8743 ,"%",stats->GetStatFormat());
8744 tt.Form(tf.Data(),fH->GetStdDev(2),fH->GetStdDevError(2));
8745 }
8746 stats->AddText(tt.Data());
8747 }
8748 }
8749 if (print_under) {
8750 tf.Form("%s = %s%s",gStringUnderflow.Data(),"%",stats->GetStatFormat());
8751 tt.Form(tf.Data(),fH->GetBinContent(0));
8752 stats->AddText(tt.Data());
8753 }
8754 if (print_over) {
8755 tf.Form("%s = %s%s",gStringOverflow.Data(),"%",stats->GetStatFormat());
8756 tt.Form(tf.Data(),fH->GetBinContent(fXaxis->GetNbins()+1));
8757 stats->AddText(tt.Data());
8758 }
8759 if (print_integral) {
8760 if (print_integral == 1) {
8761 tf.Form("%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
8762 tt.Form(tf.Data(),fH->Integral());
8763 } else {
8764 tf.Form("%s = %s%s",gStringIntegralBinWidth.Data(),"%",stats->GetStatFormat());
8765 tt.Form(tf.Data(),fH->Integral("width"));
8766 }
8767 stats->AddText(tt.Data());
8768 }
8769 if (print_skew) {
8770 if (print_skew == 1) {
8771 tf.Form("%s = %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat());
8772 tt.Form(tf.Data(),fH->GetSkewness(1));
8773 } else {
8774 tf.Form("%s = %s%s #pm %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat()
8775 ,"%",stats->GetStatFormat());
8776 tt.Form(tf.Data(),fH->GetSkewness(1),fH->GetSkewness(11));
8777 }
8778 stats->AddText(tt.Data());
8779 }
8780 if (print_kurt) {
8781 if (print_kurt == 1) {
8782 tf.Form("%s = %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat());
8783 tt.Form(tf.Data(),fH->GetKurtosis(1));
8784 } else {
8785 tf.Form("%s = %s%s #pm %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat()
8786 ,"%",stats->GetStatFormat());
8787 tt.Form(tf.Data(),fH->GetKurtosis(1),fH->GetKurtosis(11));
8788 }
8789 stats->AddText(tt.Data());
8790 }
8791
8792 // Draw Fit parameters
8793 if (fit) {
8794 Int_t ndf = fit->GetNDF();
8795 tf.Form("#chi^{2} / ndf = %s%s / %d","%",stats->GetFitFormat(),ndf);
8796 tt.Form(tf.Data(),fit->GetChisquare());
8797 if (print_fchi2) stats->AddText(tt.Data());
8798 if (print_fprob) {
8799 tf.Form("Prob = %s%s","%",stats->GetFitFormat());
8800 tt.Form(tf.Data(),TMath::Prob(fit->GetChisquare(),ndf));
8801 stats->AddText(tt.Data());
8802 }
8803 if (print_fval || print_ferrors) {
8804 Double_t parmin,parmax;
8805 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
8806 fit->GetParLimits(ipar,parmin,parmax);
8807 if (print_fval < 2 && parmin*parmax != 0 && parmin >= parmax) continue;
8808 if (print_ferrors) {
8809 tf.Form("%-8s = %s%s #pm %s ", fit->GetParName(ipar), "%",stats->GetFitFormat(),
8810 GetBestFormat(fit->GetParameter(ipar), fit->GetParError(ipar), stats->GetFitFormat()));
8811 tt.Form(tf.Data(),fit->GetParameter(ipar)
8812 ,fit->GetParError(ipar));
8813 } else {
8814 tf.Form("%-8s = %s%s ",fit->GetParName(ipar), "%",stats->GetFitFormat());
8815 tt.Form(tf.Data(),fit->GetParameter(ipar));
8816 }
8817 stats->AddText(tt.Data());
8818 }
8819 }
8820 }
8821
8822 if (!done) fFunctions->Add(stats);
8823 stats->Paint();
8824}
8825
8826////////////////////////////////////////////////////////////////////////////////
8827/// [Draw the statistics box for 2D histograms.](\ref HP07)
8828
8830{
8831
8832 if (fH->GetDimension() != 2) return;
8833 TH2 *h2 = (TH2*)fH;
8834
8835 TString tt, tf;
8836 Int_t dofit;
8837 TPaveStats *stats = nullptr;
8838 TIter next(fFunctions);
8839 while (auto obj = next()) {
8840 if (obj->InheritsFrom(TPaveStats::Class())) {
8841 stats = (TPaveStats*)obj;
8842 break;
8843 }
8844 }
8845 if (stats && dostat) {
8846 dofit = stats->GetOptFit();
8847 dostat = stats->GetOptStat();
8848 } else {
8849 dofit = gStyle->GetOptFit();
8850 }
8851 if (dostat == 1) dostat = 1111;
8852 Int_t print_name = dostat%10;
8853 Int_t print_entries = (dostat/10)%10;
8854 Int_t print_mean = (dostat/100)%10;
8855 Int_t print_stddev = (dostat/1000)%10;
8856 Int_t print_under = (dostat/10000)%10;
8857 Int_t print_over = (dostat/100000)%10;
8858 Int_t print_integral= (dostat/1000000)%10;
8859 Int_t print_skew = (dostat/10000000)%10;
8860 Int_t print_kurt = (dostat/100000000)%10;
8861 Int_t nlines = print_name + print_entries + 2*print_mean + 2*print_stddev + print_integral;
8862 if (print_under || print_over) nlines += 3;
8863
8864 // Pavetext with statistics
8865 if (!gStyle->GetOptFit()) fit = nullptr;
8866 Bool_t done = kFALSE;
8867 if (!dostat && !fit) {
8868 if (stats) { fFunctions->Remove(stats); delete stats;}
8869 return;
8870 }
8871 Double_t statw = gStyle->GetStatW();
8872 if (fit) statw = 1.8*gStyle->GetStatW();
8873 Double_t stath = nlines*gStyle->GetStatFontSize();
8874 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
8875 stath = 0.25*nlines*gStyle->GetStatH();
8876 }
8877 if (fit) stath += gStyle->GetStatH();
8878 if (stats) {
8879 stats->Clear();
8880 done = kTRUE;
8881 } else {
8882 stats = new TPaveStats(
8883 gStyle->GetStatX()-statw,
8884 gStyle->GetStatY()-stath,
8885 gStyle->GetStatX(),
8886 gStyle->GetStatY(),"brNDC");
8887
8888 stats->SetParent(fH);
8889 stats->SetOptFit(dofit);
8890 stats->SetOptStat(dostat);
8891 stats->SetFillColor(gStyle->GetStatColor());
8892 stats->SetFillStyle(gStyle->GetStatStyle());
8894 stats->SetName("stats");
8895
8897 stats->SetTextAlign(12);
8898 stats->SetTextFont(gStyle->GetStatFont());
8899 if (gStyle->GetStatFont()%10 > 2)
8901 stats->SetFitFormat(gStyle->GetFitFormat());
8903 stats->SetBit(kCanDelete);
8904 stats->SetBit(kMustCleanup);
8905 }
8906 if (print_name) stats->AddText(h2->GetName());
8907 if (print_entries) {
8908 if (h2->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(h2->GetEntries()+0.5));
8909 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(h2->GetEntries()));
8910 stats->AddText(tt.Data());
8911 }
8912 if (print_mean) {
8913 if (print_mean == 1) {
8914 tf.Form("%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
8915 tt.Form(tf.Data(),h2->GetMean(1));
8916 stats->AddText(tt.Data());
8917 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
8918 tt.Form(tf.Data(),h2->GetMean(2));
8919 stats->AddText(tt.Data());
8920 } else {
8921 tf.Form("%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
8922 ,"%",stats->GetStatFormat());
8923 tt.Form(tf.Data(),h2->GetMean(1),h2->GetMeanError(1));
8924 stats->AddText(tt.Data());
8925 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
8926 ,"%",stats->GetStatFormat());
8927 tt.Form(tf.Data(),h2->GetMean(2),h2->GetMeanError(2));
8928 stats->AddText(tt.Data());
8929 }
8930 }
8931 if (print_stddev) {
8932 if (print_stddev == 1) {
8933 tf.Form("%s = %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat());
8934 tt.Form(tf.Data(),h2->GetStdDev(1));
8935 stats->AddText(tt.Data());
8936 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
8937 tt.Form(tf.Data(),h2->GetStdDev(2));
8938 stats->AddText(tt.Data());
8939 } else {
8940 tf.Form("%s = %s%s #pm %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat()
8941 ,"%",stats->GetStatFormat());
8942 tt.Form(tf.Data(),h2->GetStdDev(1),h2->GetStdDevError(1));
8943 stats->AddText(tt.Data());
8944 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
8945 ,"%",stats->GetStatFormat());
8946 tt.Form(tf.Data(),h2->GetStdDev(2),h2->GetStdDevError(2));
8947 stats->AddText(tt.Data());
8948 }
8949 }
8950 if (print_integral) {
8951 tf.Form("%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
8952 tt.Form(tf.Data(),fH->Integral());
8953 stats->AddText(tt.Data());
8954 }
8955 if (print_skew) {
8956 if (print_skew == 1) {
8957 tf.Form("%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
8958 tt.Form(tf.Data(),h2->GetSkewness(1));
8959 stats->AddText(tt.Data());
8960 tf.Form("%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
8961 tt.Form(tf.Data(),h2->GetSkewness(2));
8962 stats->AddText(tt.Data());
8963 } else {
8964 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
8965 ,"%",stats->GetStatFormat());
8966 tt.Form(tf.Data(),h2->GetSkewness(1),h2->GetSkewness(11));
8967 stats->AddText(tt.Data());
8968 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
8969 ,"%",stats->GetStatFormat());
8970 tt.Form(tf.Data(),h2->GetSkewness(2),h2->GetSkewness(12));
8971 stats->AddText(tt.Data());
8972 }
8973 }
8974 if (print_kurt) {
8975 if (print_kurt == 1) {
8976 tf.Form("%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
8977 tt.Form(tf.Data(),h2->GetKurtosis(1));
8978 stats->AddText(tt.Data());
8979 tf.Form("%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
8980 tt.Form(tf.Data(),h2->GetKurtosis(2));
8981 stats->AddText(tt.Data());
8982 } else {
8983 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
8984 ,"%",stats->GetStatFormat());
8985 tt.Form(tf.Data(),h2->GetKurtosis(1),h2->GetKurtosis(11));
8986 stats->AddText(tt.Data());
8987 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
8988 ,"%",stats->GetStatFormat());
8989 tt.Form(tf.Data(),h2->GetKurtosis(2),h2->GetKurtosis(12));
8990 stats->AddText(tt.Data());
8991 }
8992 }
8993 if (print_under || print_over) {
8994 //get 3*3 under/overflows for 2d hist
8995 Double_t unov[9];
8996
8997 Int_t cellsX = h2->GetXaxis()->GetNbins() + 1;
8998 Int_t cellsY = h2->GetYaxis()->GetNbins() + 1;
8999 Int_t firstX = std::max(1, h2->GetXaxis()->GetFirst());
9000 Int_t firstY = std::max(1, h2->GetYaxis()->GetFirst());
9001 Int_t lastX = std::min(h2->GetXaxis()->GetLast(), h2->GetXaxis()->GetNbins());
9002 Int_t lastY = std::min(h2->GetYaxis()->GetLast(), h2->GetYaxis()->GetNbins());
9003
9004 unov[0] = h2->Integral( 0, firstX-1, lastY+1, cellsY );
9005 unov[1] = h2->Integral(firstX , lastX , lastY+1, cellsY );
9006 unov[2] = h2->Integral(lastX+1, cellsX , lastY+1, cellsY );
9007 unov[3] = h2->Integral( 0, firstX-1, firstY , lastY );
9008 unov[4] = h2->Integral(firstX , lastX , firstY , lastY );
9009 unov[5] = h2->Integral(lastX+1, cellsX , firstY , lastY );
9010 unov[6] = h2->Integral( 0, firstX-1, 0, firstY-1);
9011 unov[7] = h2->Integral(firstX, lastX, 0, firstY-1);
9012 unov[8] = h2->Integral(lastX+1, cellsX , 0, firstY-1);
9013
9014 tt.Form("%g|%g|%g\n", unov[0], unov[1], unov[2]);
9015 stats->AddText(tt.Data());
9016 tt.Form("%g|%g|%g\n", unov[3], unov[4], unov[5]);
9017 stats->AddText(tt.Data());
9018 tt.Form("%g|%g|%g\n", unov[6], unov[7], unov[8]);
9019 stats->AddText(tt.Data());
9020 }
9021
9022 // Draw Fit parameters
9023 if (fit) {
9024 Int_t ndf = fit->GetNDF();
9025 tt.Form("#chi^{2} / ndf = %6.4g / %d",fit->GetChisquare(),ndf);
9026 stats->AddText(tt.Data());
9027 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
9028 tt.Form("%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
9029 ,fit->GetParameter(ipar)
9030 ,fit->GetParError(ipar));
9031 stats->AddText(tt.Data());
9032 }
9033 }
9034
9035 if (!done) fFunctions->Add(stats);
9036 stats->Paint();
9037}
9038
9039////////////////////////////////////////////////////////////////////////////////
9040/// [Draw the statistics box for 3D histograms.](\ref HP07)
9041
9043{
9044
9045 if (fH->GetDimension() != 3) return;
9046 TH3 *h3 = (TH3*)fH;
9047
9048 TString tt, tf;
9049 Int_t dofit;
9050 TPaveStats *stats = nullptr;
9051 TIter next(fFunctions);
9052 while (auto obj = next()) {
9053 if (obj->InheritsFrom(TPaveStats::Class())) {
9054 stats = (TPaveStats*)obj;
9055 break;
9056 }
9057 }
9058 if (stats && dostat) {
9059 dofit = stats->GetOptFit();
9060 dostat = stats->GetOptStat();
9061 } else {
9062 dofit = gStyle->GetOptFit();
9063 }
9064 if (dostat == 1) dostat = 1111;
9065 Int_t print_name = dostat%10;
9066 Int_t print_entries = (dostat/10)%10;
9067 Int_t print_mean = (dostat/100)%10;
9068 Int_t print_stddev = (dostat/1000)%10;
9069 Int_t print_under = (dostat/10000)%10;
9070 Int_t print_over = (dostat/100000)%10;
9071 Int_t print_integral= (dostat/1000000)%10;
9072 Int_t print_skew = (dostat/10000000)%10;
9073 Int_t print_kurt = (dostat/100000000)%10;
9074 Int_t nlines = print_name + print_entries + 3*print_mean + 3*print_stddev + print_integral;
9075 if (print_under || print_over) nlines += 3;
9076
9077 // Pavetext with statistics
9078 if (!gStyle->GetOptFit()) fit = nullptr;
9079 Bool_t done = kFALSE;
9080 if (!dostat && !fit) {
9081 if (stats) { fFunctions->Remove(stats); delete stats;}
9082 return;
9083 }
9084 Double_t statw = gStyle->GetStatW();
9085 if (fit) statw = 1.8*gStyle->GetStatW();
9086 Double_t stath = nlines*gStyle->GetStatFontSize();
9087 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
9088 stath = 0.25*nlines*gStyle->GetStatH();
9089 }
9090 if (fit) stath += gStyle->GetStatH();
9091 if (stats) {
9092 stats->Clear();
9093 done = kTRUE;
9094 } else {
9095 stats = new TPaveStats(
9096 gStyle->GetStatX()-statw,
9097 gStyle->GetStatY()-stath,
9098 gStyle->GetStatX(),
9099 gStyle->GetStatY(),"brNDC");
9100
9101 stats->SetParent(fH);
9102 stats->SetOptFit(dofit);
9103 stats->SetOptStat(dostat);
9104 stats->SetFillColor(gStyle->GetStatColor());
9105 stats->SetFillStyle(gStyle->GetStatStyle());
9107 stats->SetName("stats");
9108
9110 stats->SetTextAlign(12);
9111 stats->SetTextFont(gStyle->GetStatFont());
9112 stats->SetFitFormat(gStyle->GetFitFormat());
9114 stats->SetBit(kCanDelete);
9115 stats->SetBit(kMustCleanup);
9116 }
9117 if (print_name) stats->AddText(h3->GetName());
9118 if (print_entries) {
9119 if (h3->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(h3->GetEntries()+0.5));
9120 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(h3->GetEntries()+0.5));
9121 stats->AddText(tt.Data());
9122 }
9123 if (print_mean) {
9124 if (print_mean == 1) {
9125 tf.Form("%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
9126 tt.Form(tf.Data(),h3->GetMean(1));
9127 stats->AddText(tt.Data());
9128 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
9129 tt.Form(tf.Data(),h3->GetMean(2));
9130 stats->AddText(tt.Data());
9131 tf.Form("%s = %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat());
9132 tt.Form(tf.Data(),h3->GetMean(3));
9133 stats->AddText(tt.Data());
9134 } else {
9135 tf.Form("%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
9136 ,"%",stats->GetStatFormat());
9137 tt.Form(tf.Data(),h3->GetMean(1),h3->GetMeanError(1));
9138 stats->AddText(tt.Data());
9139 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
9140 ,"%",stats->GetStatFormat());
9141 tt.Form(tf.Data(),h3->GetMean(2),h3->GetMeanError(2));
9142 stats->AddText(tt.Data());
9143 tf.Form("%s = %s%s #pm %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat()
9144 ,"%",stats->GetStatFormat());
9145 tt.Form(tf.Data(),h3->GetMean(3),h3->GetMeanError(3));
9146 stats->AddText(tt.Data());
9147 }
9148 }
9149 if (print_stddev) {
9150 if (print_stddev == 1) {
9151 tf.Form("%s = %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat());
9152 tt.Form(tf.Data(),h3->GetStdDev(1));
9153 stats->AddText(tt.Data());
9154 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
9155 tt.Form(tf.Data(),h3->GetStdDev(2));
9156 stats->AddText(tt.Data());
9157 tf.Form("%s = %s%s",gStringStdDevZ.Data(),"%",stats->GetStatFormat());
9158 tt.Form(tf.Data(),h3->GetStdDev(3));
9159 stats->AddText(tt.Data());
9160 } else {
9161 tf.Form("%s = %s%s #pm %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat()
9162 ,"%",stats->GetStatFormat());
9163 tt.Form(tf.Data(),h3->GetStdDev(1),h3->GetStdDevError(1));
9164 stats->AddText(tt.Data());
9165 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
9166 ,"%",stats->GetStatFormat());
9167 tt.Form(tf.Data(),h3->GetStdDev(2),h3->GetStdDevError(2));
9168 stats->AddText(tt.Data());
9169 tf.Form("%s = %s%s #pm %s%s",gStringStdDevZ.Data(),"%",stats->GetStatFormat()
9170 ,"%",stats->GetStatFormat());
9171 tt.Form(tf.Data(),h3->GetStdDev(3),h3->GetStdDevError(3));
9172 stats->AddText(tt.Data());
9173 }
9174 }
9175 if (print_integral) {
9176 tt.Form("%s = %6.4g",gStringIntegral.Data(),h3->Integral());
9177 stats->AddText(tt.Data());
9178 }
9179 if (print_skew) {
9180 if (print_skew == 1) {
9181 tf.Form("%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
9182 tt.Form(tf.Data(),h3->GetSkewness(1));
9183 stats->AddText(tt.Data());
9184 tf.Form("%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
9185 tt.Form(tf.Data(),h3->GetSkewness(2));
9186 stats->AddText(tt.Data());
9187 tf.Form("%s = %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat());
9188 tt.Form(tf.Data(),h3->GetSkewness(3));
9189 stats->AddText(tt.Data());
9190 } else {
9191 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
9192 ,"%",stats->GetStatFormat());
9193 tt.Form(tf.Data(),h3->GetSkewness(1),h3->GetSkewness(11));
9194 stats->AddText(tt.Data());
9195 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
9196 ,"%",stats->GetStatFormat());
9197 tt.Form(tf.Data(),h3->GetSkewness(2),h3->GetSkewness(12));
9198 stats->AddText(tt.Data());
9199 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat()
9200 ,"%",stats->GetStatFormat());
9201 tt.Form(tf.Data(),h3->GetSkewness(3),h3->GetSkewness(13));
9202 stats->AddText(tt.Data());
9203 }
9204 }
9205 if (print_kurt) {
9206 if (print_kurt == 1) {
9207 tf.Form("%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
9208 tt.Form(tf.Data(),h3->GetKurtosis(1));
9209 stats->AddText(tt.Data());
9210 tf.Form("%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
9211 tt.Form(tf.Data(),h3->GetKurtosis(2));
9212 stats->AddText(tt.Data());
9213 tf.Form("%s = %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat());
9214 tt.Form(tf.Data(),h3->GetKurtosis(3));
9215 stats->AddText(tt.Data());
9216 } else {
9217 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
9218 ,"%",stats->GetStatFormat());
9219 tt.Form(tf.Data(),h3->GetKurtosis(1),h3->GetKurtosis(11));
9220 stats->AddText(tt.Data());
9221 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
9222 ,"%",stats->GetStatFormat());
9223 tt.Form(tf.Data(),h3->GetKurtosis(2),h3->GetKurtosis(12));
9224 stats->AddText(tt.Data());
9225 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat()
9226 ,"%",stats->GetStatFormat());
9227 tt.Form(tf.Data(),h3->GetKurtosis(3),h3->GetKurtosis(13));
9228 stats->AddText(tt.Data());
9229 }
9230 }
9231 if (print_under || print_over) {
9232 // no underflow - overflow printing for a 3D histogram
9233 // one would need a 3D table
9234 }
9235
9236 // Draw Fit parameters
9237 if (fit) {
9238 Int_t ndf = fit->GetNDF();
9239 tt.Form("#chi^{2} / ndf = %6.4g / %d",fit->GetChisquare(),ndf);
9240 stats->AddText(tt.Data());
9241 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
9242 tt.Form("%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
9243 ,fit->GetParameter(ipar)
9244 ,fit->GetParError(ipar));
9245 stats->AddText(tt.Data());
9246 }
9247 }
9248
9249 if (!done) fFunctions->Add(stats);
9250 stats->Paint();
9251}
9252
9253////////////////////////////////////////////////////////////////////////////////
9254/// [Control function to draw a 2D histogram as a surface plot.](\ref HP18)
9255
9257{
9258
9259 const Double_t ydiff = 1;
9260 const Double_t yligh1 = 10;
9261 const Double_t qa = 0.15;
9262 const Double_t qd = 0.15;
9263 const Double_t qs = 0.8;
9264 Double_t fmin, fmax;
9265 Int_t raster = 0;
9266 Int_t irep = 0;
9267
9268 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
9271 Double_t zmin = Hparam.zmin;
9272 Double_t zmax = Hparam.zmax;
9273 Double_t xlab1 = Hparam.xmin;
9274 Double_t xlab2 = Hparam.xmax;
9275 Double_t ylab1 = Hparam.ymin;
9276 Double_t ylab2 = Hparam.ymax;
9277 Double_t dangle = 10*3.141592/180; //Delta angle for Rapidity option
9278 Double_t deltaz = TMath::Abs(zmin);
9279 if (deltaz == 0) deltaz = 1;
9280 if (zmin >= zmax) {
9281 zmin -= 0.5*deltaz;
9282 zmax += 0.5*deltaz;
9283 }
9284 Double_t z1c = zmin;
9285 Double_t z2c = zmin + (zmax-zmin)*(1+gStyle->GetHistTopMargin());
9286 // Compute the lego limits and instantiate a lego object
9287 fXbuf[0] = -1;
9288 fYbuf[0] = 1;
9289 fXbuf[1] = -1;
9290 fYbuf[1] = 1;
9291 if (Hoption.System >= kPOLAR && (Hoption.Surf == 1 || Hoption.Surf == 13)) raster = 1;
9292 if (Hoption.System == kPOLAR) {
9293 fXbuf[2] = z1c;
9294 fYbuf[2] = z2c;
9295 } else if (Hoption.System == kCYLINDRICAL) {
9296 if (Hoption.Logy) {
9297 if (ylab1 > 0) fXbuf[2] = TMath::Log10(ylab1);
9298 else fXbuf[2] = 0;
9299 if (ylab2 > 0) fYbuf[2] = TMath::Log10(ylab2);
9300 else fYbuf[2] = 0;
9301 } else {
9302 fXbuf[2] = ylab1;
9303 fYbuf[2] = ylab2;
9304 }
9305 z1c = 0; z2c = 1;
9306 } else if (Hoption.System == kSPHERICAL) {
9307 fXbuf[2] = -1;
9308 fYbuf[2] = 1;
9309 z1c = 0; z2c = 1;
9310 } else if (Hoption.System == kRAPIDITY) {
9311 fXbuf[2] = -1/TMath::Tan(dangle);
9312 fYbuf[2] = 1/TMath::Tan(dangle);
9313 } else {
9314 fXbuf[0] = xlab1;
9315 fYbuf[0] = xlab2;
9316 fXbuf[1] = ylab1;
9317 fYbuf[1] = ylab2;
9318 fXbuf[2] = z1c;
9319 fYbuf[2] = z2c;
9320 }
9321
9322 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data(), Hoption.System);
9323 fLego->SetEdgeAtt(fH->GetLineColor(),fH->GetLineStyle(),fH->GetLineWidth(),0);
9324 fLego->SetFillColor(fH->GetFillColor());
9325
9326 // Initialize the levels on the Z axis
9327 Int_t ndiv = fH->GetContour();
9328 if (ndiv == 0 ) {
9329 ndiv = gStyle->GetNumberContours();
9330 fH->SetContour(ndiv);
9331 }
9332 Int_t ndivz = TMath::Abs(ndiv);
9333 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
9334
9335 if (Hoption.Surf == 13 || Hoption.Surf == 15) fLego->SetMesh(3);
9336 if (Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) fLego->SetMesh(0);
9337
9338 // Close the surface in case of non cartesian coordinates.
9339
9340 if (Hoption.System != kCARTESIAN) {nx++; ny++;}
9341
9342 // Now ready to draw the surface plot
9343
9344 TView *view = gPad ? gPad->GetView() : nullptr;
9345 if (!view) {
9346 Error("PaintSurface", "no TView in current pad");
9347 return;
9348 }
9349
9350 Double_t thedeg = 90 - gPad->GetTheta();
9351 Double_t phideg = -90 - gPad->GetPhi();
9352 Double_t psideg = view->GetPsi();
9353 view->SetView(phideg, thedeg, psideg, irep);
9354
9355 // Set color/style for back box
9356 if (Hoption.Same) {
9357 fLego->SetFillStyle(0);
9358 fLego->SetFillColor(1);
9359 } else {
9360 fLego->SetFillStyle(gPad->GetFrameFillStyle());
9361 fLego->SetFillColor(gPad->GetFrameFillColor());
9362 }
9363 fLego->TAttFill::Modify();
9364
9365 Int_t backcolor = gPad->GetFrameFillColor();
9366 if (Hoption.System != kCARTESIAN) backcolor = 0;
9367 view->PadRange(backcolor);
9368
9369 fLego->SetFillStyle(fH->GetFillStyle());
9370 fLego->SetFillColor(fH->GetFillColor());
9371 fLego->TAttFill::Modify();
9372
9373 // Draw the filled contour on top
9374 Int_t icol1 = fH->GetFillColor();
9375
9376 Int_t hoption35 = Hoption.Surf;
9377 if (Hoption.Surf == 13 || Hoption.Surf == 15) {
9378 DefineColorLevels(ndivz);
9379 Hoption.Surf = 23;
9380 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9382 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"BF");
9383 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9384 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9385 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9386 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"BF");
9387 Hoption.Surf = hoption35;
9388 fLego->SetMesh(1);
9389 }
9390
9391 if (raster) fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
9392 else fLego->InitMoveScreen(-1.1,1.1);
9393
9394 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) {
9395 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9398 fLego->BackBox(90);
9399 }
9400 }
9401
9402 // Gouraud Shading surface
9403 if (Hoption.Surf == 14) {
9404 // Set light sources
9405 fLego->LightSource(0, ydiff, 0,0,0,irep);
9406 fLego->LightSource(1, yligh1 ,1,1,1,irep);
9407 fLego->SurfaceProperty(qa, qd, qs, 1, irep);
9408 fmin = ydiff*qa;
9409 fmax = fmin + (yligh1+0.1)*(qd+qs);
9410 Int_t nbcol = 28;
9411 icol1 = 201;
9412 Double_t dcol = 0.5/Double_t(nbcol);
9413 TColor *colref = gROOT->GetColor(fH->GetFillColor());
9414 if (!colref) return;
9415 Float_t r,g,b,hue,light,satur;
9416 colref->GetRGB(r,g,b);
9417 TColor::RGBtoHLS(r,g,b,hue,light,satur);
9418 TColor *acol;
9419 for (Int_t col=0;col<nbcol;col++) {
9420 acol = gROOT->GetColor(col+icol1);
9421 TColor::HLStoRGB(hue,.4+col*dcol,satur,r,g,b);
9422 if (acol) acol->SetRGB(r,g,b);
9423 }
9424 fLego->Spectrum(nbcol, fmin, fmax, icol1, 1, irep);
9425 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::GouraudFunction);
9427 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"BF");
9428 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9429 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9430 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9431 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"BF");
9432 } else if (Hoption.Surf == 15) {
9433 // The surface is not drawn in this case.
9434 } else {
9435 // Draw the surface
9436 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 16 || Hoption.Surf == 17) {
9437 DefineColorLevels(ndivz);
9438 } else {
9439 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9440 }
9441 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9442 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceRaster1);
9443 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode2);
9444 if (Hoption.System == kPOLAR) {
9445 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfacePolar(1,nx,ny,"FB");
9446 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfacePolar(1,nx,ny,"BF");
9447 } else if (Hoption.System == kCYLINDRICAL) {
9448 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceCylindrical(1,nx,ny,"FB");
9449 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9450 } else if (Hoption.System == kSPHERICAL) {
9451 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceSpherical(0,1,nx,ny,"FB");
9452 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9453 } else if (Hoption.System == kRAPIDITY) {
9454 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceSpherical(1,1,nx,ny,"FB");
9455 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9456 } else {
9457 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove1);
9458 if (Hoption.Surf == 16) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove3);
9459 if (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16) fLego->SurfaceCartesian(90,nx,ny,"FB");
9460 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCartesian(90,nx,ny,"BF");
9461 }
9462 }
9463
9464 // Paint the line contour on top for option SURF7
9465 if (Hoption.Surf == 17) {
9466 fLego->InitMoveScreen(-1.1,1.1);
9467 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9468 Hoption.Surf = 23;
9469 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9471 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"FB");
9472 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"FB");
9473 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"FB");
9474 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"FB");
9475 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"FB");
9476 }
9477
9478 if ((!Hoption.Same) &&
9479 (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16)) {
9482 fLego->BackBox(90);
9483 }
9484 }
9485 if (Hoption.System == kCARTESIAN) {
9486 fLego->InitMoveScreen(-1.1,1.1);
9488 if (Hoption.FrontBox) fLego->FrontBox(90);
9489 }
9490 if (!Hoption.Axis && !Hoption.Same) {
9491 TGaxis axis;
9492 PaintLegoAxis(&axis, 90);
9493 }
9494
9496
9497 fLego.reset();
9498}
9499
9500////////////////////////////////////////////////////////////////////////////////
9501/// Control function to draw a table using Delaunay triangles.
9502
9504{
9505
9506 TGraphDelaunay2D *dt = nullptr;
9507 TGraphDelaunay *dtOld = nullptr;
9508
9509 // Check if fH contains a TGraphDelaunay2D
9510 TList *hl = fH->GetListOfFunctions();
9511 dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
9512 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
9513 if (!dt && !dtOld) return;
9514
9515 // If needed, create a TGraph2DPainter
9516 if (!fGraph2DPainter)
9517 fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
9518
9519 // Define the 3D view
9520 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
9521 if (Hoption.Same) {
9522 TView *viewsame = gPad ? gPad->GetView() : nullptr;
9523 if (!viewsame) {
9524 Error("PaintTriangles", "no TView in current pad, do not use option SAME");
9525 return;
9526 }
9527 Double_t *rmin = viewsame->GetRmin();
9528 Double_t *rmax = viewsame->GetRmax();
9529 if (!rmin || !rmax) return;
9530 fXbuf[0] = rmin[0];
9531 fYbuf[0] = rmax[0];
9532 fXbuf[1] = rmin[1];
9533 fYbuf[1] = rmax[1];
9534 fXbuf[2] = rmin[2];
9535 fYbuf[2] = rmax[2];
9536 fH->SetMaximum(rmax[2]);
9537 fH->SetMinimum(rmin[2]);
9538 fH->GetXaxis()->SetRangeUser(rmin[0],rmax[0]);
9539 fH->GetYaxis()->SetRangeUser(rmin[1],rmax[1]);
9540 } else {
9541 fXbuf[0] = Hparam.xmin;
9542 fYbuf[0] = Hparam.xmax;
9543 fXbuf[1] = Hparam.ymin;
9544 fYbuf[1] = Hparam.ymax;
9545 fXbuf[2] = Hparam.zmin;
9546 fYbuf[2] = Hparam.zmax;
9547 }
9548
9549 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
9550 TView *view = gPad ? gPad->GetView() : nullptr;
9551 if (!view) {
9552 Error("PaintTriangles", "no TView in current pad");
9553 return;
9554 }
9555 Double_t thedeg = 90 - gPad->GetTheta();
9556 Double_t phideg = -90 - gPad->GetPhi();
9557 Double_t psideg = view->GetPsi();
9558 Int_t irep;
9559 view->SetView(phideg, thedeg, psideg, irep);
9560
9561 // Set color/style for back box
9562 fLego->SetFillStyle(gPad->GetFrameFillStyle());
9563 fLego->SetFillColor(gPad->GetFrameFillColor());
9564 fLego->TAttFill::Modify();
9565 Int_t backcolor = gPad->GetFrameFillColor();
9566 if (Hoption.System != kCARTESIAN) backcolor = 0;
9567 view->PadRange(backcolor);
9568 fLego->SetFillStyle(fH->GetFillStyle());
9569 fLego->SetFillColor(fH->GetFillColor());
9570 fLego->TAttFill::Modify();
9571
9572 // Paint the Back Box if needed
9573 if (Hoption.BackBox && !Hoption.Same) {
9574 fLego->InitMoveScreen(-1.1,1.1);
9575 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9577 fLego->BackBox(90);
9578 }
9579
9580 // Paint the triangles
9581 fGraph2DPainter->Paint(option);
9582
9583 // Paint the Front Box if needed
9584 if (Hoption.FrontBox) {
9585 fLego->InitMoveScreen(-1.1,1.1);
9587 fLego->FrontBox(90);
9588 }
9589
9590 // Paint the Axis if needed
9591 if (!Hoption.Axis && !Hoption.Same) {
9592 TGaxis axis;
9593 PaintLegoAxis(&axis, 90);
9594 }
9595
9597
9598 fLego.reset();
9599}
9600
9601////////////////////////////////////////////////////////////////////////////////
9602/// Define the color levels used to paint legos, surfaces etc..
9603
9605{
9606
9607 Int_t i, irep;
9608
9609 // Initialize the color levels
9610 if (ndivz >= 100) {
9611 Warning("PaintSurface", "too many color levels, %d >= 100, reset to 99", ndivz);
9612 ndivz = 99;
9613 }
9614 std::vector<Double_t> funlevel(ndivz+1);
9615 std::vector<Int_t> colorlevel(ndivz+1);
9616 Int_t theColor;
9617 Int_t ncolors = gStyle->GetNumberOfColors();
9618 for (i = 0; i < ndivz; ++i) {
9619 funlevel[i] = fH->GetContourLevelPad(i);
9620 theColor = Int_t((i+0.99)*Float_t(ncolors)/Float_t(ndivz));
9621 colorlevel[i] = gStyle->GetColorPalette(theColor);
9622 }
9623 colorlevel[ndivz] = gStyle->GetColorPalette(ncolors-1);
9624 fLego->ColorFunction(ndivz, funlevel.data(), colorlevel.data(), irep);
9625}
9626
9627////////////////////////////////////////////////////////////////////////////////
9628/// [Control function to draw 2D/3D histograms (tables).](\ref HP01c)
9629
9631{
9632
9633 // Fill Hparam structure with histo parameters
9634 if (!TableInit()) return;
9635
9636 // Draw histogram frame
9637 PaintFrame();
9638
9639 // If palette option not specified, delete a possible existing palette
9640 if (!Hoption.Zscale) {
9641 TObject *palette = fFunctions->FindObject("palette");
9642 if (palette) { fFunctions->Remove(palette); delete palette;}
9643 }
9644
9645 // Do not draw the histogram. Only the attached functions will be drawn.
9646 if (Hoption.Func == 2) {
9647 if (Hoption.Zscale) {
9648 Int_t ndiv = fH->GetContour();
9649 if (ndiv == 0 ) {
9650 ndiv = gStyle->GetNumberContours();
9651 fH->SetContour(ndiv);
9652 }
9653 PaintPalette();
9654 }
9655
9656 // Draw the histogram according to the option
9657 } else {
9658 if (fH->InheritsFrom(TH2Poly::Class()) && Hoption.Axis<=0) {
9659 if (Hoption.Fill) PaintTH2PolyBins("f");
9663 if (Hoption.Line) PaintTH2PolyBins("l");
9664 if (Hoption.Mark) PaintTH2PolyBins("P");
9665 } else if (fH->GetEntries() != 0 && Hoption.Axis<=0) {
9669 if (Hoption.Color) {
9672 }
9675 if (Hoption.Error >= 100) Paint2DErrors(option);
9677 }
9681 }
9682
9683 // Draw histogram title
9684 PaintTitle();
9685
9686 // Draw the axes
9687 if (!Hoption.Lego && !Hoption.Surf &&
9688 !Hoption.Tri && !(Hoption.Error >= 100)) PaintAxis(kFALSE);
9689
9690 TF1 *fit = nullptr;
9691 TIter next(fFunctions);
9692 while (auto obj = next()) {
9693 if (obj->InheritsFrom(TF1::Class())) {
9694 fit = (TF1*)obj;
9695 break;
9696 }
9697 }
9698 if ((Hoption.Same%10) != 1) {
9699 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
9700 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
9701 //ALWAYS executed on non-iOS platform.
9702 //On iOS, depends on mode.
9704 }
9705 }
9706 }
9707}
9708
9709////////////////////////////////////////////////////////////////////////////////
9710/// Control function to draw a TH2Poly bins' contours.
9711///
9712/// - option = "F" draw the bins as filled areas.
9713/// - option = "L" draw the bins as line.
9714/// - option = "P" draw the bins as markers.
9715
9717{
9718
9719 //Do not highlight the histogram, if its part was picked.
9720 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH) return;
9721
9722 TString opt = option;
9723 opt.ToLower();
9724 Bool_t line = kFALSE;
9725 Bool_t fill = kFALSE;
9726 Bool_t mark = kFALSE;
9727 if (opt.Contains("l")) line = kTRUE;
9728 if (opt.Contains("f")) fill = kTRUE;
9729 if (opt.Contains("p")) mark = kTRUE;
9730
9731 TH2PolyBin *b;
9732 Double_t z;
9733
9734 TIter next(((TH2Poly*)fH)->GetBins());
9735 TObject *obj, *poly;
9736
9737 while ((obj=next())) {
9738 b = (TH2PolyBin*)obj;
9739 z = b->GetContent();
9740 if (z==0 && Hoption.Zero) continue; // Do not draw empty bins in case of option "COL0 L"
9741 poly = b->GetPolygon();
9742
9743 // Paint the TGraph bins.
9744 if (poly->IsA() == TGraph::Class()) {
9745 TGraph *g = (TGraph*)poly;
9746 g->TAttLine::Modify();
9747 g->TAttMarker::Modify();
9748 g->TAttFill::Modify();
9749 if (line) {
9750 Int_t fs = g->GetFillStyle();
9751 Int_t db = gStyle->GetDrawBorder();
9752 g->SetFillStyle(0);
9754 g->Paint("F");
9755 gStyle->SetDrawBorder(db);
9756 g->SetFillStyle(fs);
9757 }
9758 if (fill) g->Paint("F");
9759 if (mark) g->Paint("P");
9760 }
9761
9762 // Paint the TMultiGraph bins.
9763 if (poly->IsA() == TMultiGraph::Class()) {
9764 TMultiGraph *mg = (TMultiGraph*)poly;
9765 TList *gl = mg->GetListOfGraphs();
9766 if (!gl) return;
9767 TGraph *g;
9768 TIter nextg(gl);
9769 while ((g = (TGraph*) nextg())) {
9770 g->TAttLine::Modify();
9771 g->TAttMarker::Modify();
9772 g->TAttFill::Modify();
9773 if (line) {
9774 Int_t fs = g->GetFillStyle();
9775 Int_t db = gStyle->GetDrawBorder();
9776 g->SetFillStyle(0);
9778 g->Paint("F");
9779 gStyle->SetDrawBorder(db);
9780 g->SetFillStyle(fs);
9781 }
9782 if (fill) g->Paint("F");
9783 if (mark) g->Paint("P");
9784 }
9785 }
9786 }
9787}
9788
9789////////////////////////////////////////////////////////////////////////////////
9790/// [Control function to draw a TH2Poly as a color plot.](\ref HP20a)
9791
9793{
9794
9795 //Do not highlight the histogram, if its part was picked.
9796 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
9797 return;
9798
9799 Int_t ncolors, color, theColor;
9800 Double_t z, zc;
9801 Double_t zmin = fH->GetMinimum();
9802 Double_t zmax = fH->GetMaximum();
9803 if (Hoption.Logz) {
9804 if (zmax > 0) {
9805 if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
9806 zmin = TMath::Log10(zmin);
9807 zmax = TMath::Log10(zmax);
9808 } else {
9809 return;
9810 }
9811 }
9812 Double_t dz = zmax - zmin;
9813
9814 // Initialize the levels on the Z axis
9815 ncolors = gStyle->GetNumberOfColors();
9816 Int_t ndiv = fH->GetContour();
9817 if (ndiv == 0 ) {
9818 ndiv = gStyle->GetNumberContours();
9819 fH->SetContour(ndiv);
9820 }
9821 Int_t ndivz = TMath::Abs(ndiv);
9822 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
9823 Double_t scale = ndivz/dz;
9824
9825 TIter next(((TH2Poly*)fH)->GetBins());
9826
9827 while (auto obj = next()) {
9828 TH2PolyBin *b = (TH2PolyBin*)obj;
9829 TObject *poly = b->GetPolygon();
9830
9831 z = b->GetContent();
9832 if (z==0 && Hoption.Zero) continue;
9833 if (Hoption.Logz) {
9834 if (z > 0) z = TMath::Log10(z);
9835 else z = zmin;
9836 }
9837 if (z < zmin) continue;
9838
9839 // Define the bin color.
9841 zc = fH->GetContourLevelPad(0);
9842 if (z < zc) continue;
9843 color = -1;
9844 for (Int_t k=0; k<ndiv; k++) {
9845 zc = fH->GetContourLevelPad(k);
9846 if (z < zc) {
9847 continue;
9848 } else {
9849 color++;
9850 }
9851 }
9852 } else {
9853 color = Int_t(0.01+(z-zmin)*scale);
9854 }
9855 theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
9856 if (theColor > ncolors-1) theColor = ncolors-1;
9857
9858 // Paint the TGraph bins.
9859 if (poly->IsA() == TGraph::Class()) {
9860 TGraph *g = (TGraph*)poly;
9861 g->SetFillColor(gStyle->GetColorPalette(theColor));
9862 g->TAttFill::Modify();
9863 g->Paint("F");
9864 }
9865
9866 // Paint the TMultiGraph bins.
9867 if (poly->IsA() == TMultiGraph::Class()) {
9868 TMultiGraph *mg = (TMultiGraph*)poly;
9869 TList *gl = mg->GetListOfGraphs();
9870 if (!gl) return;
9871 TGraph *g;
9872 TIter nextg(gl);
9873 while ((g = (TGraph*) nextg())) {
9874 g->SetFillColor(gStyle->GetColorPalette(theColor));
9875 g->TAttFill::Modify();
9876 g->Paint("F");
9877 }
9878 }
9879 }
9881}
9882
9883////////////////////////////////////////////////////////////////////////////////
9884/// [Control function to draw a TH2Poly as a scatter plot.](\ref HP20a)
9885
9887{
9888
9889 //Do not highlight the histogram, if its part was selected.
9890 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
9891 return;
9892
9893 Int_t k, loop, marker=0;
9894 Double_t z, xk,xstep, yk, ystep, xp, yp;
9895 Double_t scale = 1;
9896 Double_t zmin = fH->GetMinimum();
9897 Double_t zmax = fH->GetMaximum();
9898 if (Hoption.Logz) {
9899 if (zmax > 0) {
9900 if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
9901 zmin = TMath::Log10(zmin);
9902 zmax = TMath::Log10(zmax);
9903 } else {
9904 return;
9905 }
9906 }
9907 Double_t dz = zmax - zmin;
9908 scale = (kNMAX-1)/dz;
9909
9910
9911 // use an independent instance of a random generator
9912 // instead of gRandom to avoid conflicts and
9913 // to get same random numbers when drawing the same histogram
9914 TRandom2 random;
9915
9916 TH2PolyBin *b;
9917
9918 TIter next(((TH2Poly*)fH)->GetBins());
9919 TObject *obj, *poly;
9920
9921 Double_t maxarea = 0, a;
9922 while ((obj=next())) {
9923 b = (TH2PolyBin*)obj;
9924 a = b->GetArea();
9925 if (a>maxarea) maxarea = a;
9926 }
9927
9928 next.Reset();
9929
9930 while ((obj=next())) {
9931 b = (TH2PolyBin*)obj;
9932 poly = b->GetPolygon();
9933 z = b->GetContent();
9934 if (z < zmin) z = zmin;
9935 if (z > zmax) z = zmax;
9936 if (Hoption.Logz) {
9937 if (z > 0) z = TMath::Log10(z) - zmin;
9938 } else {
9939 z -= zmin;
9940 }
9941 k = Int_t((z*scale)*(b->GetArea()/maxarea));
9942 xk = b->GetXMin();
9943 yk = b->GetYMin();
9944 xstep = b->GetXMax()-xk;
9945 ystep = b->GetYMax()-yk;
9946
9947 // Paint the TGraph bins.
9948 if (poly->IsA() == TGraph::Class()) {
9949 TGraph *g = (TGraph*)poly;
9950 if (k <= 0 || z <= 0) continue;
9951 loop = 0;
9952 while (loop<k) {
9953 if (k+marker >= kNMAX) {
9954 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
9955 marker=0;
9956 }
9957 xp = (random.Rndm()*xstep) + xk;
9958 yp = (random.Rndm()*ystep) + yk;
9959 if (g->IsInside(xp,yp)) {
9960 fXbuf[marker] = xp;
9961 fYbuf[marker] = yp;
9962 marker++;
9963 loop++;
9964 }
9965 }
9966 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
9967 }
9968
9969 // Paint the TMultiGraph bins.
9970 if (poly->IsA() == TMultiGraph::Class()) {
9971 TMultiGraph *mg = (TMultiGraph*)poly;
9972 TList *gl = mg->GetListOfGraphs();
9973 if (!gl) return;
9974 if (k <= 0 || z <= 0) continue;
9975 loop = 0;
9976 while (loop<k) {
9977 if (k+marker >= kNMAX) {
9978 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
9979 marker=0;
9980 }
9981 xp = (random.Rndm()*xstep) + xk;
9982 yp = (random.Rndm()*ystep) + yk;
9983 if (mg->IsInside(xp,yp)) {
9984 fXbuf[marker] = xp;
9985 fYbuf[marker] = yp;
9986 marker++;
9987 loop++;
9988 }
9989 }
9990 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
9991 }
9992 }
9993 PaintTH2PolyBins("l");
9994}
9995
9996////////////////////////////////////////////////////////////////////////////////
9997/// [Control function to draw a TH2Poly as a text plot.](\ref HP20a)
9998
10000{
10001
10002 TLatex text;
10003 text.SetTextFont(gStyle->GetTextFont());
10004 text.SetTextColor(fH->GetMarkerColor());
10005 text.SetTextSize(0.02*fH->GetMarkerSize());
10006
10007 Double_t x, y, z, e, angle = 0;
10008 TString tt, tf;
10009 tf.Form("%s%s","%",gStyle->GetPaintTextFormat());
10010 if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
10011 Int_t opt = (Int_t)Hoption.Text/1000;
10012
10013 text.SetTextAlign(22);
10014 if (Hoption.Text == 1) angle = 0;
10015 text.SetTextAngle(angle);
10016 text.TAttText::Modify();
10017
10018 TH2PolyBin *b;
10019
10020 TIter next(((TH2Poly*)fH)->GetBins());
10021 TObject *obj, *p;
10022
10023 while ((obj=next())) {
10024 b = (TH2PolyBin*)obj;
10025 p = b->GetPolygon();
10026 x = (b->GetXMin()+b->GetXMax())/2;
10027 if (Hoption.Logx) {
10028 if (x > 0) x = TMath::Log10(x);
10029 else continue;
10030 }
10031 y = (b->GetYMin()+b->GetYMax())/2;
10032 if (Hoption.Logy) {
10033 if (y > 0) y = TMath::Log10(y);
10034 else continue;
10035 }
10036 z = b->GetContent();
10037 if (z < fH->GetMinimum() || (z == 0 && !Hoption.MinimumZero)) continue;
10038 if (opt==2) {
10039 e = fH->GetBinError(b->GetBinNumber());
10040 tf.Form("#splitline{%s%s}{#pm %s%s}",
10042 "%",gStyle->GetPaintTextFormat());
10043 tt.Form(tf.Data(),z,e);
10044 } else {
10045 tt.Form(tf.Data(),z);
10046 }
10047 if (opt==3) text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),p->GetName());
10048 else text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),tt.Data());
10049 }
10050
10051 PaintTH2PolyBins("l");
10052}
10053
10054////////////////////////////////////////////////////////////////////////////////
10055/// [Control function to draw a 1D/2D histograms with the bin values.](\ref HP15)
10056
10058{
10059
10060 TLatex text;
10061 text.SetTextFont(gStyle->GetTextFont());
10062 text.SetTextColor(fH->GetMarkerColor());
10063 text.SetTextSize(0.02*fH->GetMarkerSize());
10064
10065 Double_t x, y, z, e, angle = 0;
10066 TString tt, tf;
10067 tf.Form("%s%s","%",gStyle->GetPaintTextFormat());
10068 if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
10069
10070 // 1D histograms
10071 if (fH->GetDimension() == 1) {
10072 Bool_t getentries = kFALSE;
10073 Double_t yt;
10074 TProfile *hp = (TProfile*)fH;
10075 if (Hoption.Text>2000 && fH->InheritsFrom(TProfile::Class())) {
10076 Hoption.Text = Hoption.Text-2000;
10077 getentries = kTRUE;
10078 }
10079 if (Hoption.Text == 1) angle = 90;
10080 text.SetTextAlign(11);
10081 if (angle == 90) text.SetTextAlign(12);
10082 if (angle == 0) text.SetTextAlign(21);
10083 text.TAttText::Modify();
10084 Double_t dt = 0.02*(gPad->GetY2()-gPad->GetY1());
10085 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10086 if (Hoption.Bar) {
10087 x = fH->GetXaxis()->GetBinLowEdge(i)+
10088 fH->GetXaxis()->GetBinWidth(i)*
10089 (fH->GetBarOffset()+0.5*fH->GetBarWidth());
10090 } else {
10091 x = fH->GetXaxis()->GetBinCenter(i);
10092 }
10093 y = fH->GetBinContent(i);
10094 yt = y;
10095 if (Hoption.MinimumZero && y<0) y = 0;
10096 if (getentries) yt = hp->GetBinEntries(i);
10097 if (yt == 0.) continue;
10098 tt.Form(tf.Data(),yt);
10099 if (Hoption.Logx) {
10100 if (x > 0) x = TMath::Log10(x);
10101 else continue;
10102 }
10103 if (Hoption.Logy) {
10104 if (y > 0) y = TMath::Log10(y);
10105 else continue;
10106 }
10107 if (y >= gPad->GetY2()) continue;
10108 if (y <= gPad->GetY1()) continue;
10109 text.PaintLatex(x,y+0.2*dt,angle,0.02*fH->GetMarkerSize(),tt.Data());
10110 }
10111
10112 // 2D histograms
10113 } else {
10114 text.SetTextAlign(22);
10115 if (Hoption.Text == 1) angle = 0;
10116 text.SetTextAngle(angle);
10117 text.TAttText::Modify();
10118 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
10119 y = fYaxis->GetBinCenter(j);
10120 if (Hoption.Logy) {
10121 if (y > 0) y = TMath::Log10(y);
10122 else continue;
10123 }
10124 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10125 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
10126 x = fXaxis->GetBinCenter(i);
10127 if (Hoption.Logx) {
10128 if (x > 0) x = TMath::Log10(x);
10129 else continue;
10130 }
10131 if (!IsInside(x,y)) continue;
10132 z = fH->GetBinContent(bin);
10133 if (z < Hparam.zmin || (z == 0 && !Hoption.MinimumZero)) continue;
10134 if (Hoption.Text>2000) {
10135 e = fH->GetBinError(bin);
10136 tf.Form("#splitline{%s%s}{#pm %s%s}",
10138 "%",gStyle->GetPaintTextFormat());
10139 tt.Form(tf.Data(),z,e);
10140 } else {
10141 tt.Form(tf.Data(),z);
10142 }
10143 text.PaintLatex(x,y+fH->GetBarOffset()*fYaxis->GetBinWidth(j),
10144 angle,0.02*fH->GetMarkerSize(),tt.Data());
10145 }
10146 }
10147 }
10148}
10149
10150////////////////////////////////////////////////////////////////////////////////
10151/// [Control function to draw a 3D implicit functions.](\ref HP27)
10152
10154{
10155
10156 Int_t irep;
10157
10158 TAxis *xaxis = fH->GetXaxis();
10159 TAxis *yaxis = fH->GetYaxis();
10160 TAxis *zaxis = fH->GetZaxis();
10161
10162 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
10163 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
10164 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
10165 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
10166 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
10167 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
10168
10169 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
10170
10171 TView *view = gPad ? gPad->GetView() : nullptr;
10172 if (!view) {
10173 Error("PaintTF3", "no TView in current pad");
10174 return;
10175 }
10176 Double_t thedeg = 90 - gPad->GetTheta();
10177 Double_t phideg = -90 - gPad->GetPhi();
10178 Double_t psideg = view->GetPsi();
10179 view->SetView(phideg, thedeg, psideg, irep);
10180
10181 fLego->InitMoveScreen(-1.1,1.1);
10182
10183 if (Hoption.BackBox) {
10184 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
10186 fLego->BackBox(90);
10187 }
10188
10190
10191 fLego->ImplicitFunction(fCurrentF3, fXbuf.data(), fYbuf.data(), fH->GetNbinsX(),
10192 fH->GetNbinsY(),
10193 fH->GetNbinsZ(), "BF");
10194
10195 if (Hoption.FrontBox) {
10196 fLego->InitMoveScreen(-1.1,1.1);
10198 fLego->FrontBox(90);
10199 }
10200 if (!Hoption.Axis && !Hoption.Same) {
10201 TGaxis axis;
10202 PaintLegoAxis(&axis, 90);
10203 }
10204
10205 PaintTitle();
10206
10207 fLego.reset();
10208}
10209
10210/////////////////////////////////////////////////////////////new TGaxis///////////////////
10211/// Draw the histogram title
10212///
10213/// The title is drawn according to the title alignment returned by
10214/// `GetTitleAlign()`. It is a 2 digits integer): hv
10215///
10216/// where `h` is the horizontal alignment and `v` is the
10217/// vertical alignment.
10218///
10219/// - `h` can get the values 1 2 3 for left, center, and right
10220/// - `v` can get the values 1 2 3 for bottom, middle and top
10221///
10222/// for instance the default alignment is: 13 (left top)
10223
10225{
10226 // probably best place for calls PaintHighlightBin
10227 // calls after paint histo (1D or 2D) and before paint title and stats
10228 if (!gPad->GetView()) PaintHighlightBin();
10229
10230 if (Hoption.Same) return;
10231 if (fH->TestBit(TH1::kNoTitle)) return;
10232 Int_t nt = strlen(fH->GetTitle());
10233 TPaveText *title = nullptr;
10234 TObject *obj;
10235 TIter next(gPad->GetListOfPrimitives());
10236 while ((obj = next())) {
10237 if (!obj->InheritsFrom(TPaveText::Class())) continue;
10238 title = (TPaveText*)obj;
10239 if (strcmp(title->GetName(),"title")) {title = nullptr; continue;}
10240 break;
10241 }
10242 if (nt == 0 || gStyle->GetOptTitle() <= 0) {
10243 if (title) delete title;
10244 return;
10245 }
10246 Double_t ht = gStyle->GetTitleH();
10247 Double_t wt = gStyle->GetTitleW();
10248
10249 if (ht <= 0) {
10250 if (gStyle->GetTitleFont("")%10 == 3) {
10251 Double_t hw = TMath::Max((Double_t)gPad->XtoPixel(gPad->GetX2()),
10252 (Double_t)gPad->YtoPixel(gPad->GetY1()));
10253 ht = 1.1*(gStyle->GetTitleSize("")/hw);
10254 } else {
10255 ht = 1.1*gStyle->GetTitleFontSize();
10256 }
10257 }
10258 if (ht <= 0) ht = 0.05;
10259 if (wt <= 0) {
10260 TLatex l;
10261 l.SetTextSize(ht);
10262 l.SetTitle(fH->GetTitle());
10263 // adjustment in case the title has several lines (#splitline)
10264 ht = TMath::Max(ht, 1.2*l.GetYsize()/(gPad->GetY2() - gPad->GetY1()));
10265 Double_t wndc = l.GetXsize()/(gPad->GetX2() - gPad->GetX1());
10266 wt = TMath::Min(0.7, 0.02+wndc);
10267 }
10268 if (title) {
10269 TText *t0 = (TText*)title->GetLine(0);
10270 if (t0) {
10271 if (!strcmp(t0->GetTitle(),fH->GetTitle())) return;
10272 t0->SetTitle(fH->GetTitle());
10273 if (wt > 0) title->SetX2NDC(title->GetX1NDC()+wt);
10274 }
10275 return;
10276 }
10277
10278 Int_t talh = gStyle->GetTitleAlign()/10;
10279 if (talh < 1) talh = 1; else if (talh > 3) talh = 3;
10280 Int_t talv = gStyle->GetTitleAlign()%10;
10281 if (talv < 1) talv = 1; else if (talv > 3) talv = 3;
10283 xpos = gStyle->GetTitleX();
10284 ypos = gStyle->GetTitleY();
10285 if (talh == 2) xpos = xpos-wt/2.;
10286 if (talh == 3) xpos = xpos-wt;
10287 if (talv == 2) ypos = ypos+ht/2.;
10288 if (talv == 1) ypos = ypos+ht;
10289
10290 TPaveText *ptitle = new TPaveText(xpos, ypos-ht, xpos+wt, ypos,"blNDC");
10291
10292 // box with the histogram title
10294 ptitle->SetFillStyle(gStyle->GetTitleStyle());
10295 ptitle->SetName("title");
10298 ptitle->SetTextFont(gStyle->GetTitleFont(""));
10299 if (gStyle->GetTitleFont("")%10 > 2)
10301 ptitle->AddText(fH->GetTitle());
10302 ptitle->SetBit(kCanDelete);
10303 ptitle->Draw();
10304 ptitle->Paint();
10305
10306 if(!gPad->IsEditable()) delete ptitle;
10307}
10308
10309////////////////////////////////////////////////////////////////////////////////
10310/// Process message `mess`.
10311
10312void THistPainter::ProcessMessage(const char *mess, const TObject *obj)
10313{
10314 if (!strcmp(mess,"SetF3")) {
10315 fCurrentF3 = (TF3 *)obj;
10316 }
10317}
10318
10319////////////////////////////////////////////////////////////////////////////////
10320/// Static function.
10321///
10322/// Convert Right Ascension, Declination to X,Y using an AITOFF projection.
10323/// This procedure can be used to create an all-sky map in Galactic
10324/// coordinates with an equal-area Aitoff projection. Output map
10325/// coordinates are zero longitude centered.
10326/// Also called Hammer-Aitoff projection (first presented by Ernst von Hammer in 1892)
10327///
10328/// source: GMT
10329///
10330/// code from Ernst-Jan Buis
10331
10333{
10334
10335 Double_t x, y;
10336
10337 Double_t alpha2 = (l/2)*TMath::DegToRad();
10338 Double_t delta = b*TMath::DegToRad();
10339 Double_t r2 = TMath::Sqrt(2.);
10340 Double_t f = 2*r2/TMath::Pi();
10341 Double_t cdec = TMath::Cos(delta);
10342 Double_t denom = TMath::Sqrt(1. + cdec*TMath::Cos(alpha2));
10343 x = cdec*TMath::Sin(alpha2)*2.*r2/denom;
10344 y = TMath::Sin(delta)*r2/denom;
10345 x *= TMath::RadToDeg()/f;
10346 y *= TMath::RadToDeg()/f;
10347 // x *= -1.; // for a skymap swap left<->right
10348 Al = x;
10349 Ab = y;
10350
10351 return 0;
10352}
10353
10354////////////////////////////////////////////////////////////////////////////////
10355/// Static function
10356///
10357/// Probably the most famous of the various map projections, the Mercator projection
10358/// takes its name from Mercator who presented it in 1569. It is a cylindrical, conformal projection
10359/// with no distortion along the equator.
10360/// The Mercator projection has been used extensively for world maps in which the distortion towards
10361/// the polar regions grows rather large, thus incorrectly giving the impression that, for example,
10362/// Greenland is larger than South America. In reality, the latter is about eight times the size of
10363/// Greenland. Also, the Former Soviet Union looks much bigger than Africa or South America. One may wonder
10364/// whether this illusion has had any influence on U.S. foreign policy.' (Source: GMT)
10365/// code from Ernst-Jan Buis
10366
10368{
10369
10370 Al = l;
10372 Ab = TMath::Log(aid);
10373 return 0;
10374}
10375
10376////////////////////////////////////////////////////////////////////////////////
10377/// Static function code for sinusoidal projection
10378/// from Ernst-Jan Buis
10379/// Source https://en.wikipedia.org/wiki/Sinusoidal_projection
10380
10382{
10383
10384 Al = l*cos(b*TMath::DegToRad());
10385 Ab = b;
10386 return 0;
10387}
10388
10389////////////////////////////////////////////////////////////////////////////////
10390/// Static function code for parabolic projection
10391/// from Ernst-Jan Buis
10392
10394{
10395
10396 Al = l*(2.*TMath::Cos(2*b*TMath::DegToRad()/3) - 1);
10397 Ab = 180*TMath::Sin(b*TMath::DegToRad()/3);
10398 return 0;
10399}
10400
10401////////////////////////////////////////////////////////////////////////////////
10402/// Static function.
10403///
10404/// Convert Right Ascension, Declination to X,Y using an MOLLWEIDE projection.
10405/// This procedure can be used to create an all-sky map in Galactic
10406/// coordinates with an equal-area Mollweide projection. Output map
10407/// coordinates are zero longitude centered.
10408/// It is also known as the Babinet projection, homalographic projection, homolographic projection, and elliptical projection.
10409/// Source: https://en.wikipedia.org/wiki/Mollweide_projection
10410///
10411/// code from Marco Meyer-Conde
10412
10414{
10415
10416 Double_t theta0 = b * TMath::DegToRad(), theta = theta0;
10417
10418 for (int i = 0; i < 100; i++) {
10419 Double_t num = 2 * theta + TMath::Sin(2 * theta) - TMath::Pi() * TMath::Sin(theta0);
10420 Double_t den = 4 * TMath::Power(TMath::Cos(theta), 2);
10421
10422 if (den < 1e-20) {
10423 theta = theta0;
10424 break;
10425 }
10426
10427 theta -= num / den;
10428
10429 if (TMath::Abs(num / den) < 1e-4) break;
10430 }
10431
10432 Al = l * TMath::Cos(theta);
10433 Ab = 90 * TMath::Sin(theta);
10434
10435 return 0;
10436}
10437
10438////////////////////////////////////////////////////////////////////////////////
10439/// Recompute the histogram range following graphics operations.
10440
10442{
10443
10444 if (Hoption.Same) return;
10445
10446 // Compute x,y range
10448 xmax = Hparam.xmax,
10449 ymin = Hparam.ymin,
10450 ymax = Hparam.ymax,
10451 xscale = 1;
10452
10453 std::function<Int_t(Double_t,Double_t,Double_t&,Double_t&)> func;
10454
10455 if (Hoption.Proj == 1) {
10456 func = ProjectAitoff2xy;
10457 xscale = 0.9999;
10458 } else if (Hoption.Proj == 2) {
10459 if (Hparam.ymin <= -90 || Hparam.ymax >= 90) {
10460 Warning("Mercator Projection", "Latitude out of range %f or %f", Hparam.ymin, Hparam.ymax);
10461 Hoption.Proj = 0;
10462 } else {
10465 }
10466 } else if (Hoption.Proj == 3) {
10467 func = ProjectSinusoidal2xy;
10468 } else if (Hoption.Proj == 4) {
10469 func = ProjectParabolic2xy;
10470 } else if (Hoption.Proj == 5) {
10471 func = ProjectMollweide2xy;
10472 }
10473
10474 if (func) {
10475 Double_t xmin_aid, ymin_aid, xmax_aid, ymax_aid;
10476
10477 func(Hparam.xmin, Hparam.ymin, xmin_aid, ymin_aid);
10478 func(Hparam.xmin, Hparam.ymax, xmin, ymax_aid);
10479 func(Hparam.xmax, Hparam.ymax, xmax_aid, ymax);
10480 func(Hparam.xmax, Hparam.ymin, xmax, ymin);
10481
10482 if (xmin > xmin_aid) xmin = xmin_aid;
10483 if (ymin > ymin_aid) ymin = ymin_aid;
10484 if (xmax < xmax_aid) xmax = xmax_aid;
10485 if (ymax < ymax_aid) ymax = ymax_aid;
10486 if (Hparam.ymin < 0 && Hparam.ymax > 0) {
10487 // there is an 'equator', check its range in the plot..
10488 func(Hparam.xmin*xscale, 0, xmin_aid, ymin_aid);
10489 func(Hparam.xmax*xscale, 0, xmax_aid, ymin_aid);
10490 if (xmin > xmin_aid) xmin = xmin_aid;
10491 if (xmax < xmax_aid) xmax = xmax_aid;
10492 }
10493 if (Hparam.xmin < 0 && Hparam.xmax > 0) {
10494 func(0, Hparam.ymin, xmin_aid, ymin_aid);
10495 func(0, Hparam.ymax, xmax_aid, ymax_aid);
10496 if (ymin > ymin_aid) ymin = ymin_aid;
10497 if (ymax < ymax_aid) ymax = ymax_aid;
10498 }
10499 }
10500
10501 Hparam.xmin = xmin;
10502 Hparam.xmax = xmax;
10503 Hparam.ymin = ymin;
10504 Hparam.ymax = ymax;
10505
10506 Double_t dx = xmax-xmin;
10507 Double_t dy = ymax-ymin;
10508 Double_t dxr = dx/(1 - gPad->GetLeftMargin() - gPad->GetRightMargin());
10509 Double_t dyr = dy/(1 - gPad->GetBottomMargin() - gPad->GetTopMargin());
10510
10511 // Range() could change the size of the pad pixmap and therefore should
10512 // be called before the other paint routines
10513 gPad->Range(xmin - dxr*gPad->GetLeftMargin(),
10514 ymin - dyr*gPad->GetBottomMargin(),
10515 xmax + dxr*gPad->GetRightMargin(),
10516 ymax + dyr*gPad->GetTopMargin());
10517 gPad->RangeAxis(xmin, ymin, xmax, ymax);
10518}
10519
10520////////////////////////////////////////////////////////////////////////////////
10521/// Set current histogram to `h`
10522
10524{
10525
10526 if (h == nullptr) return;
10527 fH = h;
10528 fXaxis = h->GetXaxis();
10529 fYaxis = h->GetYaxis();
10530 fZaxis = h->GetZaxis();
10532}
10533
10534////////////////////////////////////////////////////////////////////////////////
10535/// Initialize various options to draw 2D histograms.
10536
10538{
10539
10540 static const char *where = "TableInit";
10541
10542 Int_t first, last;
10543 Double_t yMARGIN= gStyle->GetHistTopMargin();
10544 Double_t zmin, zmax;
10545 Int_t maximum = 0;
10546 Int_t minimum = 0;
10547 if (fH->GetMaximumStored() != -1111) maximum = 1;
10548 if (fH->GetMinimumStored() != -1111) minimum = 1;
10549
10550 // ----------------- Compute X axis parameters
10551 first = fXaxis->GetFirst();
10552 last = fXaxis->GetLast();
10553 Hparam.xlast = last;
10554 Hparam.xfirst = first;
10559
10560 // if log scale in X, replace xmin,max by the log
10561 if (Hoption.Logx) {
10562 // find the first edge of a bin that is > 0
10563 if (Hparam.xlowedge <=0 ) {
10566 }
10567 if (Hparam.xmin <=0 || Hparam.xmax <=0) {
10568 Error(where, "cannot set X axis to log scale");
10569 return 0;
10570 }
10572 if (Hparam.xfirst < first) Hparam.xfirst = first;
10574 if (Hparam.xlast > last) Hparam.xlast = last;
10577 }
10578
10579 // ----------------- Compute Y axis parameters
10580 first = fYaxis->GetFirst();
10581 last = fYaxis->GetLast();
10582 Hparam.ylast = last;
10583 Hparam.yfirst = first;
10586 if (!Hparam.ybinsize) Hparam.ybinsize = 1;
10589
10590 // if log scale in Y, replace ymin,max by the log
10591 if (Hoption.Logy) {
10592 if (Hparam.ylowedge <=0 ) {
10595 }
10596 if (Hparam.ymin <=0 || Hparam.ymax <=0) {
10597 Error(where, "cannot set Y axis to log scale");
10598 return 0;
10599 }
10601 if (Hparam.yfirst < first) Hparam.yfirst = first;
10603 if (Hparam.ylast > last) Hparam.ylast = last;
10606 }
10607
10608
10609 // ----------------- Compute Z axis parameters
10610 Double_t bigp = TMath::Power(10,32);
10611 zmax = -bigp;
10612 zmin = bigp;
10613 Double_t c1, e1;
10614 Double_t allchan = 0;
10615 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
10616 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10617 c1 = fH->GetBinContent(i,j);
10618 zmax = TMath::Max(zmax,c1);
10619 if (Hoption.Error) {
10620 e1 = fH->GetBinError(i,j);
10621 zmax = TMath::Max(zmax,c1+e1);
10622 }
10623 zmin = TMath::Min(zmin,c1);
10624 allchan += c1;
10625 }
10626 }
10627
10628 // Take into account maximum , minimum
10629
10630 if (maximum) zmax = fH->GetMaximumStored();
10631 if (minimum) zmin = fH->GetMinimumStored();
10632 if (Hoption.Logz && zmax < 0) {
10633 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10634 return 0;
10635 } else if (Hoption.Logz && zmin>=0 && zmax==0) { // empty histogram in log scale
10636 zmin = 0.01;
10637 zmax = 10.;
10638 }
10639 if (zmin >= zmax) {
10640 if (Hoption.Logz) {
10641 if (zmax > 0) zmin = 0.001*zmax;
10642 else {
10643 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10644 return 0;
10645 }
10646 }
10647 }
10648
10649 // take into account normalization factor
10650 Hparam.allchan = allchan;
10651 Double_t factor = allchan;
10652 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
10653 if (allchan) factor /= allchan;
10654 if (factor == 0) factor = 1;
10655 Hparam.factor = factor;
10656 zmax = factor*zmax;
10657 zmin = factor*zmin;
10658 c1 = zmax;
10659 if (TMath::Abs(zmin) > TMath::Abs(c1)) c1 = zmin;
10660
10661 // For log scales, histogram coordinates are log10(ymin) and
10662 // log10(ymax). Final adjustment (if not option "Same")
10663 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
10664 // Maximum and Minimum are not defined.
10665 if (Hoption.Logz) {
10666 if (zmin <= 0) {
10667 zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
10668 fH->SetMinimum(zmin);
10669 }
10670 zmin = TMath::Log10(zmin);
10671 if (!minimum) zmin += TMath::Log10(0.5);
10672 zmax = TMath::Log10(zmax);
10673 if (!maximum) zmax += TMath::Log10(2*(0.9/0.95));
10674 goto LZMIN;
10675 }
10676
10677 // final adjustment of YMAXI for linear scale (if not option "Same"):
10678 // decrease histogram height to MAX% of allowed height if HMAXIM
10679 // has not been called.
10680 // MAX% is the value in percent which has been set in HPLSET
10681 // (default is 90%).
10682 if (!maximum) {
10683 zmax += yMARGIN*(zmax-zmin);
10684 }
10685
10686 // final adjustment of ymin for linear scale.
10687 // if minimum is not set , then ymin is set to zero if >0
10688 // or to ymin - yMARGIN if <0.
10689 if (!minimum) {
10690 if (Hoption.MinimumZero) {
10691 if (zmin >= 0) zmin = 0;
10692 else zmin -= yMARGIN*(zmax-zmin);
10693 } else {
10694 Double_t dzmin = yMARGIN*(zmax-zmin);
10695 if (zmin >= 0 && (zmin-dzmin <= 0)) zmin = 0;
10696 else zmin -= dzmin;
10697 }
10698 }
10699
10700LZMIN:
10701 Hparam.zmin = zmin;
10702 Hparam.zmax = zmax;
10703
10704 // Set bar offset and width
10707
10708 return 1;
10709}
10710
10711////////////////////////////////////////////////////////////////////////////////
10712/// This function returns the best format to print the error value (e)
10713/// knowing the parameter value (v) and the format (f) used to print it.
10714
10716{
10717
10718 static TString ef;
10719 TString tf, tv;
10720
10721 // print v with the format f in tv.
10722 tf.Form("%s%s","%",f);
10723 tv.Form(tf.Data(),v);
10724
10725 // Analyse tv.
10726 int ie = tv.Index("e");
10727 int iE = tv.Index("E");
10728 int id = tv.Index(".");
10729
10730 // v has been printed with the exponent notation.
10731 // There is 2 cases, the exponent is positive or negative
10732 if (ie >= 0 || iE >= 0) {
10733 if (tv.Index("+") >= 0) {
10734 if (e < 1) {
10735 ef.Form("%s.1f","%");
10736 } else {
10737 if (ie >= 0) {
10738 ef.Form("%s.%de","%",ie-id-1);
10739 } else {
10740 ef.Form("%s.%dE","%",iE-id-1);
10741 }
10742 }
10743 } else {
10744 if (ie >= 0) {
10745 ef.Form("%s.%de","%",ie-id-1);
10746 } else {
10747 ef.Form("%s.%dE","%",iE-id-1);
10748 }
10749 }
10750
10751 // There is not '.' in tv. e will be printed with one decimal digit.
10752 } else if (id < 0) {
10753 ef.Form("%s.1f","%");
10754
10755 // There is a '.' in tv and no exponent notation. e's decimal part will
10756 // have the same number of digits as v's one.
10757 } else {
10758 ef.Form("%s.%df","%",tv.Length()-id-1);
10759 }
10760
10761 return ef.Data();
10762}
10763
10764////////////////////////////////////////////////////////////////////////////////
10765/// Set projection.
10766
10768{
10769 if (fShowProjection2) {
10770 auto name2 = TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2);
10771 auto c2 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name2.Data()));
10772 if (c2) c2->Close();
10773 fShowProjection2 = 0;
10774 }
10775 if (fShowProjection) {
10776 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10777 auto c1 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name1.Data()));
10778 if (c1) c1->Close();
10779 fShowProjection = 0;
10780 }
10781
10782 if (nbins <= 0) return;
10783
10784 TString opt = option;
10785 opt.ToLower();
10786 Int_t projection = 0;
10787 if (opt.Contains("x")) projection = 1;
10788 if (opt.Contains("y")) projection = 2;
10789 if (opt.Contains("z")) projection = 3;
10790 if (opt.Contains("xy")) projection = 4;
10791 if (opt.Contains("yx")) projection = 5;
10792 if (opt.Contains("xz")) projection = 6;
10793 if (opt.Contains("zx")) projection = 7;
10794 if (opt.Contains("yz")) projection = 8;
10795 if (opt.Contains("zy")) projection = 9;
10796 if (projection < 4) fShowOption = option+1;
10797 else fShowOption = option+2;
10798 fShowProjection = projection+100*nbins;
10799 fShowProjection2 = 0;
10800 gROOT->MakeDefCanvas();
10801 gPad->SetName(TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection).Data());
10802 gPad->SetGrid();
10803}
10804
10806{
10807 if (fShowProjection2) {
10808 auto name2 = TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2);
10809 auto c2 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name2.Data()));
10810 if (c2) c2->Close();
10811 fShowProjection2 = 0;
10812 }
10813 if (fShowProjection) {
10814 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10815 auto c1 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name1.Data()));
10816 if (c1) c1->Close();
10817 fShowProjection = 0;
10818 }
10819
10820 if ((nbinsX <= 0) || (nbinsY <= 0)) return;
10821
10822
10823 TString opt = option;
10824 opt.ToLower();
10825 Int_t projection = 0;
10826 if (opt.Contains("x")) projection = 1;
10827 if (opt.Contains("y")) projection = 2;
10828 if (opt.Contains("z")) projection = 3;
10829 if (opt.Contains("xy")) projection = 4;
10830 if (opt.Contains("yx")) projection = 5;
10831 if (opt.Contains("xz")) projection = 6;
10832 if (opt.Contains("zx")) projection = 7;
10833 if (opt.Contains("yz")) projection = 8;
10834 if (opt.Contains("zy")) projection = 9;
10835 if (projection < 4) fShowOption = option+1;
10836 else fShowOption = option+2;
10837 fShowProjection = projection+100*nbinsY;
10838 fShowProjection2 = projection+100*nbinsX;
10839 gROOT->MakeDefCanvas();
10840 gPad->SetName(TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection).Data());
10841 gPad->SetGrid();
10842 gROOT->MakeDefCanvas();
10843 gPad->SetName(TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2).Data());
10844 gPad->SetGrid();
10845}
10846
10847
10848////////////////////////////////////////////////////////////////////////////////
10849/// Show projection onto X.
10850
10852{
10853
10854 Int_t nbins = (Int_t)fShowProjection/100;
10855 gPad->SetDoubleBuffer(0); // turn off double buffer mode
10856 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
10857
10858 // Erase old position and draw a line at current position
10859 static int pyold1 = 0;
10860 static int pyold2 = 0;
10861 float uxmin = gPad->GetUxmin();
10862 float uxmax = gPad->GetUxmax();
10863 int pxmin = gPad->XtoAbsPixel(uxmin);
10864 int pxmax = gPad->XtoAbsPixel(uxmax);
10865 Float_t upy = gPad->AbsPixeltoY(py);
10866 Float_t y = gPad->PadtoY(upy);
10867 Int_t biny1 = fH->GetYaxis()->FindBin(y);
10868 Int_t biny2 = TMath::Min(biny1+nbins-1, fH->GetYaxis()->GetNbins());
10869 Int_t py1 = gPad->YtoAbsPixel(fH->GetYaxis()->GetBinLowEdge(biny1));
10870 Int_t py2 = gPad->YtoAbsPixel(fH->GetYaxis()->GetBinUpEdge(biny2));
10871
10872 if (pyold1 || pyold2) gVirtualX->DrawBox(pxmin,pyold1,pxmax,pyold2,TVirtualX::kFilled);
10873 gVirtualX->DrawBox(pxmin,py1,pxmax,py2,TVirtualX::kFilled);
10874 pyold1 = py1;
10875 pyold2 = py2;
10876
10877 // Create or set the new canvas proj x
10878 TVirtualPad::TContext ctxt(true);
10879 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10880 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(name1.Data());
10881 if (c) {
10882 c->Clear();
10883 } else {
10884 fShowProjection = 0;
10885 fShowProjection2 = 0;
10886 pyold1 = 0;
10887 pyold2 = 0;
10888 return;
10889 }
10890 c->cd();
10891 c->SetLogy(ctxt.GetSaved()->GetLogz());
10892 c->SetLogx(ctxt.GetSaved()->GetLogx());
10893
10894 // Draw slice corresponding to mouse position
10895 TString prjName = TString::Format("slice_px_of_%s",fH->GetName());
10896 TH1D *hp = ((TH2*)fH)->ProjectionX(prjName, biny1, biny2);
10897 if (hp) {
10898 hp->SetFillColor(38);
10899 // apply a patch from Oliver Freyermuth to set the title in the projection
10900 // using the range of the projected Y values
10901 if (biny1 == biny2) {
10902 Double_t valueFrom = fH->GetYaxis()->GetBinLowEdge(biny1);
10903 Double_t valueTo = fH->GetYaxis()->GetBinUpEdge(biny1);
10904 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
10905 Int_t valuePrecision = -TMath::Nint(TMath::Log10(valueTo-valueFrom))+1;
10906 if (fH->GetYaxis()->GetLabels() != nullptr) {
10907 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf] %s", biny1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetYaxis()->GetBinLabel(biny1)));
10908 } else {
10909 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf]", biny1, valuePrecision, valueFrom, valuePrecision, valueTo));
10910 }
10911 } else {
10912 Double_t valueFrom = fH->GetYaxis()->GetBinLowEdge(biny1);
10913 Double_t valueTo = fH->GetYaxis()->GetBinUpEdge(biny2);
10914 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
10915 // biny1 is used here to get equal precision no matter how large the binrange is,
10916 // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
10917 Int_t valuePrecision = -TMath::Nint(TMath::Log10(fH->GetYaxis()->GetBinUpEdge(biny1)-valueFrom))+1;
10918 if (fH->GetYaxis()->GetLabels() != nullptr) {
10919 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)));
10920 } else {
10921 hp->SetTitle(TString::Format("ProjectionX of biny=[%d,%d] [y=%.*lf..%.*lf]", biny1, biny2, valuePrecision, valueFrom, valuePrecision, valueTo));
10922 }
10923 }
10924 hp->SetXTitle(fH->GetXaxis()->GetTitle());
10925 hp->SetYTitle(((TH2*)fH)->GetZaxis()->GetTitle() ? ((TH2*)fH)->GetZaxis()->GetTitle() : "Number of Entries");
10926 hp->Draw();
10927 c->Update();
10928 }
10929}
10930
10931////////////////////////////////////////////////////////////////////////////////
10932/// Show projection onto Y.
10933
10935{
10936
10937 Int_t nbins = (Int_t)fShowProjection/100;
10938 if (fShowProjection2)
10939 nbins = (Int_t)fShowProjection2/100;
10940 gPad->SetDoubleBuffer(0); // turn off double buffer mode
10941 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
10942
10943 // Erase old position and draw a line at current position
10944 static int pxold1 = 0;
10945 static int pxold2 = 0;
10946 float uymin = gPad->GetUymin();
10947 float uymax = gPad->GetUymax();
10948 int pymin = gPad->YtoAbsPixel(uymin);
10949 int pymax = gPad->YtoAbsPixel(uymax);
10950 Float_t upx = gPad->AbsPixeltoX(px);
10951 Float_t x = gPad->PadtoX(upx);
10952 Int_t binx1 = fH->GetXaxis()->FindBin(x);
10953 Int_t binx2 = TMath::Min(binx1+nbins-1, fH->GetXaxis()->GetNbins());
10954 Int_t px1 = gPad->XtoAbsPixel(fH->GetXaxis()->GetBinLowEdge(binx1));
10955 Int_t px2 = gPad->XtoAbsPixel(fH->GetXaxis()->GetBinUpEdge(binx2));
10956
10957 if (pxold1 || pxold2) gVirtualX->DrawBox(pxold1,pymin,pxold2,pymax,TVirtualX::kFilled);
10958 gVirtualX->DrawBox(px1,pymin,px2,pymax,TVirtualX::kFilled);
10959 pxold1 = px1;
10960 pxold2 = px2;
10961
10962 // Create or set the new canvas proj y
10963 TVirtualPad::TContext ctxt(true);
10964
10965 TString name2 = fShowProjection2 ? TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2)
10966 : TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10967
10968 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(name2.Data());
10969 if (c) {
10970 c->Clear();
10971 } else {
10972 fShowProjection = 0;
10973 fShowProjection2 = 0;
10974 pxold1 = 0;
10975 pxold2 = 0;
10976 return;
10977 }
10978 c->cd();
10979 c->SetLogy(ctxt.GetSaved()->GetLogz());
10980 c->SetLogx(ctxt.GetSaved()->GetLogy());
10981
10982 // Draw slice corresponding to mouse position
10983 TString prjName = TString::Format("slice_py_of_%s",fH->GetName());
10984 TH1D *hp = ((TH2*)fH)->ProjectionY(prjName, binx1, binx2);
10985 if (hp) {
10986 hp->SetFillColor(38);
10987 // apply a patch from Oliver Freyermuth to set the title in the projection
10988 // using the range of the projected X values
10989 if (binx1 == binx2) {
10990 Double_t valueFrom = fH->GetXaxis()->GetBinLowEdge(binx1);
10991 Double_t valueTo = fH->GetXaxis()->GetBinUpEdge(binx1);
10992 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
10993 Int_t valuePrecision = -TMath::Nint(TMath::Log10(valueTo-valueFrom))+1;
10994 if (fH->GetXaxis()->GetLabels() != nullptr) {
10995 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf] [%s]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetXaxis()->GetBinLabel(binx1)));
10996 } else {
10997 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo));
10998 }
10999 } else {
11000 Double_t valueFrom = fH->GetXaxis()->GetBinLowEdge(binx1);
11001 Double_t valueTo = fH->GetXaxis()->GetBinUpEdge(binx2);
11002 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11003 // binx1 is used here to get equal precision no matter how large the binrange is,
11004 // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
11005 Int_t valuePrecision = -TMath::Nint(TMath::Log10(fH->GetXaxis()->GetBinUpEdge(binx1)-valueFrom))+1;
11006 if (fH->GetXaxis()->GetLabels() != nullptr) {
11007 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)));
11008 } else {
11009 hp->SetTitle(TString::Format("ProjectionY of binx=[%d,%d] [x=%.*lf..%.*lf]", binx1, binx2, valuePrecision, valueFrom, valuePrecision, valueTo));
11010 }
11011 }
11012 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11013 hp->SetYTitle(((TH2*)fH)->GetZaxis()->GetTitle() ? ((TH2*)fH)->GetZaxis()->GetTitle() : "Number of Entries");
11014 hp->Draw(fShowProjection2 ? "hbar" : "");
11015 c->Update();
11016 }
11017}
11018
11019////////////////////////////////////////////////////////////////////////////////
11020/// Show projection (specified by `fShowProjection`) of a `TH3`.
11021/// The drawing option for the projection is in `fShowOption`.
11022///
11023/// First implementation; R.Brun
11024///
11025/// Full implementation: Tim Tran (timtran@jlab.org) April 2006
11026
11028{
11029
11030 Int_t nbins=(Int_t)fShowProjection/100; //decode nbins
11031 if (fH->GetDimension() < 3) {
11032 if (fShowProjection2 % 100 == 1) {
11033 ShowProjectionY(px, py);
11034 }
11035 if (fShowProjection % 100 == 1) {
11036 ShowProjectionX(px, py);
11037 return;
11038 }
11039 if (fShowProjection % 100 == 2) {
11040 ShowProjectionY(px, py);
11041 return;
11042 }
11043 }
11044
11045 gPad->SetDoubleBuffer(0); // turn off double buffer mode
11046 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
11047
11048 // Erase old position and draw a line at current position
11049 TView *view = gPad->GetView();
11050 if (!view) return;
11051 TH3 *h3 = (TH3*)fH;
11052 TAxis *xaxis = h3->GetXaxis();
11053 TAxis *yaxis = h3->GetYaxis();
11054 TAxis *zaxis = h3->GetZaxis();
11055 Double_t u[3],xx[3];
11056
11057 static TPoint line1[2];//store end points of a line, initialised 0 by default
11058 static TPoint line2[2];// second line when slice thickness > 1 bin thickness
11059 static TPoint line3[2];
11060 static TPoint line4[2];
11061 static TPoint endface1[5];
11062 static TPoint endface2[5];
11063 static TPoint rect1[5];//store vertices of the polyline (rectangle), initialsed 0 by default
11064 static TPoint rect2[5];// second rectangle when slice thickness > 1 bin thickness
11065
11066 Double_t uxmin = gPad->GetUxmin();
11067 Double_t uxmax = gPad->GetUxmax();
11068 Double_t uymin = gPad->GetUymin();
11069 Double_t uymax = gPad->GetUymax();
11070
11071 int pxmin = gPad->XtoAbsPixel(uxmin);
11072 int pxmax = gPad->XtoAbsPixel(uxmax);
11073 if (pxmin==pxmax) return;
11074 int pymin = gPad->YtoAbsPixel(uymin);
11075 int pymax = gPad->YtoAbsPixel(uymax);
11076 if (pymin==pymax) return;
11077 Double_t cx = (pxmax-pxmin)/(uxmax-uxmin);
11078 Double_t cy = (pymax-pymin)/(uymax-uymin);
11079 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(TString::Format("c_%zx_projection_%d",
11080 (size_t)fH, fShowProjection).Data());
11081 if (!c) {
11082 fShowProjection = 0;
11083 return;
11084 }
11085
11086 TVirtualPad::TContext ctxt(true);
11087
11088 switch ((Int_t)fShowProjection%100) {
11089 case 1:
11090 // "x"
11091 {
11092 Int_t firstY = yaxis->GetFirst();
11093 Int_t lastY = yaxis->GetLast();
11094 Int_t biny = firstY + Int_t((lastY-firstY)*(px-pxmin)/(pxmax-pxmin));
11095 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11096 yaxis->SetRange(biny,biny2);
11097 Int_t firstZ = zaxis->GetFirst();
11098 Int_t lastZ = zaxis->GetLast();
11099 Int_t binz = firstZ + Int_t((lastZ-firstZ)*(py-pymin)/(pymax-pymin));
11100 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11101 zaxis->SetRange(binz,binz2);
11102 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11103 if (nbins>1 && line1[0].GetX()) {
11104 gVirtualX->DrawPolyLine(2,line2);
11105 gVirtualX->DrawPolyLine(2,line3);
11106 gVirtualX->DrawPolyLine(2,line4);
11107 gVirtualX->DrawPolyLine(5,endface1);
11108 gVirtualX->DrawPolyLine(5,endface2);
11109 }
11110 xx[0] = xaxis->GetXmin();
11111 xx[2] = zaxis->GetBinCenter(binz);
11112 xx[1] = yaxis->GetBinCenter(biny);
11113 view->WCtoNDC(xx,u);
11114 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11115 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11116 xx[0] = xaxis->GetXmax();
11117 view->WCtoNDC(xx,u);
11118 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11119 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11120 gVirtualX->DrawPolyLine(2,line1);
11121 if (nbins>1) {
11122 xx[0] = xaxis->GetXmin();
11123 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11124 xx[1] = yaxis->GetBinCenter(biny);
11125 view->WCtoNDC(xx,u);
11126 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11127 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11128 xx[0] = xaxis->GetXmax();
11129 view->WCtoNDC(xx,u);
11130 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11131 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11132
11133 xx[0] = xaxis->GetXmin();
11134 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11135 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11136 view->WCtoNDC(xx,u);
11137 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11138 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11139 xx[0] = xaxis->GetXmax();
11140 view->WCtoNDC(xx,u);
11141 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11142 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11143
11144 xx[0] = xaxis->GetXmin();
11145 xx[2] = zaxis->GetBinCenter(binz);
11146 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11147 view->WCtoNDC(xx,u);
11148 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11149 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11150 xx[0] = xaxis->GetXmax();
11151 view->WCtoNDC(xx,u);
11152 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11153 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11154
11155 endface1[0].SetX(line1[0].GetX());
11156 endface1[0].SetY(line1[0].GetY());
11157 endface1[1].SetX(line2[0].GetX());
11158 endface1[1].SetY(line2[0].GetY());
11159 endface1[2].SetX(line3[0].GetX());
11160 endface1[2].SetY(line3[0].GetY());
11161 endface1[3].SetX(line4[0].GetX());
11162 endface1[3].SetY(line4[0].GetY());
11163 endface1[4].SetX(line1[0].GetX());
11164 endface1[4].SetY(line1[0].GetY());
11165
11166 endface2[0].SetX(line1[1].GetX());
11167 endface2[0].SetY(line1[1].GetY());
11168 endface2[1].SetX(line2[1].GetX());
11169 endface2[1].SetY(line2[1].GetY());
11170 endface2[2].SetX(line3[1].GetX());
11171 endface2[2].SetY(line3[1].GetY());
11172 endface2[3].SetX(line4[1].GetX());
11173 endface2[3].SetY(line4[1].GetY());
11174 endface2[4].SetX(line1[1].GetX());
11175 endface2[4].SetY(line1[1].GetY());
11176
11177 gVirtualX->DrawPolyLine(2,line2);
11178 gVirtualX->DrawPolyLine(2,line3);
11179 gVirtualX->DrawPolyLine(2,line4);
11180 gVirtualX->DrawPolyLine(5,endface1);
11181 gVirtualX->DrawPolyLine(5,endface2);
11182 }
11183 c->Clear();
11184 c->cd();
11185 TH1 *hp = h3->Project3D("x");
11186 yaxis->SetRange(firstY,lastY);
11187 zaxis->SetRange(firstZ,lastZ);
11188 if (hp) {
11189 hp->SetFillColor(38);
11190 if (nbins == 1)
11191 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny),
11192 binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
11193 else {
11194 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),
11195 binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
11196 }
11197 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11198 hp->SetYTitle("Number of Entries");
11199 hp->Draw(fShowOption.Data());
11200 }
11201 }
11202 break;
11203
11204 case 2:
11205 // "y"
11206 {
11207 Int_t firstX = xaxis->GetFirst();
11208 Int_t lastX = xaxis->GetLast();
11209 Int_t binx = firstX + Int_t((lastX-firstX)*(px-pxmin)/(pxmax-pxmin));
11210 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11211 xaxis->SetRange(binx,binx2);
11212 Int_t firstZ = zaxis->GetFirst();
11213 Int_t lastZ = zaxis->GetLast();
11214 Int_t binz = firstZ + Int_t((lastZ-firstZ)*(py-pymin)/(pymax-pymin));
11215 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11216 zaxis->SetRange(binz,binz2);
11217 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11218 if (nbins>1 && line1[0].GetX()) {
11219 gVirtualX->DrawPolyLine(2,line2);
11220 gVirtualX->DrawPolyLine(2,line3);
11221 gVirtualX->DrawPolyLine(2,line4);
11222 gVirtualX->DrawPolyLine(5,endface1);
11223 gVirtualX->DrawPolyLine(5,endface2);
11224 }
11225 xx[0]=xaxis->GetBinCenter(binx);
11226 xx[2] = zaxis->GetBinCenter(binz);
11227 xx[1] = yaxis->GetXmin();
11228 view->WCtoNDC(xx,u);
11229 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11230 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11231 xx[1] = yaxis->GetXmax();
11232 view->WCtoNDC(xx,u);
11233 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11234 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11235 gVirtualX->DrawPolyLine(2,line1);
11236 if (nbins>1) {
11237 xx[1] = yaxis->GetXmin();
11238 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11239 xx[0] = xaxis->GetBinCenter(binx);
11240 view->WCtoNDC(xx,u);
11241 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11242 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11243 xx[1] = yaxis->GetXmax();
11244 view->WCtoNDC(xx,u);
11245 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11246 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11247
11248 xx[1] = yaxis->GetXmin();
11249 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11250 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11251 view->WCtoNDC(xx,u);
11252 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11253 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11254 xx[1] = yaxis->GetXmax();
11255 view->WCtoNDC(xx,u);
11256 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11257 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11258
11259 xx[1] = yaxis->GetXmin();
11260 xx[2] = zaxis->GetBinCenter(binz);
11261 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11262 view->WCtoNDC(xx,u);
11263 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11264 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11265 xx[1] = yaxis->GetXmax();
11266 view->WCtoNDC(xx,u);
11267 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11268 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11269
11270 endface1[0].SetX(line1[0].GetX());
11271 endface1[0].SetY(line1[0].GetY());
11272 endface1[1].SetX(line2[0].GetX());
11273 endface1[1].SetY(line2[0].GetY());
11274 endface1[2].SetX(line3[0].GetX());
11275 endface1[2].SetY(line3[0].GetY());
11276 endface1[3].SetX(line4[0].GetX());
11277 endface1[3].SetY(line4[0].GetY());
11278 endface1[4].SetX(line1[0].GetX());
11279 endface1[4].SetY(line1[0].GetY());
11280
11281 endface2[0].SetX(line1[1].GetX());
11282 endface2[0].SetY(line1[1].GetY());
11283 endface2[1].SetX(line2[1].GetX());
11284 endface2[1].SetY(line2[1].GetY());
11285 endface2[2].SetX(line3[1].GetX());
11286 endface2[2].SetY(line3[1].GetY());
11287 endface2[3].SetX(line4[1].GetX());
11288 endface2[3].SetY(line4[1].GetY());
11289 endface2[4].SetX(line1[1].GetX());
11290 endface2[4].SetY(line1[1].GetY());
11291
11292 gVirtualX->DrawPolyLine(2,line2);
11293 gVirtualX->DrawPolyLine(2,line3);
11294 gVirtualX->DrawPolyLine(2,line4);
11295 gVirtualX->DrawPolyLine(5,endface1);
11296 gVirtualX->DrawPolyLine(5,endface2);
11297 }
11298 c->Clear();
11299 c->cd();
11300 TH1 *hp = h3->Project3D("y");
11301 xaxis->SetRange(firstX,lastX);
11302 zaxis->SetRange(firstZ,lastZ);
11303 if (hp) {
11304 hp->SetFillColor(38);
11305 if (nbins == 1)
11306 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
11307 binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
11308 else
11309 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),
11310 binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
11311 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11312 hp->SetYTitle("Number of Entries");
11313 hp->Draw(fShowOption.Data());
11314 }
11315 }
11316 break;
11317
11318 case 3:
11319 // "z"
11320 {
11321 Int_t firstX = xaxis->GetFirst();
11322 Int_t lastX = xaxis->GetLast();
11323 Int_t binx = firstX + Int_t((lastX-firstX)*(px-pxmin)/(pxmax-pxmin));
11324 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11325 xaxis->SetRange(binx,binx2);
11326 Int_t firstY = yaxis->GetFirst();
11327 Int_t lastY = yaxis->GetLast();
11328 Int_t biny = firstY + Int_t((lastY-firstY)*(py-pymin)/(pymax-pymin));
11329 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11330 yaxis->SetRange(biny,biny2);
11331 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11332 if (nbins>1 && line1[0].GetX()) {
11333 gVirtualX->DrawPolyLine(2,line2);
11334 gVirtualX->DrawPolyLine(2,line3);
11335 gVirtualX->DrawPolyLine(2,line4);
11336 gVirtualX->DrawPolyLine(5,endface1);
11337 gVirtualX->DrawPolyLine(5,endface2);
11338 }
11339 xx[0] = xaxis->GetBinCenter(binx);
11340 xx[1] = yaxis->GetBinCenter(biny);
11341 xx[2] = zaxis->GetXmin();
11342 view->WCtoNDC(xx,u);
11343 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11344 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11345 xx[2] = zaxis->GetXmax();
11346 view->WCtoNDC(xx,u);
11347 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11348 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11349 gVirtualX->DrawPolyLine(2,line1);
11350 if (nbins>1) {
11351 xx[2] = zaxis->GetXmin();
11352 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11353 xx[0] = xaxis->GetBinCenter(binx);
11354 view->WCtoNDC(xx,u);
11355 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11356 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11357 xx[2] = zaxis->GetXmax();
11358 view->WCtoNDC(xx,u);
11359 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11360 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11361
11362 xx[2] = zaxis->GetXmin();
11363 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11364 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11365 view->WCtoNDC(xx,u);
11366 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11367 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11368 xx[2] = zaxis->GetXmax();
11369 view->WCtoNDC(xx,u);
11370 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11371 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11372
11373 xx[2] = zaxis->GetXmin();
11374 xx[1] = yaxis->GetBinCenter(biny);
11375 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11376 view->WCtoNDC(xx,u);
11377 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11378 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11379 xx[2] = zaxis->GetXmax();
11380 view->WCtoNDC(xx,u);
11381 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11382 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11383
11384 endface1[0].SetX(line1[0].GetX());
11385 endface1[0].SetY(line1[0].GetY());
11386 endface1[1].SetX(line2[0].GetX());
11387 endface1[1].SetY(line2[0].GetY());
11388 endface1[2].SetX(line3[0].GetX());
11389 endface1[2].SetY(line3[0].GetY());
11390 endface1[3].SetX(line4[0].GetX());
11391 endface1[3].SetY(line4[0].GetY());
11392 endface1[4].SetX(line1[0].GetX());
11393 endface1[4].SetY(line1[0].GetY());
11394
11395 endface2[0].SetX(line1[1].GetX());
11396 endface2[0].SetY(line1[1].GetY());
11397 endface2[1].SetX(line2[1].GetX());
11398 endface2[1].SetY(line2[1].GetY());
11399 endface2[2].SetX(line3[1].GetX());
11400 endface2[2].SetY(line3[1].GetY());
11401 endface2[3].SetX(line4[1].GetX());
11402 endface2[3].SetY(line4[1].GetY());
11403 endface2[4].SetX(line1[1].GetX());
11404 endface2[4].SetY(line1[1].GetY());
11405
11406 gVirtualX->DrawPolyLine(2,line2);
11407 gVirtualX->DrawPolyLine(2,line3);
11408 gVirtualX->DrawPolyLine(2,line4);
11409 gVirtualX->DrawPolyLine(5,endface1);
11410 gVirtualX->DrawPolyLine(5,endface2);
11411 }
11412 c->Clear();
11413 c->cd();
11414 TH1 *hp = h3->Project3D("z");
11415 xaxis->SetRange(firstX,lastX);
11416 yaxis->SetRange(firstY,lastY);
11417 if (hp) {
11418 hp->SetFillColor(38);
11419 if (nbins == 1)
11420 hp->SetTitle(TString::Format("ProjectionZ of binx=%d [x=%.1f..%.1f] biny=%d [y=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
11421 biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny)));
11422 else
11423 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),
11424 biny, biny2, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny2) ) );
11425 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11426 hp->SetYTitle("Number of Entries");
11427 hp->Draw(fShowOption.Data());
11428 }
11429 }
11430 break;
11431
11432 case 4:
11433 // "xy"
11434 {
11435 Int_t first = zaxis->GetFirst();
11436 Int_t last = zaxis->GetLast();
11437 Int_t binz = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11438 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11439 zaxis->SetRange(binz,binz2);
11440 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11441 if (nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11442 xx[0] = xaxis->GetXmin();
11443 xx[1] = yaxis->GetXmax();
11444 xx[2] = zaxis->GetBinCenter(binz);
11445 view->WCtoNDC(xx,u);
11446 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11447 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11448 rect1[4].SetX(rect1[0].GetX());
11449 rect1[4].SetY(rect1[0].GetY());
11450 xx[0] = xaxis->GetXmax();
11451 view->WCtoNDC(xx,u);
11452 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11453 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11454 xx[1] = yaxis->GetXmin();
11455 view->WCtoNDC(xx,u);
11456 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11457 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11458 xx[0] = xaxis->GetXmin();
11459 view->WCtoNDC(xx,u);
11460 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11461 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11462 gVirtualX->DrawPolyLine(5,rect1);
11463 if (nbins>1) {
11464 xx[0] = xaxis->GetXmin();
11465 xx[1] = yaxis->GetXmax();
11466 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11467 view->WCtoNDC(xx,u);
11468 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11469 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11470 rect2[4].SetX(rect2[0].GetX());
11471 rect2[4].SetY(rect2[0].GetY());
11472 xx[0] = xaxis->GetXmax();
11473 view->WCtoNDC(xx,u);
11474 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11475 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11476 xx[1] = yaxis->GetXmin();
11477 view->WCtoNDC(xx,u);
11478 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11479 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11480 xx[0] = xaxis->GetXmin();
11481 view->WCtoNDC(xx,u);
11482 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11483 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11484 gVirtualX->DrawPolyLine(5,rect2);
11485 }
11486
11487 c->Clear();
11488 c->cd();
11489 TH2 *hp = (TH2*)h3->Project3D("xy");
11490 zaxis->SetRange(first,last);
11491 if (hp) {
11492 hp->SetFillColor(38);
11493 if (nbins==1)hp->SetTitle(TString::Format("ProjectionXY of binz=%d [z=%.1f..%.f]", binz,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz)));
11494 else hp->SetTitle(TString::Format("ProjectionXY, binz=[%d,%d] [z=%.1f..%.1f]", binz,binz2,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz2)));
11495 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11496 hp->SetYTitle(fH->GetXaxis()->GetTitle());
11497 hp->SetZTitle("Number of Entries");
11498 hp->Draw(fShowOption.Data());
11499 }
11500 }
11501 break;
11502
11503 case 5:
11504 // "yx"
11505 {
11506 Int_t first = zaxis->GetFirst();
11507 Int_t last = zaxis->GetLast();
11508 Int_t binz = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11509 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11510 zaxis->SetRange(binz,binz2);
11511 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11512 if (nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11513 xx[0] = xaxis->GetXmin();
11514 xx[1] = yaxis->GetXmax();
11515 xx[2] = zaxis->GetBinCenter(binz);
11516 view->WCtoNDC(xx,u);
11517 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11518 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11519 rect1[4].SetX(rect1[0].GetX());
11520 rect1[4].SetY(rect1[0].GetY());
11521 xx[0] = xaxis->GetXmax();
11522 view->WCtoNDC(xx,u);
11523 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11524 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11525 xx[1] = yaxis->GetXmin();
11526 view->WCtoNDC(xx,u);
11527 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11528 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11529 xx[0] = xaxis->GetXmin();
11530 view->WCtoNDC(xx,u);
11531 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11532 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11533 gVirtualX->DrawPolyLine(5,rect1);
11534 if (nbins>1) {
11535 xx[0] = xaxis->GetXmin();
11536 xx[1] = yaxis->GetXmax();
11537 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11538 view->WCtoNDC(xx,u);
11539 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11540 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11541 rect2[4].SetX(rect2[0].GetX());
11542 rect2[4].SetY(rect2[0].GetY());
11543 xx[0] = xaxis->GetXmax();
11544 view->WCtoNDC(xx,u);
11545 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11546 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11547 xx[1] = yaxis->GetXmin();
11548 view->WCtoNDC(xx,u);
11549 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11550 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11551 xx[0] = xaxis->GetXmin();
11552 view->WCtoNDC(xx,u);
11553 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11554 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11555 gVirtualX->DrawPolyLine(5,rect2);
11556 }
11557 c->Clear();
11558 c->cd();
11559 TH2 *hp = (TH2*)h3->Project3D("yx");
11560 zaxis->SetRange(first,last);
11561 if (hp) {
11562 hp->SetFillColor(38);
11563 if (nbins==1)hp->SetTitle(TString::Format("ProjectionYX of binz=%d [z=%.1f..%.f]", binz,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz)));
11564 else hp->SetTitle(TString::Format("ProjectionYX, binz=[%d,%d] [z=%.1f..%.1f]", binz,binz2,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz2)));
11565 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11566 hp->SetYTitle(fH->GetYaxis()->GetTitle());
11567 hp->SetZTitle("Number of Entries");
11568 hp->Draw(fShowOption.Data());
11569 }
11570 }
11571 break;
11572
11573 case 6:
11574 // "xz"
11575 {
11576 Int_t first = yaxis->GetFirst();
11577 Int_t last = yaxis->GetLast();
11578 Int_t biny = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11579 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11580 yaxis->SetRange(biny,biny2);
11581 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11582 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11583 xx[0] = xaxis->GetXmin();
11584 xx[2] = zaxis->GetXmax();
11585 xx[1] = yaxis->GetBinCenter(biny);
11586 view->WCtoNDC(xx,u);
11587 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11588 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11589 rect1[4].SetX(rect1[0].GetX());
11590 rect1[4].SetY(rect1[0].GetY());
11591 xx[0] = xaxis->GetXmax();
11592 view->WCtoNDC(xx,u);
11593 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11594 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11595 xx[2] = zaxis->GetXmin();
11596 view->WCtoNDC(xx,u);
11597 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11598 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11599 xx[0] = xaxis->GetXmin();
11600 view->WCtoNDC(xx,u);
11601 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11602 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11603 gVirtualX->DrawPolyLine(5,rect1);
11604 if (nbins>1) {
11605 xx[0] = xaxis->GetXmin();
11606 xx[2] = zaxis->GetXmax();
11607 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11608 view->WCtoNDC(xx,u);
11609 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11610 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11611 rect2[4].SetX(rect2[0].GetX());
11612 rect2[4].SetY(rect2[0].GetY());
11613 xx[0] = xaxis->GetXmax();
11614 view->WCtoNDC(xx,u);
11615 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11616 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11617 xx[2] = zaxis->GetXmin();
11618 view->WCtoNDC(xx,u);
11619 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11620 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11621 xx[0] = xaxis->GetXmin();
11622 view->WCtoNDC(xx,u);
11623 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11624 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11625 gVirtualX->DrawPolyLine(5,rect2);
11626 }
11627 c->Clear();
11628 c->cd();
11629 TH2 *hp = (TH2*)h3->Project3D("xz");
11630 yaxis->SetRange(first,last);
11631 if (hp) {
11632 hp->SetFillColor(38);
11633 if (nbins==1)hp->SetTitle(TString::Format("ProjectionXZ of biny=%d [y=%.1f..%.f]", biny,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny)));
11634 else hp->SetTitle(TString::Format("ProjectionXZ, biny=[%d,%d] [y=%.1f..%.1f]", biny,biny2,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny2)));
11635 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11636 hp->SetYTitle(fH->GetXaxis()->GetTitle());
11637 hp->SetZTitle("Number of Entries");
11638 hp->Draw(fShowOption.Data());
11639 }
11640 }
11641 break;
11642
11643 case 7:
11644 // "zx"
11645 {
11646 Int_t first = yaxis->GetFirst();
11647 Int_t last = yaxis->GetLast();
11648 Int_t biny = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11649 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11650 yaxis->SetRange(biny,biny2);
11651 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11652 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11653 xx[0] = xaxis->GetXmin();
11654 xx[2] = zaxis->GetXmax();
11655 xx[1] = yaxis->GetBinCenter(biny);
11656 view->WCtoNDC(xx,u);
11657 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11658 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11659 rect1[4].SetX(rect1[0].GetX());
11660 rect1[4].SetY(rect1[0].GetY());
11661 xx[0] = xaxis->GetXmax();
11662 view->WCtoNDC(xx,u);
11663 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11664 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11665 xx[2] = zaxis->GetXmin();
11666 view->WCtoNDC(xx,u);
11667 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11668 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11669 xx[0] = xaxis->GetXmin();
11670 view->WCtoNDC(xx,u);
11671 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11672 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11673 gVirtualX->DrawPolyLine(5,rect1);
11674 if (nbins>1) {
11675 xx[0] = xaxis->GetXmin();
11676 xx[2] = zaxis->GetXmax();
11677 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11678 view->WCtoNDC(xx,u);
11679 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11680 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11681 rect2[4].SetX(rect2[0].GetX());
11682 rect2[4].SetY(rect2[0].GetY());
11683 xx[0] = xaxis->GetXmax();
11684 view->WCtoNDC(xx,u);
11685 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11686 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11687 xx[2] = zaxis->GetXmin();
11688 view->WCtoNDC(xx,u);
11689 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11690 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11691 xx[0] = xaxis->GetXmin();
11692 view->WCtoNDC(xx,u);
11693 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11694 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11695 gVirtualX->DrawPolyLine(5,rect2);
11696 }
11697 c->Clear();
11698 c->cd();
11699 TH2 *hp = (TH2*)h3->Project3D("zx");
11700 yaxis->SetRange(first,last);
11701 if (hp) {
11702 hp->SetFillColor(38);
11703 if (nbins==1)hp->SetTitle(TString::Format("ProjectionZX of biny=%d [y=%.1f..%.f]", biny,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny)));
11704 else hp->SetTitle(TString::Format("ProjectionZX, biny=[%d,%d] [y=%.1f..%.1f]", biny,biny2,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny2)));
11705 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11706 hp->SetYTitle(fH->GetZaxis()->GetTitle());
11707 hp->SetZTitle("Number of Entries");
11708 hp->Draw(fShowOption.Data());
11709 }
11710 }
11711 break;
11712
11713 case 8:
11714 // "yz"
11715 {
11716 Int_t first = xaxis->GetFirst();
11717 Int_t last = xaxis->GetLast();
11718 Int_t binx = first + Int_t((last-first)*(px-pxmin)/(pxmax-pxmin));
11719 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11720 xaxis->SetRange(binx,binx2);
11721 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11722 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11723 xx[2] = zaxis->GetXmin();
11724 xx[1] = yaxis->GetXmax();
11725 xx[0] = xaxis->GetBinCenter(binx);
11726 view->WCtoNDC(xx,u);
11727 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11728 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11729 rect1[4].SetX(rect1[0].GetX());
11730 rect1[4].SetY(rect1[0].GetY());
11731 xx[2] = zaxis->GetXmax();
11732 view->WCtoNDC(xx,u);
11733 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11734 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11735 xx[1] = yaxis->GetXmin();
11736 view->WCtoNDC(xx,u);
11737 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11738 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11739 xx[2] = zaxis->GetXmin();
11740 view->WCtoNDC(xx,u);
11741 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11742 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11743 gVirtualX->DrawPolyLine(5,rect1);
11744 if (nbins>1) {
11745 xx[2] = zaxis->GetXmin();
11746 xx[1] = yaxis->GetXmax();
11747 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11748 view->WCtoNDC(xx,u);
11749 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11750 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11751 rect2[4].SetX(rect2[0].GetX());
11752 rect2[4].SetY(rect2[0].GetY());
11753 xx[2] = zaxis->GetXmax();
11754 view->WCtoNDC(xx,u);
11755 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11756 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11757 xx[1] = yaxis->GetXmin();
11758 view->WCtoNDC(xx,u);
11759 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11760 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11761 xx[2] = zaxis->GetXmin();
11762 view->WCtoNDC(xx,u);
11763 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11764 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11765 gVirtualX->DrawPolyLine(5,rect2);
11766 }
11767 c->Clear();
11768 c->cd();
11769 TH2 *hp = (TH2*)h3->Project3D("yz");
11770 xaxis->SetRange(first,last);
11771 if (hp) {
11772 hp->SetFillColor(38);
11773 if (nbins==1)hp->SetTitle(TString::Format("ProjectionYZ of binx=%d [x=%.1f..%.f]", binx,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx)));
11774 else hp->SetTitle(TString::Format("ProjectionYZ, binx=[%d,%d] [x=%.1f..%.1f]", binx,binx2,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx2)));
11775 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11776 hp->SetYTitle(fH->GetYaxis()->GetTitle());
11777 hp->SetZTitle("Number of Entries");
11778 hp->Draw(fShowOption.Data());
11779 }
11780 }
11781 break;
11782
11783 case 9:
11784 // "zy"
11785 {
11786 Int_t first = xaxis->GetFirst();
11787 Int_t last = xaxis->GetLast();
11788 Int_t binx = first + Int_t((last-first)*(px-pxmin)/(pxmax-pxmin));
11789 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11790 xaxis->SetRange(binx,binx2);
11791 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11792 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11793 xx[2] = zaxis->GetXmin();
11794 xx[1] = yaxis->GetXmax();
11795 xx[0] = xaxis->GetBinCenter(binx);
11796 view->WCtoNDC(xx,u);
11797 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11798 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11799 rect1[4].SetX(rect1[0].GetX());
11800 rect1[4].SetY(rect1[0].GetY());
11801 xx[2] = zaxis->GetXmax();
11802 view->WCtoNDC(xx,u);
11803 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11804 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11805 xx[1] = yaxis->GetXmin();
11806 view->WCtoNDC(xx,u);
11807 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11808 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11809 xx[2] = zaxis->GetXmin();
11810 view->WCtoNDC(xx,u);
11811 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11812 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11813 gVirtualX->DrawPolyLine(5,rect1);
11814 if (nbins>1) {
11815 xx[2] = zaxis->GetXmin();
11816 xx[1] = yaxis->GetXmax();
11817 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11818 view->WCtoNDC(xx,u);
11819 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11820 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11821 rect2[4].SetX(rect2[0].GetX());
11822 rect2[4].SetY(rect2[0].GetY());
11823 xx[2] = zaxis->GetXmax();
11824 view->WCtoNDC(xx,u);
11825 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11826 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11827 xx[1] = yaxis->GetXmin();
11828 view->WCtoNDC(xx,u);
11829 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11830 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11831 xx[2] = zaxis->GetXmin();
11832 view->WCtoNDC(xx,u);
11833 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11834 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11835 gVirtualX->DrawPolyLine(5,rect2);
11836 }
11837 c->Clear();
11838 c->cd();
11839 TH2 *hp = (TH2*)h3->Project3D("zy");
11840 xaxis->SetRange(first,last);
11841 if (hp) {
11842 hp->SetFillColor(38);
11843 if (nbins==1)hp->SetTitle(TString::Format("ProjectionZY of binx=%d [x=%.1f..%.f]", binx,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx)));
11844 else hp->SetTitle(TString::Format("ProjectionZY, binx=[%d,%d] [x=%.1f..%.1f]", binx,binx2,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx2)));
11845 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11846 hp->SetYTitle(fH->GetZaxis()->GetTitle());
11847 hp->SetZTitle("Number of Entries");
11848 hp->Draw(fShowOption.Data());
11849 }
11850 }
11851 break;
11852 }
11853 c->Update();
11854}
@ kMouseMotion
Definition Buttons.h:23
@ kWheelUp
Definition Buttons.h:18
@ kButton1Motion
Definition Buttons.h:20
@ kButton1Up
Definition Buttons.h:19
@ kWheelDown
Definition Buttons.h:18
@ kButton1Down
Definition Buttons.h:17
@ kButton1Locate
Definition Buttons.h:22
@ kArrowVer
Definition GuiTypes.h:374
@ kPointer
Definition GuiTypes.h:375
Handle_t Window_t
Window handle.
Definition GuiTypes.h:29
#define d(i)
Definition RSha256.hxx:102
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
#define c(i)
Definition RSha256.hxx:101
#define g(i)
Definition RSha256.hxx:105
#define a(i)
Definition RSha256.hxx:99
#define h(i)
Definition RSha256.hxx:106
#define e(i)
Definition RSha256.hxx:103
short Style_t
Definition RtypesCore.h:89
int Int_t
Definition RtypesCore.h:45
short Color_t
Definition RtypesCore.h:92
unsigned int UInt_t
Definition RtypesCore.h:46
short Width_t
Definition RtypesCore.h:91
float Float_t
Definition RtypesCore.h:57
short Short_t
Definition RtypesCore.h:39
constexpr Bool_t kFALSE
Definition RtypesCore.h:101
double Double_t
Definition RtypesCore.h:59
constexpr Bool_t kTRUE
Definition RtypesCore.h:100
const char Option_t
Definition RtypesCore.h:66
#define BIT(n)
Definition Rtypes.h:85
#define ClassImp(name)
Definition Rtypes.h:377
@ kBlack
Definition Rtypes.h:65
R__EXTERN TEnv * gEnv
Definition TEnv.h:170
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t option
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void pixel
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t wmin
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize wid
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t np
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize id
Option_t Option_t TPoint TPoint const char x2
Option_t Option_t TPoint TPoint const char x1
Option_t Option_t TPoint TPoint angle
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void xpos
Option_t Option_t TPoint TPoint const char mode
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char backcolor
Option_t Option_t TPoint TPoint const char y2
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void ypos
Option_t Option_t width
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize fs
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t wmax
Option_t Option_t TPoint TPoint const char text
Option_t Option_t TPoint TPoint const char y1
R__EXTERN TH1 * gCurrentHist
R__EXTERN Hoption_t Hoption
float xmin
int ncx
float ymin
int ncy
float xmax
float ymax
static TString gStringStdDevZ
static TString gStringStdDevX
static TString gStringIntegralBinWidth
const UInt_t kCannotRotate
static TString gStringStdDev
const Int_t kNMAX
Hparam_t Hparam
const Int_t kMAXCONTOUR
static TString gStringOverflow
static TString gStringUnderflow
static TString gStringSkewnessY
static TString gStringMean
static TString gStringKurtosis
Hoption_t Hoption
static TString gStringMeanX
static TString gStringEntries
static TString gStringIntegral
static TString gStringKurtosisY
static TString gStringStdDevY
static TString gStringMeanY
static TString gStringSkewnessX
static TString gStringKurtosisX
static std::unique_ptr< TBox > gXHighlightBox
static std::unique_ptr< TBox > gYHighlightBox
static TString gStringSkewnessZ
TH1 * gCurrentHist
static TString gStringMeanZ
static TString gStringSkewness
static TString gStringKurtosisZ
const Int_t kMaxCuts
const Int_t kCYLINDRICAL
const Int_t kSPHERICAL
const Int_t kRAPIDITY
#define gROOT
Definition TROOT.h:406
R__EXTERN TStyle * gStyle
Definition TStyle.h:433
R__EXTERN TSystem * gSystem
Definition TSystem.h:555
const Int_t kCARTESIAN
Definition TView3D.cxx:33
const Int_t kPOLAR
Definition TView3D.cxx:34
#define gPad
#define gVirtualX
Definition TVirtualX.h:337
polygon * polys
Definition X3DBuffer.c:24
Int_t fN
Definition TArray.h:38
Draw all kinds of Arrows.
Definition TArrow.h:29
virtual Int_t GetNdivisions() const
Definition TAttAxis.h:36
virtual Float_t GetLabelOffset() const
Definition TAttAxis.h:40
virtual Float_t GetLabelSize() const
Definition TAttAxis.h:41
virtual Float_t GetTickLength() const
Definition TAttAxis.h:45
virtual Float_t GetTitleOffset() const
Definition TAttAxis.h:43
virtual Color_t GetFillColor() const
Return the fill area color.
Definition TAttFill.h:30
virtual Style_t GetFillStyle() const
Return the fill area style.
Definition TAttFill.h:31
virtual void SetFillColor(Color_t fcolor)
Set the fill area color.
Definition TAttFill.h:37
virtual void SetFillStyle(Style_t fstyle)
Set the fill area style.
Definition TAttFill.h:39
virtual void SetImageQuality(EImageQuality lquality)
Definition TAttImage.h:99
virtual Color_t GetLineColor() const
Return the line color.
Definition TAttLine.h:33
virtual void SetLineStyle(Style_t lstyle)
Set the line style.
Definition TAttLine.h:42
virtual Width_t GetLineWidth() const
Return the line width.
Definition TAttLine.h:35
virtual void SetLineWidth(Width_t lwidth)
Set the line width.
Definition TAttLine.h:43
virtual void SetLineColor(Color_t lcolor)
Set the line color.
Definition TAttLine.h:40
virtual Style_t GetLineStyle() const
Return the line style.
Definition TAttLine.h:34
virtual Style_t GetMarkerStyle() const
Return the marker style.
Definition TAttMarker.h:32
virtual void SetMarkerColor(Color_t mcolor=1)
Set the marker color.
Definition TAttMarker.h:38
virtual Color_t GetMarkerColor() const
Return the marker color.
Definition TAttMarker.h:31
virtual Size_t GetMarkerSize() const
Return the marker size.
Definition TAttMarker.h:33
virtual void SetMarkerStyle(Style_t mstyle=1)
Set the marker style.
Definition TAttMarker.h:40
virtual void SetMarkerSize(Size_t msize=1)
Set the marker size.
Definition TAttMarker.h:45
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:42
virtual Font_t GetTextFont() const
Return the text font.
Definition TAttText.h:35
virtual void SetTextAngle(Float_t tangle=0)
Set the text angle.
Definition TAttText.h:43
virtual void SetTextColor(Color_t tcolor=1)
Set the text color.
Definition TAttText.h:44
virtual void SetTextFont(Font_t tfont=62)
Set the text font.
Definition TAttText.h:46
virtual void SetTextSize(Float_t tsize=1)
Set the text size.
Definition TAttText.h:47
Class to manage histogram axis.
Definition TAxis.h:31
virtual Bool_t GetTimeDisplay() const
Definition TAxis.h:131
Bool_t IsAlphanumeric() const
Definition TAxis.h:88
const char * GetTitle() const override
Returns title of object.
Definition TAxis.h:135
virtual Double_t GetBinCenter(Int_t bin) const
Return center of bin.
Definition TAxis.cxx:478
Bool_t CanExtend() const
Definition TAxis.h:86
const TArrayD * GetXbins() const
Definition TAxis.h:136
Double_t GetXmax() const
Definition TAxis.h:140
const char * GetBinLabel(Int_t bin) const
Return label for bin.
Definition TAxis.cxx:440
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:518
virtual Int_t FindFixBin(Double_t x) const
Find bin number corresponding to abscissa x.
Definition TAxis.cxx:419
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:132
Int_t GetLast() const
Return last bin on the axis i.e.
Definition TAxis.cxx:469
virtual const char * GetTimeFormatOnly() const
Return only the time format from the string fTimeFormat.
Definition TAxis.cxx:599
Double_t GetXmin() const
Definition TAxis.h:139
Int_t GetNbins() const
Definition TAxis.h:125
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:1080
virtual const char * GetTimeFormat() const
Definition TAxis.h:132
virtual void SetRange(Int_t first=0, Int_t last=0)
Set the viewing range for the axis using bin numbers.
Definition TAxis.cxx:1052
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width.
Definition TAxis.cxx:540
virtual Double_t GetBinUpEdge(Int_t bin) const
Return up edge of bin.
Definition TAxis.cxx:528
Int_t GetFirst() const
Return first bin on the axis i.e.
Definition TAxis.cxx:458
THashList * GetLabels() const
Definition TAxis.h:121
Create a Box.
Definition TBox.h:22
The candle plot painter class.
Definition TCandle.h:27
void SetLog(int x, int y, int z)
Definition TCandle.h:118
CandleOption
Definition TCandle.h:30
void SetHistoWidth(const Double_t width)
Definition TCandle.h:122
virtual void Paint(Option_t *option="")
Paint one candle with its current attributes.
Definition TCandle.cxx:666
Bool_t IsViolinScaled() const
Returns true if violin plot should be scaled.
Definition TCandle.cxx:191
Bool_t IsHorizontal() const
Definition TCandle.h:112
int ParseOption(char *optin)
Parsing of the option-string.
Definition TCandle.cxx:244
void SetOption(CandleOption opt)
Definition TCandle.h:117
void SetHistogram(TH1D *proj)
Definition TCandle.h:123
Bool_t IsCandleScaled() const
Returns true if candle plot should be scaled.
Definition TCandle.cxx:183
void SetCandleWidth(const Double_t width)
Definition TCandle.h:121
void SetAxisPosition(const Double_t candlePos)
Definition TCandle.h:119
static Bool_t SupportAlpha()
Static function returning "true" if transparency is supported.
Definition TCanvas.cxx:2463
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:2968
void SetName(const char *name)
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
void Paint(Option_t *option="") override
Paint all objects in this collection.
The color creation and management class.
Definition TColor.h:21
virtual void SetRGB(Float_t r, Float_t g, Float_t b)
Initialize this color and its associated colors.
Definition TColor.cxx:1775
static void RGBtoHLS(Float_t r, Float_t g, Float_t b, Float_t &h, Float_t &l, Float_t &s)
Definition TColor.h:81
virtual void GetRGB(Float_t &r, Float_t &g, Float_t &b) const
Definition TColor.h:54
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:1839
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:2015
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:2047
static void HLStoRGB(Float_t h, Float_t l, Float_t s, Float_t &r, Float_t &g, Float_t &b)
Definition TColor.h:76
virtual void SetAlpha(Float_t a)
Definition TColor.h:70
To draw a Crown.
Definition TCrown.h:19
void Paint(Option_t *option="") override
Paint this crown with its current attributes.
Definition TCrown.cxx:218
Graphical cut class.
Definition TCutG.h:20
static TClass * Class()
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition TEnv.cxx:491
1-Dim function class
Definition TF1.h:233
virtual Double_t GetXmax() const
Definition TF1.h:582
static TClass * Class()
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:3394
virtual Double_t GetMaximumStored() const
Definition TF1.h:499
@ kNotDraw
Definition TF1.h:346
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:3407
virtual Double_t Eval(Double_t x, Double_t y=0, Double_t z=0, Double_t t=0) const
Evaluate this function.
Definition TF1.cxx:1441
virtual Double_t GetXmin() const
Definition TF1.h:578
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:742
void SetRange(Double_t xmin, Double_t xmax) override
Initialize the upper and lower bounds to draw the function.
Definition TF2.h:146
static TClass * Class()
A 3-Dim function with parameters.
Definition TF3.h:28
The axis painter class.
Definition TGaxis.h:24
void SetTimeFormat(const char *tformat)
Change the format used for time plotting.
Definition TGaxis.cxx:2969
virtual void PaintAxis(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax, Double_t &wmin, Double_t &wmax, Int_t &ndiv, Option_t *chopt="", Double_t gridlength=0, Bool_t drawGridOnly=kFALSE)
Control function to draw an axis.
Definition TGaxis.cxx:1008
void SetTitleOffset(Float_t titleoffset=1)
Definition TGaxis.h:128
virtual void SetTitle(const char *title="")
Change the title of the axis.
Definition TGaxis.cxx:2942
void SetLabelOffset(Float_t labeloffset)
Definition TGaxis.h:106
virtual void ImportAxisAttributes(TAxis *axis)
Internal method to import TAxis attributes to this TGaxis.
Definition TGaxis.cxx:955
void SetTickSize(Float_t ticksize)
Definition TGaxis.h:122
void SetLabelSize(Float_t labelsize)
Definition TGaxis.h:107
void SetOption(Option_t *option="")
To set axis options.
Definition TGaxis.cxx:2934
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:76
1-D histogram with a double per channel (see TH1 documentation)
Definition TH1.h:669
1-D histogram with a float per channel (see TH1 documentation)
Definition TH1.h:621
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:59
TAxis * GetZaxis()
Definition TH1.h:326
void SetTitle(const char *title) override
Change/set the title.
Definition TH1.cxx:6686
virtual EBinErrorOpt GetBinErrorOption() const
Definition TH1.h:273
virtual Float_t GetBarWidth() const
Definition TH1.h:257
virtual Double_t GetMinimumStored() const
Definition TH1.h:293
virtual Float_t GetBarOffset() const
Definition TH1.h:256
static TClass * Class()
virtual Double_t GetStdDev(Int_t axis=1) const
Returns the Standard Deviation (Sigma).
Definition TH1.cxx:7575
virtual Int_t GetNbinsY() const
Definition TH1.h:298
virtual Double_t GetBinError(Int_t bin) const
Return value of error associated to bin number bin.
Definition TH1.cxx:9031
virtual Int_t GetNbinsZ() const
Definition TH1.h:299
virtual Double_t GetNormFactor() const
Definition TH1.h:301
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:7503
virtual Double_t GetSkewness(Int_t axis=1) const
Definition TH1.cxx:7639
virtual Double_t GetContourLevelPad(Int_t level) const
Return the value of contour number "level" in Pad coordinates.
Definition TH1.cxx:8408
virtual void SetXTitle(const char *title)
Definition TH1.h:418
virtual Int_t GetDimension() const
Definition TH1.h:283
static void AddDirectory(Bool_t add=kTRUE)
Sets the flag controlling the automatic add of histograms in memory.
Definition TH1.cxx:1294
@ kNoTitle
Don't draw the histogram title.
Definition TH1.h:170
@ kUserContour
User specified contour levels.
Definition TH1.h:166
@ kNoStats
Don't draw stats box.
Definition TH1.h:165
TAxis * GetXaxis()
Definition TH1.h:324
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:4929
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:8513
virtual Int_t GetNbinsX() const
Definition TH1.h:297
virtual void SetMaximum(Double_t maximum=-1111)
Definition TH1.h:403
TAxis * GetYaxis()
Definition TH1.h:325
virtual Double_t GetBinErrorLow(Int_t bin) const
Return lower error associated to bin number bin.
Definition TH1.cxx:9047
void Draw(Option_t *option="") override
Draw this histogram with options.
Definition TH1.cxx:3066
virtual void SetMinimum(Double_t minimum=-1111)
Definition TH1.h:404
virtual Double_t Integral(Option_t *option="") const
Return integral of bin contents.
Definition TH1.cxx:7909
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:9190
virtual Double_t GetBinLowEdge(Int_t bin) const
Return bin lower edge for 1D histogram.
Definition TH1.cxx:9120
virtual Double_t GetEntries() const
Return the current number of entries.
Definition TH1.cxx:4423
virtual void SetZTitle(const char *title)
Definition TH1.h:420
TList * GetListOfFunctions() const
Definition TH1.h:244
virtual Double_t GetMeanError(Int_t axis=1) const
Return standard error of mean of this histogram along the X axis.
Definition TH1.cxx:7543
virtual Double_t GetMaximumStored() const
Definition TH1.h:289
virtual void GetMinimumAndMaximum(Double_t &min, Double_t &max) const
Retrieve the minimum and maximum values in the histogram.
Definition TH1.cxx:8699
virtual Int_t GetMaximumBin() const
Return location of bin with maximum value in the range.
Definition TH1.cxx:8545
@ kNormal
Errors with Normal (Wald) approximation: errorUp=errorLow= sqrt(N)
Definition TH1.h:65
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition TH1.cxx:5029
virtual Int_t GetContour(Double_t *levels=nullptr)
Return contour values into array levels if pointer levels is non zero.
Definition TH1.cxx:8379
const Double_t * GetBuffer() const
Definition TH1.h:239
virtual Bool_t IsHighlight() const
Definition TH1.h:338
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width for 1D histogram.
Definition TH1.cxx:9131
virtual void SetContour(Int_t nlevels, const Double_t *levels=nullptr)
Set the number and values of contour levels.
Definition TH1.cxx:8451
virtual Double_t GetBinErrorUp(Int_t bin) const
Return upper error associated to bin number bin.
Definition TH1.cxx:9078
virtual void SetYTitle(const char *title)
Definition TH1.h:419
virtual Int_t GetSumw2N() const
Definition TH1.h:315
virtual Double_t GetStdDevError(Int_t axis=1) const
Return error of standard deviation estimation for Normal distribution.
Definition TH1.cxx:7623
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:8603
virtual Double_t GetSumOfWeights() const
Return the sum of weights excluding under/overflows.
Definition TH1.cxx:7885
static Bool_t AddDirectoryStatus()
Static function: cannot be inlined on Windows/NT.
Definition TH1.cxx:754
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:5213
virtual Int_t BufferEmpty(Int_t action=0)
Fill histogram with all entries in the buffer.
Definition TH1.cxx:1414
virtual Double_t GetKurtosis(Int_t axis=1) const
Definition TH1.cxx:7712
2-D histogram with a double per channel (see TH1 documentation)
Definition TH2.h:357
2-D histogram with a float per channel (see TH1 documentation)
Definition TH2.h:307
Helper class to represent a bin in the TH2Poly histogram.
Definition TH2Poly.h:25
2D Histogram with Polygonal Bins
Definition TH2Poly.h:66
static TClass * Class()
Service class for 2-D histogram classes.
Definition TH2.h:30
static TClass * Class()
The 3-D histogram classes derived from the 1-D histogram classes.
Definition TH3.h:31
static TClass * Class()
The Histogram stack class.
Definition THStack.h:40
static TClass * Class()
The histogram painter class.
static Int_t ProjectSinusoidal2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function code for sinusoidal projection from Ernst-Jan Buis Source https://en....
void Paint(Option_t *option="") override
Control routine to paint any kind of histograms
TAxis * fYaxis
Pointer to Y axis.
std::unique_ptr< TPainter3dAlgorithms > fLego
Pointer to a TPainter3dAlgorithms object.
std::vector< Double_t > fXbuf
X buffer coordinates.
Int_t fXHighlightBin
X highlight bin.
TF3 * fCurrentF3
Current TF3 function.
virtual void PaintErrors(Option_t *option)
Draw 1D histograms error bars.
~THistPainter() override
destructor.
Int_t fShowProjection2
True if a second projection must be drawn (when calling SetShowProjectionXY on a TH2)
virtual void PaintTF3()
Control function to draw a 3D implicit functions.
virtual Int_t TableInit()
Initialize various options to draw 2D histograms.
virtual void PaintTH2PolyScatterPlot(Option_t *option)
Control function to draw a TH2Poly as a scatter plot.
static Int_t ProjectMollweide2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
static Int_t ProjectAitoff2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
virtual void PaintText(Option_t *option)
Control function to draw a 1D/2D histograms with the bin values.
Int_t DistancetoPrimitive(Int_t px, Int_t py) override
Compute the distance from the point px,py to a line.
virtual void PaintAxis(Bool_t drawGridOnly=kFALSE)
Draw axis (2D case) of an histogram.
virtual void PaintColorLevelsFast(Option_t *option)
[Rendering scheme for the COL2 and COLZ2 options] (HP14)
virtual Int_t PaintInit()
Compute histogram parameters used by the drawing routines.
virtual void Paint2DErrors(Option_t *option)
Draw 2D histograms errors.
Int_t fYHighlightBin
Y highlight bin.
virtual void PaintCandlePlot(Option_t *option)
Control function to draw a 2D histogram as a candle (box) plot or violin plot
virtual void PaintScatterPlot(Option_t *option)
Control function to draw a 2D histogram as a scatter plot.
void SetShowProjectionXY(const char *option, Int_t nbinsY, Int_t nbinsX) override
virtual void PaintLego(Option_t *option)
Control function to draw a 2D histogram as a lego plot.
virtual void PaintH3(Option_t *option="")
Control function to draw a 3D histograms.
Int_t fNcuts
Number of graphical cuts.
TString fShowOption
Option to draw the projection.
virtual void PaintHighlightBin(Option_t *option="")
Paint highlight bin as TBox object.
virtual void PaintTH2PolyBins(Option_t *option)
Control function to draw a TH2Poly bins' contours.
virtual Int_t PaintContourLine(Double_t elev1, Int_t icont1, Double_t x1, Double_t y1, Double_t elev2, Int_t icont2, Double_t x2, Double_t y2, Double_t *xarr, Double_t *yarr, Int_t *itarr, Double_t *levels)
Fill the matrix xarr and yarr for Contour Plot.
Int_t fShowProjection
True if a projection must be drawn.
virtual void PaintLegoAxis(TGaxis *axis, Double_t ang)
Draw the axis for legos and surface plots.
virtual void PaintTriangles(Option_t *option)
Control function to draw a table using Delaunay triangles.
virtual void HighlightBin(Int_t px, Int_t py)
Check on highlight bin.
virtual void PaintH3Box(Int_t iopt)
Control function to draw a 3D histogram with boxes.
Int_t MakeCuts(char *cutsopt) override
Decode string choptin and fill Graphical cuts structure.
TList * fFunctions
Pointer to histogram list of functions.
void DrawPanel() override
Display a panel with all histogram drawing options.
std::unique_ptr< TPie > fPie
Pointer to a TPie in case of option PIE.
static void PaintSpecialObjects(const TObject *obj, Option_t *option)
Static function to paint special objects like vectors and matrices.
virtual void PaintTitle()
new TGaxis/////////////////// Draw the histogram title
virtual void PaintTH2PolyColorLevels(Option_t *option)
Control function to draw a TH2Poly as a color plot.
virtual std::vector< THistRenderingRegion > ComputeRenderingRegions(TAxis *pAxis, Int_t nPixels, bool isLog)
Returns the rendering regions for an axis to use in the COL2 option.
virtual void ShowProjectionX(Int_t px, Int_t py)
Show projection onto X.
virtual void PaintPalette()
Paint the color palette on the right side of the pad.
TAxis * fXaxis
Pointer to X axis.
virtual void PaintStat2(Int_t dostat, TF1 *fit)
Draw the statistics box for 2D histograms.
virtual void PaintArrows(Option_t *option)
Control function to draw a table as an arrow plot
virtual void RecalculateRange()
Recompute the histogram range following graphics operations.
void PaintStat(Int_t dostat, TF1 *fit) override
Draw the statistics box for 1D and profile histograms.
static Int_t ProjectParabolic2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function code for parabolic projection from Ernst-Jan Buis.
std::unique_ptr< TGraph2DPainter > fGraph2DPainter
Pointer to a TGraph2DPainter object.
virtual void PaintBarH(Option_t *option)
Draw a bar char in a rotated pad (X vertical, Y horizontal)
virtual void PaintStat3(Int_t dostat, TF1 *fit)
Draw the statistics box for 3D histograms.
virtual void PaintSurface(Option_t *option)
Control function to draw a 2D histogram as a surface plot.
TList * fStack
Pointer to stack of histograms (if any)
THistPainter()
Default constructor.
TH1 * fH
Pointer to histogram to paint.
virtual void PaintTH2PolyText(Option_t *option)
Control function to draw a TH2Poly as a text plot.
virtual void ShowProjection3(Int_t px, Int_t py)
Show projection (specified by fShowProjection) of a TH3.
TAxis * fZaxis
Pointer to Z axis.
void SetHistogram(TH1 *h) override
Set current histogram to h
virtual void PaintFunction(Option_t *option)
[Paint functions associated to an histogram.](HP28")
virtual void PaintBar(Option_t *option)
Draw a bar-chart in a normal pad.
static Int_t ProjectMercator2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
virtual void PaintBoxes(Option_t *option)
Control function to draw a 2D histogram as a box plot
virtual Int_t MakeChopt(Option_t *option)
Decode string choptin and fill Hoption structure.
char * GetObjectInfo(Int_t px, Int_t py) const override
Display the histogram info (bin number, contents, integral up to bin corresponding to cursor position...
TList * GetContourList(Double_t contour) const override
Get a contour (as a list of TGraphs) using the Delaunay triangulation.
void ProcessMessage(const char *mess, const TObject *obj) override
Process message mess.
void SetShowProjection(const char *option, Int_t nbins) override
Set projection.
virtual void ShowProjectionY(Int_t px, Int_t py)
Show projection onto Y.
static const char * GetBestFormat(Double_t v, Double_t e, const char *f)
This function returns the best format to print the error value (e) knowing the parameter value (v) an...
virtual void PaintContour(Option_t *option)
Control function to draw a 2D histogram as a contour plot.
TCutG * fCuts[kMaxCuts]
Pointers to graphical cuts.
virtual void PaintTable(Option_t *option)
Control function to draw 2D/3D histograms (tables).
void ExecuteEvent(Int_t event, Int_t px, Int_t py) override
Execute the actions corresponding to event.
virtual Int_t PaintInitH()
Compute histogram parameters used by the drawing routines for a rotated pad.
virtual void PaintFrame()
Calculate range and clear pad (canvas).
Int_t fCutsOpt[kMaxCuts]
Sign of each cut.
virtual void PaintH3Iso()
Control function to draw a 3D histogram with Iso Surfaces.
std::vector< Double_t > fYbuf
Y buffer coordinates.
virtual void PaintH3BoxRaster()
Control function to draw a 3D histogram with boxes.
virtual void PaintHist(Option_t *option)
Control routine to draw 1D histograms
void SetHighlight() override
Set highlight (enable/disable) mode for fH.
virtual void DefineColorLevels(Int_t ndivz)
Define the color levels used to paint legos, surfaces etc..
TString fObjectInfo
virtual void PaintColorLevels(Option_t *option)
Control function to draw a 2D histogram as a color plot.
Bool_t IsInside(Int_t x, Int_t y) override
Return kTRUE if the cell ix, iy is inside one of the graphical cuts.
A class to define a conversion from pixel values to pixel color.
Definition TAttImage.h:33
static TImagePalette * CreateCOLPalette(Int_t nContours)
Factory method to creates an image palette for histogram plotting.
An abstract interface to image processing library.
Definition TImage.h:29
static TImage * Create()
Create an image.
Definition TImage.cxx:35
virtual void SetImage(const Double_t *, UInt_t, UInt_t, TImagePalette *=nullptr)
Definition TImage.h:116
virtual void PaintImage(Drawable_t, Int_t, Int_t, Int_t=0, Int_t=0, UInt_t=0, UInt_t=0, Option_t *="")
Definition TImage.h:243
void Reset()
To draw Mathematical Formula.
Definition TLatex.h:18
A doubly linked list.
Definition TList.h:38
TObject * FindObject(const char *name) const override
Find an object in this list using its name.
Definition TList.cxx:576
void Add(TObject *obj) override
Definition TList.h:83
TObject * Remove(TObject *obj) override
Remove object from the list.
Definition TList.cxx:820
TObject * First() const override
Return the first object in the list. Returns 0 when list is empty.
Definition TList.cxx:657
virtual TObjLink * FirstLink() const
Definition TList.h:104
void Delete(Option_t *option="") override
Remove all objects from the list AND delete all heap based objects.
Definition TList.cxx:468
TObject * At(Int_t idx) const override
Returns the object at position idx. Returns 0 if idx is out of range.
Definition TList.cxx:355
void AddFirst(TObject *obj) override
Add object at the beginning of the list.
Definition TList.cxx:98
TMatrixTBase.
static TClass * Class()
A TMultiGraph is a collection of TGraph (or derived) objects.
Definition TMultiGraph.h:34
TList * GetListOfGraphs() const
Definition TMultiGraph.h:68
static TClass * Class()
virtual Int_t IsInside(Double_t x, Double_t y) const
Return 1 if the point (x,y) is inside one of the graphs 0 otherwise.
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition TNamed.cxx:164
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:48
An array of TObjects.
Definition TObjArray.h:31
void Delete(Option_t *option="") override
Remove all objects from the array AND delete all heap based objects.
TObject * At(Int_t idx) const override
Definition TObjArray.h:164
TObject * FindObject(const char *name) const override
Find an object in this collection using its name.
void Add(TObject *obj) override
Definition TObjArray.h:68
Mother of all ROOT objects.
Definition TObject.h:41
virtual void Clear(Option_t *="")
Definition TObject.h:119
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:439
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:199
virtual Option_t * GetDrawOption() const
Get option used by the graphics system to draw this object.
Definition TObject.cxx:423
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:973
virtual TObject * FindObject(const char *name) const
Must be redefined in derived classes.
Definition TObject.cxx:403
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:780
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:525
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:987
virtual const char * GetTitle() const
Returns title of object.
Definition TObject.cxx:483
virtual TClass * IsA() const
Definition TObject.h:243
virtual void Paint(Option_t *option="")
This method must be overridden if a class wants to paint itself.
Definition TObject.cxx:607
@ kCannotPick
if object in a pad cannot be picked
Definition TObject.h:67
@ kCanDelete
if object in a list can be deleted
Definition TObject.h:62
@ kMustCleanup
if object destructor must call RecursiveRemove()
Definition TObject.h:64
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.
void Paint(Option_t *option="") override
Paint the palette.
void SetHistogram(TH1 *h)
TH1 * GetHistogram()
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:52
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.
void Draw(Option_t *option="") override
Draw this pavetext with its current attributes.
void Paint(Option_t *option="") override
Paint this pavetext with its current attributes.
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:56
virtual void SetName(const char *name="")
Definition TPave.h:79
virtual void SetBorderSize(Int_t bordersize=4)
Sets the border size of the TPave box and shadow.
Definition TPave.h:77
Double_t GetX1NDC() const
Definition TPave.h:59
virtual void SetX2NDC(Double_t x2)
Definition TPave.h:83
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()
virtual Double_t GetBinEntries(Int_t bin) const
Return bin entries of a Profile2D histogram.
Profile Histogram.
Definition TProfile.h:32
virtual Double_t GetBinEntries(Int_t bin) const
Return bin entries of a Profile histogram.
Definition TProfile.cxx:837
static TClass * Class()
Random number generator class based on the maximally quidistributed combined Tausworthe generator by ...
Definition TRandom2.h:27
Double_t Rndm() override
TausWorth generator from L'Ecuyer, uses as seed 3x32bits integers Use a mask of 0xffffffffUL to make ...
Definition TRandom2.cxx:55
Sequenceable collection abstract base class.
Basic string class.
Definition TString.h:139
Ssiz_t Length() const
Definition TString.h:417
void ToLower()
Change string to lower-case.
Definition TString.cxx:1182
const char * Data() const
Definition TString.h:376
TString & Remove(Ssiz_t pos)
Definition TString.h:685
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2378
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2356
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:632
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:651
Int_t GetOptStat() const
Definition TStyle.h:243
Color_t GetStatTextColor() const
Definition TStyle.h:256
Float_t GetTitleX() const
Definition TStyle.h:278
Int_t GetOptTitle() const
Definition TStyle.h:244
Float_t GetStatFontSize() const
Definition TStyle.h:259
Float_t GetBarOffset() const
Definition TStyle.h:181
Float_t GetStatX() const
Definition TStyle.h:262
Float_t GetTitleSize(Option_t *axis="X") const
Return title size.
Definition TStyle.cxx:1236
Float_t GetTitleY() const
Definition TStyle.h:279
Style_t GetTitleFont(Option_t *axis="X") const
Return title font.
Definition TStyle.cxx:1212
Bool_t GetHistMinimumZero() const
Definition TStyle.h:235
Float_t GetStatY() const
Definition TStyle.h:263
Color_t GetTitleFillColor() const
Definition TStyle.h:269
Style_t GetTitleStyle() const
Definition TStyle.h:271
Color_t GetStatColor() const
Definition TStyle.h:255
Float_t GetBarWidth() const
Definition TStyle.h:182
void SetDrawBorder(Int_t drawborder=1)
Definition TStyle.h:340
Float_t GetStatH() const
Definition TStyle.h:265
Width_t GetTitleBorderSize() const
Definition TStyle.h:273
Int_t GetColorPalette(Int_t i) const
Return color number i in current palette.
Definition TStyle.cxx:1097
Float_t GetErrorX() const
Definition TStyle.h:185
Double_t GetHistTopMargin() const
Definition TStyle.h:236
void SetBarOffset(Float_t baroff=0.5)
Definition TStyle.h:333
Float_t GetEndErrorSize() const
Definition TStyle.h:184
Int_t GetDrawBorder() const
Definition TStyle.h:183
Width_t GetStatBorderSize() const
Definition TStyle.h:257
Color_t GetTitleTextColor() const
Definition TStyle.h:270
void SetBarWidth(Float_t barwidth=0.5)
Definition TStyle.h:334
Float_t GetTitleH() const
Definition TStyle.h:281
Style_t GetStatStyle() const
Definition TStyle.h:260
Float_t GetStatW() const
Definition TStyle.h:264
const char * GetFitFormat() const
Definition TStyle.h:198
const char * GetStatFormat() const
Definition TStyle.h:261
Int_t GetNumberOfColors() const
Return number of colors in the color palette.
Definition TStyle.cxx:1171
Int_t GetOptFit() const
Definition TStyle.h:242
Int_t GetNumberContours() const
Definition TStyle.h:239
const char * GetPaintTextFormat() const
Definition TStyle.h:248
Style_t GetStatFont() const
Definition TStyle.h:258
Float_t GetTitleFontSize() const
Definition TStyle.h:272
Int_t GetTitleAlign() const
Definition TStyle.h:268
Float_t GetTitleW() const
Definition TStyle.h:280
virtual int Load(const char *module, const char *entry="", Bool_t system=kFALSE)
Load a shared library.
Definition TSystem.cxx:1857
Base class for several text objects.
Definition TText.h:22
TVectorT.
Definition TVectorT.h:27
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.
virtual void Show()
small helper class to store/restore gPad context in TPad methods
Definition TVirtualPad.h:61
auto GetSaved() const
Definition TVirtualPad.h:69
TVirtualPad is an abstract base class for the Pad and Canvas classes.
Definition TVirtualPad.h:51
virtual void Close(Option_t *option="")=0
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:693
Short_t Max(Short_t a, Short_t b)
Returns the largest of a and b.
Definition TMathBase.h:250
Double_t Prob(Double_t chi2, Int_t ndf)
Computation of the probability for a certain Chi-squared (chi2) and number of degrees of freedom (ndf...
Definition TMath.cxx:637
Double_t ATan(Double_t)
Returns the principal value of the arc tangent of x, expressed in radians.
Definition TMath.h:640
constexpr Double_t PiOver2()
Definition TMath.h:51
Double_t Log(Double_t x)
Returns the natural logarithm of x.
Definition TMath.h:756
constexpr Double_t DegToRad()
Conversion from degree to radian: .
Definition TMath.h:79
Double_t Sqrt(Double_t x)
Returns the square root of x.
Definition TMath.h:662
LongDouble_t Power(LongDouble_t x, LongDouble_t y)
Returns x raised to the power y.
Definition TMath.h:721
Short_t Min(Short_t a, Short_t b)
Returns the smallest of a and b.
Definition TMathBase.h:198
Double_t Cos(Double_t)
Returns the cosine of an angle of x radians.
Definition TMath.h:594
constexpr Double_t Pi()
Definition TMath.h:37
Bool_t AreEqualRel(Double_t af, Double_t bf, Double_t relPrec)
Comparing floating points.
Definition TMath.h:426
Double_t Sin(Double_t)
Returns the sine of an angle of x radians.
Definition TMath.h:588
Double_t Tan(Double_t)
Returns the tangent of an angle of x radians.
Definition TMath.h:600
Long64_t BinarySearch(Long64_t n, const T *array, T value)
Binary search in an array of n values to locate value.
Definition TMathBase.h:347
constexpr Double_t RadToDeg()
Conversion from radian to degree: .
Definition TMath.h:72
Double_t Log10(Double_t x)
Returns the common (base-10) logarithm of x.
Definition TMath.h:762
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:123
Definition graph.py:1
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