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.ch/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;
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
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();
7102 Hparam.xlast = last;
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;
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();
7351 Hparam.xlast = last;
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 axis->PaintAxis(z1[0], z1[1], z2[0], z2[1], bmin, bmax, ndivz, chopaz);
8409 }
8410
8411 //fH->SetLineStyle(1); /// otherwise fEdgeStyle[i] gets overwritten!
8412}
8413
8414////////////////////////////////////////////////////////////////////////////////
8415/// [Paint the color palette on the right side of the pad.](\ref HP22)
8416
8418{
8419 TPaletteAxis *palette = (TPaletteAxis*)fFunctions->FindObject("palette");
8420 TView *view = gPad ? gPad->GetView() : nullptr;
8421 if (palette) {
8422 if (view) {
8423 if (!palette->TestBit(TPaletteAxis::kHasView)) {
8424 fFunctions->Remove(palette);
8425 delete palette; palette = nullptr;
8426 }
8427 } else {
8428 if (palette->TestBit(TPaletteAxis::kHasView)) {
8429 fFunctions->Remove(palette);
8430 delete palette; palette = nullptr;
8431 }
8432 }
8433 // make sure the histogram member of the palette is setup correctly. It may not be after a Clone()
8434 if (palette && !palette->GetHistogram()) palette->SetHistogram(fH);
8435 }
8436
8437 if (!palette) {
8438 Double_t xup = gPad->GetUxmax();
8439 Double_t x2 = gPad->PadtoX(gPad->GetX2());
8440 Double_t ymin = gPad->PadtoY(gPad->GetUymin());
8441 Double_t ymax = gPad->PadtoY(gPad->GetUymax());
8442 Double_t xr = 0.05*(gPad->GetX2() - gPad->GetX1());
8443 Double_t xmin = gPad->PadtoX(xup +0.1*xr);
8444 Double_t xmax = gPad->PadtoX(xup + xr);
8445 if (xmax > x2) xmax = gPad->PadtoX(gPad->GetX2()-0.01*xr);
8446 palette = new TPaletteAxis(xmin,ymin,xmax,ymax,fH);
8447 fFunctions->AddFirst(palette);
8448 palette->Paint();
8449 }
8450}
8451
8452////////////////////////////////////////////////////////////////////////////////
8453/// [Control function to draw a 2D histogram as a scatter plot.](\ref HP11)
8454
8456{
8457
8458 fH->TAttMarker::Modify();
8459
8460 Int_t k, marker;
8461 Double_t dz, z, xk,xstep, yk, ystep;
8462 Double_t scale = 1;
8463 Bool_t ltest = kFALSE;
8464 Double_t zmax = fH->GetMaximum();
8465 Double_t zmin = fH->GetMinimum();
8466 if (zmin == 0 && zmax == 0) return;
8467 if (zmin == zmax) {
8468 zmax += 0.1*TMath::Abs(zmax);
8469 zmin -= 0.1*TMath::Abs(zmin);
8470 }
8472 if (Hoption.Logz) {
8473 if (zmin > 0) zmin = TMath::Log10(zmin);
8474 else zmin = 0;
8475 if (zmax > 0) zmax = TMath::Log10(zmax);
8476 else zmax = 0;
8477 if (zmin == 0 && zmax == 0) return;
8478 dz = zmax - zmin;
8479 scale = 100/dz;
8480 if (ncells > 10000) scale /= 5;
8481 ltest = kTRUE;
8482 } else {
8483 dz = zmax - zmin;
8484 if (dz >= kNMAX || zmax < 1) {
8485 scale = (kNMAX-1)/dz;
8486 if (ncells > 10000) scale /= 5;
8487 ltest = kTRUE;
8488 }
8489 }
8490 if (fH->GetMinimumStored() == -1111) {
8491 Double_t yMARGIN = gStyle->GetHistTopMargin();
8492 if (Hoption.MinimumZero) {
8493 if (zmin >= 0) zmin = 0;
8494 else zmin -= yMARGIN*(zmax-zmin);
8495 } else {
8496 Double_t dzmin = yMARGIN*(zmax-zmin);
8497 if (zmin >= 0 && (zmin-dzmin <= 0)) zmin = 0;
8498 else zmin -= dzmin;
8499 }
8500 }
8501
8502 TString opt = option;
8503 opt.ToLower();
8504 if (opt.Contains("scat=")) {
8505 char optscat[100];
8506 strlcpy(optscat,opt.Data(),100);
8507 char *oscat = strstr(optscat,"scat=");
8508 char *blank = strstr(oscat," "); if (blank) *blank = 0;
8509 sscanf(oscat+5,"%lg",&scale);
8510 }
8511 // use an independent instance of a random generator
8512 // instead of gRandom to avoid conflicts and
8513 // to get same random numbers when drawing the same histogram
8514 TRandom2 random;
8515 marker=0;
8516 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
8517 yk = fYaxis->GetBinLowEdge(j);
8518 ystep = fYaxis->GetBinWidth(j);
8519 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
8520 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
8521 xk = fXaxis->GetBinLowEdge(i);
8522 xstep = fXaxis->GetBinWidth(i);
8523 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
8524 z = fH->GetBinContent(bin);
8525 if (z < zmin) z = zmin;
8526 if (z > zmax) z = zmax;
8527 if (Hoption.Logz) {
8528 if (z > 0) z = TMath::Log10(z) - zmin;
8529 } else {
8530 z -= zmin;
8531 }
8532 if (z <= 0) continue;
8533 k = Int_t(z*scale);
8534 if (ltest) k++;
8535 if (k > 0) {
8536 for (Int_t loop=0; loop<k; loop++) {
8537 if (k+marker >= kNMAX) {
8538 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
8539 marker=0;
8540 }
8541 fXbuf[marker] = (random.Rndm()*xstep) + xk;
8542 fYbuf[marker] = (random.Rndm()*ystep) + yk;
8543 if (Hoption.Logx) {
8544 if (fXbuf[marker] > 0) fXbuf[marker] = TMath::Log10(fXbuf[marker]);
8545 else break;
8546 }
8547 if (Hoption.Logy) {
8548 if (fYbuf[marker] > 0) fYbuf[marker] = TMath::Log10(fYbuf[marker]);
8549 else break;
8550 }
8551 if (fXbuf[marker] < gPad->GetUxmin()) break;
8552 if (fYbuf[marker] < gPad->GetUymin()) break;
8553 if (fXbuf[marker] > gPad->GetUxmax()) break;
8554 if (fYbuf[marker] > gPad->GetUymax()) break;
8555 marker++;
8556 }
8557 }
8558 }
8559 }
8560 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
8561
8563}
8564
8565////////////////////////////////////////////////////////////////////////////////
8566/// Static function to paint special objects like vectors and matrices.
8567/// This function is called via `gROOT->ProcessLine` to paint these objects
8568/// without having a direct dependency of the graphics or histogramming
8569/// system.
8570
8572{
8573
8574 if (!obj) return;
8577
8578 if (obj->InheritsFrom(TMatrixFBase::Class())) {
8579 // case TMatrixF
8580 TH2F *R__TMatrixFBase = new TH2F((TMatrixFBase &)*obj);
8581 R__TMatrixFBase->SetBit(kCanDelete);
8582 R__TMatrixFBase->Draw(option);
8583
8584 } else if (obj->InheritsFrom(TMatrixDBase::Class())) {
8585 // case TMatrixD
8586 TH2D *R__TMatrixDBase = new TH2D((TMatrixDBase &)*obj);
8587 R__TMatrixDBase->SetBit(kCanDelete);
8588 R__TMatrixDBase->Draw(option);
8589
8590 } else if (obj->InheritsFrom(TVectorF::Class())) {
8591 //case TVectorF
8592 TH1F *R__TVectorF = new TH1F((TVectorF &)*obj);
8593 R__TVectorF->SetBit(kCanDelete);
8594 R__TVectorF->Draw(option);
8595
8596 } else if (obj->InheritsFrom(TVectorD::Class())) {
8597 //case TVectorD
8598 TH1D *R__TVectorD = new TH1D((TVectorD &)*obj);
8599 R__TVectorD->SetBit(kCanDelete);
8600 R__TVectorD->Draw(option);
8601 }
8602
8603 TH1::AddDirectory(status);
8604}
8605
8606////////////////////////////////////////////////////////////////////////////////
8607/// [Draw the statistics box for 1D and profile histograms.](\ref HP07)
8608
8610{
8611 TString tt, tf;
8612 Int_t dofit;
8613 TPaveStats *stats = nullptr;
8614 TIter next(fFunctions);
8615 while (auto obj = next()) {
8616 if (obj->InheritsFrom(TPaveStats::Class())) {
8617 stats = (TPaveStats*)obj;
8618 break;
8619 }
8620 }
8621
8622 if (stats && dostat) {
8623 dofit = stats->GetOptFit();
8624 dostat = stats->GetOptStat();
8625 } else {
8626 dofit = gStyle->GetOptFit();
8627 }
8628 if (!dofit) fit = nullptr;
8629 if (dofit == 1) dofit = 111;
8630 if (dostat == 1) dostat = 1111;
8631 Int_t print_name = dostat%10;
8632 Int_t print_entries = (dostat/10)%10;
8633 Int_t print_mean = (dostat/100)%10;
8634 Int_t print_stddev = (dostat/1000)%10;
8635 Int_t print_under = (dostat/10000)%10;
8636 Int_t print_over = (dostat/100000)%10;
8637 Int_t print_integral= (dostat/1000000)%10;
8638 Int_t print_skew = (dostat/10000000)%10;
8639 Int_t print_kurt = (dostat/100000000)%10;
8640 Int_t nlines = print_name + print_entries + print_mean + print_stddev +
8641 print_under + print_over + print_integral +
8642 print_skew + print_kurt;
8643 Int_t print_fval = dofit%10;
8644 Int_t print_ferrors = (dofit/10)%10;
8645 Int_t print_fchi2 = (dofit/100)%10;
8646 Int_t print_fprob = (dofit/1000)%10;
8647 Int_t nlinesf = print_fval + print_fchi2 + print_fprob;
8648 if (fit) {
8649 if (print_fval < 2) nlinesf += fit->GetNumberFreeParameters();
8650 else nlinesf += fit->GetNpar();
8651 }
8652 if (fH->InheritsFrom(TProfile::Class())) nlinesf += print_mean + print_stddev;
8653
8654 // Pavetext with statistics
8655 Bool_t done = kFALSE;
8656 if (!dostat && !fit) {
8657 if (stats) { fFunctions->Remove(stats); delete stats;}
8658 return;
8659 }
8660 Double_t statw = gStyle->GetStatW();
8661 if (fit) statw = 1.8*gStyle->GetStatW();
8662 Double_t stath = (nlines+nlinesf)*gStyle->GetStatFontSize();
8663 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
8664 stath = 0.25*(nlines+nlinesf)*gStyle->GetStatH();
8665 }
8666 if (stats) {
8667 stats->Clear();
8668 done = kTRUE;
8669 } else {
8670 stats = new TPaveStats(
8671 gStyle->GetStatX()-statw,
8672 gStyle->GetStatY()-stath,
8673 gStyle->GetStatX(),
8674 gStyle->GetStatY(),"brNDC");
8675
8676 stats->SetParent(fH);
8677 stats->SetOptFit(dofit);
8678 stats->SetOptStat(dostat);
8679 stats->SetFillColor(gStyle->GetStatColor());
8680 stats->SetFillStyle(gStyle->GetStatStyle());
8682 stats->SetTextFont(gStyle->GetStatFont());
8683 if (gStyle->GetStatFont()%10 > 2)
8685 stats->SetFitFormat(gStyle->GetFitFormat());
8687 stats->SetName("stats");
8688
8690 stats->SetTextAlign(12);
8691 stats->SetBit(kCanDelete);
8692 stats->SetBit(kMustCleanup);
8693 }
8694 if (print_name) stats->AddText(fH->GetName());
8695 if (print_entries) {
8696 if (fH->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(fH->GetEntries()+0.5));
8697 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(fH->GetEntries()));
8698 stats->AddText(tt.Data());
8699 }
8700 if (print_mean) {
8701 if (print_mean == 1) {
8702 tf.Form("%s = %s%s",gStringMean.Data(),"%",stats->GetStatFormat());
8703 tt.Form(tf.Data(),fH->GetMean(1));
8704 } else {
8705 tf.Form("%s = %s%s #pm %s%s",gStringMean.Data(),"%",stats->GetStatFormat()
8706 ,"%",stats->GetStatFormat());
8707 tt.Form(tf.Data(),fH->GetMean(1),fH->GetMeanError(1));
8708 }
8709 stats->AddText(tt.Data());
8711 if (print_mean == 1) {
8712 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
8713 tt.Form(tf.Data(),fH->GetMean(2));
8714 } else {
8715 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
8716 ,"%",stats->GetStatFormat());
8717 tt.Form(tf.Data(),fH->GetMean(2),fH->GetMeanError(2));
8718 }
8719 stats->AddText(tt.Data());
8720 }
8721 }
8722 if (print_stddev) {
8723 if (print_stddev == 1) {
8724 tf.Form("%s = %s%s",gStringStdDev.Data(),"%",stats->GetStatFormat());
8725 tt.Form(tf.Data(),fH->GetStdDev(1));
8726 } else {
8727 tf.Form("%s = %s%s #pm %s%s",gStringStdDev.Data(),"%",stats->GetStatFormat()
8728 ,"%",stats->GetStatFormat());
8729 tt.Form(tf.Data(),fH->GetStdDev(1),fH->GetStdDevError(1));
8730 }
8731 stats->AddText(tt.Data());
8733 if (print_stddev == 1) {
8734 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
8735 tt.Form(tf.Data(),fH->GetStdDev(2));
8736 } else {
8737 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
8738 ,"%",stats->GetStatFormat());
8739 tt.Form(tf.Data(),fH->GetStdDev(2),fH->GetStdDevError(2));
8740 }
8741 stats->AddText(tt.Data());
8742 }
8743 }
8744 if (print_under) {
8745 tf.Form("%s = %s%s",gStringUnderflow.Data(),"%",stats->GetStatFormat());
8746 tt.Form(tf.Data(),fH->GetBinContent(0));
8747 stats->AddText(tt.Data());
8748 }
8749 if (print_over) {
8750 tf.Form("%s = %s%s",gStringOverflow.Data(),"%",stats->GetStatFormat());
8751 tt.Form(tf.Data(),fH->GetBinContent(fXaxis->GetNbins()+1));
8752 stats->AddText(tt.Data());
8753 }
8754 if (print_integral) {
8755 if (print_integral == 1) {
8756 tf.Form("%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
8757 tt.Form(tf.Data(),fH->Integral());
8758 } else {
8759 tf.Form("%s = %s%s",gStringIntegralBinWidth.Data(),"%",stats->GetStatFormat());
8760 tt.Form(tf.Data(),fH->Integral("width"));
8761 }
8762 stats->AddText(tt.Data());
8763 }
8764 if (print_skew) {
8765 if (print_skew == 1) {
8766 tf.Form("%s = %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat());
8767 tt.Form(tf.Data(),fH->GetSkewness(1));
8768 } else {
8769 tf.Form("%s = %s%s #pm %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat()
8770 ,"%",stats->GetStatFormat());
8771 tt.Form(tf.Data(),fH->GetSkewness(1),fH->GetSkewness(11));
8772 }
8773 stats->AddText(tt.Data());
8774 }
8775 if (print_kurt) {
8776 if (print_kurt == 1) {
8777 tf.Form("%s = %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat());
8778 tt.Form(tf.Data(),fH->GetKurtosis(1));
8779 } else {
8780 tf.Form("%s = %s%s #pm %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat()
8781 ,"%",stats->GetStatFormat());
8782 tt.Form(tf.Data(),fH->GetKurtosis(1),fH->GetKurtosis(11));
8783 }
8784 stats->AddText(tt.Data());
8785 }
8786
8787 // Draw Fit parameters
8788 if (fit) {
8789 Int_t ndf = fit->GetNDF();
8790 tf.Form("#chi^{2} / ndf = %s%s / %d","%",stats->GetFitFormat(),ndf);
8791 tt.Form(tf.Data(),fit->GetChisquare());
8792 if (print_fchi2) stats->AddText(tt.Data());
8793 if (print_fprob) {
8794 tf.Form("Prob = %s%s","%",stats->GetFitFormat());
8795 tt.Form(tf.Data(),TMath::Prob(fit->GetChisquare(),ndf));
8796 stats->AddText(tt.Data());
8797 }
8798 if (print_fval || print_ferrors) {
8799 Double_t parmin,parmax;
8800 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
8801 fit->GetParLimits(ipar,parmin,parmax);
8802 if (print_fval < 2 && parmin*parmax != 0 && parmin >= parmax) continue;
8803 if (print_ferrors) {
8804 tf.Form("%-8s = %s%s #pm %s ", fit->GetParName(ipar), "%",stats->GetFitFormat(),
8805 GetBestFormat(fit->GetParameter(ipar), fit->GetParError(ipar), stats->GetFitFormat()));
8806 tt.Form(tf.Data(),fit->GetParameter(ipar)
8807 ,fit->GetParError(ipar));
8808 } else {
8809 tf.Form("%-8s = %s%s ",fit->GetParName(ipar), "%",stats->GetFitFormat());
8810 tt.Form(tf.Data(),fit->GetParameter(ipar));
8811 }
8812 stats->AddText(tt.Data());
8813 }
8814 }
8815 }
8816
8817 if (!done) fFunctions->Add(stats);
8818 stats->Paint();
8819}
8820
8821////////////////////////////////////////////////////////////////////////////////
8822/// [Draw the statistics box for 2D histograms.](\ref HP07)
8823
8825{
8826
8827 if (fH->GetDimension() != 2) return;
8828 TH2 *h2 = (TH2*)fH;
8829
8830 TString tt, tf;
8831 Int_t dofit;
8832 TPaveStats *stats = nullptr;
8833 TIter next(fFunctions);
8834 while (auto obj = next()) {
8835 if (obj->InheritsFrom(TPaveStats::Class())) {
8836 stats = (TPaveStats*)obj;
8837 break;
8838 }
8839 }
8840 if (stats && dostat) {
8841 dofit = stats->GetOptFit();
8842 dostat = stats->GetOptStat();
8843 } else {
8844 dofit = gStyle->GetOptFit();
8845 }
8846 if (dostat == 1) dostat = 1111;
8847 Int_t print_name = dostat%10;
8848 Int_t print_entries = (dostat/10)%10;
8849 Int_t print_mean = (dostat/100)%10;
8850 Int_t print_stddev = (dostat/1000)%10;
8851 Int_t print_under = (dostat/10000)%10;
8852 Int_t print_over = (dostat/100000)%10;
8853 Int_t print_integral= (dostat/1000000)%10;
8854 Int_t print_skew = (dostat/10000000)%10;
8855 Int_t print_kurt = (dostat/100000000)%10;
8856 Int_t nlines = print_name + print_entries + 2*print_mean + 2*print_stddev + print_integral;
8857 if (print_under || print_over) nlines += 3;
8858
8859 // Pavetext with statistics
8860 if (!gStyle->GetOptFit()) fit = nullptr;
8861 Bool_t done = kFALSE;
8862 if (!dostat && !fit) {
8863 if (stats) { fFunctions->Remove(stats); delete stats;}
8864 return;
8865 }
8866 Double_t statw = gStyle->GetStatW();
8867 if (fit) statw = 1.8*gStyle->GetStatW();
8868 Double_t stath = nlines*gStyle->GetStatFontSize();
8869 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
8870 stath = 0.25*nlines*gStyle->GetStatH();
8871 }
8872 if (fit) stath += gStyle->GetStatH();
8873 if (stats) {
8874 stats->Clear();
8875 done = kTRUE;
8876 } else {
8877 stats = new TPaveStats(
8878 gStyle->GetStatX()-statw,
8879 gStyle->GetStatY()-stath,
8880 gStyle->GetStatX(),
8881 gStyle->GetStatY(),"brNDC");
8882
8883 stats->SetParent(fH);
8884 stats->SetOptFit(dofit);
8885 stats->SetOptStat(dostat);
8886 stats->SetFillColor(gStyle->GetStatColor());
8887 stats->SetFillStyle(gStyle->GetStatStyle());
8889 stats->SetName("stats");
8890
8892 stats->SetTextAlign(12);
8893 stats->SetTextFont(gStyle->GetStatFont());
8894 if (gStyle->GetStatFont()%10 > 2)
8896 stats->SetFitFormat(gStyle->GetFitFormat());
8898 stats->SetBit(kCanDelete);
8899 stats->SetBit(kMustCleanup);
8900 }
8901 if (print_name) stats->AddText(h2->GetName());
8902 if (print_entries) {
8903 if (h2->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(h2->GetEntries()+0.5));
8904 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(h2->GetEntries()));
8905 stats->AddText(tt.Data());
8906 }
8907 if (print_mean) {
8908 if (print_mean == 1) {
8909 tf.Form("%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
8910 tt.Form(tf.Data(),h2->GetMean(1));
8911 stats->AddText(tt.Data());
8912 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
8913 tt.Form(tf.Data(),h2->GetMean(2));
8914 stats->AddText(tt.Data());
8915 } else {
8916 tf.Form("%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
8917 ,"%",stats->GetStatFormat());
8918 tt.Form(tf.Data(),h2->GetMean(1),h2->GetMeanError(1));
8919 stats->AddText(tt.Data());
8920 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
8921 ,"%",stats->GetStatFormat());
8922 tt.Form(tf.Data(),h2->GetMean(2),h2->GetMeanError(2));
8923 stats->AddText(tt.Data());
8924 }
8925 }
8926 if (print_stddev) {
8927 if (print_stddev == 1) {
8928 tf.Form("%s = %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat());
8929 tt.Form(tf.Data(),h2->GetStdDev(1));
8930 stats->AddText(tt.Data());
8931 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
8932 tt.Form(tf.Data(),h2->GetStdDev(2));
8933 stats->AddText(tt.Data());
8934 } else {
8935 tf.Form("%s = %s%s #pm %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat()
8936 ,"%",stats->GetStatFormat());
8937 tt.Form(tf.Data(),h2->GetStdDev(1),h2->GetStdDevError(1));
8938 stats->AddText(tt.Data());
8939 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
8940 ,"%",stats->GetStatFormat());
8941 tt.Form(tf.Data(),h2->GetStdDev(2),h2->GetStdDevError(2));
8942 stats->AddText(tt.Data());
8943 }
8944 }
8945 if (print_integral) {
8946 tf.Form("%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
8947 tt.Form(tf.Data(),fH->Integral());
8948 stats->AddText(tt.Data());
8949 }
8950 if (print_skew) {
8951 if (print_skew == 1) {
8952 tf.Form("%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
8953 tt.Form(tf.Data(),h2->GetSkewness(1));
8954 stats->AddText(tt.Data());
8955 tf.Form("%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
8956 tt.Form(tf.Data(),h2->GetSkewness(2));
8957 stats->AddText(tt.Data());
8958 } else {
8959 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
8960 ,"%",stats->GetStatFormat());
8961 tt.Form(tf.Data(),h2->GetSkewness(1),h2->GetSkewness(11));
8962 stats->AddText(tt.Data());
8963 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
8964 ,"%",stats->GetStatFormat());
8965 tt.Form(tf.Data(),h2->GetSkewness(2),h2->GetSkewness(12));
8966 stats->AddText(tt.Data());
8967 }
8968 }
8969 if (print_kurt) {
8970 if (print_kurt == 1) {
8971 tf.Form("%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
8972 tt.Form(tf.Data(),h2->GetKurtosis(1));
8973 stats->AddText(tt.Data());
8974 tf.Form("%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
8975 tt.Form(tf.Data(),h2->GetKurtosis(2));
8976 stats->AddText(tt.Data());
8977 } else {
8978 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
8979 ,"%",stats->GetStatFormat());
8980 tt.Form(tf.Data(),h2->GetKurtosis(1),h2->GetKurtosis(11));
8981 stats->AddText(tt.Data());
8982 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
8983 ,"%",stats->GetStatFormat());
8984 tt.Form(tf.Data(),h2->GetKurtosis(2),h2->GetKurtosis(12));
8985 stats->AddText(tt.Data());
8986 }
8987 }
8988 if (print_under || print_over) {
8989 //get 3*3 under/overflows for 2d hist
8990 Double_t unov[9];
8991
8992 Int_t cellsX = h2->GetXaxis()->GetNbins() + 1;
8993 Int_t cellsY = h2->GetYaxis()->GetNbins() + 1;
8994 Int_t firstX = std::max(1, h2->GetXaxis()->GetFirst());
8995 Int_t firstY = std::max(1, h2->GetYaxis()->GetFirst());
8996 Int_t lastX = std::min(h2->GetXaxis()->GetLast(), h2->GetXaxis()->GetNbins());
8997 Int_t lastY = std::min(h2->GetYaxis()->GetLast(), h2->GetYaxis()->GetNbins());
8998
8999 unov[0] = h2->Integral( 0, firstX-1, lastY+1, cellsY );
9000 unov[1] = h2->Integral(firstX , lastX , lastY+1, cellsY );
9001 unov[2] = h2->Integral(lastX+1, cellsX , lastY+1, cellsY );
9002 unov[3] = h2->Integral( 0, firstX-1, firstY , lastY );
9003 unov[4] = h2->Integral(firstX , lastX , firstY , lastY );
9004 unov[5] = h2->Integral(lastX+1, cellsX , firstY , lastY );
9005 unov[6] = h2->Integral( 0, firstX-1, 0, firstY-1);
9006 unov[7] = h2->Integral(firstX, lastX, 0, firstY-1);
9007 unov[8] = h2->Integral(lastX+1, cellsX , 0, firstY-1);
9008
9009 tt.Form("%g|%g|%g\n", unov[0], unov[1], unov[2]);
9010 stats->AddText(tt.Data());
9011 tt.Form("%g|%g|%g\n", unov[3], unov[4], unov[5]);
9012 stats->AddText(tt.Data());
9013 tt.Form("%g|%g|%g\n", unov[6], unov[7], unov[8]);
9014 stats->AddText(tt.Data());
9015 }
9016
9017 // Draw Fit parameters
9018 if (fit) {
9019 Int_t ndf = fit->GetNDF();
9020 tt.Form("#chi^{2} / ndf = %6.4g / %d",fit->GetChisquare(),ndf);
9021 stats->AddText(tt.Data());
9022 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
9023 tt.Form("%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
9024 ,fit->GetParameter(ipar)
9025 ,fit->GetParError(ipar));
9026 stats->AddText(tt.Data());
9027 }
9028 }
9029
9030 if (!done) fFunctions->Add(stats);
9031 stats->Paint();
9032}
9033
9034////////////////////////////////////////////////////////////////////////////////
9035/// [Draw the statistics box for 3D histograms.](\ref HP07)
9036
9038{
9039
9040 if (fH->GetDimension() != 3) return;
9041 TH3 *h3 = (TH3*)fH;
9042
9043 TString tt, tf;
9044 Int_t dofit;
9045 TPaveStats *stats = nullptr;
9046 TIter next(fFunctions);
9047 while (auto obj = next()) {
9048 if (obj->InheritsFrom(TPaveStats::Class())) {
9049 stats = (TPaveStats*)obj;
9050 break;
9051 }
9052 }
9053 if (stats && dostat) {
9054 dofit = stats->GetOptFit();
9055 dostat = stats->GetOptStat();
9056 } else {
9057 dofit = gStyle->GetOptFit();
9058 }
9059 if (dostat == 1) dostat = 1111;
9060 Int_t print_name = dostat%10;
9061 Int_t print_entries = (dostat/10)%10;
9062 Int_t print_mean = (dostat/100)%10;
9063 Int_t print_stddev = (dostat/1000)%10;
9064 Int_t print_under = (dostat/10000)%10;
9065 Int_t print_over = (dostat/100000)%10;
9066 Int_t print_integral= (dostat/1000000)%10;
9067 Int_t print_skew = (dostat/10000000)%10;
9068 Int_t print_kurt = (dostat/100000000)%10;
9069 Int_t nlines = print_name + print_entries + 3*print_mean + 3*print_stddev + print_integral;
9070 if (print_under || print_over) nlines += 3;
9071
9072 // Pavetext with statistics
9073 if (!gStyle->GetOptFit()) fit = nullptr;
9074 Bool_t done = kFALSE;
9075 if (!dostat && !fit) {
9076 if (stats) { fFunctions->Remove(stats); delete stats;}
9077 return;
9078 }
9079 Double_t statw = gStyle->GetStatW();
9080 if (fit) statw = 1.8*gStyle->GetStatW();
9081 Double_t stath = nlines*gStyle->GetStatFontSize();
9082 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
9083 stath = 0.25*nlines*gStyle->GetStatH();
9084 }
9085 if (fit) stath += gStyle->GetStatH();
9086 if (stats) {
9087 stats->Clear();
9088 done = kTRUE;
9089 } else {
9090 stats = new TPaveStats(
9091 gStyle->GetStatX()-statw,
9092 gStyle->GetStatY()-stath,
9093 gStyle->GetStatX(),
9094 gStyle->GetStatY(),"brNDC");
9095
9096 stats->SetParent(fH);
9097 stats->SetOptFit(dofit);
9098 stats->SetOptStat(dostat);
9099 stats->SetFillColor(gStyle->GetStatColor());
9100 stats->SetFillStyle(gStyle->GetStatStyle());
9102 stats->SetName("stats");
9103
9105 stats->SetTextAlign(12);
9106 stats->SetTextFont(gStyle->GetStatFont());
9107 stats->SetFitFormat(gStyle->GetFitFormat());
9109 stats->SetBit(kCanDelete);
9110 stats->SetBit(kMustCleanup);
9111 }
9112 if (print_name) stats->AddText(h3->GetName());
9113 if (print_entries) {
9114 if (h3->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(h3->GetEntries()+0.5));
9115 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(h3->GetEntries()+0.5));
9116 stats->AddText(tt.Data());
9117 }
9118 if (print_mean) {
9119 if (print_mean == 1) {
9120 tf.Form("%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
9121 tt.Form(tf.Data(),h3->GetMean(1));
9122 stats->AddText(tt.Data());
9123 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
9124 tt.Form(tf.Data(),h3->GetMean(2));
9125 stats->AddText(tt.Data());
9126 tf.Form("%s = %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat());
9127 tt.Form(tf.Data(),h3->GetMean(3));
9128 stats->AddText(tt.Data());
9129 } else {
9130 tf.Form("%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
9131 ,"%",stats->GetStatFormat());
9132 tt.Form(tf.Data(),h3->GetMean(1),h3->GetMeanError(1));
9133 stats->AddText(tt.Data());
9134 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
9135 ,"%",stats->GetStatFormat());
9136 tt.Form(tf.Data(),h3->GetMean(2),h3->GetMeanError(2));
9137 stats->AddText(tt.Data());
9138 tf.Form("%s = %s%s #pm %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat()
9139 ,"%",stats->GetStatFormat());
9140 tt.Form(tf.Data(),h3->GetMean(3),h3->GetMeanError(3));
9141 stats->AddText(tt.Data());
9142 }
9143 }
9144 if (print_stddev) {
9145 if (print_stddev == 1) {
9146 tf.Form("%s = %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat());
9147 tt.Form(tf.Data(),h3->GetStdDev(1));
9148 stats->AddText(tt.Data());
9149 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
9150 tt.Form(tf.Data(),h3->GetStdDev(2));
9151 stats->AddText(tt.Data());
9152 tf.Form("%s = %s%s",gStringStdDevZ.Data(),"%",stats->GetStatFormat());
9153 tt.Form(tf.Data(),h3->GetStdDev(3));
9154 stats->AddText(tt.Data());
9155 } else {
9156 tf.Form("%s = %s%s #pm %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat()
9157 ,"%",stats->GetStatFormat());
9158 tt.Form(tf.Data(),h3->GetStdDev(1),h3->GetStdDevError(1));
9159 stats->AddText(tt.Data());
9160 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
9161 ,"%",stats->GetStatFormat());
9162 tt.Form(tf.Data(),h3->GetStdDev(2),h3->GetStdDevError(2));
9163 stats->AddText(tt.Data());
9164 tf.Form("%s = %s%s #pm %s%s",gStringStdDevZ.Data(),"%",stats->GetStatFormat()
9165 ,"%",stats->GetStatFormat());
9166 tt.Form(tf.Data(),h3->GetStdDev(3),h3->GetStdDevError(3));
9167 stats->AddText(tt.Data());
9168 }
9169 }
9170 if (print_integral) {
9171 tt.Form("%s = %6.4g",gStringIntegral.Data(),h3->Integral());
9172 stats->AddText(tt.Data());
9173 }
9174 if (print_skew) {
9175 if (print_skew == 1) {
9176 tf.Form("%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
9177 tt.Form(tf.Data(),h3->GetSkewness(1));
9178 stats->AddText(tt.Data());
9179 tf.Form("%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
9180 tt.Form(tf.Data(),h3->GetSkewness(2));
9181 stats->AddText(tt.Data());
9182 tf.Form("%s = %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat());
9183 tt.Form(tf.Data(),h3->GetSkewness(3));
9184 stats->AddText(tt.Data());
9185 } else {
9186 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
9187 ,"%",stats->GetStatFormat());
9188 tt.Form(tf.Data(),h3->GetSkewness(1),h3->GetSkewness(11));
9189 stats->AddText(tt.Data());
9190 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
9191 ,"%",stats->GetStatFormat());
9192 tt.Form(tf.Data(),h3->GetSkewness(2),h3->GetSkewness(12));
9193 stats->AddText(tt.Data());
9194 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat()
9195 ,"%",stats->GetStatFormat());
9196 tt.Form(tf.Data(),h3->GetSkewness(3),h3->GetSkewness(13));
9197 stats->AddText(tt.Data());
9198 }
9199 }
9200 if (print_kurt) {
9201 if (print_kurt == 1) {
9202 tf.Form("%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
9203 tt.Form(tf.Data(),h3->GetKurtosis(1));
9204 stats->AddText(tt.Data());
9205 tf.Form("%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
9206 tt.Form(tf.Data(),h3->GetKurtosis(2));
9207 stats->AddText(tt.Data());
9208 tf.Form("%s = %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat());
9209 tt.Form(tf.Data(),h3->GetKurtosis(3));
9210 stats->AddText(tt.Data());
9211 } else {
9212 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
9213 ,"%",stats->GetStatFormat());
9214 tt.Form(tf.Data(),h3->GetKurtosis(1),h3->GetKurtosis(11));
9215 stats->AddText(tt.Data());
9216 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
9217 ,"%",stats->GetStatFormat());
9218 tt.Form(tf.Data(),h3->GetKurtosis(2),h3->GetKurtosis(12));
9219 stats->AddText(tt.Data());
9220 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat()
9221 ,"%",stats->GetStatFormat());
9222 tt.Form(tf.Data(),h3->GetKurtosis(3),h3->GetKurtosis(13));
9223 stats->AddText(tt.Data());
9224 }
9225 }
9226 if (print_under || print_over) {
9227 // no underflow - overflow printing for a 3D histogram
9228 // one would need a 3D table
9229 }
9230
9231 // Draw Fit parameters
9232 if (fit) {
9233 Int_t ndf = fit->GetNDF();
9234 tt.Form("#chi^{2} / ndf = %6.4g / %d",fit->GetChisquare(),ndf);
9235 stats->AddText(tt.Data());
9236 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
9237 tt.Form("%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
9238 ,fit->GetParameter(ipar)
9239 ,fit->GetParError(ipar));
9240 stats->AddText(tt.Data());
9241 }
9242 }
9243
9244 if (!done) fFunctions->Add(stats);
9245 stats->Paint();
9246}
9247
9248////////////////////////////////////////////////////////////////////////////////
9249/// [Control function to draw a 2D histogram as a surface plot.](\ref HP18)
9250
9252{
9253
9254 const Double_t ydiff = 1;
9255 const Double_t yligh1 = 10;
9256 const Double_t qa = 0.15;
9257 const Double_t qd = 0.15;
9258 const Double_t qs = 0.8;
9259 Double_t fmin, fmax;
9260 Int_t raster = 0;
9261 Int_t irep = 0;
9262
9263 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
9266 Double_t zmin = Hparam.zmin;
9267 Double_t zmax = Hparam.zmax;
9268 Double_t xlab1 = Hparam.xmin;
9269 Double_t xlab2 = Hparam.xmax;
9270 Double_t ylab1 = Hparam.ymin;
9271 Double_t ylab2 = Hparam.ymax;
9272 Double_t dangle = 10*3.141592/180; //Delta angle for Rapidity option
9273 Double_t deltaz = TMath::Abs(zmin);
9274 if (deltaz == 0) deltaz = 1;
9275 if (zmin >= zmax) {
9276 zmin -= 0.5*deltaz;
9277 zmax += 0.5*deltaz;
9278 }
9279 Double_t z1c = zmin;
9280 Double_t z2c = zmin + (zmax-zmin)*(1+gStyle->GetHistTopMargin());
9281 // Compute the lego limits and instantiate a lego object
9282 fXbuf[0] = -1;
9283 fYbuf[0] = 1;
9284 fXbuf[1] = -1;
9285 fYbuf[1] = 1;
9286 if (Hoption.System >= kPOLAR && (Hoption.Surf == 1 || Hoption.Surf == 13)) raster = 1;
9287 if (Hoption.System == kPOLAR) {
9288 fXbuf[2] = z1c;
9289 fYbuf[2] = z2c;
9290 } else if (Hoption.System == kCYLINDRICAL) {
9291 if (Hoption.Logy) {
9292 if (ylab1 > 0) fXbuf[2] = TMath::Log10(ylab1);
9293 else fXbuf[2] = 0;
9294 if (ylab2 > 0) fYbuf[2] = TMath::Log10(ylab2);
9295 else fYbuf[2] = 0;
9296 } else {
9297 fXbuf[2] = ylab1;
9298 fYbuf[2] = ylab2;
9299 }
9300 z1c = 0; z2c = 1;
9301 } else if (Hoption.System == kSPHERICAL) {
9302 fXbuf[2] = -1;
9303 fYbuf[2] = 1;
9304 z1c = 0; z2c = 1;
9305 } else if (Hoption.System == kRAPIDITY) {
9306 fXbuf[2] = -1/TMath::Tan(dangle);
9307 fYbuf[2] = 1/TMath::Tan(dangle);
9308 } else {
9309 fXbuf[0] = xlab1;
9310 fYbuf[0] = xlab2;
9311 fXbuf[1] = ylab1;
9312 fYbuf[1] = ylab2;
9313 fXbuf[2] = z1c;
9314 fYbuf[2] = z2c;
9315 }
9316
9317 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data(), Hoption.System);
9318 fLego->SetEdgeAtt(fH->GetLineColor(),fH->GetLineStyle(),fH->GetLineWidth(),0);
9319 fLego->SetFillColor(fH->GetFillColor());
9320
9321 // Initialize the levels on the Z axis
9322 Int_t ndiv = fH->GetContour();
9323 if (ndiv == 0 ) {
9324 ndiv = gStyle->GetNumberContours();
9325 fH->SetContour(ndiv);
9326 }
9327 Int_t ndivz = TMath::Abs(ndiv);
9328 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
9329
9330 if (Hoption.Surf == 13 || Hoption.Surf == 15) fLego->SetMesh(3);
9331 if (Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) fLego->SetMesh(0);
9332
9333 // Close the surface in case of non cartesian coordinates.
9334
9335 if (Hoption.System != kCARTESIAN) {nx++; ny++;}
9336
9337 // Now ready to draw the surface plot
9338
9339 TView *view = gPad ? gPad->GetView() : nullptr;
9340 if (!view) {
9341 Error("PaintSurface", "no TView in current pad");
9342 return;
9343 }
9344
9345 Double_t thedeg = 90 - gPad->GetTheta();
9346 Double_t phideg = -90 - gPad->GetPhi();
9347 Double_t psideg = view->GetPsi();
9348 view->SetView(phideg, thedeg, psideg, irep);
9349
9350 // Set color/style for back box
9351 if (Hoption.Same) {
9352 fLego->SetFillStyle(0);
9353 fLego->SetFillColor(1);
9354 } else {
9355 fLego->SetFillStyle(gPad->GetFrameFillStyle());
9356 fLego->SetFillColor(gPad->GetFrameFillColor());
9357 }
9358 fLego->TAttFill::Modify();
9359
9360 Int_t backcolor = gPad->GetFrameFillColor();
9361 if (Hoption.System != kCARTESIAN) backcolor = 0;
9362 view->PadRange(backcolor);
9363
9364 fLego->SetFillStyle(fH->GetFillStyle());
9365 fLego->SetFillColor(fH->GetFillColor());
9366 fLego->TAttFill::Modify();
9367
9368 // Draw the filled contour on top
9369 Int_t icol1 = fH->GetFillColor();
9370
9371 Int_t hoption35 = Hoption.Surf;
9372 if (Hoption.Surf == 13 || Hoption.Surf == 15) {
9373 DefineColorLevels(ndivz);
9374 Hoption.Surf = 23;
9375 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9377 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"BF");
9378 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9379 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9380 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9381 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"BF");
9382 Hoption.Surf = hoption35;
9383 fLego->SetMesh(1);
9384 }
9385
9386 if (raster) fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
9387 else fLego->InitMoveScreen(-1.1,1.1);
9388
9389 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) {
9390 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9393 fLego->BackBox(90);
9394 }
9395 }
9396
9397 // Gouraud Shading surface
9398 if (Hoption.Surf == 14) {
9399 // Set light sources
9400 fLego->LightSource(0, ydiff, 0,0,0,irep);
9401 fLego->LightSource(1, yligh1 ,1,1,1,irep);
9402 fLego->SurfaceProperty(qa, qd, qs, 1, irep);
9403 fmin = ydiff*qa;
9404 fmax = fmin + (yligh1+0.1)*(qd+qs);
9405 Int_t nbcol = 28;
9406 icol1 = 201;
9407 Double_t dcol = 0.5/Double_t(nbcol);
9408 TColor *colref = gROOT->GetColor(fH->GetFillColor());
9409 if (!colref) return;
9410 Float_t r,g,b,hue,light,satur;
9411 colref->GetRGB(r,g,b);
9412 TColor::RGBtoHLS(r,g,b,hue,light,satur);
9413 TColor *acol;
9414 for (Int_t col=0;col<nbcol;col++) {
9415 acol = gROOT->GetColor(col+icol1);
9416 TColor::HLStoRGB(hue,.4+col*dcol,satur,r,g,b);
9417 if (acol) acol->SetRGB(r,g,b);
9418 }
9419 fLego->Spectrum(nbcol, fmin, fmax, icol1, 1, irep);
9420 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::GouraudFunction);
9422 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"BF");
9423 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9424 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9425 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9426 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"BF");
9427 } else if (Hoption.Surf == 15) {
9428 // The surface is not drawn in this case.
9429 } else {
9430 // Draw the surface
9431 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 16 || Hoption.Surf == 17) {
9432 DefineColorLevels(ndivz);
9433 } else {
9434 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9435 }
9436 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9437 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceRaster1);
9438 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode2);
9439 if (Hoption.System == kPOLAR) {
9440 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfacePolar(1,nx,ny,"FB");
9441 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfacePolar(1,nx,ny,"BF");
9442 } else if (Hoption.System == kCYLINDRICAL) {
9443 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceCylindrical(1,nx,ny,"FB");
9444 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9445 } else if (Hoption.System == kSPHERICAL) {
9446 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceSpherical(0,1,nx,ny,"FB");
9447 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9448 } else if (Hoption.System == kRAPIDITY) {
9449 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceSpherical(1,1,nx,ny,"FB");
9450 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9451 } else {
9452 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove1);
9453 if (Hoption.Surf == 16) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove3);
9454 if (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16) fLego->SurfaceCartesian(90,nx,ny,"FB");
9455 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCartesian(90,nx,ny,"BF");
9456 }
9457 }
9458
9459 // Paint the line contour on top for option SURF7
9460 if (Hoption.Surf == 17) {
9461 fLego->InitMoveScreen(-1.1,1.1);
9462 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9463 Hoption.Surf = 23;
9464 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9466 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"FB");
9467 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"FB");
9468 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"FB");
9469 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"FB");
9470 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"FB");
9471 }
9472
9473 if ((!Hoption.Same) &&
9474 (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16)) {
9477 fLego->BackBox(90);
9478 }
9479 }
9480 if (Hoption.System == kCARTESIAN) {
9481 fLego->InitMoveScreen(-1.1,1.1);
9483 if (Hoption.FrontBox) fLego->FrontBox(90);
9484 }
9485 if (!Hoption.Axis && !Hoption.Same) {
9486 TGaxis axis;
9487 PaintLegoAxis(&axis, 90);
9488 }
9489
9491
9492 fLego.reset();
9493}
9494
9495////////////////////////////////////////////////////////////////////////////////
9496/// Control function to draw a table using Delaunay triangles.
9497
9499{
9500
9501 TGraphDelaunay2D *dt = nullptr;
9502 TGraphDelaunay *dtOld = nullptr;
9503
9504 // Check if fH contains a TGraphDelaunay2D
9505 TList *hl = fH->GetListOfFunctions();
9506 dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
9507 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
9508 if (!dt && !dtOld) return;
9509
9510 // If needed, create a TGraph2DPainter
9511 if (!fGraph2DPainter)
9512 fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
9513
9514 // Define the 3D view
9515 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
9516 if (Hoption.Same) {
9517 TView *viewsame = gPad ? gPad->GetView() : nullptr;
9518 if (!viewsame) {
9519 Error("PaintTriangles", "no TView in current pad, do not use option SAME");
9520 return;
9521 }
9522 Double_t *rmin = viewsame->GetRmin();
9523 Double_t *rmax = viewsame->GetRmax();
9524 if (!rmin || !rmax) return;
9525 fXbuf[0] = rmin[0];
9526 fYbuf[0] = rmax[0];
9527 fXbuf[1] = rmin[1];
9528 fYbuf[1] = rmax[1];
9529 fXbuf[2] = rmin[2];
9530 fYbuf[2] = rmax[2];
9531 } else {
9532 fXbuf[0] = Hparam.xmin;
9533 fYbuf[0] = Hparam.xmax;
9534 fXbuf[1] = Hparam.ymin;
9535 fYbuf[1] = Hparam.ymax;
9536 fXbuf[2] = Hparam.zmin;
9537 fYbuf[2] = Hparam.zmax;
9538 }
9539
9540 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
9541 TView *view = gPad ? gPad->GetView() : nullptr;
9542 if (!view) {
9543 Error("PaintTriangles", "no TView in current pad");
9544 return;
9545 }
9546 Double_t thedeg = 90 - gPad->GetTheta();
9547 Double_t phideg = -90 - gPad->GetPhi();
9548 Double_t psideg = view->GetPsi();
9549 Int_t irep;
9550 view->SetView(phideg, thedeg, psideg, irep);
9551
9552 // Set color/style for back box
9553 fLego->SetFillStyle(gPad->GetFrameFillStyle());
9554 fLego->SetFillColor(gPad->GetFrameFillColor());
9555 fLego->TAttFill::Modify();
9556 Int_t backcolor = gPad->GetFrameFillColor();
9557 if (Hoption.System != kCARTESIAN) backcolor = 0;
9558 view->PadRange(backcolor);
9559 fLego->SetFillStyle(fH->GetFillStyle());
9560 fLego->SetFillColor(fH->GetFillColor());
9561 fLego->TAttFill::Modify();
9562
9563 // Paint the Back Box if needed
9564 if (Hoption.BackBox && !Hoption.Same) {
9565 fLego->InitMoveScreen(-1.1,1.1);
9566 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9568 fLego->BackBox(90);
9569 }
9570
9571 // Paint the triangles
9572 fGraph2DPainter->Paint(option);
9573
9574 // Paint the Front Box if needed
9575 if (Hoption.FrontBox) {
9576 fLego->InitMoveScreen(-1.1,1.1);
9578 fLego->FrontBox(90);
9579 }
9580
9581 // Paint the Axis if needed
9582 if (!Hoption.Axis && !Hoption.Same) {
9583 TGaxis axis;
9584 PaintLegoAxis(&axis, 90);
9585 }
9586
9588
9589 fLego.reset();
9590}
9591
9592////////////////////////////////////////////////////////////////////////////////
9593/// Define the color levels used to paint legos, surfaces etc..
9594
9596{
9597
9598 Int_t i, irep;
9599
9600 // Initialize the color levels
9601 if (ndivz >= 100) {
9602 Warning("PaintSurface", "too many color levels, %d >= 100, reset to 99", ndivz);
9603 ndivz = 99;
9604 }
9605 std::vector<Double_t> funlevel(ndivz+1);
9606 std::vector<Int_t> colorlevel(ndivz+1);
9607 Int_t theColor;
9608 Int_t ncolors = gStyle->GetNumberOfColors();
9609 for (i = 0; i < ndivz; ++i) {
9610 funlevel[i] = fH->GetContourLevelPad(i);
9611 theColor = Int_t((i+0.99)*Float_t(ncolors)/Float_t(ndivz));
9612 colorlevel[i] = gStyle->GetColorPalette(theColor);
9613 }
9614 colorlevel[ndivz] = gStyle->GetColorPalette(ncolors-1);
9615 fLego->ColorFunction(ndivz, funlevel.data(), colorlevel.data(), irep);
9616}
9617
9618////////////////////////////////////////////////////////////////////////////////
9619/// [Control function to draw 2D/3D histograms (tables).](\ref HP01c)
9620
9622{
9623
9624 // Fill Hparam structure with histo parameters
9625 if (!TableInit()) return;
9626
9627 // Draw histogram frame
9628 PaintFrame();
9629
9630 // If palette option not specified, delete a possible existing palette
9631 if (!Hoption.Zscale) {
9632 TObject *palette = fFunctions->FindObject("palette");
9633 if (palette) { fFunctions->Remove(palette); delete palette;}
9634 }
9635
9636 // Do not draw the histogram. Only the attached functions will be drawn.
9637 if (Hoption.Func == 2) {
9638 if (Hoption.Zscale) {
9639 Int_t ndiv = fH->GetContour();
9640 if (ndiv == 0 ) {
9641 ndiv = gStyle->GetNumberContours();
9642 fH->SetContour(ndiv);
9643 }
9644 PaintPalette();
9645 }
9646
9647 // Draw the histogram according to the option
9648 } else {
9649 if (fH->InheritsFrom(TH2Poly::Class()) && Hoption.Axis<=0) {
9650 if (Hoption.Fill) PaintTH2PolyBins("f");
9654 if (Hoption.Line) PaintTH2PolyBins("l");
9655 if (Hoption.Mark) PaintTH2PolyBins("P");
9656 } else if (fH->GetEntries() != 0 && Hoption.Axis<=0) {
9660 if (Hoption.Color) {
9663 }
9666 if (Hoption.Error >= 100) Paint2DErrors(option);
9668 }
9672 }
9673
9674 // Draw histogram title
9675 PaintTitle();
9676
9677 // Draw the axes
9678 if (!Hoption.Lego && !Hoption.Surf &&
9679 !Hoption.Tri && !(Hoption.Error >= 100)) PaintAxis(kFALSE);
9680
9681 TF1 *fit = nullptr;
9682 TIter next(fFunctions);
9683 while (auto obj = next()) {
9684 if (obj->InheritsFrom(TF1::Class())) {
9685 fit = (TF1*)obj;
9686 break;
9687 }
9688 }
9689 if ((Hoption.Same%10) != 1) {
9690 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
9691 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
9692 //ALWAYS executed on non-iOS platform.
9693 //On iOS, depends on mode.
9695 }
9696 }
9697 }
9698}
9699
9700////////////////////////////////////////////////////////////////////////////////
9701/// Control function to draw a TH2Poly bins' contours.
9702///
9703/// - option = "F" draw the bins as filled areas.
9704/// - option = "L" draw the bins as line.
9705/// - option = "P" draw the bins as markers.
9706
9708{
9709
9710 //Do not highlight the histogram, if its part was picked.
9711 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH) return;
9712
9713 TString opt = option;
9714 opt.ToLower();
9715 Bool_t line = kFALSE;
9716 Bool_t fill = kFALSE;
9717 Bool_t mark = kFALSE;
9718 if (opt.Contains("l")) line = kTRUE;
9719 if (opt.Contains("f")) fill = kTRUE;
9720 if (opt.Contains("p")) mark = kTRUE;
9721
9722 TH2PolyBin *b;
9723 Double_t z;
9724
9725 TIter next(((TH2Poly*)fH)->GetBins());
9726 TObject *obj, *poly;
9727
9728 while ((obj=next())) {
9729 b = (TH2PolyBin*)obj;
9730 z = b->GetContent();
9731 if (z==0 && Hoption.Zero) continue; // Do not draw empty bins in case of option "COL0 L"
9732 poly = b->GetPolygon();
9733
9734 // Paint the TGraph bins.
9735 if (poly->IsA() == TGraph::Class()) {
9736 TGraph *g = (TGraph*)poly;
9737 g->TAttLine::Modify();
9738 g->TAttMarker::Modify();
9739 g->TAttFill::Modify();
9740 if (line) {
9741 Int_t fs = g->GetFillStyle();
9742 Int_t fc = g->GetFillColor();
9743 g->SetFillStyle(0);
9744 g->SetFillColor(g->GetLineColor());
9745 g->Paint("F");
9746 g->SetFillStyle(fs);
9747 g->SetFillColor(fc);
9748 }
9749 if (fill) g->Paint("F");
9750 if (mark) g->Paint("P");
9751 }
9752
9753 // Paint the TMultiGraph bins.
9754 if (poly->IsA() == TMultiGraph::Class()) {
9755 TMultiGraph *mg = (TMultiGraph*)poly;
9756 TList *gl = mg->GetListOfGraphs();
9757 if (!gl) return;
9758 TGraph *g;
9759 TIter nextg(gl);
9760 while ((g = (TGraph*) nextg())) {
9761 g->TAttLine::Modify();
9762 g->TAttMarker::Modify();
9763 g->TAttFill::Modify();
9764 if (line) {
9765 Int_t fs = g->GetFillStyle();
9766 Int_t fc = g->GetFillColor();
9767 g->SetFillStyle(0);
9768 g->SetFillColor(g->GetLineColor());
9769 g->Paint("F");
9770 g->SetFillStyle(fs);
9771 g->SetFillColor(fc);
9772 }
9773 if (fill) g->Paint("F");
9774 if (mark) g->Paint("P");
9775 }
9776 }
9777 }
9778}
9779
9780////////////////////////////////////////////////////////////////////////////////
9781/// [Control function to draw a TH2Poly as a color plot.](\ref HP20a)
9782
9784{
9785
9786 //Do not highlight the histogram, if its part was picked.
9787 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
9788 return;
9789
9790 Int_t ncolors, color, theColor;
9791 Double_t z, zc;
9792 Double_t zmin = fH->GetMinimum();
9793 Double_t zmax = fH->GetMaximum();
9794 if (Hoption.Logz) {
9795 if (zmax > 0) {
9796 if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
9797 zmin = TMath::Log10(zmin);
9798 zmax = TMath::Log10(zmax);
9799 } else {
9800 return;
9801 }
9802 }
9803 Double_t dz = zmax - zmin;
9804
9805 // Initialize the levels on the Z axis
9806 ncolors = gStyle->GetNumberOfColors();
9807 Int_t ndiv = fH->GetContour();
9808 if (ndiv == 0 ) {
9809 ndiv = gStyle->GetNumberContours();
9810 fH->SetContour(ndiv);
9811 }
9812 Int_t ndivz = TMath::Abs(ndiv);
9813 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
9814 Double_t scale = ndivz/dz;
9815
9816 TIter next(((TH2Poly*)fH)->GetBins());
9817
9818 while (auto obj = next()) {
9819 TH2PolyBin *b = (TH2PolyBin*)obj;
9820 TObject *poly = b->GetPolygon();
9821
9822 z = b->GetContent();
9823 if (z==0 && Hoption.Zero) continue;
9824 if (Hoption.Logz) {
9825 if (z > 0) z = TMath::Log10(z);
9826 else z = zmin;
9827 }
9828 if (z < zmin) continue;
9829
9830 // Define the bin color.
9832 zc = fH->GetContourLevelPad(0);
9833 if (z < zc) continue;
9834 color = -1;
9835 for (Int_t k=0; k<ndiv; k++) {
9836 zc = fH->GetContourLevelPad(k);
9837 if (z < zc) {
9838 continue;
9839 } else {
9840 color++;
9841 }
9842 }
9843 } else {
9844 color = Int_t(0.01+(z-zmin)*scale);
9845 }
9846 theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
9847 if (theColor > ncolors-1) theColor = ncolors-1;
9848
9849 // Paint the TGraph bins.
9850 if (poly->IsA() == TGraph::Class()) {
9851 TGraph *g = (TGraph*)poly;
9852 g->SetFillColor(gStyle->GetColorPalette(theColor));
9853 g->TAttFill::Modify();
9854 g->Paint("F");
9855 }
9856
9857 // Paint the TMultiGraph bins.
9858 if (poly->IsA() == TMultiGraph::Class()) {
9859 TMultiGraph *mg = (TMultiGraph*)poly;
9860 TList *gl = mg->GetListOfGraphs();
9861 if (!gl) return;
9862 TGraph *g;
9863 TIter nextg(gl);
9864 while ((g = (TGraph*) nextg())) {
9865 g->SetFillColor(gStyle->GetColorPalette(theColor));
9866 g->TAttFill::Modify();
9867 g->Paint("F");
9868 }
9869 }
9870 }
9872}
9873
9874////////////////////////////////////////////////////////////////////////////////
9875/// [Control function to draw a TH2Poly as a scatter plot.](\ref HP20a)
9876
9878{
9879
9880 //Do not highlight the histogram, if its part was selected.
9881 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
9882 return;
9883
9884 Int_t k, loop, marker=0;
9885 Double_t z, xk,xstep, yk, ystep, xp, yp;
9886 Double_t scale = 1;
9887 Double_t zmin = fH->GetMinimum();
9888 Double_t zmax = fH->GetMaximum();
9889 if (Hoption.Logz) {
9890 if (zmax > 0) {
9891 if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
9892 zmin = TMath::Log10(zmin);
9893 zmax = TMath::Log10(zmax);
9894 } else {
9895 return;
9896 }
9897 }
9898 Double_t dz = zmax - zmin;
9899 scale = (kNMAX-1)/dz;
9900
9901
9902 // use an independent instance of a random generator
9903 // instead of gRandom to avoid conflicts and
9904 // to get same random numbers when drawing the same histogram
9905 TRandom2 random;
9906
9907 TH2PolyBin *b;
9908
9909 TIter next(((TH2Poly*)fH)->GetBins());
9910 TObject *obj, *poly;
9911
9912 Double_t maxarea = 0, a;
9913 while ((obj=next())) {
9914 b = (TH2PolyBin*)obj;
9915 a = b->GetArea();
9916 if (a>maxarea) maxarea = a;
9917 }
9918
9919 next.Reset();
9920
9921 while ((obj=next())) {
9922 b = (TH2PolyBin*)obj;
9923 poly = b->GetPolygon();
9924 z = b->GetContent();
9925 if (z < zmin) z = zmin;
9926 if (z > zmax) z = zmax;
9927 if (Hoption.Logz) {
9928 if (z > 0) z = TMath::Log10(z) - zmin;
9929 } else {
9930 z -= zmin;
9931 }
9932 k = Int_t((z*scale)*(b->GetArea()/maxarea));
9933 xk = b->GetXMin();
9934 yk = b->GetYMin();
9935 xstep = b->GetXMax()-xk;
9936 ystep = b->GetYMax()-yk;
9937
9938 // Paint the TGraph bins.
9939 if (poly->IsA() == TGraph::Class()) {
9940 TGraph *g = (TGraph*)poly;
9941 if (k <= 0 || z <= 0) continue;
9942 loop = 0;
9943 while (loop<k) {
9944 if (k+marker >= kNMAX) {
9945 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
9946 marker=0;
9947 }
9948 xp = (random.Rndm()*xstep) + xk;
9949 yp = (random.Rndm()*ystep) + yk;
9950 if (g->IsInside(xp,yp)) {
9951 fXbuf[marker] = xp;
9952 fYbuf[marker] = yp;
9953 marker++;
9954 loop++;
9955 }
9956 }
9957 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
9958 }
9959
9960 // Paint the TMultiGraph bins.
9961 if (poly->IsA() == TMultiGraph::Class()) {
9962 TMultiGraph *mg = (TMultiGraph*)poly;
9963 TList *gl = mg->GetListOfGraphs();
9964 if (!gl) return;
9965 if (k <= 0 || z <= 0) continue;
9966 loop = 0;
9967 while (loop<k) {
9968 if (k+marker >= kNMAX) {
9969 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
9970 marker=0;
9971 }
9972 xp = (random.Rndm()*xstep) + xk;
9973 yp = (random.Rndm()*ystep) + yk;
9974 if (mg->IsInside(xp,yp)) {
9975 fXbuf[marker] = xp;
9976 fYbuf[marker] = yp;
9977 marker++;
9978 loop++;
9979 }
9980 }
9981 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
9982 }
9983 }
9984 PaintTH2PolyBins("l");
9985}
9986
9987////////////////////////////////////////////////////////////////////////////////
9988/// [Control function to draw a TH2Poly as a text plot.](\ref HP20a)
9989
9991{
9992
9993 TLatex text;
9994 text.SetTextFont(gStyle->GetTextFont());
9995 text.SetTextColor(fH->GetMarkerColor());
9996 text.SetTextSize(0.02*fH->GetMarkerSize());
9997
9998 Double_t x, y, z, e, angle = 0;
9999 TString tt, tf;
10000 tf.Form("%s%s","%",gStyle->GetPaintTextFormat());
10001 if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
10002 Int_t opt = (Int_t)Hoption.Text/1000;
10003
10004 text.SetTextAlign(22);
10005 if (Hoption.Text == 1) angle = 0;
10006 text.SetTextAngle(angle);
10007 text.TAttText::Modify();
10008
10009 TH2PolyBin *b;
10010
10011 TIter next(((TH2Poly*)fH)->GetBins());
10012 TObject *obj, *p;
10013
10014 while ((obj=next())) {
10015 b = (TH2PolyBin*)obj;
10016 p = b->GetPolygon();
10017 x = (b->GetXMin()+b->GetXMax())/2;
10018 if (Hoption.Logx) {
10019 if (x > 0) x = TMath::Log10(x);
10020 else continue;
10021 }
10022 y = (b->GetYMin()+b->GetYMax())/2;
10023 if (Hoption.Logy) {
10024 if (y > 0) y = TMath::Log10(y);
10025 else continue;
10026 }
10027 z = b->GetContent();
10028 if (z < fH->GetMinimum() || (z == 0 && !Hoption.MinimumZero)) continue;
10029 if (opt==2) {
10030 e = fH->GetBinError(b->GetBinNumber());
10031 tf.Form("#splitline{%s%s}{#pm %s%s}",
10033 "%",gStyle->GetPaintTextFormat());
10034 tt.Form(tf.Data(),z,e);
10035 } else {
10036 tt.Form(tf.Data(),z);
10037 }
10038 if (opt==3) text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),p->GetName());
10039 else text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),tt.Data());
10040 }
10041
10042 PaintTH2PolyBins("l");
10043}
10044
10045////////////////////////////////////////////////////////////////////////////////
10046/// [Control function to draw a 1D/2D histograms with the bin values.](\ref HP15)
10047
10049{
10050
10051 TLatex text;
10052 text.SetTextFont(gStyle->GetTextFont());
10053 text.SetTextColor(fH->GetMarkerColor());
10054 text.SetTextSize(0.02*fH->GetMarkerSize());
10055
10056 Double_t x, y, z, e, angle = 0;
10057 TString tt, tf;
10058 tf.Form("%s%s","%",gStyle->GetPaintTextFormat());
10059 if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
10060
10061 // 1D histograms
10062 if (fH->GetDimension() == 1) {
10063 Bool_t getentries = kFALSE;
10064 Double_t yt;
10065 TProfile *hp = (TProfile*)fH;
10066 if (Hoption.Text>2000 && fH->InheritsFrom(TProfile::Class())) {
10067 Hoption.Text = Hoption.Text-2000;
10068 getentries = kTRUE;
10069 }
10070 if (Hoption.Text == 1) angle = 90;
10071 text.SetTextAlign(11);
10072 if (angle == 90) text.SetTextAlign(12);
10073 if (angle == 0) text.SetTextAlign(21);
10074 text.TAttText::Modify();
10075 Double_t dt = 0.02*(gPad->GetY2()-gPad->GetY1());
10076 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10077 if (Hoption.Bar) {
10078 x = fH->GetXaxis()->GetBinLowEdge(i)+
10079 fH->GetXaxis()->GetBinWidth(i)*
10080 (fH->GetBarOffset()+0.5*fH->GetBarWidth());
10081 } else {
10082 x = fH->GetXaxis()->GetBinCenter(i);
10083 }
10084 y = fH->GetBinContent(i);
10085 yt = y;
10086 if (Hoption.MinimumZero && y<0) y = 0;
10087 if (getentries) yt = hp->GetBinEntries(i);
10088 if (yt == 0.) continue;
10089 tt.Form(tf.Data(),yt);
10090 if (Hoption.Logx) {
10091 if (x > 0) x = TMath::Log10(x);
10092 else continue;
10093 }
10094 if (Hoption.Logy) {
10095 if (y > 0) y = TMath::Log10(y);
10096 else continue;
10097 }
10098 if (y >= gPad->GetY2()) continue;
10099 if (y <= gPad->GetY1()) continue;
10100 text.PaintLatex(x,y+0.2*dt,angle,0.02*fH->GetMarkerSize(),tt.Data());
10101 }
10102
10103 // 2D histograms
10104 } else {
10105 text.SetTextAlign(22);
10106 if (Hoption.Text == 1) angle = 0;
10107 text.SetTextAngle(angle);
10108 text.TAttText::Modify();
10109 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
10110 y = fYaxis->GetBinCenter(j);
10111 if (Hoption.Logy) {
10112 if (y > 0) y = TMath::Log10(y);
10113 else continue;
10114 }
10115 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10116 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
10117 x = fXaxis->GetBinCenter(i);
10118 if (Hoption.Logx) {
10119 if (x > 0) x = TMath::Log10(x);
10120 else continue;
10121 }
10122 if (!IsInside(x,y)) continue;
10123 z = fH->GetBinContent(bin);
10124 if (z < Hparam.zmin || (z == 0 && !Hoption.MinimumZero)) continue;
10125 if (Hoption.Text>2000) {
10126 e = fH->GetBinError(bin);
10127 tf.Form("#splitline{%s%s}{#pm %s%s}",
10129 "%",gStyle->GetPaintTextFormat());
10130 tt.Form(tf.Data(),z,e);
10131 } else {
10132 tt.Form(tf.Data(),z);
10133 }
10134 text.PaintLatex(x,y+fH->GetBarOffset()*fYaxis->GetBinWidth(j),
10135 angle,0.02*fH->GetMarkerSize(),tt.Data());
10136 }
10137 }
10138 }
10139}
10140
10141////////////////////////////////////////////////////////////////////////////////
10142/// [Control function to draw a 3D implicit functions.](\ref HP27)
10143
10145{
10146
10147 Int_t irep;
10148
10149 TAxis *xaxis = fH->GetXaxis();
10150 TAxis *yaxis = fH->GetYaxis();
10151 TAxis *zaxis = fH->GetZaxis();
10152
10153 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
10154 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
10155 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
10156 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
10157 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
10158 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
10159
10160 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
10161
10162 TView *view = gPad ? gPad->GetView() : nullptr;
10163 if (!view) {
10164 Error("PaintTF3", "no TView in current pad");
10165 return;
10166 }
10167 Double_t thedeg = 90 - gPad->GetTheta();
10168 Double_t phideg = -90 - gPad->GetPhi();
10169 Double_t psideg = view->GetPsi();
10170 view->SetView(phideg, thedeg, psideg, irep);
10171
10172 fLego->InitMoveScreen(-1.1,1.1);
10173
10174 if (Hoption.BackBox) {
10175 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
10177 fLego->BackBox(90);
10178 }
10179
10181
10182 fLego->ImplicitFunction(fCurrentF3, fXbuf.data(), fYbuf.data(), fH->GetNbinsX(),
10183 fH->GetNbinsY(),
10184 fH->GetNbinsZ(), "BF");
10185
10186 if (Hoption.FrontBox) {
10187 fLego->InitMoveScreen(-1.1,1.1);
10189 fLego->FrontBox(90);
10190 }
10191 if (!Hoption.Axis && !Hoption.Same) {
10192 TGaxis axis;
10193 PaintLegoAxis(&axis, 90);
10194 }
10195
10196 PaintTitle();
10197
10198 fLego.reset();
10199}
10200
10201/////////////////////////////////////////////////////////////new TGaxis///////////////////
10202/// Draw the histogram title
10203///
10204/// The title is drawn according to the title alignment returned by
10205/// `GetTitleAlign()`. It is a 2 digits integer): hv
10206///
10207/// where `h` is the horizontal alignment and `v` is the
10208/// vertical alignment.
10209///
10210/// - `h` can get the values 1 2 3 for left, center, and right
10211/// - `v` can get the values 1 2 3 for bottom, middle and top
10212///
10213/// for instance the default alignment is: 13 (left top)
10214
10216{
10217 // probably best place for calls PaintHighlightBin
10218 // calls after paint histo (1D or 2D) and before paint title and stats
10219 if (!gPad->GetView()) PaintHighlightBin();
10220
10221 if (Hoption.Same) return;
10222 if (fH->TestBit(TH1::kNoTitle)) return;
10223 Int_t nt = strlen(fH->GetTitle());
10224 TPaveText *title = nullptr;
10225 TObject *obj;
10226 TIter next(gPad->GetListOfPrimitives());
10227 while ((obj = next())) {
10228 if (!obj->InheritsFrom(TPaveText::Class())) continue;
10229 title = (TPaveText*)obj;
10230 if (strcmp(title->GetName(),"title")) {title = nullptr; continue;}
10231 break;
10232 }
10233 if (nt == 0 || gStyle->GetOptTitle() <= 0) {
10234 if (title) delete title;
10235 return;
10236 }
10237 Double_t ht = gStyle->GetTitleH();
10238 Double_t wt = gStyle->GetTitleW();
10239
10240 if (ht <= 0) {
10241 if (gStyle->GetTitleFont("")%10 == 3) {
10242 Double_t hw = TMath::Max((Double_t)gPad->XtoPixel(gPad->GetX2()),
10243 (Double_t)gPad->YtoPixel(gPad->GetY1()));
10244 ht = 1.1*(gStyle->GetTitleSize("")/hw);
10245 } else {
10246 ht = 1.1*gStyle->GetTitleFontSize();
10247 }
10248 }
10249 if (ht <= 0) ht = 0.05;
10250 if (wt <= 0) {
10251 TLatex l;
10252 l.SetTextSize(ht);
10253 l.SetTitle(fH->GetTitle());
10254 // adjustment in case the title has several lines (#splitline)
10255 ht = TMath::Max(ht, 1.2*l.GetYsize()/(gPad->GetY2() - gPad->GetY1()));
10256 Double_t wndc = l.GetXsize()/(gPad->GetX2() - gPad->GetX1());
10257 wt = TMath::Min(0.7, 0.02+wndc);
10258 }
10259 if (title) {
10260 TText *t0 = (TText*)title->GetLine(0);
10261 if (t0) {
10262 if (!strcmp(t0->GetTitle(),fH->GetTitle())) return;
10263 t0->SetTitle(fH->GetTitle());
10264 if (wt > 0) title->SetX2NDC(title->GetX1NDC()+wt);
10265 }
10266 return;
10267 }
10268
10269 Int_t talh = gStyle->GetTitleAlign()/10;
10270 if (talh < 1) talh = 1; else if (talh > 3) talh = 3;
10271 Int_t talv = gStyle->GetTitleAlign()%10;
10272 if (talv < 1) talv = 1; else if (talv > 3) talv = 3;
10274 xpos = gStyle->GetTitleX();
10275 ypos = gStyle->GetTitleY();
10276 if (talh == 2) xpos = xpos-wt/2.;
10277 if (talh == 3) xpos = xpos-wt;
10278 if (talv == 2) ypos = ypos+ht/2.;
10279 if (talv == 1) ypos = ypos+ht;
10280
10281 TPaveText *ptitle = new TPaveText(xpos, ypos-ht, xpos+wt, ypos,"blNDC");
10282
10283 // box with the histogram title
10285 ptitle->SetFillStyle(gStyle->GetTitleStyle());
10286 ptitle->SetName("title");
10289 ptitle->SetTextFont(gStyle->GetTitleFont(""));
10290 if (gStyle->GetTitleFont("")%10 > 2)
10292 ptitle->AddText(fH->GetTitle());
10293 ptitle->SetBit(kCanDelete);
10294 ptitle->Draw();
10295 ptitle->Paint();
10296
10297 if(!gPad->IsEditable()) delete ptitle;
10298}
10299
10300////////////////////////////////////////////////////////////////////////////////
10301/// Process message `mess`.
10302
10303void THistPainter::ProcessMessage(const char *mess, const TObject *obj)
10304{
10305 if (!strcmp(mess,"SetF3")) {
10306 fCurrentF3 = (TF3 *)obj;
10307 }
10308}
10309
10310////////////////////////////////////////////////////////////////////////////////
10311/// Static function.
10312///
10313/// Convert Right Ascension, Declination to X,Y using an AITOFF projection.
10314/// This procedure can be used to create an all-sky map in Galactic
10315/// coordinates with an equal-area Aitoff projection. Output map
10316/// coordinates are zero longitude centered.
10317/// Also called Hammer-Aitoff projection (first presented by Ernst von Hammer in 1892)
10318///
10319/// source: GMT
10320///
10321/// code from Ernst-Jan Buis
10322
10324{
10325
10326 Double_t x, y;
10327
10328 Double_t alpha2 = (l/2)*TMath::DegToRad();
10329 Double_t delta = b*TMath::DegToRad();
10330 Double_t r2 = TMath::Sqrt(2.);
10331 Double_t f = 2*r2/TMath::Pi();
10332 Double_t cdec = TMath::Cos(delta);
10333 Double_t denom = TMath::Sqrt(1. + cdec*TMath::Cos(alpha2));
10334 x = cdec*TMath::Sin(alpha2)*2.*r2/denom;
10335 y = TMath::Sin(delta)*r2/denom;
10336 x *= TMath::RadToDeg()/f;
10337 y *= TMath::RadToDeg()/f;
10338 // x *= -1.; // for a skymap swap left<->right
10339 Al = x;
10340 Ab = y;
10341
10342 return 0;
10343}
10344
10345////////////////////////////////////////////////////////////////////////////////
10346/// Static function
10347///
10348/// Probably the most famous of the various map projections, the Mercator projection
10349/// takes its name from Mercator who presented it in 1569. It is a cylindrical, conformal projection
10350/// with no distortion along the equator.
10351/// The Mercator projection has been used extensively for world maps in which the distortion towards
10352/// the polar regions grows rather large, thus incorrectly giving the impression that, for example,
10353/// Greenland is larger than South America. In reality, the latter is about eight times the size of
10354/// Greenland. Also, the Former Soviet Union looks much bigger than Africa or South America. One may wonder
10355/// whether this illusion has had any influence on U.S. foreign policy.' (Source: GMT)
10356/// code from Ernst-Jan Buis
10357
10359{
10360
10361 Al = l;
10363 Ab = TMath::Log(aid);
10364 return 0;
10365}
10366
10367////////////////////////////////////////////////////////////////////////////////
10368/// Static function code for sinusoidal projection
10369/// from Ernst-Jan Buis
10370/// Source https://en.wikipedia.org/wiki/Sinusoidal_projection
10371
10373{
10374
10375 Al = l*cos(b*TMath::DegToRad());
10376 Ab = b;
10377 return 0;
10378}
10379
10380////////////////////////////////////////////////////////////////////////////////
10381/// Static function code for parabolic projection
10382/// from Ernst-Jan Buis
10383
10385{
10386
10387 Al = l*(2.*TMath::Cos(2*b*TMath::DegToRad()/3) - 1);
10388 Ab = 180*TMath::Sin(b*TMath::DegToRad()/3);
10389 return 0;
10390}
10391
10392////////////////////////////////////////////////////////////////////////////////
10393/// Static function.
10394///
10395/// Convert Right Ascension, Declination to X,Y using an MOLLWEIDE projection.
10396/// This procedure can be used to create an all-sky map in Galactic
10397/// coordinates with an equal-area Mollweide projection. Output map
10398/// coordinates are zero longitude centered.
10399/// It is also known as the Babinet projection, homalographic projection, homolographic projection, and elliptical projection.
10400/// Source: https://en.wikipedia.org/wiki/Mollweide_projection
10401///
10402/// code from Marco Meyer-Conde
10403
10405{
10406
10407 Double_t theta0 = b * TMath::DegToRad(), theta = theta0;
10408
10409 for (int i = 0; i < 100; i++) {
10410 Double_t num = 2 * theta + TMath::Sin(2 * theta) - TMath::Pi() * TMath::Sin(theta0);
10411 Double_t den = 4 * TMath::Power(TMath::Cos(theta), 2);
10412
10413 if (den < 1e-20) {
10414 theta = theta0;
10415 break;
10416 }
10417
10418 theta -= num / den;
10419
10420 if (TMath::Abs(num / den) < 1e-4) break;
10421 }
10422
10423 Al = l * TMath::Cos(theta);
10424 Ab = 90 * TMath::Sin(theta);
10425
10426 return 0;
10427}
10428
10429////////////////////////////////////////////////////////////////////////////////
10430/// Recompute the histogram range following graphics operations.
10431
10433{
10434
10435 if (Hoption.Same) return;
10436
10437 // Compute x,y range
10439 xmax = Hparam.xmax,
10440 ymin = Hparam.ymin,
10441 ymax = Hparam.ymax,
10442 xscale = 1;
10443
10444 std::function<Int_t(Double_t,Double_t,Double_t&,Double_t&)> func;
10445
10446 if (Hoption.Proj == 1) {
10447 func = ProjectAitoff2xy;
10448 xscale = 0.9999;
10449 } else if (Hoption.Proj == 2) {
10450 if (Hparam.ymin <= -90 || Hparam.ymax >= 90) {
10451 Warning("Mercator Projection", "Latitude out of range %f or %f", Hparam.ymin, Hparam.ymax);
10452 Hoption.Proj = 0;
10453 } else {
10456 }
10457 } else if (Hoption.Proj == 3) {
10458 func = ProjectSinusoidal2xy;
10459 } else if (Hoption.Proj == 4) {
10460 func = ProjectParabolic2xy;
10461 } else if (Hoption.Proj == 5) {
10462 func = ProjectMollweide2xy;
10463 }
10464
10465 if (func) {
10466 Double_t xmin_aid, ymin_aid, xmax_aid, ymax_aid;
10467
10468 func(Hparam.xmin, Hparam.ymin, xmin_aid, ymin_aid);
10469 func(Hparam.xmin, Hparam.ymax, xmin, ymax_aid);
10470 func(Hparam.xmax, Hparam.ymax, xmax_aid, ymax);
10471 func(Hparam.xmax, Hparam.ymin, xmax, ymin);
10472
10473 if (xmin > xmin_aid) xmin = xmin_aid;
10474 if (ymin > ymin_aid) ymin = ymin_aid;
10475 if (xmax < xmax_aid) xmax = xmax_aid;
10476 if (ymax < ymax_aid) ymax = ymax_aid;
10477 if (Hparam.ymin < 0 && Hparam.ymax > 0) {
10478 // there is an 'equator', check its range in the plot..
10479 func(Hparam.xmin*xscale, 0, xmin_aid, ymin_aid);
10480 func(Hparam.xmax*xscale, 0, xmax_aid, ymin_aid);
10481 if (xmin > xmin_aid) xmin = xmin_aid;
10482 if (xmax < xmax_aid) xmax = xmax_aid;
10483 }
10484 if (Hparam.xmin < 0 && Hparam.xmax > 0) {
10485 func(0, Hparam.ymin, xmin_aid, ymin_aid);
10486 func(0, Hparam.ymax, xmax_aid, ymax_aid);
10487 if (ymin > ymin_aid) ymin = ymin_aid;
10488 if (ymax < ymax_aid) ymax = ymax_aid;
10489 }
10490 }
10491
10492 Hparam.xmin = xmin;
10493 Hparam.xmax = xmax;
10494 Hparam.ymin = ymin;
10495 Hparam.ymax = ymax;
10496
10497 Double_t dx = xmax-xmin;
10498 Double_t dy = ymax-ymin;
10499 Double_t dxr = dx/(1 - gPad->GetLeftMargin() - gPad->GetRightMargin());
10500 Double_t dyr = dy/(1 - gPad->GetBottomMargin() - gPad->GetTopMargin());
10501
10502 // Range() could change the size of the pad pixmap and therefore should
10503 // be called before the other paint routines
10504 gPad->Range(xmin - dxr*gPad->GetLeftMargin(),
10505 ymin - dyr*gPad->GetBottomMargin(),
10506 xmax + dxr*gPad->GetRightMargin(),
10507 ymax + dyr*gPad->GetTopMargin());
10508 gPad->RangeAxis(xmin, ymin, xmax, ymax);
10509}
10510
10511////////////////////////////////////////////////////////////////////////////////
10512/// Set current histogram to `h`
10513
10515{
10516
10517 if (h == nullptr) return;
10518 fH = h;
10519 fXaxis = h->GetXaxis();
10520 fYaxis = h->GetYaxis();
10521 fZaxis = h->GetZaxis();
10523}
10524
10525////////////////////////////////////////////////////////////////////////////////
10526/// Initialize various options to draw 2D histograms.
10527
10529{
10530
10531 static const char *where = "TableInit";
10532
10533 Int_t first, last;
10534 Double_t yMARGIN= gStyle->GetHistTopMargin();
10535 Double_t zmin, zmax;
10536 Int_t maximum = 0;
10537 Int_t minimum = 0;
10538 if (fH->GetMaximumStored() != -1111) maximum = 1;
10539 if (fH->GetMinimumStored() != -1111) minimum = 1;
10540
10541 // ----------------- Compute X axis parameters
10542 first = fXaxis->GetFirst();
10543 last = fXaxis->GetLast();
10544 Hparam.xlast = last;
10550
10551 // if log scale in X, replace xmin,max by the log
10552 if (Hoption.Logx) {
10553 // find the first edge of a bin that is > 0
10554 if (Hparam.xlowedge <=0 ) {
10557 }
10558 if (Hparam.xmin <=0 || Hparam.xmax <=0) {
10559 Error(where, "cannot set X axis to log scale");
10560 return 0;
10561 }
10565 if (Hparam.xlast > last) Hparam.xlast = last;
10568 }
10569
10570 // ----------------- Compute Y axis parameters
10571 first = fYaxis->GetFirst();
10572 last = fYaxis->GetLast();
10573 Hparam.ylast = last;
10577 if (!Hparam.ybinsize) Hparam.ybinsize = 1;
10580
10581 // if log scale in Y, replace ymin,max by the log
10582 if (Hoption.Logy) {
10583 if (Hparam.ylowedge <=0 ) {
10586 }
10587 if (Hparam.ymin <=0 || Hparam.ymax <=0) {
10588 Error(where, "cannot set Y axis to log scale");
10589 return 0;
10590 }
10594 if (Hparam.ylast > last) Hparam.ylast = last;
10597 }
10598
10599
10600 // ----------------- Compute Z axis parameters
10601 Double_t bigp = TMath::Power(10,32);
10602 zmax = -bigp;
10603 zmin = bigp;
10604 Double_t c1, e1;
10605 Double_t allchan = 0;
10606 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
10607 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10608 c1 = fH->GetBinContent(i,j);
10609 zmax = TMath::Max(zmax,c1);
10610 if (Hoption.Error) {
10611 e1 = fH->GetBinError(i,j);
10612 zmax = TMath::Max(zmax,c1+e1);
10613 }
10614 zmin = TMath::Min(zmin,c1);
10615 allchan += c1;
10616 }
10617 }
10618
10619 // Take into account maximum , minimum
10620
10621 if (maximum) zmax = fH->GetMaximumStored();
10622 if (minimum) zmin = fH->GetMinimumStored();
10623 if (Hoption.Logz && zmax < 0) {
10624 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10625 return 0;
10626 } else if (Hoption.Logz && zmin>=0 && zmax==0) { // empty histogram in log scale
10627 zmin = 0.01;
10628 zmax = 10.;
10629 }
10630 if (zmin >= zmax) {
10631 if (Hoption.Logz) {
10632 if (zmax > 0) zmin = 0.001*zmax;
10633 else {
10634 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10635 return 0;
10636 }
10637 }
10638 }
10639
10640 // take into account normalization factor
10641 Hparam.allchan = allchan;
10642 Double_t factor = allchan;
10643 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
10644 if (allchan) factor /= allchan;
10645 if (factor == 0) factor = 1;
10646 Hparam.factor = factor;
10647 zmax = factor*zmax;
10648 zmin = factor*zmin;
10649 c1 = zmax;
10650 if (TMath::Abs(zmin) > TMath::Abs(c1)) c1 = zmin;
10651
10652 // For log scales, histogram coordinates are log10(ymin) and
10653 // log10(ymax). Final adjustment (if not option "Same")
10654 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
10655 // Maximum and Minimum are not defined.
10656 if (Hoption.Logz) {
10657 if (zmin <= 0) {
10658 zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
10659 fH->SetMinimum(zmin);
10660 }
10661 zmin = TMath::Log10(zmin);
10662 if (!minimum) zmin += TMath::Log10(0.5);
10663 zmax = TMath::Log10(zmax);
10664 if (!maximum) zmax += TMath::Log10(2*(0.9/0.95));
10665 goto LZMIN;
10666 }
10667
10668 // final adjustment of YMAXI for linear scale (if not option "Same"):
10669 // decrease histogram height to MAX% of allowed height if HMAXIM
10670 // has not been called.
10671 // MAX% is the value in percent which has been set in HPLSET
10672 // (default is 90%).
10673 if (!maximum) {
10674 zmax += yMARGIN*(zmax-zmin);
10675 }
10676
10677 // final adjustment of ymin for linear scale.
10678 // if minimum is not set , then ymin is set to zero if >0
10679 // or to ymin - yMARGIN if <0.
10680 if (!minimum) {
10681 if (Hoption.MinimumZero) {
10682 if (zmin >= 0) zmin = 0;
10683 else zmin -= yMARGIN*(zmax-zmin);
10684 } else {
10685 Double_t dzmin = yMARGIN*(zmax-zmin);
10686 if (zmin >= 0 && (zmin-dzmin <= 0)) zmin = 0;
10687 else zmin -= dzmin;
10688 }
10689 }
10690
10691LZMIN:
10692 Hparam.zmin = zmin;
10693 Hparam.zmax = zmax;
10694
10695 // Set bar offset and width
10698
10699 return 1;
10700}
10701
10702////////////////////////////////////////////////////////////////////////////////
10703/// This function returns the best format to print the error value (e)
10704/// knowing the parameter value (v) and the format (f) used to print it.
10705
10707{
10708
10709 static TString ef;
10710 TString tf, tv;
10711
10712 // print v with the format f in tv.
10713 tf.Form("%s%s","%",f);
10714 tv.Form(tf.Data(),v);
10715
10716 // Analyse tv.
10717 int ie = tv.Index("e");
10718 int iE = tv.Index("E");
10719 int id = tv.Index(".");
10720
10721 // v has been printed with the exponent notation.
10722 // There is 2 cases, the exponent is positive or negative
10723 if (ie >= 0 || iE >= 0) {
10724 if (tv.Index("+") >= 0) {
10725 if (e < 1) {
10726 ef.Form("%s.1f","%");
10727 } else {
10728 if (ie >= 0) {
10729 ef.Form("%s.%de","%",ie-id-1);
10730 } else {
10731 ef.Form("%s.%dE","%",iE-id-1);
10732 }
10733 }
10734 } else {
10735 if (ie >= 0) {
10736 ef.Form("%s.%de","%",ie-id-1);
10737 } else {
10738 ef.Form("%s.%dE","%",iE-id-1);
10739 }
10740 }
10741
10742 // There is not '.' in tv. e will be printed with one decimal digit.
10743 } else if (id < 0) {
10744 ef.Form("%s.1f","%");
10745
10746 // There is a '.' in tv and no exponent notation. e's decimal part will
10747 // have the same number of digits as v's one.
10748 } else {
10749 ef.Form("%s.%df","%",tv.Length()-id-1);
10750 }
10751
10752 return ef.Data();
10753}
10754
10755////////////////////////////////////////////////////////////////////////////////
10756/// Set projection.
10757
10759{
10760 if (fShowProjection2) {
10761 auto name2 = TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2);
10762 auto c2 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name2.Data()));
10763 if (c2) c2->Close();
10764 fShowProjection2 = 0;
10765 }
10766 if (fShowProjection) {
10767 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10768 auto c1 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name1.Data()));
10769 if (c1) c1->Close();
10770 fShowProjection = 0;
10771 }
10772
10773 if (nbins <= 0) return;
10774
10775 TString opt = option;
10776 opt.ToLower();
10777 Int_t projection = 0;
10778 if (opt.Contains("x")) projection = 1;
10779 if (opt.Contains("y")) projection = 2;
10780 if (opt.Contains("z")) projection = 3;
10781 if (opt.Contains("xy")) projection = 4;
10782 if (opt.Contains("yx")) projection = 5;
10783 if (opt.Contains("xz")) projection = 6;
10784 if (opt.Contains("zx")) projection = 7;
10785 if (opt.Contains("yz")) projection = 8;
10786 if (opt.Contains("zy")) projection = 9;
10787 if (projection < 4) fShowOption = option+1;
10788 else fShowOption = option+2;
10789 fShowProjection = projection+100*nbins;
10790 fShowProjection2 = 0;
10791 gROOT->MakeDefCanvas();
10792 gPad->SetName(TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection).Data());
10793 gPad->SetGrid();
10794}
10795
10797{
10798 if (fShowProjection2) {
10799 auto name2 = TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2);
10800 auto c2 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name2.Data()));
10801 if (c2) c2->Close();
10802 fShowProjection2 = 0;
10803 }
10804 if (fShowProjection) {
10805 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10806 auto c1 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name1.Data()));
10807 if (c1) c1->Close();
10808 fShowProjection = 0;
10809 }
10810
10811 if ((nbinsX <= 0) || (nbinsY <= 0)) return;
10812
10813
10814 TString opt = option;
10815 opt.ToLower();
10816 Int_t projection = 0;
10817 if (opt.Contains("x")) projection = 1;
10818 if (opt.Contains("y")) projection = 2;
10819 if (opt.Contains("z")) projection = 3;
10820 if (opt.Contains("xy")) projection = 4;
10821 if (opt.Contains("yx")) projection = 5;
10822 if (opt.Contains("xz")) projection = 6;
10823 if (opt.Contains("zx")) projection = 7;
10824 if (opt.Contains("yz")) projection = 8;
10825 if (opt.Contains("zy")) projection = 9;
10826 if (projection < 4) fShowOption = option+1;
10827 else fShowOption = option+2;
10828 fShowProjection = projection+100*nbinsY;
10829 fShowProjection2 = projection+100*nbinsX;
10830 gROOT->MakeDefCanvas();
10831 gPad->SetName(TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection).Data());
10832 gPad->SetGrid();
10833 gROOT->MakeDefCanvas();
10834 gPad->SetName(TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2).Data());
10835 gPad->SetGrid();
10836}
10837
10838
10839////////////////////////////////////////////////////////////////////////////////
10840/// Show projection onto X.
10841
10843{
10844
10845 Int_t nbins = (Int_t)fShowProjection/100;
10846 gPad->SetDoubleBuffer(0); // turn off double buffer mode
10847 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
10848
10849 // Erase old position and draw a line at current position
10850 static int pyold1 = 0;
10851 static int pyold2 = 0;
10852 float uxmin = gPad->GetUxmin();
10853 float uxmax = gPad->GetUxmax();
10854 int pxmin = gPad->XtoAbsPixel(uxmin);
10855 int pxmax = gPad->XtoAbsPixel(uxmax);
10856 Float_t upy = gPad->AbsPixeltoY(py);
10857 Float_t y = gPad->PadtoY(upy);
10858 Int_t biny1 = fH->GetYaxis()->FindBin(y);
10859 Int_t biny2 = TMath::Min(biny1+nbins-1, fH->GetYaxis()->GetNbins());
10860 Int_t py1 = gPad->YtoAbsPixel(fH->GetYaxis()->GetBinLowEdge(biny1));
10861 Int_t py2 = gPad->YtoAbsPixel(fH->GetYaxis()->GetBinUpEdge(biny2));
10862
10863 if (pyold1 || pyold2) gVirtualX->DrawBox(pxmin,pyold1,pxmax,pyold2,TVirtualX::kFilled);
10864 gVirtualX->DrawBox(pxmin,py1,pxmax,py2,TVirtualX::kFilled);
10865 pyold1 = py1;
10866 pyold2 = py2;
10867
10868 // Create or set the new canvas proj x
10869 TVirtualPad::TContext ctxt(true);
10870 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10871 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(name1.Data());
10872 if (c) {
10873 c->Clear();
10874 } else {
10875 fShowProjection = 0;
10876 fShowProjection2 = 0;
10877 pyold1 = 0;
10878 pyold2 = 0;
10879 return;
10880 }
10881 c->cd();
10882 c->SetLogy(ctxt.GetSaved()->GetLogz());
10883 c->SetLogx(ctxt.GetSaved()->GetLogx());
10884
10885 // Draw slice corresponding to mouse position
10886 TString prjName = TString::Format("slice_px_of_%s",fH->GetName());
10887 TH1D *hp = ((TH2*)fH)->ProjectionX(prjName, biny1, biny2);
10888 if (hp) {
10889 hp->SetFillColor(38);
10890 // apply a patch from Oliver Freyermuth to set the title in the projection
10891 // using the range of the projected Y values
10892 if (biny1 == biny2) {
10893 Double_t valueFrom = fH->GetYaxis()->GetBinLowEdge(biny1);
10894 Double_t valueTo = fH->GetYaxis()->GetBinUpEdge(biny1);
10895 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
10896 Int_t valuePrecision = -TMath::Nint(TMath::Log10(valueTo-valueFrom))+1;
10897 if (fH->GetYaxis()->GetLabels() != nullptr) {
10898 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf] %s", biny1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetYaxis()->GetBinLabel(biny1)));
10899 } else {
10900 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf]", biny1, valuePrecision, valueFrom, valuePrecision, valueTo));
10901 }
10902 } else {
10903 Double_t valueFrom = fH->GetYaxis()->GetBinLowEdge(biny1);
10904 Double_t valueTo = fH->GetYaxis()->GetBinUpEdge(biny2);
10905 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
10906 // biny1 is used here to get equal precision no matter how large the binrange is,
10907 // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
10908 Int_t valuePrecision = -TMath::Nint(TMath::Log10(fH->GetYaxis()->GetBinUpEdge(biny1)-valueFrom))+1;
10909 if (fH->GetYaxis()->GetLabels() != nullptr) {
10910 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)));
10911 } else {
10912 hp->SetTitle(TString::Format("ProjectionX of biny=[%d,%d] [y=%.*lf..%.*lf]", biny1, biny2, valuePrecision, valueFrom, valuePrecision, valueTo));
10913 }
10914 }
10915 hp->SetXTitle(fH->GetXaxis()->GetTitle());
10916 hp->SetYTitle(((TH2*)fH)->GetZaxis()->GetTitle() ? ((TH2*)fH)->GetZaxis()->GetTitle() : "Number of Entries");
10917 hp->Draw();
10918 c->Update();
10919 }
10920}
10921
10922////////////////////////////////////////////////////////////////////////////////
10923/// Show projection onto Y.
10924
10926{
10927
10928 Int_t nbins = (Int_t)fShowProjection/100;
10929 if (fShowProjection2)
10930 nbins = (Int_t)fShowProjection2/100;
10931 gPad->SetDoubleBuffer(0); // turn off double buffer mode
10932 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
10933
10934 // Erase old position and draw a line at current position
10935 static int pxold1 = 0;
10936 static int pxold2 = 0;
10937 float uymin = gPad->GetUymin();
10938 float uymax = gPad->GetUymax();
10939 int pymin = gPad->YtoAbsPixel(uymin);
10940 int pymax = gPad->YtoAbsPixel(uymax);
10941 Float_t upx = gPad->AbsPixeltoX(px);
10942 Float_t x = gPad->PadtoX(upx);
10943 Int_t binx1 = fH->GetXaxis()->FindBin(x);
10944 Int_t binx2 = TMath::Min(binx1+nbins-1, fH->GetXaxis()->GetNbins());
10945 Int_t px1 = gPad->XtoAbsPixel(fH->GetXaxis()->GetBinLowEdge(binx1));
10946 Int_t px2 = gPad->XtoAbsPixel(fH->GetXaxis()->GetBinUpEdge(binx2));
10947
10948 if (pxold1 || pxold2) gVirtualX->DrawBox(pxold1,pymin,pxold2,pymax,TVirtualX::kFilled);
10949 gVirtualX->DrawBox(px1,pymin,px2,pymax,TVirtualX::kFilled);
10950 pxold1 = px1;
10951 pxold2 = px2;
10952
10953 // Create or set the new canvas proj y
10954 TVirtualPad::TContext ctxt(true);
10955
10956 TString name2 = fShowProjection2 ? TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2)
10957 : TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10958
10959 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(name2.Data());
10960 if (c) {
10961 c->Clear();
10962 } else {
10963 fShowProjection = 0;
10964 fShowProjection2 = 0;
10965 pxold1 = 0;
10966 pxold2 = 0;
10967 return;
10968 }
10969 c->cd();
10970 c->SetLogy(ctxt.GetSaved()->GetLogz());
10971 c->SetLogx(ctxt.GetSaved()->GetLogy());
10972
10973 // Draw slice corresponding to mouse position
10974 TString prjName = TString::Format("slice_py_of_%s",fH->GetName());
10975 TH1D *hp = ((TH2*)fH)->ProjectionY(prjName, binx1, binx2);
10976 if (hp) {
10977 hp->SetFillColor(38);
10978 // apply a patch from Oliver Freyermuth to set the title in the projection
10979 // using the range of the projected X values
10980 if (binx1 == binx2) {
10981 Double_t valueFrom = fH->GetXaxis()->GetBinLowEdge(binx1);
10982 Double_t valueTo = fH->GetXaxis()->GetBinUpEdge(binx1);
10983 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
10984 Int_t valuePrecision = -TMath::Nint(TMath::Log10(valueTo-valueFrom))+1;
10985 if (fH->GetXaxis()->GetLabels() != nullptr) {
10986 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf] [%s]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetXaxis()->GetBinLabel(binx1)));
10987 } else {
10988 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo));
10989 }
10990 } else {
10991 Double_t valueFrom = fH->GetXaxis()->GetBinLowEdge(binx1);
10992 Double_t valueTo = fH->GetXaxis()->GetBinUpEdge(binx2);
10993 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
10994 // binx1 is used here to get equal precision no matter how large the binrange is,
10995 // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
10996 Int_t valuePrecision = -TMath::Nint(TMath::Log10(fH->GetXaxis()->GetBinUpEdge(binx1)-valueFrom))+1;
10997 if (fH->GetXaxis()->GetLabels() != nullptr) {
10998 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)));
10999 } else {
11000 hp->SetTitle(TString::Format("ProjectionY of binx=[%d,%d] [x=%.*lf..%.*lf]", binx1, binx2, valuePrecision, valueFrom, valuePrecision, valueTo));
11001 }
11002 }
11003 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11004 hp->SetYTitle(((TH2*)fH)->GetZaxis()->GetTitle() ? ((TH2*)fH)->GetZaxis()->GetTitle() : "Number of Entries");
11005 hp->Draw(fShowProjection2 ? "hbar" : "");
11006 c->Update();
11007 }
11008}
11009
11010////////////////////////////////////////////////////////////////////////////////
11011/// Show projection (specified by `fShowProjection`) of a `TH3`.
11012/// The drawing option for the projection is in `fShowOption`.
11013///
11014/// First implementation; R.Brun
11015///
11016/// Full implementation: Tim Tran (timtran@jlab.org) April 2006
11017
11019{
11020
11021 Int_t nbins=(Int_t)fShowProjection/100; //decode nbins
11022 if (fH->GetDimension() < 3) {
11023 if (fShowProjection2 % 100 == 1) {
11024 ShowProjectionY(px, py);
11025 }
11026 if (fShowProjection % 100 == 1) {
11027 ShowProjectionX(px, py);
11028 return;
11029 }
11030 if (fShowProjection % 100 == 2) {
11031 ShowProjectionY(px, py);
11032 return;
11033 }
11034 }
11035
11036 gPad->SetDoubleBuffer(0); // turn off double buffer mode
11037 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
11038
11039 // Erase old position and draw a line at current position
11040 TView *view = gPad->GetView();
11041 if (!view) return;
11042 TH3 *h3 = (TH3*)fH;
11043 TAxis *xaxis = h3->GetXaxis();
11044 TAxis *yaxis = h3->GetYaxis();
11045 TAxis *zaxis = h3->GetZaxis();
11046 Double_t u[3],xx[3];
11047
11048 static TPoint line1[2];//store end points of a line, initialised 0 by default
11049 static TPoint line2[2];// second line when slice thickness > 1 bin thickness
11050 static TPoint line3[2];
11051 static TPoint line4[2];
11052 static TPoint endface1[5];
11053 static TPoint endface2[5];
11054 static TPoint rect1[5];//store vertices of the polyline (rectangle), initialsed 0 by default
11055 static TPoint rect2[5];// second rectangle when slice thickness > 1 bin thickness
11056
11057 Double_t uxmin = gPad->GetUxmin();
11058 Double_t uxmax = gPad->GetUxmax();
11059 Double_t uymin = gPad->GetUymin();
11060 Double_t uymax = gPad->GetUymax();
11061
11062 int pxmin = gPad->XtoAbsPixel(uxmin);
11063 int pxmax = gPad->XtoAbsPixel(uxmax);
11064 if (pxmin==pxmax) return;
11065 int pymin = gPad->YtoAbsPixel(uymin);
11066 int pymax = gPad->YtoAbsPixel(uymax);
11067 if (pymin==pymax) return;
11068 Double_t cx = (pxmax-pxmin)/(uxmax-uxmin);
11069 Double_t cy = (pymax-pymin)/(uymax-uymin);
11070 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(TString::Format("c_%zx_projection_%d",
11071 (size_t)fH, fShowProjection).Data());
11072 if (!c) {
11073 fShowProjection = 0;
11074 return;
11075 }
11076
11077 TVirtualPad::TContext ctxt(true);
11078
11079 switch ((Int_t)fShowProjection%100) {
11080 case 1:
11081 // "x"
11082 {
11083 Int_t firstY = yaxis->GetFirst();
11084 Int_t lastY = yaxis->GetLast();
11085 Int_t biny = firstY + Int_t((lastY-firstY)*(px-pxmin)/(pxmax-pxmin));
11086 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11087 yaxis->SetRange(biny,biny2);
11088 Int_t firstZ = zaxis->GetFirst();
11089 Int_t lastZ = zaxis->GetLast();
11090 Int_t binz = firstZ + Int_t((lastZ-firstZ)*(py-pymin)/(pymax-pymin));
11091 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11092 zaxis->SetRange(binz,binz2);
11093 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11094 if (nbins>1 && line1[0].GetX()) {
11095 gVirtualX->DrawPolyLine(2,line2);
11096 gVirtualX->DrawPolyLine(2,line3);
11097 gVirtualX->DrawPolyLine(2,line4);
11098 gVirtualX->DrawPolyLine(5,endface1);
11099 gVirtualX->DrawPolyLine(5,endface2);
11100 }
11101 xx[0] = xaxis->GetXmin();
11102 xx[2] = zaxis->GetBinCenter(binz);
11103 xx[1] = yaxis->GetBinCenter(biny);
11104 view->WCtoNDC(xx,u);
11105 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11106 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11107 xx[0] = xaxis->GetXmax();
11108 view->WCtoNDC(xx,u);
11109 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11110 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11111 gVirtualX->DrawPolyLine(2,line1);
11112 if (nbins>1) {
11113 xx[0] = xaxis->GetXmin();
11114 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11115 xx[1] = yaxis->GetBinCenter(biny);
11116 view->WCtoNDC(xx,u);
11117 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11118 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11119 xx[0] = xaxis->GetXmax();
11120 view->WCtoNDC(xx,u);
11121 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11122 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11123
11124 xx[0] = xaxis->GetXmin();
11125 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11126 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11127 view->WCtoNDC(xx,u);
11128 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11129 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11130 xx[0] = xaxis->GetXmax();
11131 view->WCtoNDC(xx,u);
11132 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11133 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11134
11135 xx[0] = xaxis->GetXmin();
11136 xx[2] = zaxis->GetBinCenter(binz);
11137 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11138 view->WCtoNDC(xx,u);
11139 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11140 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11141 xx[0] = xaxis->GetXmax();
11142 view->WCtoNDC(xx,u);
11143 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11144 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11145
11146 endface1[0].SetX(line1[0].GetX());
11147 endface1[0].SetY(line1[0].GetY());
11148 endface1[1].SetX(line2[0].GetX());
11149 endface1[1].SetY(line2[0].GetY());
11150 endface1[2].SetX(line3[0].GetX());
11151 endface1[2].SetY(line3[0].GetY());
11152 endface1[3].SetX(line4[0].GetX());
11153 endface1[3].SetY(line4[0].GetY());
11154 endface1[4].SetX(line1[0].GetX());
11155 endface1[4].SetY(line1[0].GetY());
11156
11157 endface2[0].SetX(line1[1].GetX());
11158 endface2[0].SetY(line1[1].GetY());
11159 endface2[1].SetX(line2[1].GetX());
11160 endface2[1].SetY(line2[1].GetY());
11161 endface2[2].SetX(line3[1].GetX());
11162 endface2[2].SetY(line3[1].GetY());
11163 endface2[3].SetX(line4[1].GetX());
11164 endface2[3].SetY(line4[1].GetY());
11165 endface2[4].SetX(line1[1].GetX());
11166 endface2[4].SetY(line1[1].GetY());
11167
11168 gVirtualX->DrawPolyLine(2,line2);
11169 gVirtualX->DrawPolyLine(2,line3);
11170 gVirtualX->DrawPolyLine(2,line4);
11171 gVirtualX->DrawPolyLine(5,endface1);
11172 gVirtualX->DrawPolyLine(5,endface2);
11173 }
11174 c->Clear();
11175 c->cd();
11176 TH1 *hp = h3->Project3D("x");
11177 yaxis->SetRange(firstY,lastY);
11178 zaxis->SetRange(firstZ,lastZ);
11179 if (hp) {
11180 hp->SetFillColor(38);
11181 if (nbins == 1)
11182 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny),
11183 binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
11184 else {
11185 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),
11186 binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
11187 }
11188 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11189 hp->SetYTitle("Number of Entries");
11190 hp->Draw(fShowOption.Data());
11191 }
11192 }
11193 break;
11194
11195 case 2:
11196 // "y"
11197 {
11198 Int_t firstX = xaxis->GetFirst();
11199 Int_t lastX = xaxis->GetLast();
11200 Int_t binx = firstX + Int_t((lastX-firstX)*(px-pxmin)/(pxmax-pxmin));
11201 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11202 xaxis->SetRange(binx,binx2);
11203 Int_t firstZ = zaxis->GetFirst();
11204 Int_t lastZ = zaxis->GetLast();
11205 Int_t binz = firstZ + Int_t((lastZ-firstZ)*(py-pymin)/(pymax-pymin));
11206 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11207 zaxis->SetRange(binz,binz2);
11208 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11209 if (nbins>1 && line1[0].GetX()) {
11210 gVirtualX->DrawPolyLine(2,line2);
11211 gVirtualX->DrawPolyLine(2,line3);
11212 gVirtualX->DrawPolyLine(2,line4);
11213 gVirtualX->DrawPolyLine(5,endface1);
11214 gVirtualX->DrawPolyLine(5,endface2);
11215 }
11216 xx[0]=xaxis->GetBinCenter(binx);
11217 xx[2] = zaxis->GetBinCenter(binz);
11218 xx[1] = yaxis->GetXmin();
11219 view->WCtoNDC(xx,u);
11220 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11221 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11222 xx[1] = yaxis->GetXmax();
11223 view->WCtoNDC(xx,u);
11224 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11225 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11226 gVirtualX->DrawPolyLine(2,line1);
11227 if (nbins>1) {
11228 xx[1] = yaxis->GetXmin();
11229 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11230 xx[0] = xaxis->GetBinCenter(binx);
11231 view->WCtoNDC(xx,u);
11232 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11233 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11234 xx[1] = yaxis->GetXmax();
11235 view->WCtoNDC(xx,u);
11236 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11237 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11238
11239 xx[1] = yaxis->GetXmin();
11240 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11241 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11242 view->WCtoNDC(xx,u);
11243 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11244 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11245 xx[1] = yaxis->GetXmax();
11246 view->WCtoNDC(xx,u);
11247 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11248 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11249
11250 xx[1] = yaxis->GetXmin();
11251 xx[2] = zaxis->GetBinCenter(binz);
11252 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11253 view->WCtoNDC(xx,u);
11254 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11255 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11256 xx[1] = yaxis->GetXmax();
11257 view->WCtoNDC(xx,u);
11258 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11259 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11260
11261 endface1[0].SetX(line1[0].GetX());
11262 endface1[0].SetY(line1[0].GetY());
11263 endface1[1].SetX(line2[0].GetX());
11264 endface1[1].SetY(line2[0].GetY());
11265 endface1[2].SetX(line3[0].GetX());
11266 endface1[2].SetY(line3[0].GetY());
11267 endface1[3].SetX(line4[0].GetX());
11268 endface1[3].SetY(line4[0].GetY());
11269 endface1[4].SetX(line1[0].GetX());
11270 endface1[4].SetY(line1[0].GetY());
11271
11272 endface2[0].SetX(line1[1].GetX());
11273 endface2[0].SetY(line1[1].GetY());
11274 endface2[1].SetX(line2[1].GetX());
11275 endface2[1].SetY(line2[1].GetY());
11276 endface2[2].SetX(line3[1].GetX());
11277 endface2[2].SetY(line3[1].GetY());
11278 endface2[3].SetX(line4[1].GetX());
11279 endface2[3].SetY(line4[1].GetY());
11280 endface2[4].SetX(line1[1].GetX());
11281 endface2[4].SetY(line1[1].GetY());
11282
11283 gVirtualX->DrawPolyLine(2,line2);
11284 gVirtualX->DrawPolyLine(2,line3);
11285 gVirtualX->DrawPolyLine(2,line4);
11286 gVirtualX->DrawPolyLine(5,endface1);
11287 gVirtualX->DrawPolyLine(5,endface2);
11288 }
11289 c->Clear();
11290 c->cd();
11291 TH1 *hp = h3->Project3D("y");
11292 xaxis->SetRange(firstX,lastX);
11293 zaxis->SetRange(firstZ,lastZ);
11294 if (hp) {
11295 hp->SetFillColor(38);
11296 if (nbins == 1)
11297 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
11298 binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
11299 else
11300 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),
11301 binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
11302 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11303 hp->SetYTitle("Number of Entries");
11304 hp->Draw(fShowOption.Data());
11305 }
11306 }
11307 break;
11308
11309 case 3:
11310 // "z"
11311 {
11312 Int_t firstX = xaxis->GetFirst();
11313 Int_t lastX = xaxis->GetLast();
11314 Int_t binx = firstX + Int_t((lastX-firstX)*(px-pxmin)/(pxmax-pxmin));
11315 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11316 xaxis->SetRange(binx,binx2);
11317 Int_t firstY = yaxis->GetFirst();
11318 Int_t lastY = yaxis->GetLast();
11319 Int_t biny = firstY + Int_t((lastY-firstY)*(py-pymin)/(pymax-pymin));
11320 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11321 yaxis->SetRange(biny,biny2);
11322 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11323 if (nbins>1 && line1[0].GetX()) {
11324 gVirtualX->DrawPolyLine(2,line2);
11325 gVirtualX->DrawPolyLine(2,line3);
11326 gVirtualX->DrawPolyLine(2,line4);
11327 gVirtualX->DrawPolyLine(5,endface1);
11328 gVirtualX->DrawPolyLine(5,endface2);
11329 }
11330 xx[0] = xaxis->GetBinCenter(binx);
11331 xx[1] = yaxis->GetBinCenter(biny);
11332 xx[2] = zaxis->GetXmin();
11333 view->WCtoNDC(xx,u);
11334 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11335 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11336 xx[2] = zaxis->GetXmax();
11337 view->WCtoNDC(xx,u);
11338 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11339 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11340 gVirtualX->DrawPolyLine(2,line1);
11341 if (nbins>1) {
11342 xx[2] = zaxis->GetXmin();
11343 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11344 xx[0] = xaxis->GetBinCenter(binx);
11345 view->WCtoNDC(xx,u);
11346 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11347 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11348 xx[2] = zaxis->GetXmax();
11349 view->WCtoNDC(xx,u);
11350 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11351 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11352
11353 xx[2] = zaxis->GetXmin();
11354 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11355 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11356 view->WCtoNDC(xx,u);
11357 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11358 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11359 xx[2] = zaxis->GetXmax();
11360 view->WCtoNDC(xx,u);
11361 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11362 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11363
11364 xx[2] = zaxis->GetXmin();
11365 xx[1] = yaxis->GetBinCenter(biny);
11366 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11367 view->WCtoNDC(xx,u);
11368 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11369 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11370 xx[2] = zaxis->GetXmax();
11371 view->WCtoNDC(xx,u);
11372 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11373 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11374
11375 endface1[0].SetX(line1[0].GetX());
11376 endface1[0].SetY(line1[0].GetY());
11377 endface1[1].SetX(line2[0].GetX());
11378 endface1[1].SetY(line2[0].GetY());
11379 endface1[2].SetX(line3[0].GetX());
11380 endface1[2].SetY(line3[0].GetY());
11381 endface1[3].SetX(line4[0].GetX());
11382 endface1[3].SetY(line4[0].GetY());
11383 endface1[4].SetX(line1[0].GetX());
11384 endface1[4].SetY(line1[0].GetY());
11385
11386 endface2[0].SetX(line1[1].GetX());
11387 endface2[0].SetY(line1[1].GetY());
11388 endface2[1].SetX(line2[1].GetX());
11389 endface2[1].SetY(line2[1].GetY());
11390 endface2[2].SetX(line3[1].GetX());
11391 endface2[2].SetY(line3[1].GetY());
11392 endface2[3].SetX(line4[1].GetX());
11393 endface2[3].SetY(line4[1].GetY());
11394 endface2[4].SetX(line1[1].GetX());
11395 endface2[4].SetY(line1[1].GetY());
11396
11397 gVirtualX->DrawPolyLine(2,line2);
11398 gVirtualX->DrawPolyLine(2,line3);
11399 gVirtualX->DrawPolyLine(2,line4);
11400 gVirtualX->DrawPolyLine(5,endface1);
11401 gVirtualX->DrawPolyLine(5,endface2);
11402 }
11403 c->Clear();
11404 c->cd();
11405 TH1 *hp = h3->Project3D("z");
11406 xaxis->SetRange(firstX,lastX);
11407 yaxis->SetRange(firstY,lastY);
11408 if (hp) {
11409 hp->SetFillColor(38);
11410 if (nbins == 1)
11411 hp->SetTitle(TString::Format("ProjectionZ of binx=%d [x=%.1f..%.1f] biny=%d [y=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
11412 biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny)));
11413 else
11414 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),
11415 biny, biny2, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny2) ) );
11416 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11417 hp->SetYTitle("Number of Entries");
11418 hp->Draw(fShowOption.Data());
11419 }
11420 }
11421 break;
11422
11423 case 4:
11424 // "xy"
11425 {
11426 Int_t first = zaxis->GetFirst();
11427 Int_t last = zaxis->GetLast();
11428 Int_t binz = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11429 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11430 zaxis->SetRange(binz,binz2);
11431 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11432 if (nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11433 xx[0] = xaxis->GetXmin();
11434 xx[1] = yaxis->GetXmax();
11435 xx[2] = zaxis->GetBinCenter(binz);
11436 view->WCtoNDC(xx,u);
11437 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11438 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11439 rect1[4].SetX(rect1[0].GetX());
11440 rect1[4].SetY(rect1[0].GetY());
11441 xx[0] = xaxis->GetXmax();
11442 view->WCtoNDC(xx,u);
11443 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11444 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11445 xx[1] = yaxis->GetXmin();
11446 view->WCtoNDC(xx,u);
11447 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11448 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11449 xx[0] = xaxis->GetXmin();
11450 view->WCtoNDC(xx,u);
11451 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11452 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11453 gVirtualX->DrawPolyLine(5,rect1);
11454 if (nbins>1) {
11455 xx[0] = xaxis->GetXmin();
11456 xx[1] = yaxis->GetXmax();
11457 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11458 view->WCtoNDC(xx,u);
11459 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11460 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11461 rect2[4].SetX(rect2[0].GetX());
11462 rect2[4].SetY(rect2[0].GetY());
11463 xx[0] = xaxis->GetXmax();
11464 view->WCtoNDC(xx,u);
11465 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11466 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11467 xx[1] = yaxis->GetXmin();
11468 view->WCtoNDC(xx,u);
11469 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11470 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11471 xx[0] = xaxis->GetXmin();
11472 view->WCtoNDC(xx,u);
11473 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11474 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11475 gVirtualX->DrawPolyLine(5,rect2);
11476 }
11477
11478 c->Clear();
11479 c->cd();
11480 TH2 *hp = (TH2*)h3->Project3D("xy");
11481 zaxis->SetRange(first,last);
11482 if (hp) {
11483 hp->SetFillColor(38);
11484 if (nbins==1)hp->SetTitle(TString::Format("ProjectionXY of binz=%d [z=%.1f..%.f]", binz,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz)));
11485 else hp->SetTitle(TString::Format("ProjectionXY, binz=[%d,%d] [z=%.1f..%.1f]", binz,binz2,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz2)));
11486 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11487 hp->SetYTitle(fH->GetXaxis()->GetTitle());
11488 hp->SetZTitle("Number of Entries");
11489 hp->Draw(fShowOption.Data());
11490 }
11491 }
11492 break;
11493
11494 case 5:
11495 // "yx"
11496 {
11497 Int_t first = zaxis->GetFirst();
11498 Int_t last = zaxis->GetLast();
11499 Int_t binz = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11500 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11501 zaxis->SetRange(binz,binz2);
11502 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11503 if (nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11504 xx[0] = xaxis->GetXmin();
11505 xx[1] = yaxis->GetXmax();
11506 xx[2] = zaxis->GetBinCenter(binz);
11507 view->WCtoNDC(xx,u);
11508 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11509 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11510 rect1[4].SetX(rect1[0].GetX());
11511 rect1[4].SetY(rect1[0].GetY());
11512 xx[0] = xaxis->GetXmax();
11513 view->WCtoNDC(xx,u);
11514 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11515 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11516 xx[1] = yaxis->GetXmin();
11517 view->WCtoNDC(xx,u);
11518 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11519 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11520 xx[0] = xaxis->GetXmin();
11521 view->WCtoNDC(xx,u);
11522 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11523 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11524 gVirtualX->DrawPolyLine(5,rect1);
11525 if (nbins>1) {
11526 xx[0] = xaxis->GetXmin();
11527 xx[1] = yaxis->GetXmax();
11528 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11529 view->WCtoNDC(xx,u);
11530 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11531 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11532 rect2[4].SetX(rect2[0].GetX());
11533 rect2[4].SetY(rect2[0].GetY());
11534 xx[0] = xaxis->GetXmax();
11535 view->WCtoNDC(xx,u);
11536 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11537 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11538 xx[1] = yaxis->GetXmin();
11539 view->WCtoNDC(xx,u);
11540 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11541 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11542 xx[0] = xaxis->GetXmin();
11543 view->WCtoNDC(xx,u);
11544 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11545 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11546 gVirtualX->DrawPolyLine(5,rect2);
11547 }
11548 c->Clear();
11549 c->cd();
11550 TH2 *hp = (TH2*)h3->Project3D("yx");
11551 zaxis->SetRange(first,last);
11552 if (hp) {
11553 hp->SetFillColor(38);
11554 if (nbins==1)hp->SetTitle(TString::Format("ProjectionYX of binz=%d [z=%.1f..%.f]", binz,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz)));
11555 else hp->SetTitle(TString::Format("ProjectionYX, binz=[%d,%d] [z=%.1f..%.1f]", binz,binz2,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz2)));
11556 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11557 hp->SetYTitle(fH->GetYaxis()->GetTitle());
11558 hp->SetZTitle("Number of Entries");
11559 hp->Draw(fShowOption.Data());
11560 }
11561 }
11562 break;
11563
11564 case 6:
11565 // "xz"
11566 {
11567 Int_t first = yaxis->GetFirst();
11568 Int_t last = yaxis->GetLast();
11569 Int_t biny = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11570 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11571 yaxis->SetRange(biny,biny2);
11572 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11573 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11574 xx[0] = xaxis->GetXmin();
11575 xx[2] = zaxis->GetXmax();
11576 xx[1] = yaxis->GetBinCenter(biny);
11577 view->WCtoNDC(xx,u);
11578 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11579 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11580 rect1[4].SetX(rect1[0].GetX());
11581 rect1[4].SetY(rect1[0].GetY());
11582 xx[0] = xaxis->GetXmax();
11583 view->WCtoNDC(xx,u);
11584 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11585 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11586 xx[2] = zaxis->GetXmin();
11587 view->WCtoNDC(xx,u);
11588 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11589 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11590 xx[0] = xaxis->GetXmin();
11591 view->WCtoNDC(xx,u);
11592 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11593 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11594 gVirtualX->DrawPolyLine(5,rect1);
11595 if (nbins>1) {
11596 xx[0] = xaxis->GetXmin();
11597 xx[2] = zaxis->GetXmax();
11598 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11599 view->WCtoNDC(xx,u);
11600 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11601 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11602 rect2[4].SetX(rect2[0].GetX());
11603 rect2[4].SetY(rect2[0].GetY());
11604 xx[0] = xaxis->GetXmax();
11605 view->WCtoNDC(xx,u);
11606 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11607 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11608 xx[2] = zaxis->GetXmin();
11609 view->WCtoNDC(xx,u);
11610 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11611 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11612 xx[0] = xaxis->GetXmin();
11613 view->WCtoNDC(xx,u);
11614 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11615 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11616 gVirtualX->DrawPolyLine(5,rect2);
11617 }
11618 c->Clear();
11619 c->cd();
11620 TH2 *hp = (TH2*)h3->Project3D("xz");
11621 yaxis->SetRange(first,last);
11622 if (hp) {
11623 hp->SetFillColor(38);
11624 if (nbins==1)hp->SetTitle(TString::Format("ProjectionXZ of biny=%d [y=%.1f..%.f]", biny,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny)));
11625 else hp->SetTitle(TString::Format("ProjectionXZ, biny=[%d,%d] [y=%.1f..%.1f]", biny,biny2,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny2)));
11626 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11627 hp->SetYTitle(fH->GetXaxis()->GetTitle());
11628 hp->SetZTitle("Number of Entries");
11629 hp->Draw(fShowOption.Data());
11630 }
11631 }
11632 break;
11633
11634 case 7:
11635 // "zx"
11636 {
11637 Int_t first = yaxis->GetFirst();
11638 Int_t last = yaxis->GetLast();
11639 Int_t biny = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11640 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11641 yaxis->SetRange(biny,biny2);
11642 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11643 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11644 xx[0] = xaxis->GetXmin();
11645 xx[2] = zaxis->GetXmax();
11646 xx[1] = yaxis->GetBinCenter(biny);
11647 view->WCtoNDC(xx,u);
11648 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11649 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11650 rect1[4].SetX(rect1[0].GetX());
11651 rect1[4].SetY(rect1[0].GetY());
11652 xx[0] = xaxis->GetXmax();
11653 view->WCtoNDC(xx,u);
11654 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11655 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11656 xx[2] = zaxis->GetXmin();
11657 view->WCtoNDC(xx,u);
11658 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11659 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11660 xx[0] = xaxis->GetXmin();
11661 view->WCtoNDC(xx,u);
11662 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11663 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11664 gVirtualX->DrawPolyLine(5,rect1);
11665 if (nbins>1) {
11666 xx[0] = xaxis->GetXmin();
11667 xx[2] = zaxis->GetXmax();
11668 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11669 view->WCtoNDC(xx,u);
11670 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11671 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11672 rect2[4].SetX(rect2[0].GetX());
11673 rect2[4].SetY(rect2[0].GetY());
11674 xx[0] = xaxis->GetXmax();
11675 view->WCtoNDC(xx,u);
11676 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11677 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11678 xx[2] = zaxis->GetXmin();
11679 view->WCtoNDC(xx,u);
11680 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11681 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11682 xx[0] = xaxis->GetXmin();
11683 view->WCtoNDC(xx,u);
11684 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11685 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11686 gVirtualX->DrawPolyLine(5,rect2);
11687 }
11688 c->Clear();
11689 c->cd();
11690 TH2 *hp = (TH2*)h3->Project3D("zx");
11691 yaxis->SetRange(first,last);
11692 if (hp) {
11693 hp->SetFillColor(38);
11694 if (nbins==1)hp->SetTitle(TString::Format("ProjectionZX of biny=%d [y=%.1f..%.f]", biny,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny)));
11695 else hp->SetTitle(TString::Format("ProjectionZX, biny=[%d,%d] [y=%.1f..%.1f]", biny,biny2,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny2)));
11696 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11697 hp->SetYTitle(fH->GetZaxis()->GetTitle());
11698 hp->SetZTitle("Number of Entries");
11699 hp->Draw(fShowOption.Data());
11700 }
11701 }
11702 break;
11703
11704 case 8:
11705 // "yz"
11706 {
11707 Int_t first = xaxis->GetFirst();
11708 Int_t last = xaxis->GetLast();
11709 Int_t binx = first + Int_t((last-first)*(px-pxmin)/(pxmax-pxmin));
11710 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11711 xaxis->SetRange(binx,binx2);
11712 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11713 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11714 xx[2] = zaxis->GetXmin();
11715 xx[1] = yaxis->GetXmax();
11716 xx[0] = xaxis->GetBinCenter(binx);
11717 view->WCtoNDC(xx,u);
11718 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11719 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11720 rect1[4].SetX(rect1[0].GetX());
11721 rect1[4].SetY(rect1[0].GetY());
11722 xx[2] = zaxis->GetXmax();
11723 view->WCtoNDC(xx,u);
11724 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11725 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11726 xx[1] = yaxis->GetXmin();
11727 view->WCtoNDC(xx,u);
11728 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11729 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11730 xx[2] = zaxis->GetXmin();
11731 view->WCtoNDC(xx,u);
11732 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11733 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11734 gVirtualX->DrawPolyLine(5,rect1);
11735 if (nbins>1) {
11736 xx[2] = zaxis->GetXmin();
11737 xx[1] = yaxis->GetXmax();
11738 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11739 view->WCtoNDC(xx,u);
11740 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11741 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11742 rect2[4].SetX(rect2[0].GetX());
11743 rect2[4].SetY(rect2[0].GetY());
11744 xx[2] = zaxis->GetXmax();
11745 view->WCtoNDC(xx,u);
11746 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11747 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11748 xx[1] = yaxis->GetXmin();
11749 view->WCtoNDC(xx,u);
11750 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11751 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11752 xx[2] = zaxis->GetXmin();
11753 view->WCtoNDC(xx,u);
11754 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11755 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11756 gVirtualX->DrawPolyLine(5,rect2);
11757 }
11758 c->Clear();
11759 c->cd();
11760 TH2 *hp = (TH2*)h3->Project3D("yz");
11761 xaxis->SetRange(first,last);
11762 if (hp) {
11763 hp->SetFillColor(38);
11764 if (nbins==1)hp->SetTitle(TString::Format("ProjectionYZ of binx=%d [x=%.1f..%.f]", binx,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx)));
11765 else hp->SetTitle(TString::Format("ProjectionYZ, binx=[%d,%d] [x=%.1f..%.1f]", binx,binx2,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx2)));
11766 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11767 hp->SetYTitle(fH->GetYaxis()->GetTitle());
11768 hp->SetZTitle("Number of Entries");
11769 hp->Draw(fShowOption.Data());
11770 }
11771 }
11772 break;
11773
11774 case 9:
11775 // "zy"
11776 {
11777 Int_t first = xaxis->GetFirst();
11778 Int_t last = xaxis->GetLast();
11779 Int_t binx = first + Int_t((last-first)*(px-pxmin)/(pxmax-pxmin));
11780 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11781 xaxis->SetRange(binx,binx2);
11782 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11783 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11784 xx[2] = zaxis->GetXmin();
11785 xx[1] = yaxis->GetXmax();
11786 xx[0] = xaxis->GetBinCenter(binx);
11787 view->WCtoNDC(xx,u);
11788 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11789 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11790 rect1[4].SetX(rect1[0].GetX());
11791 rect1[4].SetY(rect1[0].GetY());
11792 xx[2] = zaxis->GetXmax();
11793 view->WCtoNDC(xx,u);
11794 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11795 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11796 xx[1] = yaxis->GetXmin();
11797 view->WCtoNDC(xx,u);
11798 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11799 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11800 xx[2] = zaxis->GetXmin();
11801 view->WCtoNDC(xx,u);
11802 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11803 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11804 gVirtualX->DrawPolyLine(5,rect1);
11805 if (nbins>1) {
11806 xx[2] = zaxis->GetXmin();
11807 xx[1] = yaxis->GetXmax();
11808 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11809 view->WCtoNDC(xx,u);
11810 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11811 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11812 rect2[4].SetX(rect2[0].GetX());
11813 rect2[4].SetY(rect2[0].GetY());
11814 xx[2] = zaxis->GetXmax();
11815 view->WCtoNDC(xx,u);
11816 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11817 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11818 xx[1] = yaxis->GetXmin();
11819 view->WCtoNDC(xx,u);
11820 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11821 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11822 xx[2] = zaxis->GetXmin();
11823 view->WCtoNDC(xx,u);
11824 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11825 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11826 gVirtualX->DrawPolyLine(5,rect2);
11827 }
11828 c->Clear();
11829 c->cd();
11830 TH2 *hp = (TH2*)h3->Project3D("zy");
11831 xaxis->SetRange(first,last);
11832 if (hp) {
11833 hp->SetFillColor(38);
11834 if (nbins==1)hp->SetTitle(TString::Format("ProjectionZY of binx=%d [x=%.1f..%.f]", binx,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx)));
11835 else hp->SetTitle(TString::Format("ProjectionZY, binx=[%d,%d] [x=%.1f..%.1f]", binx,binx2,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx2)));
11836 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11837 hp->SetYTitle(fH->GetZaxis()->GetTitle());
11838 hp->SetZTitle("Number of Entries");
11839 hp->Draw(fShowOption.Data());
11840 }
11841 }
11842 break;
11843 }
11844 c->Update();
11845}
@ 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:407
R__EXTERN TStyle * gStyle
Definition TStyle.h:433
R__EXTERN TSystem * gSystem
Definition TSystem.h:560
const Int_t kCARTESIAN
Definition TView3D.cxx:33
const Int_t kPOLAR
Definition TView3D.cxx:34
#define gPad
#define gVirtualX
Definition TVirtualX.h:338
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:1078
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:2462
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:19
virtual void SetRGB(Float_t r, Float_t g, Float_t b)
Initialize this color and its associated colors.
Definition TColor.cxx:1759
static void RGBtoHLS(Float_t r, Float_t g, Float_t b, Float_t &h, Float_t &l, Float_t &s)
Definition TColor.h:79
virtual void GetRGB(Float_t &r, Float_t &g, Float_t &b) const
Definition TColor.h:52
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:1823
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:1970
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:2002
static void HLStoRGB(Float_t h, Float_t l, Float_t s, Float_t &r, Float_t &g, Float_t &b)
Definition TColor.h:74
virtual void SetAlpha(Float_t a)
Definition TColor.h:68
To draw a Crown.
Definition TCrown.h:19
void Paint(Option_t *option="") override
Paint this crown with its current attributes.
Definition TCrown.cxx:179
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:214
virtual Double_t GetXmax() const
Definition TF1.h:562
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:479
@ kNotDraw
Definition TF1.h:327
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:558
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:148
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:75
1-D histogram with a double per channel (see TH1 documentation)}
Definition TH1.h:620
1-D histogram with a float per channel (see TH1 documentation)}
Definition TH1.h:577
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:58
TAxis * GetZaxis()
Definition TH1.h:324
void SetTitle(const char *title) override
Change/set the title.
Definition TH1.cxx:6707
virtual EBinErrorOpt GetBinErrorOption() const
Definition TH1.h:271
virtual Float_t GetBarWidth() const
Definition TH1.h:255
virtual Double_t GetMinimumStored() const
Definition TH1.h:291
virtual Float_t GetBarOffset() const
Definition TH1.h:254
static TClass * Class()
virtual Double_t GetStdDev(Int_t axis=1) const
Returns the Standard Deviation (Sigma).
Definition TH1.cxx:7524
virtual Int_t GetNbinsY() const
Definition TH1.h:296
virtual Double_t GetBinError(Int_t bin) const
Return value of error associated to bin number bin.
Definition TH1.cxx:8980
virtual Int_t GetNbinsZ() const
Definition TH1.h:297
virtual Double_t GetNormFactor() const
Definition TH1.h:299
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:7452
virtual Double_t GetSkewness(Int_t axis=1) const
Definition TH1.cxx:7588
virtual Double_t GetContourLevelPad(Int_t level) const
Return the value of contour number "level" in Pad coordinates.
Definition TH1.cxx:8357
virtual void SetXTitle(const char *title)
Definition TH1.h:415
virtual Int_t GetDimension() const
Definition TH1.h:281
static void AddDirectory(Bool_t add=kTRUE)
Sets the flag controlling the automatic add of histograms in memory.
Definition TH1.cxx:1267
@ kNoTitle
Don't draw the histogram title.
Definition TH1.h:168
@ kUserContour
User specified contour levels.
Definition TH1.h:164
@ kNoStats
Don't draw stats box.
Definition TH1.h:163
TAxis * GetXaxis()
Definition TH1.h:322
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:4932
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:8462
virtual Int_t GetNbinsX() const
Definition TH1.h:295
virtual void SetMaximum(Double_t maximum=-1111)
Definition TH1.h:400
TAxis * GetYaxis()
Definition TH1.h:323
virtual Double_t GetBinErrorLow(Int_t bin) const
Return lower error associated to bin number bin.
Definition TH1.cxx:8996
void Draw(Option_t *option="") override
Draw this histogram with options.
Definition TH1.cxx:3067
virtual void SetMinimum(Double_t minimum=-1111)
Definition TH1.h:401
virtual Double_t Integral(Option_t *option="") const
Return integral of bin contents.
Definition TH1.cxx:7858
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:9139
virtual Double_t GetBinLowEdge(Int_t bin) const
Return bin lower edge for 1D histogram.
Definition TH1.cxx:9069
virtual Double_t GetEntries() const
Return the current number of entries.
Definition TH1.cxx:4426
virtual void SetZTitle(const char *title)
Definition TH1.h:417
TList * GetListOfFunctions() const
Definition TH1.h:242
virtual Double_t GetMeanError(Int_t axis=1) const
Return standard error of mean of this histogram along the X axis.
Definition TH1.cxx:7492
virtual Double_t GetMaximumStored() const
Definition TH1.h:287
virtual void GetMinimumAndMaximum(Double_t &min, Double_t &max) const
Retrieve the minimum and maximum values in the histogram.
Definition TH1.cxx:8648
virtual Int_t GetMaximumBin() const
Return location of bin with maximum value in the range.
Definition TH1.cxx:8494
@ kNormal
Errors with Normal (Wald) approximation: errorUp=errorLow= sqrt(N)
Definition TH1.h:64
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition TH1.cxx:5032
virtual Int_t GetContour(Double_t *levels=nullptr)
Return contour values into array levels if pointer levels is non zero.
Definition TH1.cxx:8328
const Double_t * GetBuffer() const
Definition TH1.h:237
virtual Bool_t IsHighlight() const
Definition TH1.h:336
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width for 1D histogram.
Definition TH1.cxx:9080
virtual void SetContour(Int_t nlevels, const Double_t *levels=nullptr)
Set the number and values of contour levels.
Definition TH1.cxx:8400
virtual Double_t GetBinErrorUp(Int_t bin) const
Return upper error associated to bin number bin.
Definition TH1.cxx:9027
virtual void SetYTitle(const char *title)
Definition TH1.h:416
virtual Int_t GetSumw2N() const
Definition TH1.h:313
virtual Double_t GetStdDevError(Int_t axis=1) const
Return error of standard deviation estimation for Normal distribution.
Definition TH1.cxx:7572
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:8552
virtual Double_t GetSumOfWeights() const
Return the sum of weights excluding under/overflows.
Definition TH1.cxx:7834
static Bool_t AddDirectoryStatus()
Static function: cannot be inlined on Windows/NT.
Definition TH1.cxx:735
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:5216
virtual Int_t BufferEmpty(Int_t action=0)
Fill histogram with all entries in the buffer.
Definition TH1.cxx:1387
virtual Double_t GetKurtosis(Int_t axis=1) const
Definition TH1.cxx:7661
2-D histogram with a double per channel (see TH1 documentation)}
Definition TH2.h:301
2-D histogram with a float per channel (see TH1 documentation)}
Definition TH2.h:258
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
TH1D * ProjectionY(const char *name="_py", Int_t firstxbin=0, Int_t lastxbin=-1, Option_t *option="") const
Project a 2-D histogram into a 1-D histogram along Y.
Definition TH2.cxx:2414
TH1D * ProjectionX(const char *name="_px", Int_t firstybin=0, Int_t lastybin=-1, Option_t *option="") const
Project a 2-D histogram into a 1-D histogram along X.
Definition TH2.cxx:2374
Double_t GetBinContent(Int_t binx, Int_t biny) const override
Definition TH2.h:89
static TClass * Class()
Double_t Integral(Option_t *option="") const override
Return integral of bin contents.
Definition TH2.cxx:1270
The 3-D histogram classes derived from the 1-D histogram classes.
Definition TH3.h:31
static TClass * Class()
virtual TH1 * Project3D(Option_t *option="x") const
Project a 3-d histogram into 1 or 2-d histograms depending on the option parameter,...
Definition TH3.cxx:2363
Double_t Integral(Option_t *option="") const override
Return integral of bin contents.
Definition TH3.cxx:1348
The Histogram stack class.
Definition THStack.h:38
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:578
void Add(TObject *obj) override
Definition TList.h:81
TObject * Remove(TObject *obj) override
Remove object from the list.
Definition TList.cxx:822
TObject * First() const override
Return the first object in the list. Returns 0 when list is empty.
Definition TList.cxx:659
virtual TObjLink * FirstLink() const
Definition TList.h:102
void Delete(Option_t *option="") override
Remove all objects from the list AND delete all heap based objects.
Definition TList.cxx:470
TObject * At(Int_t idx) const override
Returns the object at position idx. Returns 0 if idx is out of range.
Definition TList.cxx:357
void AddFirst(TObject *obj) override
Add object at the beginning of the list.
Definition TList.cxx:100
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:75
virtual void SetBorderSize(Int_t bordersize=4)
Definition TPave.h:73
Double_t GetX1NDC() const
Definition TPave.h:59
virtual void SetX2NDC(Double_t x2)
Definition TPave.h:79
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:834
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:56
Sequenceable collection abstract base class.
Basic string class.
Definition TString.h:139
Ssiz_t Length() const
Definition TString.h:421
void ToLower()
Change string to lower-case.
Definition TString.cxx:1170
const char * Data() const
Definition TString.h:380
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:2356
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2334
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:636
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
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
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:1842
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 first.py:1
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
#define mark(osub)
Definition triangle.c:1207